Paymahn Moghadasian
Paymahn Moghadasian

Reputation: 10349

Pulumi modify kubernetes resource based on selected stack

what is the best way to modify kubernetes containers based on which stack is selected? I see that Input types cannot be modified. I've found the spread operator eg:

  const ledgerDeployment = new k8s.extensions.v1beta1.Deployment("ledger", {
    metadata: {
      namespace: ledgerNamespace.metadata.name,
    },
    spec: {
      template: {
        metadata: {
          labels: {name: "ledger"},
        },
        spec: {
          containers: [
              // containers
          ],

          volumes: [
            {
              //volume 1
            },
            {
              // volume 2
            },
            // conditional volume based on the stack
            ...(stack == 'dev' ? [{
              name: dbTLS.metadata.name,
              secret: {secretName: dbTLS.metadata.name, defaultMode: 256}
            }] : [])
          ]
        }
      }
    }
  });

but that feels kinda icky and in my opinion adds complexity to large resource declarations (especially as the conditionals become more complex). I've tried pulling out the container definition into a variable but since I can't declare the type of the variable I'm having some problems with assigning an Output to one of the keys in the variable:

  let apiContainer = {
    name: "api",
    image: appImage.imageName,
    // more stuff ...
    volumeMounts: [
      {
        mountPath: "/app/gunicorn-socket",
        name: "gunicorn-socket-dir",
        readOnly: false
      },
    ],
  }

  if (stack != 'local') {
    apiContainer.volumeMounts.push({
      mountPath: "/etc/secret/db",
      name: dbTLS.metadata.name,
      readOnly: true
    })
  }

Gives an error on name with Type 'Output<string>' is not assignable to type 'string'.

It seems that the interface is exported on github for tag 1.4.5 but when I view the interface locally it's not exported:

12:41PM /Users/paymahn/qwil/ledger/pulumi/infra pulumi ⬆ ⬇ ✱ ➜
 ❯❯❯ rg "interface Container" --no-ignore -g "**/*kube*/**"
node_modules/@pulumi/kubernetes/types/input.d.ts
8424:        interface Container {
8575:        interface ContainerImage {
8589:        interface ContainerPort {
8619:        interface ContainerState {
8636:        interface ContainerStateRunning {
8645:        interface ContainerStateTerminated {
8678:        interface ContainerStateWaiting {
8691:        interface ContainerStatus {

node_modules/@pulumi/kubernetes/types/output.d.ts
8508:        interface Container {
8659:        interface ContainerImage {
8673:        interface ContainerPort {
8703:        interface ContainerState {
8720:        interface ContainerStateRunning {
8729:        interface ContainerStateTerminated {
8762:        interface ContainerStateWaiting {
8775:        interface ContainerStatus {

I've verified that I'm on v1.4.5 locally:

12:37PM /Users/paymahn/qwil/ledger/pulumi/infra  ✘ 1 pulumi ⬆ ⬇ ✱ ➜
 ❯❯❯ npm list "@pulumi/kubernetes"
kubernetes-typescript@ /Users/paymahn/qwil/ledger/pulumi/infra
├── @pulumi/[email protected]
└─┬ @pulumi/[email protected]
  └── @pulumi/[email protected]

Upvotes: 0

Views: 350

Answers (1)

Mikhail Shilkov
Mikhail Shilkov

Reputation: 35144

The types are available, maybe you are looking at a wrong package. E.g. k8s.types.input.core.v1.Container is the right type name.

To dynamically build a collection of volume mounts, it's easiest to operate with arrays of mounts directly:

const volumeMounts: k8s.types.input.core.v1.VolumeMount[] = [{
    mountPath: "/app/gunicorn-socket",
    name: "gunicorn-socket-dir",
    readOnly: false
}];

if (stack != 'local') {
    volumeMounts.push({
        mountPath: "/etc/secret/db",
        name: dbTLS.metadata.name,
        readOnly: true
    });
}

const apiContainer: k8s.types.input.core.v1.Container = {
    name: "api",
    image: appImage.imageName, 
    volumeMounts,
};

Had you declared an instance of k8s.types.input.core.v1.Container, now volumeMounts property would be not an array but an input of array, so you'd have to convert it to output, apply, create a new array, and assign back.

Upvotes: 1

Related Questions