polite-sandwich-68547
04/12/2023, 4:25 PMpulumi.StringOutput
to a normal go string
?nice-guitar-7761
04/12/2023, 4:30 PM// import "<http://github.com/pulumi/pulumi/sdk/v3/go/pulumi/internals|github.com/pulumi/pulumi/sdk/v3/go/pulumi/internals>"
result, _ := internals.UnsafeAwaitOutput(context.Background(), myPulumiOutput)
strValue := result.Value.(string)
if I'm not wrongpolite-sandwich-68547
04/12/2023, 4:36 PMbillowy-army-68599
04/12/2023, 4:50 PMApplyT
polite-sandwich-68547
04/12/2023, 4:53 PMApplyT
although I keep getting empty stringsbucketName := pulumi.String("")
bucket.ID().ApplyT(func(id pulumi.ID) (string, error) {
bucketName = pulumi.String(string(id))
return "", nil
})
nice-guitar-7761
04/12/2023, 4:56 PMincalculable-parrot-23117
04/12/2023, 5:00 PMApplyT
doesn't run right away. It runs when the value becomes available, so trying to extract it like that will give you an empty string. The right way of doing this is:
bucketName := bucket.ID().ApplyT(func(id pulumi.ID) (string, error) {
return pulumi.String(string(id)), nil
}).(pulumi.StringOutput)
And then bucketName
is a StringOutput
, not string
.
Although for this specific case, you can convert an IDOutput
(bucket.ID()
) into a StringOutput
with the ToStringOutput()
method of `IDOutput`:
bucketName := bucket.ID().ToStringOutput()
With bucketName as a StringOutput, you can pass it into, say pulumi.Sprintf
to get back a formatted string output. For example:
bucketName := bucket.ID().ToStringOutput()
msg := pulumi.Sprintf("Data stored in bucket %s", bucketName)
polite-sandwich-68547
04/12/2023, 5:01 PMfunc Sprintf(format string, args ...interface{}) StringOutput {
still returns a StringOutput
though, when we need a string
StringOutput
incalculable-parrot-23117
04/12/2023, 5:03 PMpolite-sandwich-68547
04/12/2023, 5:03 PMstring
incalculable-parrot-23117
04/12/2023, 5:04 PMbucket.ID()
above, when you run pulumi preview
, the bucket doesn't have an ID because it hasn't been created yet, so the system can't give you an ID back. The IDOutput is a placeholder for a value that will become available in the future when this code runs for real (and even then, the ID won't be available right away because the operation doesn't run synchronously, but we can skip that detail for now).
The idea is that you can feed this Output
value as input to anything else, and among other things, their dependency relation will be established.polite-sandwich-68547
04/12/2023, 5:05 PMbillowy-army-68599
04/12/2023, 5:05 PMApplyT
You can’t assign the result of an ApplyT
to another value and use it elsewhere, because the value is only know inside the ApplyTincalculable-parrot-23117
04/12/2023, 5:06 PMpolite-sandwich-68547
04/12/2023, 5:06 PMsyncManager := s3sync.New(sess)
// Get the bucket name as a string using Apply
bucketName, err := internals.UnsafeAwaitOutput(context.Background(), bucket.Bucket)
if err != nil {
return err
}
err = syncManager.Sync("../../build", fmt.Sprintf("<s3://%s>", bucketName.Value.(string)))
if err != nil {
return err
}
incalculable-parrot-23117
04/12/2023, 5:10 PMbillowy-army-68599
04/12/2023, 5:11 PMpolite-sandwich-68547
04/12/2023, 5:11 PMincalculable-parrot-23117
04/12/2023, 5:11 PMpreview
and once during update
. You can verify this by trying to run fmt.Println
inside the ApplyT function. Trying to have side-effects on the world from inside ApplyT breaks things, somewhat.
Do consider the synced-folder package @billowy-army-68599 linked to above.
The S3BucketFolderArgs takes a StringInput as argument, so you can feed bucket.ID into it directly. It'll treat every file in the folder as a separate resource, so it'll update files as needed.polite-sandwich-68547
04/12/2023, 5:16 PMincalculable-parrot-23117
04/12/2023, 5:17 PMbucket := // ...
bucketName := bucket.ID().ToStringOutput()
syncedfolder.NewS3BucketFolder(ctx, "build", &synced.S3BucketFolderArgs{
Path: pulumi.String("../../build"),
BucketName: bucketName,
Acl: // ...
})
polite-sandwich-68547
04/12/2023, 5:17 PM