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

go: How to map Condition function return to specific type #2798

Closed
xrn opened this issue Apr 17, 2021 · 10 comments
Closed

go: How to map Condition function return to specific type #2798

xrn opened this issue Apr 17, 2021 · 10 comments
Assignees
Labels
effort/small Small work item – less than a day of effort guidance Question that needs advice or information. language/go Regarding GoLang bindings p1

Comments

@xrn
Copy link

xrn commented Apr 17, 2021

Affected Languages

  • [ x] Go

General Information

  • JSII Version: v1.28.0
  • Platform: SMP Debian 5.10.28-1 (2021-04-09) x86_64 GNU/Linux

The Question

I spent this long time and can not find an answer anywhere because go in still in development preview. I have code like

	// The code that defines your stack goes here
	lambdaFnA := awslambda.NewFunction(stack, jsii.String("Singleton"), &awslambda.FunctionProps{
		Code:    awslambda.NewAssetCode(jsii.String("lambda"), nil),
		Handler: jsii.String("handler.main"),
		Timeout: awscdk.Duration_Seconds(jsii.Number(300)),
		Runtime: awslambda.Runtime_PYTHON_3_6(),
	})

	lambdaFnB := awslambda.NewFunction(stack, jsii.String("Singleton"), &awslambda.FunctionProps{
		Code:    awslambda.NewAssetCode(jsii.String("lambda"), nil),
		Handler: jsii.String("handler.main"),
		Timeout: awscdk.Duration_Seconds(jsii.Number(300)),
		Runtime: awslambda.Runtime_PYTHON_3_6(),
	})

	awscognito.NewUserPool(stack, aws.String("UserPoll"), &awscognito.UserPoolProps{
		UserPoolName: awscdk.Fn_Sub(aws.String("${Environment}-SC-Pool"), nil),
		LambdaTriggers: awscdk.Fn_ConditionIf("Condition",
			&awscognito.UserPoolTriggers{
				PostAuthentication: lambdaFnA,
			},
			&awscognito.UserPoolTriggers{},
		),
	})

Which from perspective Cloudfroamtion should work - I can create if statement for the whole object. But Fn_ConditionIf returns type ICfnConditionExpression and I am expecting &awscognito.UserPoolTriggers - digging in code we can find sth from ts but I am not sure how to map this in go

new sqs.Queue(this, 'MyQueue', {
    queueName: Fn.conditionIf('Condition', 'Hello', 'World').toString()
});
@xrn xrn added guidance Question that needs advice or information. needs-triage This issue or PR still needs to be triaged. labels Apr 17, 2021
@MrArnoldPalmer MrArnoldPalmer self-assigned this May 6, 2021
@MrArnoldPalmer MrArnoldPalmer added p1 effort/small Small work item – less than a day of effort language/go Regarding GoLang bindings and removed needs-triage This issue or PR still needs to be triaged. labels May 6, 2021
@MrArnoldPalmer
Copy link
Contributor

Hey @xrn, I believe your issue is related to the usage of CFN intrinsics within L2s. This is unrelated to downcasting #2819 I believe.

As you said UserPoolProps LambdaTriggers prop is expected to be *UserPoolTriggers. When using L2 constructs you should just use normal go if/else to perform conditional logic and go string interpolation.

UserPoolName: awscdk.Fn_Sub(aws.String("${Environment}-SC-Pool"), nil),
// should be
UserPoolName: aws.String(fmt.Sprintf("%s-SC-Pool", Environment)),

If you give an example of the condition you're using we may be able to give some more examples.

@xrn
Copy link
Author

xrn commented May 6, 2021

Normal If will not work here because I need that If in template which will be deployed on multiple env with different parameters. And condition will be cloudformation.condition - https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/conditions-section-structure.html like for example

"CreateBucket": {
            "Fn::Not": [
                {
                    "Fn::Equals": [
                        {
                            "Ref": "BucketName"
                        },
                        ""
                    ]
                }
            ]
        },

and then

awscognito.NewUserPool(stack, aws.String("UserPoll"), &awscognito.UserPoolProps{
		UserPoolName: awscdk.Fn_Sub(aws.String("${Environment}-SC-Pool"), nil),
		LambdaTriggers: awscdk.Fn_ConditionIf("CreateBucket",
			&awscognito.UserPoolTriggers{
				PostAuthentication: lambdaFnA,
			},
			&awscognito.UserPoolTriggers{},
		),
	})

From pure cloudformation yaml/json my example is correct I am using it already with goFormation

@xrn
Copy link
Author

xrn commented May 7, 2021

Example from working Cloudformation template

Conditions:
  CreateWithPreAuthTrigger:
    Fn::Or:
    - Fn::Equals:
      - Ref: Environment
      - PROD
    - Fn::Equals:
      - Ref: Environment
      - STG
  UserPool:
    Properties:
      AutoVerifiedAttributes:
      - email
      DeviceConfiguration:
        DeviceOnlyRememberedOnUserPrompt: true
      EmailVerificationMessage: Your verification code is {####}.
      EmailVerificationSubject: Your verification code
      LambdaConfig:
        Fn::If:
        - CreateWithPreAuthTrigger
        - PreAuthentication:
            Fn::Sub: arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:function:${Environment}-PreAuthentication-Lambda
        - {}
      MfaConfiguration: "OFF"
      Policies:
        PasswordPolicy:
          MinimumLength: 8
          RequireLowercase: true
          RequireNumbers: true
          TemporaryPasswordValidityDays: 7
      UserPoolName:
        Fn::Sub: ${Environment}-SC-Pool
      UsernameAttributes:
      - email
    Type: AWS::Cognito::UserPool

My team is using conditions on objects in few other places like this

@xrn
Copy link
Author

xrn commented May 14, 2021

@MrArnoldPalmer any chance for help with this?

@MrArnoldPalmer
Copy link
Contributor

@xrn I'll have to spend some time working through your specific examples which I don't have at the moment, but I would encourage you again to forget about what your existing cloudformation templates look like and just treat your CDK app like a normal program, and not a static template.

You can pass in your environment to your cdk app and then switch, if/else, etc based on that value and change what resources are created and how. I don't think this is a go specific problem, but I'll look into it more when I have time available so we can provide language specific guidance here if CFN intrinsics are required.

Have you tried using the L1 constructs instead?

@xrn
Copy link
Author

xrn commented May 17, 2021

Have you tried using the L1 constructs instead?

Tbh I am not sure what it mean

@MrArnoldPalmer
Copy link
Contributor

MrArnoldPalmer commented May 17, 2021

@xrn sorry for the jargon 😄 . The L1s are the lower level constructs, ones named CfnXxx within each library. For example instead of NewUserPool you can try NewCfnUserPool. The L1's are a 1:1 represenation of the cloudformation APIs whereas the L2s, like UserPool, have some defaults and may build other resources automatically under the hood.

Additionally there are escape hatches that allow you to access the L1's from the L2's and edit any property however you want. There are some issues with these in go that we are currently working on though.

@xrn
Copy link
Author

xrn commented Jun 1, 2021

Hi @MrArnoldPalmer I used CfnUserPoolProps with LambdaConfig and looks like I was able to achieve what I need

	awscognito.NewCfnUserPool(stack, aws.String("UserPool"), &awscognito.CfnUserPoolProps{
		UserPoolName: awscdk.Fn_Sub(aws.String("${Environment}-SC-Pool"), nil),
		LambdaConfig: awscdk.Fn_ConditionIf(aws.String("Condition"),
			map[string]interface{}{
				"PostAuthentication": lambdaFn.FunctionArn(),
			},
			map[string]interface{}{},
		),
	})

It is not perfect user experience and there is lack of materials - but at least I was able to generate

UserPool:
    Type: AWS::Cognito::UserPool
    Properties:
      LambdaConfig:
        Fn::If:
          - Condition
          - PostAuthentication:
              Fn::GetAtt:
                - Singleton8C7B99F3
                - Arn
          - {}
      UserPoolName:
        Fn::Sub: ${Environment}-SC-Pool
    Metadata:
      aws:cdk:path: LambdaCronStack/UserPool

@MrArnoldPalmer
Copy link
Contributor

@xrn gonna close this for now as it's not a JSII or language specific issue. Reopen in aws/aws-cdk if you want to continue the discussion. Glad you got it resolved for now though!

@github-actions
Copy link
Contributor

⚠️COMMENT VISIBILITY WARNING⚠️

Comments on closed issues are hard for our team to see.
If you need more assistance, please either tag a team member or open a new issue that references this one.
If you wish to keep having a conversation with other community members under this issue feel free to do so.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
effort/small Small work item – less than a day of effort guidance Question that needs advice or information. language/go Regarding GoLang bindings p1
Projects
None yet
Development

No branches or pull requests

2 participants