1

I'm writing IaC to deploy Amazon EKS in Pulumi + typescript. I am using GitHub Actions as my CI/CD.

Currently I can create the EKS cluster via my pipeline with pulumi without issue but I have not figured out a clean way to acquire the resulting kubeconfig.

I can get the kubeconfig via the frequently documented example by exporting the cluster.kubeconfig value and then executing the stack output kubeconfig subcommand

# code snippet
export const kubeconfig = cluster.kubeconfig;

# command
pulumi stack output kubeconfig > kubeconfig.yml

As a current workaround, I am using this method to create the kubeconfig file in github actions, and then using an aws s3 cli command to upload the file to s3.

I have already created a private s3 bucket with kms encryption in my pulumi iac and defined the kubeconfig output in my iac. Is there a way to write my pulumi typescript code to push the output directly to my s3 bucket without these intermediary steps?

UPDATE1: Current best effort brings me to:

const keksAdminBucket = new aws.s3.Bucket("keksAdminBucket", {acl: "private"});
const keksAdminBucketObject = new aws.s3.BucketObject("keksAdminBucketObject", {
    key: "kubeconfig",
    bucket: keksAdminBucket.id,
    source: new pulumi.asset.StringAsset(String(cluster.kubeconfig)),
    serverSideEncryption: "aws:kms",
});

This and variations on the theme result in errors like:

    index.ts(45,42): error TS2345: Argument of type 'Output<any>' is not assignable to parameter of type 'string | Promise<string>'.
      Type 'OutputInstance<any>' is not assignable to type 'string | Promise<string>'.
        Type 'OutputInstance<any>' is missing the following properties from type 'Promise<string>': then, catch, [Symbol.toStringTag], finally
usrbinkat
  • 11
  • 3

2 Answers2

0

You should use the apply method because kubeconfig is an Output<string> (or Output<any>?), not just a string:

const keksAdminBucketObject = new aws.s3.BucketObject("keksAdminBucketObject", {
    key: "kubeconfig",
    bucket: keksAdminBucket.id,
    source: cluster.kubeconfig.apply(s => new pulumi.asset.StringAsset(JSON.stringify(s))),
    serverSideEncryption: "aws:kms",
});

Learn more about outputs and apply in the docs.

Mikhail Shilkov
  • 34,128
  • 3
  • 68
  • 107
  • I added a missing ```)``` and then ran the code. It ran clean, however the content of the ```kubeconfig``` file in the s3 bucket ended up being: ```[object Object]``` – usrbinkat Jul 22 '21 at 16:37
  • Okay, I didn't know your `kubeconfig` was an object not string. It makes sense now. I fixed my answer. – Mikhail Shilkov Jul 23 '21 at 08:12
0

The answer ended up being:

const keksAdminBucket = new aws.s3.Bucket("keksAdminBucket", {acl: "private"});
const keksAdminBucketObject = cluster.kubeconfig.apply(
  (config) =>
    new aws.s3.BucketObject("keksAdminBucketObject", {
      key: "kubeconfig",
      bucket: keksAdminBucket.id,
      source: new pulumi.asset.StringAsset(JSON.stringify(config)),
      serverSideEncryption: "aws:kms",
    })
)

And I do not understand it well enough to explain why yet.

usrbinkat
  • 11
  • 3
  • Creating resources in `apply` is discoraged: e.g., you will not see it in the initial preview. See my updated answer that should work better. – Mikhail Shilkov Jul 23 '21 at 08:13