What is the best method for storing Pulumi constant output in an AWS S3 bucket using TypeScript?

Currently I am developing Infrastructure as Code (IaC) to deploy Amazon EKS using Pulumi with typescript. My CI/CD pipeline is set up with GitHub Actions.

Although I am able to create the EKS cluster smoothly through my pipeline, I am facing challenges in obtaining the resulting kubeconfig file seamlessly.

The commonly cited example suggests exporting the cluster.kubeconfig value and then running the stack output kubeconfig subcommand to retrieve the kubeconfig:

# code snippet
export const kubeconfig = cluster.kubeconfig;

# command
pulumi stack output kubeconfig > kubeconfig.yml

To work around this issue temporarily, I am creating the kubeconfig file in GitHub Actions and utilizing an aws s3 cli command to upload it to S3.

In my Pulumi IaC, I have already configured a private S3 bucket with KMS encryption and defined the kubeconfig output. Is there a way to directly push this output to my S3 bucket without these interim steps?

UPDATE1: After multiple attempts, here is my current approach:

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",
});

However, implementing this method and its variations lead to 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 properties such as 'then', 'catch', [Symbol.toStringTag], finally

Answer №1

The outcome turned out to be:

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",
    })
)

However, I currently do not possess enough understanding to provide a detailed explanation of it.

Answer №2

Utilizing the apply function is essential in this scenario because the variable kubeconfig is not simply a standard string, but rather an Output<string> (or possibly an Output<any>):

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",
});

To delve deeper into the concept of outputs and apply, refer to the documentation.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Is AWS S3 the optimal solution for storing a static pickled database when utilizing Flask and Heroku?

As I transition my application from desktop to Heroku, one of the key decisions I need to make involves managing a moderately large static database (~500mb) of pickled timeseries that is frequently accessed by the app. Given that these resources are stati ...

Struggling with "Content" not being recognized in Typescript PouchDB transpilation errors?

I have been diligently working on an Ionic app for the past three months with no major issues during development or deployment to mobile devices. However, yesterday I encountered a frustrating NPM dependency problem while trying to deploy to mobile. In an ...

What is the significance of parentheses when used in a type definition?

The index.d.ts file in React contains an interface definition that includes the following code snippet. Can you explain the significance of the third line shown below? (props: P & { children?: ReactNode }, context?: any): ReactElement<any> | nu ...

Sharing information between components in Angular through service communication

In my Angular 4 project, there is a functionality where upon clicking on one of the 'groups', its tile should be added to a list of 'favourites' which is represented as an array. To implement this feature, I utilized a BehaviorSubject. ...

Do I still need to install react-router if I have already installed @types/react-router?

My React project was initiated using create-react-app create-react-app my-app --scripts-version=react-scripts-ts Upon creation, the package.json file contained the following: { "name": "my-app", "version": "0.1.0", "private": true, "dependencies ...

Sending information to a RESTapi using Angular 6

Hi there! I am just starting out with Angular 6 and I am encountering an issue while trying to post data to a web API. The error message I am getting is: Error Message: "400 Bad Request: Failed to decode JSON object: Expecting value: line 1 column 1 (char ...

Explore dual functionality options for a button in Ionic 3

I'm currently developing an app using the Ionic 3 framework. It's a simple calculator app that requires two input fields and a button for calculation. Upon pressing the button, the variables will be computed. Below is my HTML code snippet: <i ...

Warning: Potential spacing issues when dynamically adjusting Material UI Grid using Typescript

When working with Typescript, I encountered an error related to spacing values: TS2322: Type 'number' is not assignable to type 'boolean | 7 | 2 | 10 | 1 | 3 | 4 | 5 | 6 | 8 | "auto" | 9 | 11 | 12'. No lint errors found Version: typesc ...

There is no component factory available for the DialogDataExampleDialog. Have you ensured to include it in the @NgModule entryComponents?

Currently, I am a beginner in Angular. I recently started integrating MatDialog into my project. To do this, I followed the code provided on the official Angular documentation page https://material.angular.io/components/dialog/overview. However, upon click ...

Conceal the name of a property when displaying it

I have a function that retrieves data from an interface, which includes a property called name. Currently, the output includes the property name, but I would like to remove it if possible. How can I achieve this? Here is the interface structure: export i ...

Create a fresh keyValuePair instance and incorporate a pre-existing dictionary in Type Script

I have created a custom dictionary class, but I am uncertain on how to define the Dictionary attribute. There's a JSON file named Switches: {"ShowImage": true,"ShowText": false, "showButton", true} import * as switches ...

Guide on how to specify the return type for useMutation in the 'react-query' library

Here is the code snippet provided: const setFriendCode = (data: Params) => api({ data }) const [mutateSetFriendCode, state] = useMutation<Response, Params>( setFriendCode ) An issue arises with the type of parameters in the code. The compiler ...

Changes on services do not affect the Angular component

Currently facing an issue with my Angular assignment where changing an element's value doesn't reflect in the browser, even though the change is logged in the console. The task involves toggling the status of a member from active to inactive and ...

Can a specific type be created for a nested object that has varying levels of depth?

One of my functions organizes objects based on the length of an input array. For example: fn(['a']) -> Record<string, string> fn(['a', 'b']) -> Record<Record<string, string>> I've defined the ret ...

The module named "tapable" does not contain an export for the item "Tapable"

While developing a WordPress plugin for a custom Gutenberg block, I encountered a challenge. I needed to incorporate additional scripts in TypeScript and opted to use "$ tsc --watch" along with a "tsconfig.json" file for compilation. Upon installing @word ...

Move on to a different screen in a React Component once the data has been fetched

Currently, I am delving into the world of React and TypeScript and attempting to utilize "react-router-dom" in order to create a login component that will interact with my backend server. Essentially, my goal is to develop a "Login" class that, upon form ...

Importing Modules in Angular: Explicit vs Implicit Approach

My current setup includes a SharedModule that is imported by every other module. This means that some modules have an implicit import to the SharedModule because they import other modules that already import it. I'm curious if this could potentially i ...

In my attempt to assess the correlation between value 1 and a value in the preceding object, I am utilizing the *ngFor directive

Attempting to compare 2 entries in an *ngFor loop. The code should compare the value at the current object to a value at the previous object. <ng-container *ngFor="let item of s_1.comments[0]; index as b"> <article class="message i ...

The error message "Type 'Dispatch<SetStateAction<undefined>>' cannot be assigned to type 'Dispatch<SetStateAction<MyType | undefined>>'" appears in the code

I'm encountering challenges while creating a wrapper for useState() due to an unfamiliar error: Type 'Dispatch<SetStateAction>' cannot be assigned to type 'Dispatch<SetStateAction<VerifiedPurchase | undefined>>' ...

Issue with Angular 18 component not being displayed or identified

Recently, I began building an Angular 18 application and encountered an issue with adding my first component as a standalone. It appears that the app is not recognizing my component properly, as it does not display when added as an HTML tag in my app.compo ...