Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Golang CDK: synth fails when using lazy string due to circular reference #4486

Open
tdenniston opened this issue Apr 19, 2024 · 3 comments
Open
Labels
bug This issue is a bug. jsii language/dotnet Related to .NET bindings (C#, F#, ...) language/go Regarding GoLang bindings language/python Related to Python bindings p1 package/tools

Comments

@tdenniston
Copy link

Describe the bug

This is probably specific to the Go CDK bindings, or it is also possible I am misunderstanding the use of the lazy string mechanism. When I try to use the awscdk.Lazy_String method for e.g. a log group name, synth fails due to a circular reference:

$ CDK_DEBUG=true cdk synth
panic: TypeError: Resolution error: Resolution error: Resolution error: Converting circular structure to JSON
    --> starting at object with constructor 'CfnLogGroup'
    |     property 'node' -> object with constructor 'Node'
    --- property 'host' closes the circle.
Object creation stack:
  at Lazy.string (/tmp/jsii-kernel-u0LhzS/node_modules/aws-cdk-lib/core/lib/lazy.js:1:953)
  at /tmp/jsii-runtime.3237986321/lib/program.js:9876:152
  at Kernel._Kernel_ensureSync (/tmp/jsii-runtime.3237986321/lib/program.js:10480:24)
  at Kernel.sinvoke (/tmp/jsii-runtime.3237986321/lib/program.js:9876:102)
  at KernelHost.processRequest (/tmp/jsii-runtime.3237986321/lib/program.js:11696:36)
  at KernelHost.run (/tmp/jsii-runtime.3237986321/lib/program.js:11656:22)
  at Immediate._onImmediate (/tmp/jsii-runtime.3237986321/lib/program.js:11657:46)
  at process.processImmediate (node:internal/timers:476:21)..

See below for a very simple example that reproduces the issue.

Expected Behavior

Able to use the awscdk.Lazy_String function.

Current Behavior

Synth fails when using the awscdk.Lazy_String function.

Reproduction Steps

Complete example:

package main

import (
	"github.com/aws/aws-cdk-go/awscdk/v2"
	"github.com/aws/aws-cdk-go/awscdk/v2/awslogs"

	"github.com/aws/jsii-runtime-go"
)

type LazyString struct{}

func (l *LazyString) Produce() *string {
	s := "value"
	return &s
}

func main() {
	defer jsii.Close()

	app := awscdk.NewApp(nil)
	stack := awscdk.NewStack(app, jsii.String("stack"), &awscdk.StackProps{})

	lazy := &LazyString{}
	awslogs.NewLogGroup(stack, jsii.String("log-group"), &awslogs.LogGroupProps{
		LogGroupName: awscdk.Lazy_String(lazy, &awscdk.LazyStringValueOptions{}),
	})

	app.Synth(nil)
}

Then just run cdk synth, and it will fail.

Possible Solution

No response

Additional Information/Context

No response

CDK CLI Version

2.137.0 (build bb90b4c)

Framework Version

No response

Node.js Version

18.18.2

OS

Linux

Language

Go

Language Version

go version go1.20.12 linux/amd64

Other information

No response

@tdenniston tdenniston added bug This issue is a bug. needs-triage This issue or PR still needs to be triaged. labels Apr 19, 2024
@ashishdhingra ashishdhingra self-assigned this Apr 19, 2024
@ashishdhingra
Copy link
Contributor

ashishdhingra commented Apr 19, 2024

Reproducible.

  • Similar code below in TypeScript works:

    import * as cdk from 'aws-cdk-lib';
    import * as awslogs from 'aws-cdk-lib/aws-logs';
    import { TypescriptStack } from '../lib/typescript-stack';
    
    const app = new cdk.App();
    
    const stack = new cdk.Stack(app, 'MyStack');
    new awslogs.LogGroup(stack, 'log-group', {
        logGroupName: cdk.Lazy.string({
            produce() {
                return 'value';
            }})
    });
  • .NET code:

    using Amazon.CDK;
    using Amazon.CDK.AWS.Logs;
    
    namespace Dotnet
    {
        sealed class Program
        {
            public static void Main(string[] args)
            {
                var app = new App();
                var stack = new Stack(app, "MyStack");
              
                new LogGroup(stack, "log-group", new LogGroupProps()
                {
                    LogGroupName = Lazy.String(new Producer())
                });
              
                app.Synth();
            }
    
            class Producer : IStableStringProducer
            {
                public string Produce()
                {
                    return "value";
                }
            }
        }
    }

    fails with below error:

    Unhandled exception. System.ArgumentException: Could not convert argument 'Dotnet.Program+Producer' to Jsii (Parameter 'arguments')
       at Amazon.JSII.Runtime.Deputy.DeputyBase.<>c__DisplayClass20_0.<ConvertArguments>b__0(Parameter parameter, Object frameworkArgument)
       at System.Linq.Enumerable.ZipIterator[TFirst,TSecond,TResult](IEnumerable`1 first, IEnumerable`1 second, Func`3 resultSelector)+MoveNext()
       at System.Collections.Generic.LargeArrayBuilder`1.AddRange(IEnumerable`1 items)
       at System.Collections.Generic.EnumerableHelpers.ToArray[T](IEnumerable`1 source)
       at Amazon.JSII.Runtime.Deputy.DeputyBase.ConvertArguments(Parameter[] parameters, Object[] arguments)
       at Amazon.JSII.Runtime.Deputy.DeputyBase.<InvokeMethodCore>g__GetResult|18_0[T](<>c__DisplayClass18_0`1& )
       at Amazon.JSII.Runtime.Deputy.DeputyBase.InvokeMethodCore[T](JsiiMethodAttribute methodAttribute, Object[] arguments, Func`3 beginFunc, Func`3 invokeFunc)
       at Amazon.JSII.Runtime.Deputy.DeputyBase.InvokeStaticMethod[T](Type type, Type[] parameterTypes, Object[] arguments, String methodName)
       at Amazon.CDK.Lazy.String(IStableStringProducer producer, ILazyStringValueOptions options)
       at Dotnet.Program.Main(String[] args) in /Users/tempuser/dev/repros/cdk/issue29906_go/dotnet/src/Dotnet/Program.cs:line 14
    
    Subprocess exited with error 134
    
  • There was an issue Lazy still broken in Python #1781 for Python which was closed due to staleness.

@ashishdhingra ashishdhingra added p1 jsii and removed needs-triage This issue or PR still needs to be triaged. labels Apr 19, 2024
@pahud pahud transferred this issue from aws/aws-cdk Apr 22, 2024
@mrgrain mrgrain added language/dotnet Related to .NET bindings (C#, F#, ...) language/python Related to Python bindings language/go Regarding GoLang bindings labels Apr 22, 2024
@ashishdhingra ashishdhingra removed their assignment Apr 22, 2024
@teemu-laakso
Copy link

I hit this bug with python and found a workaround. Taking the example from the CDK Guide:

class Producer:
    def __init__(self, func):
        self.produce = func
class FixedProducer:
    __jsii_type__ = None

    def __init__(self, func):
        self.func = func

    @jsii.member(jsii_name='produce')
    def produce(self, context):
        return self.func()

Maybe this can be of some use with Go as well?

@floverfelt
Copy link

Also an issue in Java:

package com.myorg;

import software.amazon.awscdk.IStableStringProducer;
import software.amazon.awscdk.Lazy;
import software.amazon.awscdk.services.sqs.Queue;
import software.constructs.Construct;
import software.amazon.awscdk.Stack;
import software.amazon.awscdk.StackProps;

public class CdkBugTestStack extends Stack {

    public CdkBugTestStack(final Construct scope, final String id) {
        this(scope, id, null);
    }

    public class LazyStableString implements IStableStringProducer {
        @Override
        public String produce() {
            return "LazyStableCDKBugTestQueue";
        }
    }

    public CdkBugTestStack(final Construct scope, final String id, final StackProps props) {
        super(scope, id, props);
         Queue.Builder.create(this, "CdkBugTestQueue")
                 .queueName(Lazy.string(new LazyStableString()))
                 .build();
    }
}

produces:

An exception occurred while executing the Java class. TypeError: Resolution error: Resolution error: Resolution error: Converting circular structure to JSON
    --> starting at object with constructor 'CfnQueue'
    |     property 'node' -> object with constructor 'Node'
    --- property 'host' closes the circle.

Switching to uncachedString works fine: https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Lazy.html#static-uncachedwbrstringproducer-options

But this seems to be discouraged by the docs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug This issue is a bug. jsii language/dotnet Related to .NET bindings (C#, F#, ...) language/go Regarding GoLang bindings language/python Related to Python bindings p1 package/tools
Projects
None yet
Development

No branches or pull requests

5 participants