Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support ordering resources created in components with DependsOn relations #2880

Open
AaronFriel opened this issue Mar 13, 2024 · 0 comments
Open
Labels
area/custom-resources kind/enhancement Improvements or new features

Comments

@AaronFriel
Copy link
Member

Hello!

  • Vote on this issue by adding a 馃憤 reaction
  • If you want to implement this feature, comment to let us know (we'll work with you on design, scheduling, etc.)

Issue details

Tools like Kustomize have recognized the need to be provide a global ordering of resources created, as seen by kustomize supporting sortorder. This is used, for example, to ensure that a mutating admission webhook's dependencies are created before it is, which helps mitigate deadlocks and other deployment challenges.

With the upcoming release of yaml/v2.ConfigFile and yaml/v2.ConfigGroup and transformations unavailable, workarounds to apply CRDs and namespaces first are unavailable. One solution would be to add filtering, another would be to support a SortOrder.

This could dramatically simplify deploying complex manifests to a single resource, like this:

new k8s.kustomize.Directory(
  `${name}-crds`,
  {
    directory: './kubeflow', // relative to Pulumi project root
    sortOrder: [
      // every subsequent entry has a DependsOn of all of the previous entries
      { 
        group: [
          { kind: 'CustomResourceDefinition' },
          { kind: 'Namespace' },
        ],
      },
      { kind: 'PodSecurityPolicy' },
      // implicitly, all other resources:
    ]
  },
  { ...opts, retainOnDelete: true },
);

Implementing this today is complex enough to require several resources and applies to manipulate dependsOn between them.

import * as pulumi from '@pulumi/pulumi';
import * as k8s from '@pulumi/kubernetes';

export class Kubeflow extends pulumi.ComponentResource {
  constructor(name: string, args: {}, opts?: pulumi.ComponentResourceOptions) {
    super('component:index:KubeflowOnEks', name, args, opts);

    opts = { parent: this, ...opts };

    let dependsOn = pulumi.output(opts.dependsOn).apply((deps): pulumi.Resource[] => {
      if (deps === undefined) {
        return [];
      }

      if (Array.isArray(deps)) {
        return deps;
      }

      return [deps];
    });

    const crds = new k8s.kustomize.Directory(
      `${name}-crds`,
      {
        directory: './kubeflow', // relative to Pulumi project root
        transformations: [crdsOnly, skipAwait, patchForce],
      },
      { ...opts, retainOnDelete: true },
    );

    dependsOn = pulumi.all([dependsOn, crds, crds.resources]).apply(([dependsOn, crds, crdResources]) => {
      return [...dependsOn, crds, ...Object.values(crdResources)];
    });
    const kubeflowNs = new k8s.core.v1.Namespace(
      `${name}`,
      {
        metadata: {
          name: 'kubeflow',
          labels: {
            'control-plane': 'kubeflow',
            'istio-injection': 'enabled',
            'istio.io/dataplane-mode': 'ambient',
          },
        },
      },
      opts,
    );

    dependsOn = pulumi.all([dependsOn, kubeflowNs]).apply(([dependsOn]) => [...dependsOn, kubeflowNs]);

    new k8s.kustomize.Directory(
      `${name}`,
      {
        directory: './kubeflow', // relative to Pulumi project root
        transformations: [nonCrdsOnly, skipAwait, patchForce],
      },
      { ...opts, dependsOn },
    );
  }
}
import * as pulumi from '@pulumi/pulumi';
import * as k8s from '@pulumi/kubernetes';

export class Kubeflow extends pulumi.ComponentResource {
  constructor(name: string, args: {}, opts?: pulumi.ComponentResourceOptions) {
    super('component:index:KubeflowOnEks', name, args, opts);

    opts = { parent: this, ...opts };

    let dependsOn = pulumi.output(opts.dependsOn).apply((deps): pulumi.Resource[] => {
      if (deps === undefined) {
        return [];
      }

      if (Array.isArray(deps)) {
        return deps;
      }

      return [deps];
    });

    const crds = new k8s.kustomize.Directory(
      `${name}-crds`,
      {
        directory: './kubeflow', // relative to Pulumi project root
        transformations: [crdsOnly, skipAwait, patchForce],
      },
      { ...opts, retainOnDelete: true },
    );

    dependsOn = pulumi.all([dependsOn, crds, crds.resources]).apply(([dependsOn, crds, crdResources]) => {
      return [...dependsOn, crds, ...Object.values(crdResources)];
    });
    const kubeflowNs = new k8s.core.v1.Namespace(
      `${name}`,
      {
        metadata: {
          name: 'kubeflow',
          labels: {
            'control-plane': 'kubeflow',
            'istio-injection': 'enabled',
            'istio.io/dataplane-mode': 'ambient',
          },
        },
      },
      opts,
    );

    dependsOn = pulumi.all([dependsOn, kubeflowNs]).apply(([dependsOn]) => [...dependsOn, kubeflowNs]);

    new k8s.kustomize.Directory(
      `${name}`,
      {
        directory: './kubeflow', // relative to Pulumi project root
        transformations: [nonCrdsOnly, skipAwait, patchForce],
      },
      { ...opts, dependsOn },
    );
  }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area/custom-resources kind/enhancement Improvements or new features
Projects
None yet
Development

No branches or pull requests

2 participants