https://pulumi.com logo
#getting-started
Title
# getting-started
m

magnificent-soccer-44287

01/27/2024, 4:36 AM
Hi again folks 👋 please help 🙏 why does this code (attached in-thread to not spam) fail with this error when defined as a function in a separate file and called, but works if its in index.ts?
Copy code
Diagnostics:
  aws:s3:Bucket (pmb-main-app-bucket):
    error: connection error: desc = "transport: Error while dialing: dial tcp 127.0.0.1:38887: connect: connection refused
s3.ts File:
Copy code
import * as aws from "@pulumi/aws";
import * as pulumi from "@pulumi/pulumi";

export const createMainAppBucket = (iamUser: aws.iam.User) => {

    const pmbAppBucket = new aws.s3.Bucket('pmb-main-app-bucket', {
        bucket: 'pmb-main-app-bucket',
    }, { protect: true });
    
    const pmbBucketOwnershipControls = new aws.s3.BucketOwnershipControls('pmb-bucket-oc', {
        bucket: pmbAppBucket.id,
        rule: {
            objectOwnership: "BucketOwnerPreferred",
        },
    });
    
    const pmbAppBucketPolicy = new aws.iam.Policy('pmb-main-app-s3-policy', {
        policy: {
            Version: "2012-10-17",
            Statement: [{
                Effect: "Allow",
                Action: [
                    "s3:*"
                ],
                Resource: [
                    pmbAppBucket.arn.apply(arn => `${arn}/*`),
                    pmbAppBucket.arn.apply(arn => `${arn}`)
    
                ],
            }],
        },
    }, { dependsOn: [pmbBucketOwnershipControls] });
    
    const pmbAppBucketPolicyLink = new aws.iam.UserPolicyAttachment('pmb-main-app-s3-attachment', 
        pulumi.all([iamUser.name, pmbAppBucketPolicy.arn]).apply(([user, policyArn]) => {
            return { user, policyArn }
    }));
    
    const pmbAppBucketAccessBlock = new aws.s3.BucketPublicAccessBlock('pmb-main-app-s3-ab', {
        bucket: pmbAppBucket.id,
        blockPublicAcls: false,
        blockPublicPolicy: false,
    });
    
    return pmbAppBucket;
}
how it's being invoked in index.ts
I just did a massive refactor on our stack to get it from thousands of lines down to something more manageable. pulumi up kept passing with the refactor but the resources were all created and each up was "no changes". When I tried to re-up the stack in a different AWS account, all hell broke loose.
I've tried exporting it as consts, etc. Nothing works
Unless i just put it back in the main file
root cause seems to be this:
Copy code
pulumi:pulumi:Stack (pmb-main-dev):
    panic: interface conversion: interface {} is nil, not map[string]interface {}
    goroutine 101 [running]:
Trying to dig through source and find out what is happening
c

clever-sunset-76585

01/27/2024, 5:21 AM
I just did a massive refactor on our stack to get it from thousands of lines down to something more manageable. pulumi up kept passing with the refactor but the resources were all created and each up was "no changes". When I tried to re-up the stack in a different AWS account, all hell broke loose.
Did you create a new stack to use with the new AWS account?
m

magnificent-soccer-44287

01/27/2024, 5:21 AM
yup! just had a really odd change too... here is what seems to have fixed it.
before, in a separate file:
Copy code
export const createEcsCluster = (name: string, logGroup?: aws.cloudwatch.LogGroup) => 
    new aws.ecs.Cluster(name, { 
        name,
        configuration: logGroup ? {
            executeCommandConfiguration: {
                logging: "OVERRIDE",
                logConfiguration: {
                    cloudWatchLogGroupName: logGroup.name,
                    cloudWatchEncryptionEnabled: false,
                    s3BucketName: "",
                    s3KeyPrefix: ""
                }
            }
        } : {}
    });
And then in index:
Copy code
const pmbMainAppCluster = createEcsCluster('ecs-main-app')
const pmbSidekiqCluster = createEcsCluster('ecs-sidekiq-app');
const pmbInfraCluster = createEcsCluster('ecs-infra', pmbServiceInfraLogGroup);
^ This did not work, panic.
This, however, does - in main file:
Copy code
const pmbMainAppCluster = new aws.ecs.Cluster('ecs-main-app', { 
    name: 'ecs-main-app' });
const pmbSidekiqCluster = new aws.ecs.Cluster('ecs-sidekiq-app', { 
    name: 'ecs-sidekiq-app' });
const pmbInfraCluster = new aws.ecs.Cluster('ecs-infra', { 
    name: 'ecs-infra',
    configuration: {
        executeCommandConfiguration: {
            logging: "OVERRIDE",
            logConfiguration: {
                cloudWatchLogGroupName: pmbServiceInfraLogGroup.name,
                cloudWatchEncryptionEnabled: false,
                s3BucketName: "",
                s3KeyPrefix: ""
            }
        }
    }
});
I used the exact same pattern for extracting everything into separate files. Just aws.ecs.Cluster has that issue.\
c

clever-sunset-76585

01/27/2024, 5:25 AM
It could be because of the empty object for
logConfiguration
that you set when your parameter is false. Can you set it to
undefined
or is it not optional and that's why you used an empty object?
m

magnificent-soccer-44287

01/27/2024, 5:26 AM
hm, i dont think so? at least it shouldnt. Unless logGroup is somehow magically empty during the ternary operator and gets eval'd when passed into the constructor?
The before/after should produce the same result in TS>
That doesnt even sound possible 😂
c

clever-sunset-76585

01/27/2024, 5:28 AM
Oh I misspoke. I meant the
configuration
object. I think the problem might be that you are setting it to an empty object if
logGroup
is false.
m

magnificent-soccer-44287

01/27/2024, 5:28 AM
OH.
Are you saying that the key being present with an empty value is probably it?
c

clever-sunset-76585

01/27/2024, 5:29 AM
Yeah. I think the provider is trying to convert the empty object to its full object representation per the upstream TF inputs.
m

magnificent-soccer-44287

01/27/2024, 5:29 AM
Oh yeah, I guess the stack trace does mention basically that.
Weird... i use that pattern in a lot of places. Ex.:
Copy code
}, { dependsOn: DEV_USE_LAST_IMAGE ? [] : [pmbMainDockerImage] });
Will have to watch out for it in some spots I guess!
c

clever-sunset-76585

01/27/2024, 5:31 AM
Empty arrays are usually ok. It depends but empty objects are likely to cause issues because you are technically instantiating a top-level property but are not specifying any of the inner properties. I think that throws the TF inputs mapping off.
m

magnificent-soccer-44287

01/27/2024, 5:31 AM
that does make sense.
c

clever-sunset-76585

01/27/2024, 5:31 AM
...assuming you are using the AWS TF-bridged provider.
m

magnificent-soccer-44287

01/27/2024, 5:31 AM
yup!
so basically...
Copy code
new aws.ecs.Cluster(name, { 
        name,
        configuration: logGroup ? {
            executeCommandConfiguration: {
                logging: "OVERRIDE",
                logConfiguration: {
                    cloudWatchLogGroupName: logGroup.name,
                    cloudWatchEncryptionEnabled: false,
                    s3BucketName: "",
                    s3KeyPrefix: ""
                }
            }
        } : {}
    });
if I elevate the ternary to the top-level object, ie.:
Copy code
new aws.ecs.Cluster(name, {}); <--- switch that one
The issue goes away
bingo.
Copy code
export const createEcsCluster = (name: string, logGroup?: aws.cloudwatch.LogGroup) => 
    new aws.ecs.Cluster(name, logGroup ? { 
        name,
        configuration: {
            executeCommandConfiguration: {
                logging: "OVERRIDE",
                logConfiguration: {
                    cloudWatchLogGroupName: logGroup.name,
                    cloudWatchEncryptionEnabled: false,
                    s3BucketName: "",
                    s3KeyPrefix: ""
                }
            }
        }
    } : { name });
works
c

clever-sunset-76585

01/27/2024, 5:35 AM
Yeah my guess is
configuration
, if specified, must have some properties defined in it. there must be some validation in there. By using a top-level
{}
, basically, you are leaving everything
undefined
under it and because
name
qualifies for auto-namimg, Pulumi can satisfy that requirement by itself without an explicitly provided value.
m

magnificent-soccer-44287

01/27/2024, 5:37 AM
Thank you very much for the help.
c

clever-sunset-76585

01/27/2024, 5:37 AM
All good. Glad to have helped!