```pulumi.Run(func(ctx *pulumi.Context) error { ...
# golang
q
Copy code
pulumi.Run(func(ctx *pulumi.Context) error {
   output := cluster.Provider.ApplyT(func(p *kubernetes.Provider) (string, error) 

      appSvc, svcerr := corev1.NewService(ctx, "app-svc", &corev1.ServiceArgs{
           ...
         },
      }, pulumi.Provider(p))

      ctx.Export("appIp", appSvc.Status.ApplyT(func(status *corev1.ServiceStatus) *string {
         return status.LoadBalancer.Ingress[0].Ip
      }))
      ctx.Export("test-export", pulumi.String("testexportvalue"))
      return "", nil
   }).(pulumi.StringOutput)
   ctx.Export("output", output)

   return nil
})
Hi everyone! Im running go code like stated above, and am wondering why only the "output" ctx.Export and not "test-export" or "appIp" show up in my Stack as outputs. I assume its because its inside of an 
.apply()
 , but cant really understand why that would stop it from working. Also since it doesnt work the way I tried, how would you go about achieving a similar result?
l
@quiet-architect-91246 Calls to
ctx.Export
should be top level in your
pulumi.Run
func. The reason why you're seeing this behavior is due async work and the order of operations. What happens in your program above: 1. Program starts running 2. async work is scheduled via
Provider.Apply
3. "output" is exported (internal impl is saving this output value in a private map on the context object 4. Your function finished executing - there may still be outstanding async work 5. The pulumi runtime registers stack outputs - https://github.com/pulumi/pulumi/blob/070125e6851f21a4a82290ed94dca43e49c76422/sdk/go/pulumi/run.go#L108 6. The pulumi runtime awaits outstanding async work 7. Your
provider.apply
runs once the dependencies are fulfilled 8. When the apply runs, it tries to register stack outputs to no effect. The stack outputs were already registered in step (5).
So TLDR, do not use
ctx.Export
inside apply. The pattern is to instead return the value you want to export from an apply as an output, and then export that output at the top level. Second thing I'll mention is that creating resources inside of apply is an anti-pattern. Best to avoid it if possible.
q
Got it, Thank you @lemon-agent-27707! Could you give me a rough outline how else you would create for example the service if not inside the apply but still being able to use the provider? It seemed wrong to begin with but was the only way I got it to work for now since im pretty new to pulumi.
l
Can you share the code that creates
cluster
?
q
Sure:
Copy code
cluster, err := eks.NewCluster(ctx, "cluster",
   &eks.ClusterArgs{
      InstanceType:    pulumi.String("t2.medium"),
      DesiredCapacity: <http://pulumi.Int|pulumi.Int>(2),
      MinSize:         <http://pulumi.Int|pulumi.Int>(1),
      MaxSize:         <http://pulumi.Int|pulumi.Int>(2),
      RoleMappings: eks.RoleMappingArray{
         eks.RoleMappingArgs{
            Groups:   pulumi.StringArray{
               pulumi.String("system:nodes"),
               pulumi.String("system:bootstrappers"),
               pulumi.String("eks-console-dashboard-full-access-group"),
            },
            RoleArn:  pulumi.String("arn:aws:iam::964790551434:role/Administrator"),
            Username: pulumi.String("testuser"),
         },
      },
   },
)
l
Ah, ok. Looks like you are running into https://github.com/pulumi/pulumi/issues/7012 Give that a +1 if you don't mind.
My recommendation would be to create a kubernetes provider from the kubeconfig. That provider will be prompt and won't requiring using apply.
q
How would you go about that type conversion in go? Do I have to build a kubeconfig as string by hand out of cluster.Kubeconfig or is there some inbuilt way to do it?
l
You can run an apply over kubeconfig. It will be something like:
Copy code
cluster.Kubeconfig.ApplyT(func(v interface{})( string, error) { 
var result string
result, ok := v.(string)
if !ok {
return result, errors.New("kubeconfig was not a string")
}
return result, ok
}).(pulumi.StringOutput)
I am not super familiar with the eks library and the exact type it produces, so the types may require some massaging depending on what the actual runtime type of kubeconfig is.
q
Thats fine, I think I got the main idea. Thanks a lot for your efforts!
👍 1