Hi everyone :raised_hands: I’m using TypeScript, t...
# typescript
p
Hi everyone πŸ™Œ I’m using TypeScript, the Pulumi Automation API, and
ComponentResource
. Currently, while working with a stack, I’m running into an issue where the stack halts when a certain resource creation fails. β€’ Using
diagnostic
events and
resOpFailedEvent
, I can detect that a problem has occurred, but the process never reaches the
summary or cancel
event. No further actions are performed. β€’ The Pulumi
CommandError
is also not being caught. β€’ When I add the
continueOnError
option, the
summary
event is triggered as expected. My question is: when using the Automation API without the
continueOnError
option, is it correct that I need to explicitly call
cancel()
when a
error
(like... err: Error: Resource monitor is terminating) occurs? β€’ can't i get summary event in this case?? If I’ve misunderstood something or missed a detail, I’d appreciate your guidance.
log
Copy code
{
  "sequence": 57,
  "timestamp": 1754891003,
  "diagnosticEvent": {
    "urn": "urn:pulumi:aws-test-corp-kint5-ap-northeast-2-dev-ECS-kidol-zz-service::aws-test-corp-kint5-ap-northeast-2-dev-ECS-kidol-zz-service::ECSTemplateV1$aws:iam/role:Role::ecs-task-role",
    "prefix": "error: ",
    "message": "  sdk-v2/provider2.go:572: sdk.helper_schema: creating IAM Role (kidol-zz-service-dev): operation error IAM: CreateRole, https response error StatusCode: 409, RequestID: de501574-7a9e-4daa-b3c3-35681de74a51, EntityAlreadyExists: Role with name kidol-zz-service-dev already exists.: provider=aws@6.83.0\n\n",
    "color": "never",
    "severity": "error"
  }
}
{
  "sequence": 58,
  "timestamp": 1754891003,
  "diagnosticEvent": {
    "urn": "urn:pulumi:aws-test-corp-kint5-ap-northeast-2-dev-ECS-kidol-zz-service::aws-test-corp-kint5-ap-northeast-2-dev-ECS-kidol-zz-service::ECSTemplateV1$aws:iam/role:Role::ecs-task-role",
    "prefix": "error: ",
    "message": "1 error occurred:\n\t* creating IAM Role (kidol-zz-service-dev): operation error IAM: CreateRole, https response error StatusCode: 409, RequestID: de501574-7a9e-4daa-b3c3-35681de74a51, EntityAlreadyExists: Role with name kidol-zz-service-dev already exists.\n\n\n",
    "color": "never",
    "severity": "error"
  }
}
{
  "sequence": 59,
  "timestamp": 1754891003,
  "resOpFailedEvent": {
    "metadata": {
      "op": "create",
      "urn": "urn:pulumi:aws-test-corp-kint5-ap-northeast-2-dev-ECS-kidol-zz-service::aws-test-corp-kint5-ap-northeast-2-dev-ECS-kidol-zz-service::ECSTemplateV1$aws:iam/role:Role::ecs-task-role",
      "type": "aws:iam/role:Role",
      "old": null,
      "new": {
        "type": "aws:iam/role:Role",
        "urn": "urn:pulumi:aws-test-corp-kint5-ap-northeast-2-dev-ECS-kidol-zz-service::aws-test-corp-kint5-ap-northeast-2-dev-ECS-kidol-zz-service::ECSTemplateV1$aws:iam/role:Role::ecs-task-role",
        "custom": true,
        "id": "",
        "parent": "urn:pulumi:aws-test-corp-kint5-ap-northeast-2-dev-ECS-kidol-zz-service::aws-test-corp-kint5-ap-northeast-2-dev-ECS-kidol-zz-service::ECSTemplateV1::kint5-kidol-zz-service-dev",
        "inputs": {
          "__defaults": [
            "forceDetachPolicies",
            "maxSessionDuration",
            "path"
          ],
          "assumeRolePolicy": "{\"Statement\":[{\"Action\":\"sts:AssumeRole\",\"Effect\":\"Allow\",\"Principal\":{\"Service\":\"ecs-tasks.amazonaws.com\"}}],\"Version\":\"2012-10-17\"}",
          "forceDetachPolicies": false,
          "inlinePolicies": [],
          "maxSessionDuration": 3600,
          "name": "kidol-zz-service-dev",
          "path": "/"
        },
        "outputs": {},
        "provider": "urn:pulumi:aws-test-corp-kint5-ap-northeast-2-dev-ECS-kidol-zz-service::aws-test-corp-kint5-ap-northeast-2-dev-ECS-kidol-zz-service::ECSTemplateV1$pulumi:providers:aws::provider::b93e3cde-5d9a-4db3-94b1-b9c64cbb1f56"
      },
      "detailedDiff": null,
      "logical": true,
      "provider": "urn:pulumi:aws-test-corp-kint5-ap-northeast-2-dev-ECS-kidol-zz-service::aws-test-corp-kint5-ap-northeast-2-dev-ECS-kidol-zz-service::ECSTemplateV1$pulumi:providers:aws::provider::b93e3cde-5d9a-4db3-94b1-b9c64cbb1f56"
    },
    "status": 0,
    "steps": 3
  }
}
{
  "sequence": 60,
  "timestamp": 1754891003,
  "diagnosticEvent": {
    "prefix": "error: ",
    "message": "update failed\n",
    "color": "never",
    "severity": "error"
  }
}
{
  "sequence": 61,
  "timestamp": 1754891003,
  "diagnosticEvent": {
    "prefix": "debug: ",
    "message": "RegisterResource RPC finished: resource:ecs-task-role[aws:iam/role:Role]; err: Error: Resource monitor is terminating, resp: undefined\n",
    "color": "never",
    "severity": "debug"
  }
}

... never end
code
Copy code
@Injectable()
export class PulumiService implements IProvisioner {
  private readonly PULUMI_RUNTIME = 'nodejs';
  private readonly logger = new Logger(PulumiService.name);

  constructor(
    private readonly configService: ConfigService,
    private readonly pulumiEventService: PulumiEventService,
    private readonly pulumiProgramService: PulumiProgramService,
  ) {}

  async create(command: ProvisioningCommand) {
    await this.executeProvisioning(ProvisioningActionType.CREATE, command);
  }

  async update(command: ProvisioningCommand) {
    await this.executeProvisioning(ProvisioningActionType.UPDATE, command);
  }

  async delete(command: ProvisioningCommand) {
    await this.executeProvisioning(ProvisioningActionType.DELETE, command);
  }

  async preview(command: ProvisioningCommand) {
    await this.executeProvisioning(ProvisioningActionType.PREVIEW, command);
  }

  private async executeProvisioning(
    actionType: ProvisioningActionType,
    command: ProvisioningCommand,
  ) {
    const pulumiStack = await this.createPulumiStack(actionType, command);
    await this.executePulumiOperation(actionType, command, pulumiStack);
  }

  private async createPulumiStack(
    actionType: ProvisioningActionType,
    command: ProvisioningCommand,
  ): Promise<Stack> {
    const pulumiStackName = this.createPulumiStackName(
      command.resourceMetadata,
    );
    const pulumiProjectName = this.createPulumiProjectName(
      command.resourceMetadata,
    );
    const pulumiProgram = this.pulumiProgramService.createPulumiProgram(
      actionType,
      command.resourceMetadata,
      command.resourceConfig,
    );

    return await LocalWorkspace.createOrSelectStack(
      {
        stackName: pulumiStackName,
        projectName: pulumiProjectName,
        program: pulumiProgram,
      },
      {
        projectSettings: {
          name: pulumiProjectName,
          runtime: this.PULUMI_RUNTIME,
          backend: {
            url: this.createPulumiBackendUrl(command.resourceMetadata),
          },
        },
        envVars: {
          PULUMI_CONFIG_PASSPHRASE: this.configService.get<string>(
            'PULUMI_CONFIG_PASSPHRASE',
            'dev-passphrase',
          ),
        },
      },
    );
  }

  private async executePulumiOperation(
    actionType: ProvisioningActionType,
    command: ProvisioningCommand,
    stack: Stack,
  ): Promise<void> {
    const pulumiOnEventHandler =
      this.pulumiEventService.createPulumiEventHandler(
        command.jobId,
        command.correlatedEventId,
      );

    const pulumiExecutionOptions = {
      refresh: true,
      onEvent: pulumiOnEventHandler,
    };

    switch (actionType) {
      case ProvisioningActionType.CREATE:
        await this.executeStackWithBackendLockRetry(stack, () => stack.up(pulumiExecutionOptions));
        return;
      case ProvisioningActionType.UPDATE:
        await this.executeStackWithBackendLockRetry(stack, () => stack.up(pulumiExecutionOptions));
        return;
      case ProvisioningActionType.DELETE:
        await this.executeStackWithBackendLockRetry(stack, () => stack.destroy(pulumiExecutionOptions));
        return;
      case ProvisioningActionType.PREVIEW:
        await this.executeStackWithBackendLockRetry(stack, () =>
          stack.preview({ ...pulumiExecutionOptions, diff: true }),
        );
        return;
      default:
        throw new Error(`Invalid action type for Pulumi: ${actionType}`);
    }
  }

  private createPulumiStackName(resourceMetadata: ResourceMetadata): string {
    return PulumiUtil.createPulumiIdentifier(resourceMetadata, '-');
  }

  private createPulumiProjectName(resourceMetadata: ResourceMetadata): string {
    return PulumiUtil.createPulumiIdentifier(resourceMetadata, '-');
  }

  private createPulumiBackendUrl(resourceMetadata: ResourceMetadata): string {
    const backendBucket = this.configService.get<string>(
      'PULUMI_BACKEND_BUCKET',
      'test-idp-dev-bucket',
    );
    const backendKey = PulumiUtil.createPulumiIdentifier(
      resourceMetadata,
      '/',
    );
    return `s3://${backendBucket}/${backendKey}`;
  }

  private async executeStackWithBackendLockRetry<T>(
    stack: Stack,
    operation: () => Promise<T>,
    retries = 1,
  ): Promise<T> {
    try {
      return await operation();
    } catch (error) {
      if (retries > 0 && error instanceof ConcurrentUpdateError) {
        this.logger.warn(`Pulumi stack ${stack.name}: backend lock detected. Trying cancel()...`);
        await stack.cancel();
        await new Promise(resolve => setTimeout(resolve, 3000));
        return this.executeStackWithBackendLockRetry(stack, operation, retries - 1);        
      }

      // todo : publish kafka error event
      await stack.cancel();
      throw error;
    }
  }
}
https://www.pulumi.com/blog/continue-on-error/
Copy code
If one of those operations fails, you may have noticed that Pulumi takes the most conservative approach, letting already in-flight operations complete, but not starting any new operations. Most often, that's what you want – there might be no point in bringing up more infrastructure if a resource fails.
with below
Copy code
onOutput: (out: string) => this.logger.debug(`[pulumi out] ${out}`),

onError: (err: string) => this.logger.error(`[pulumi err] ${err}`),
Copy code
[Nest] 72132  - 08/11/2025, 9:33:10 PM   DEBUG [PulumiService] [pulumi out] Updating (aws-test-corp-kint5-ap-northeast-2-dev-ECS-kidol-zz-service):

[Nest] 72132  - 08/11/2025, 9:33:10 PM   DEBUG [PulumiService] [pulumi out] 

[Nest] 72132  - 08/11/2025, 9:33:10 PM   DEBUG [PulumiService] [pulumi out]  ~  pulumi:pulumi:Stack aws-test-corp-kint5-ap-northeast-2-dev-ECS-kidol-zz-service-aws-test-corp-kint5-ap-northeast-2-dev-ECS-kidol-zz-service refreshing (0s) 
 ~  ECSTemplateV1 kint5-kidol-zz-service-dev refreshing (0s) 

[Nest] 72132  - 08/11/2025, 9:33:10 PM   DEBUG [PulumiService] [pulumi out]  ~  pulumi:pulumi:Stack aws-test-corp-kint5-ap-northeast-2-dev-ECS-kidol-zz-service-aws-test-corp-kint5-ap-northeast-2-dev-ECS-kidol-zz-service refreshing (0s) 
 ~  ECSTemplateV1 kint5-kidol-zz-service-dev refresh (0.00s) 

[Nest] 72132  - 08/11/2025, 9:33:10 PM   DEBUG [PulumiService] [pulumi out]  ~  pulumi:providers:aws provider refreshing (0s) 
 ~  pulumi:providers:aws provider refresh (0.00s) 

[Nest] 72132  - 08/11/2025, 9:33:10 PM   DEBUG [PulumiService] [pulumi out]  ~  terraform:state:RemoteStateReference security refreshing (0s) 

[Nest] 72132  - 08/11/2025, 9:33:10 PM   DEBUG [PulumiService] [pulumi out]  ~  terraform:state:RemoteStateReference platforms refreshing (0s) 
 ~  terraform:state:RemoteStateReference network refreshing (0s) 

[Nest] 72132  - 08/11/2025, 9:33:11 PM   DEBUG [PulumiService] [pulumi out] @ updating....
[Nest] 72132  - 08/11/2025, 9:33:11 PM   DEBUG [PulumiService] [pulumi out] 
 ~  terraform:state:RemoteStateReference platforms refresh (0.85s) 

[Nest] 72132  - 08/11/2025, 9:33:11 PM   DEBUG [PulumiService] [pulumi out]  ~  terraform:state:RemoteStateReference network refresh (1s) 

[Nest] 72132  - 08/11/2025, 9:33:11 PM   DEBUG [PulumiService] [pulumi out]  ~  terraform:state:RemoteStateReference security refresh (1s) 

[Nest] 72132  - 08/11/2025, 9:33:11 PM   DEBUG [PulumiService] [pulumi out]     pulumi:pulumi:Stack aws-test-corp-kint5-ap-northeast-2-dev-ECS-kidol-zz-service-aws-test-corp-kint5-ap-northeast-2-dev-ECS-kidol-zz-service running 

[Nest] 72132  - 08/11/2025, 9:33:11 PM   DEBUG [PulumiService] [pulumi out]     ECSTemplateV1 kint5-kidol-zz-service-dev  

[Nest] 72132  - 08/11/2025, 9:33:12 PM   DEBUG [PulumiService] [pulumi out] @ updating....
[Nest] 72132  - 08/11/2025, 9:33:13 PM   DEBUG [PulumiService] [pulumi out] .
[Nest] 72132  - 08/11/2025, 9:33:13 PM   DEBUG [PulumiService] [pulumi out] 
    pulumi:providers:aws provider  
[Nest] 72132  - 08/11/2025, 9:33:13 PM   DEBUG [PulumiService] [pulumi out] 
    pulumi:pulumi:Stack aws-test-corp-kint5-ap-northeast-2-dev-ECS-kidol-zz-service-aws-test-corp-kint5-ap-northeast-2-dev-ECS-kidol-zz-service running read terraform:state:RemoteStateReference security
    pulumi:pulumi:Stack aws-test-corp-kint5-ap-northeast-2-dev-ECS-kidol-zz-service-aws-test-corp-kint5-ap-northeast-2-dev-ECS-kidol-zz-service running read terraform:state:RemoteStateReference network

[Nest] 72132  - 08/11/2025, 9:33:13 PM   DEBUG [PulumiService] [pulumi out]     pulumi:pulumi:Stack aws-test-corp-kint5-ap-northeast-2-dev-ECS-kidol-zz-service-aws-test-corp-kint5-ap-northeast-2-dev-ECS-kidol-zz-service running read terraform:state:RemoteStateReference platforms

[Nest] 72132  - 08/11/2025, 9:33:13 PM   DEBUG [PulumiService] [pulumi out]  +  aws:iam:Role ecs-task-role creating (0s) 

[Nest] 72132  - 08/11/2025, 9:33:14 PM   DEBUG [PulumiService] [pulumi out]     pulumi:pulumi:Stack aws-test-corp-kint5-ap-northeast-2-dev-ECS-kidol-zz-service-aws-test-corp-kint5-ap-northeast-2-dev-ECS-kidol-zz-service running read terraform:state:RemoteStateReference security

[Nest] 72132  - 08/11/2025, 9:33:14 PM   DEBUG [PulumiService] [pulumi out] @ updating....
[Nest] 72132  - 08/11/2025, 9:33:14 PM   DEBUG [PulumiService] [pulumi out] 
    pulumi:pulumi:Stack aws-test-corp-kint5-ap-northeast-2-dev-ECS-kidol-zz-service-aws-test-corp-kint5-ap-northeast-2-dev-ECS-kidol-zz-service running read terraform:state:RemoteStateReference network

[Nest] 72132  - 08/11/2025, 9:33:14 PM   DEBUG [PulumiService] [pulumi out]     pulumi:pulumi:Stack aws-test-corp-kint5-ap-northeast-2-dev-ECS-kidol-zz-service-aws-test-corp-kint5-ap-northeast-2-dev-ECS-kidol-zz-service running read terraform:state:RemoteStateReference platforms

[Nest] 72132  - 08/11/2025, 9:33:15 PM   DEBUG [PulumiService] [pulumi out]  +  aws:iam:Role ecs-task-role creating (1s) error:   sdk-v2/provider2.go:572: sdk.helper_schema: creating IAM Role (kidol-zz-service-dev): operation error IAM: CreateRole, https response error StatusCode: 409, RequestID: 876f22ba-3517-405f-aabc-2e8d20d43a36, EntityAlreadyExists: Role with name kidol-zz-service-dev already exists.: provider=aws@7.3.1

[Nest] 72132  - 08/11/2025, 9:33:15 PM   DEBUG [PulumiService] [pulumi out]  +  aws:iam:Role ecs-task-role creating (1s) error: 1 error occurred:

[Nest] 72132  - 08/11/2025, 9:33:15 PM   DEBUG [PulumiService] [pulumi out]  +  aws:iam:Role ecs-task-role **creating failed** error: 1 error occurred:

[Nest] 72132  - 08/11/2025, 9:33:15 PM   DEBUG [PulumiService] [pulumi out] @ updating....
[Nest] 72132  - 08/11/2025, 9:33:15 PM   DEBUG [PulumiService] [pulumi out] 
    pulumi:pulumi:Stack aws-test-corp-kint5-ap-northeast-2-dev-ECS-kidol-zz-service-aws-test-corp-kint5-ap-northeast-2-dev-ECS-kidol-zz-service running error: update failed

[Nest] 72132  - 08/11/2025, 9:33:16 PM   DEBUG [PulumiService] [pulumi out] @ updating....
[Nest] 72132  - 08/11/2025, 9:33:17 PM   DEBUG [PulumiService] [pulumi out] .
[Nest] 72132  - 08/11/2025, 9:33:18 PM   DEBUG [PulumiService] [pulumi out] .
[Nest] 72132  - 08/11/2025, 9:33:19 PM   DEBUG [PulumiService] [pulumi out] .
[Nest] 72132  - 08/11/2025, 9:33:20 PM   DEBUG [PulumiService] [pulumi out] .
[Nest] 72132  - 08/11/2025, 9:33:21 PM   DEBUG [PulumiService] [pulumi out] .
[Nest] 72132  - 08/11/2025, 9:33:22 PM   DEBUG [PulumiService] [pulumi out] .
[Nest] 72132  - 08/11/2025, 9:33:23 PM   DEBUG [PulumiService] [pulumi out] .
[Nest] 72132  - 08/11/2025, 9:33:24 PM   DEBUG [PulumiService] [pulumi out] .
[Nest] 72132  - 08/11/2025, 9:33:25 PM   DEBUG [PulumiService] [pulumi out] .
[Nest] 72132  - 08/11/2025, 9:33:26 PM   DEBUG [PulumiService] [pulumi out] .
[Nest] 72132  - 08/11/2025, 9:33:27 PM   DEBUG [PulumiService] [pulumi out] .
[Nest] 72132  - 08/11/2025, 9:33:28 PM   DEBUG [PulumiService] [pulumi out] .
[Nest] 72132  - 08/11/2025, 9:33:29 PM   DEBUG [PulumiService] [pulumi out] .
[Nest] 72132  - 08/11/2025, 9:33:30 PM   DEBUG [PulumiService] [pulumi out] .
[Nest] 72132  - 08/11/2025, 9:33:31 PM   DEBUG [PulumiService] [pulumi out] .

... endless
Copy code
"@pulumi/aws": "^7.3.1",
    "@pulumi/pulumi": "^3.188.0",
    "@pulumi/terraform": "5.13.4",
e
Do you only see this with automation api, or (if this isn't an inline program) can you repro it hanging with just the CLI?
πŸ‘€ 1
p
When running componentResource with pulumi CLI in the same situation, i was able to see the following logs. No hang occurred and I was able to see the error immediately. (..in the case of automation API, when using the continueOnError option, I was able to catch the commandError)
Copy code
Enter your passphrase to unlock config/secrets
Previewing update (dev):
     Type                        Name                        Plan       
 +   pulumi:pulumi:Stack         worker-ecs-test-dev         create     
 +   └─ ECSTemplateV1            kint5-kidol-zz-service-dev  create     
 +      β”œβ”€ pulumi:providers:aws  provider                    create     
 +      └─ aws:iam:Role          ecs-task-role               create     

Resources:
    + 4 to create

Do you want to perform this update? yes
Updating (dev):
     Type                        Name                        Status                       Info
 +   pulumi:pulumi:Stack         worker-ecs-test-dev         **creating failed (3s)**     1 error
 +   └─ ECSTemplateV1            kint5-kidol-zz-service-dev  created (0.01s)              
 +      β”œβ”€ pulumi:providers:aws  provider                    created (0.00s)              
 +      └─ aws:iam:Role          ecs-task-role               **creating failed**          2 errors

Diagnostics:
  pulumi:pulumi:Stack (worker-ecs-test-dev):
    error: update failed

  aws:iam:Role (ecs-task-role):
    error:   sdk-v2/provider2.go:572: sdk.helper_schema: creating IAM Role (kidol-zz-service-dev): operation error IAM: CreateRole, https response error StatusCode: 409, RequestID: 91bbf257-2923-4b60-87a2-377dd4522c6e, EntityAlreadyExists: Role with name kidol-zz-service-dev already exists.: provider=aws@7.3.1
    error: 1 error occurred:
        * creating IAM Role (kidol-zz-service-dev): operation error IAM: CreateRole, https response error StatusCode: 409, RequestID: 91bbf257-2923-4b60-87a2-377dd4522c6e, EntityAlreadyExists: Role with name kidol-zz-service-dev already exists.

Resources:
    + 3 created

Duration: 4s

a18144@18144ui-noteubug src %
I expected that even if some resources in the componentResource fail to update or create for various reasons, it would still finish normally or I'd be able to catch the commandError. Am I misunderstanding something here? β€’ At least I thought the stack operation wouldn't hang. In cases like this, do I generally need to explicitly call cancel() myself?
e
No you shouldn't need to call cancel yourself, this does look like a bug
πŸ‘€ 1
If you raise an issue, copy everything from this thread, we can take a look and see if we can repro as well.
p
This issue was caused by my mistake. 😒 there was a problem with the return statement. i'll leave this here in case it might help others
Copy code
@Injectable()
export class PulumiProgramService {
  constructor() {}

  createPulumiProgram(): PulumiFn {
    ~~~~
    ~~~~

    // it works
    return async () => {
      new ECSTemplateV1(~~); // componentResource
    }

    // Stack hangs when there's an issue during operation
    // return async () =>
    //   new ECSTemplateV1(~~);
  }
}
------ There's still a problem 😒
First, let me leave some reproducible code here. I was able to confirm that a hang occurs when you pre-create an IAM role with the same name and then run this code
Copy code
import { LocalWorkspace, Stack } from '@pulumi/pulumi/automation/index.js';
import * as pulumi from '@pulumi/pulumi';
import * as aws from '@pulumi/aws';


class ECSTaskRoleComponent extends pulumi.ComponentResource {
  public taskRole: aws.iam.Role;
  public taskRolePolicy: aws.iam.RolePolicy;

  constructor(name: string, opts?: pulumi.ComponentResourceOptions) {
    super('custom:aws:ECSTaskRole', name, {}, opts);

    this.taskRole = new aws.iam.Role(`${name}-task-role`, {
      name: `${name}-task-role`,
      assumeRolePolicy: JSON.stringify({
        Version: '2012-10-17',
        Statement: [
          {
            Effect: 'Allow',
            Principal: {
              Service: '<http://ecs-tasks.amazonaws.com|ecs-tasks.amazonaws.com>',
            },
            Action: 'sts:AssumeRole',
          },
        ],
      }),
      tags: {
        Name: `${name}-task-role`,
        Environment: 'test',
      },
    }, { parent: this });

    this.taskRolePolicy = new aws.iam.RolePolicy(`${name}-task-role-policy`, {
      name: `${name}-task-role-policy`,
      role: this.taskRole.id,
      policy: JSON.stringify({
        Version: '2012-10-17',
        Statement: [
          {
            Effect: 'Allow',
            Action: [
              's3:GetObject',
              's3:PutObject',
              's3:DeleteObject',
              's3:ListBucket',
            ],
            Resource: [
              'arn:aws:s3:::test-bucket',
              'arn:aws:s3:::test-bucket/*',
            ],
          },
          {
            Effect: 'Allow',
            Action: [
              'logs:CreateLogGroup',
              'logs:CreateLogStream',
              'logs:PutLogEvents',
            ],
            Resource: '*',
          },
        ],
      }),
    }, { parent: this });
    this.registerOutputs({
      taskRoleArn: this.taskRole.arn,
      taskRoleName: this.taskRole.name,
      taskRolePolicyName: this.taskRolePolicy.name,
    });
  }
}
function createSimplePulumiProgram() {
  return async () => {
    const ecsTaskRole = new ECSTaskRoleComponent('kidol-zz-service');

    // 좜λ ₯
    return {
      taskRoleArn: ecsTaskRole.taskRole.arn,
      taskRoleName: ecsTaskRole.taskRole.name,
      taskRolePolicyName: ecsTaskRole.taskRolePolicy.name,
    };
  };
}
async function testPulumiAutomation() {
  
  const stackName = 'test~';
  const projectName = 'test~';
  const backendUrl = '<s3://test>~';
  
  let stack: Stack | undefined;
  
  try {
    console.log(`Creating stack: ${stackName}`);
    console.log(`Project name: ${projectName}`);
    console.log(`Backend URL: ${backendUrl}`);
    
    stack = await LocalWorkspace.createOrSelectStack(
      {
        stackName,
        projectName,
        program: createSimplePulumiProgram(),
      },
      {
        projectSettings: {
          name: projectName,
          runtime: 'nodejs',
          backend: {
            url: backendUrl,
          },
        },
        envVars: {
          PULUMI_CONFIG_PASSPHRASE: 'dev-passphrase',
        },
      },
    );

    console.log(`Stack created: ${stack.name}`);
    console.log('Starting stack up operation...');

    const upPromise = stack.up({
      refresh: true,
      showSecrets: true,
      onOutput: console.log,
    });

    await upPromise;
    console.log('Stack up completed successfully!');

  } catch (error) {
    console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);
  }
}
testPulumiAutomation().catch((error) => {
  console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);
  process.exit(1);
});
Copy code
node dist/index.js
Creating stack: ~~
Project name: ~~~
Backend URL: ~~~
Stack created: ~~~
Starting stack up operation...
Updating (aws-test-corp-kint5-ap-northeast-2-dev-ECS-kidol-zz-service):



 ~  pulumi:pulumi:Stack aws-test-corp-kint5-ap-northeast-2-dev-ECS-kidol-zz-service-aws-test-corp-kint5-ap-northeast-2-dev-ECS-kidol-zz-service refreshing (0s) 
 ~  custom:aws:ECSTaskRole kidol-zz-service refreshing (0s) 

 ~  custom:aws:ECSTaskRole kidol-zz-service refresh (0.00s) 
 ~  pulumi:pulumi:Stack aws-test-corp-kint5-ap-northeast-2-dev-ECS-kidol-zz-service-aws-test-corp-kint5-ap-northeast-2-dev-ECS-kidol-zz-service refreshing (0s) 

    pulumi:pulumi:Stack aws-test-corp-kint5-ap-northeast-2-dev-ECS-kidol-zz-service-aws-test-corp-kint5-ap-northeast-2-dev-ECS-kidol-zz-service running 

    custom:aws:ECSTaskRole kidol-zz-service  

@ updating....
.

 +  aws:iam:Role kidol-zz-service-task-role creating (0s) 

@ updating....

 +  aws:iam:Role kidol-zz-service-task-role creating (0s) error:   sdk-v2/provider2.go:572: sdk.helper_schema: creating IAM Role (kidol-zz-service-task-role): operation error IAM: CreateRole, https response error StatusCode: 409, RequestID: 9876e2e1-0133-4f77-88a8-8bae786deef8, EntityAlreadyExists: Role with name kidol-zz-service-task-role already exists.: provider=aws@7.3.1

 +  aws:iam:Role kidol-zz-service-task-role creating (0s) error: 1 error occurred:

 +  aws:iam:Role kidol-zz-service-task-role **creating failed** error: 1 error occurred:

    pulumi:pulumi:Stack aws-test-corp-kint5-ap-northeast-2-dev-ECS-kidol-zz-service-aws-test-corp-kint5-ap-northeast-2-dev-ECS-kidol-zz-service running error: update failed

@ updating....
.
.
.
.
.
.
i've created a GitHub issue as you suggested! πŸ™ https://github.com/pulumi/pulumi/issues/20263
πŸ™ 1
It seems to be resolved after making the following changes. I think refresh is the main factor here. 1. Changed local Pulumi CLI version to 3.188.0 package.json == "@pulumi/pulumi": "^3.188.0", local pulumi cli version == 3.181.0 2. Removed the refresh option"
e
oh refresh is causing quite a few issues at the moment, so it might be that
βœ… 1
p
Thank you! Could you explain what might be causing this situation? πŸ™ what kind of refresh behavior or issues could be causing this problem? actually, I'm not quite sure why refresh would cause a hang when there's an issue with stack.up (resources already existing)
e
--refresh --run-program is the one causing issues, just --refresh is probably fine, I'll try and look into this today see if I can tell whats up
πŸ˜ƒ 1
p
thank you! for now, i've confirmed that using refresh() + up() instead of --refresh --run-program doesn't cause the issue mentioned above
Copy code
ex..
{
      await stack.refresh();
      await stack.up();
}