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

Userdata not populated properly in CfnInstance #3419

Closed
1 of 5 tasks
salovan opened this issue Jul 24, 2019 · 6 comments
Closed
1 of 5 tasks

Userdata not populated properly in CfnInstance #3419

salovan opened this issue Jul 24, 2019 · 6 comments
Assignees
Labels
@aws-cdk/aws-ec2 Related to Amazon Elastic Compute Cloud needs-triage This issue or PR still needs to be triaged.

Comments

@salovan
Copy link

salovan commented Jul 24, 2019

  • I'm submitting a ...

    • πŸͺ² bug report
    • πŸš€ feature request
    • πŸ“š construct library gap
    • ☎️ security issue or vulnerability => Please see policy
    • ❓ support request => Please see note at the top of this template.
  • What is the current behavior?
    I'm attempting to create EC2 instances with userdata to handle post-init configuration using the CfnInstance class. The userdata object is being created via the aws_ec2.UserData constructor.

from aws_cdk import (
    core,
    aws_ec2
)
class ConnectSmtpRouteStack(core.Stack):

    def __init__(self, scope: core.Construct, id: str, **kwargs) -> None:
        super().__init__(scope, id, **kwargs)

        shellCommands = aws_ec2.UserData.for_linux()
        shellCommands.add_commands("command1")
        shellCommands.add_commands("command2")

        ec2Instance1 = CfnInstance(self, 'ec2Instance1',
            image_id='ami-3ecc8f46',
            instance_type='t3.large',
            availability_zone='us-west-2b',
            user_data=shellCommands.render()
        )

The generated CloudFormation code fails with "Invalid BASE64 encoding of user data" error. The relevant YAML output looks like:

  ec2Instance1:
    Type: AWS::EC2::Instance
    Properties:
      AvailabilityZone: us-west-2b
      ImageId: ami-3ecc8f46
      InstanceType: t3.large
      UserData: >-
        #!/bin/bash

        command1

        command2
  • What is the expected behavior (or behavior of feature suggested)?
    I would expect the generated UserData stanza to include the relevant Base64 encoding blocks. Something like:
      UserData:
        Fn::Base64: !Sub |
           #!/bin/bash
           command1
           command2
  • What is the motivation / use case for changing the behavior or adding this feature?
    Immediately, I want to create an EC2 instance with additional data volumes which are partitioned, formatted, and mounted when the instance is initialized. There are other post-init workflows that I would like to build later

  • Please tell us about your environment:

    • CDK CLI Version: 1.1.0 (build 1a11e96)
    • Module Version: aws-cdk=1.1.0,@aws-cdk/aws-cloudwatch=1.1.0,@aws-cdk/aws-ec2=1.1.0,@aws-cdk/aws-iam=1.1.0,@aws-cdk/aws-ssm=1.1.0,@aws-cdk/core=1.1.0,@aws-cdk/cx-api=1.1.0,@aws-cdk/region-info=1.1.0,jsii-runtime=Python/3.6.8
    • OS: Ubuntu 18.04
    • Language: Python
@salovan salovan added the needs-triage This issue or PR still needs to be triaged. label Jul 24, 2019
@alokito
Copy link

alokito commented Jul 25, 2019

I have a related issue, I am trying to embed the IP address of another ec2 instance in the user data of a second ec2 instance with (apologies for the typescript vs python):

    const ec2Instance2 = new ec2.CfnInstance(this, 'ec2Instance2', {
          imageId: 'ami-3ecc8f46',
          instanceType:'t3.large',
          availabilityZone:'us-west-2b',
          userData:`export CDK_IP='${ec2Instance1.attrPrivateIp}'`
    });

This produces

  ec2Instance2:
    Type: AWS::EC2::Instance
    Properties:
      AvailabilityZone: us-west-2b
      ImageId: ami-3ecc8f46
      InstanceType: t3.large
      UserData:
        Fn::Join:
          - ""
          - - export CDK_IP='
            - Fn::GetAtt:
                - ec2Instance1
                - PrivateIp
            - "'"

This fails with a similar error due to lack of "Fn::Base64":

@alokito
Copy link

alokito commented Jul 25, 2019

@salovan you may be able to work around this by using an AutoScalingGroup with one ec2 in it... unfortunately, I was unable to do this since in CDK the ASG always creates a new security group, and I cannot create security groups per corporate policy. I have filed a feature request for this: #3433

@AlexCheema
Copy link
Contributor

I have a related issue, I am trying to embed the IP address of another ec2 instance in the user data of a second ec2 instance with (apologies for the typescript vs python):

    const ec2Instance2 = new ec2.CfnInstance(this, 'ec2Instance2', {
          imageId: 'ami-3ecc8f46',
          instanceType:'t3.large',
          availabilityZone:'us-west-2b',
          userData:`export CDK_IP='${ec2Instance1.attrPrivateIp}'`
    });

This produces

  ec2Instance2:
    Type: AWS::EC2::Instance
    Properties:
      AvailabilityZone: us-west-2b
      ImageId: ami-3ecc8f46
      InstanceType: t3.large
      UserData:
        Fn::Join:
          - ""
          - - export CDK_IP='
            - Fn::GetAtt:
                - ec2Instance1
                - PrivateIp
            - "'"

This fails with a similar error due to lack of "Fn::Base64":

You should be able to wrap your user data in use cdk.Fn.base64. Here's an example that works for me:

    const dbProxyInstance = new ec2.CfnInstance(this, "DBProxyInstance", {
      instanceType: "t3a.small",
      imageId: "ami-026c8acd92718196b",
      securityGroupIds: [dbProxySecurityGroup.securityGroupId],
      subnetId: vpc.publicSubnets[0].subnetId,
      userData: cdk.Fn.base64(
        `#!/bin/bash -xe 
apt-get -y update
apt-get -y install xorg xfce4 autocutsel chromium-browser
add-apt-repository -y ppa:x2go/stable
apt-get -y install -y x2goserver x2goserver-xsession
apt-get -y install gnome-icon-theme tango-icon-theme`
      )
    });

@alokito
Copy link

alokito commented Jul 26, 2019

@AlexCheema that worked, thanks!

@eladb eladb added the @aws-cdk/aws-ec2 Related to Amazon Elastic Compute Cloud label Aug 13, 2019
@rix0rrr
Copy link
Contributor

rix0rrr commented Aug 28, 2019

CfnInstance will not automatically base64 for you. An AutoScalingGroup will, and the newly added Instance class will do so as well.

@rix0rrr rix0rrr closed this as completed Aug 28, 2019
@Fzomerdijk
Copy link

Hi,
The CDK python example above misses the base64 encoding, the line should be:

user_data= core.Fn.base64(shellCommands.render())

Full code example:

from aws_cdk import (
    aws_ec2 as ec2,
    core
)

from .hello_construct import HelloConstruct

class MyStack(core.Stack):

    def __init__(self, scope: core.Construct, id: str, **kwargs) -> None:
        super().__init__(scope, id, **kwargs)

        shellCommands = ec2.UserData.for_linux()
        shellCommands.add_commands(
            "echo \"Install Java 1.8 jdk\"",
            "yum install java-1.8.0-openjdk -y"
        )

        StackStateInstance = ec2.CfnInstance(self, 'StackStateInstance',
            image_id='ami-1234567890',
            instance_type='t3.small',
            availability_zone='eu-central-1a',
            user_data= core.Fn.base64(shellCommands.render()) 
       ) 

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
@aws-cdk/aws-ec2 Related to Amazon Elastic Compute Cloud needs-triage This issue or PR still needs to be triaged.
Projects
None yet
Development

No branches or pull requests

6 participants