M. Gleria
M. Gleria

Reputation: 513

Issues with !Sub and !GetAtt on EC2 Metadata on serverless template

I’m having issues to obtain some RDS Instance attributes from my EC2 Metadata configSet block using !Sub and !GetAtt functions combined.

So, at the resources key in my serverless.yml file I have (among other things) an EC2 instance (OASInstance) and an RDS instance (OASRDSInstance). I’m trying to build a connection string for my DB hosted on RDS, and for that, I’m using !Sub and !GetAtt functions inside a file definition on the Metadata block at my EC2 instance definition.

I’ve tried this in several ways, using short and long syntax format, but I make sure that this one works on a CloudFormation template:

- Fn::Sub:
  - "${RDSEndpointURL}:${RDSEndpointPort}:ORCL"
  - {RDSEndpointURL: !GetAtt OASRDSInstance.Endpoint.Address, RDSEndpointPort: !GetAtt OASRDSInstance.Endpoint.Port}

The error I’m getting when I try to deploy this template is this one:

Serverless Error ---------------------------------------   
Invalid variable reference syntax for variable RDSEndpointURL. You can only reference env vars, options, & files. You can check our docs for more info.

However, the same code block works perfectly if I use it in the same place on a CloudFormation template.

My guess is that serverless is confusing {RDSEndpointURL} and {RDSEndpointPort} with local template variables, and doesn’t realize that those are just for the !Sub context.

The template is pretty big (especially the EC2 Metadata section), so I'm posting here just the relevant part and putting '...' in not relevant sections.

This is the path you should check: path

...
resources:
  Resources:
    OASRDSInstance:
      Type: 'AWS::RDS::DBInstance'
      Properties:
        AllocatedStorage: 20
        BackupRetentionPeriod: 0
        CopyTagsToSnapshot: True
        DBInstanceClass: db.m5.xlarge
        DBInstanceIdentifier: oas-rcu-central
        DBName: ORCL
        DBParameterGroupName: default.oracle-ee-19
        DBSubnetGroupName: default-vpc
        Engine: oracle-ee
        EngineVersion: 19.0.0.0.ru-2020-07.rur-2020-07.r1
        KmsKeyId: arn:aws:kms:us-east-1:1111111111:key/aaaa-bbbb-cccc-eeee-dddd
        LicenseModel: bring-your-own-license
        MasterUserPassword: ${self:custom.rcuSysDBPassword}
        MasterUsername: admin
        OptionGroupName: default:oracle-ee-19
        Port: 1521
        StorageEncrypted : True
        StorageType : gp2
    OASInstance:
      Type: 'AWS::EC2::Instance'
      DependsOn: OASRDSInstance
      Metadata:
        'AWS::CloudFormation::Init':
          configSets:
            InstallAndRun:
              - OsRequirements
              - AddSwap
              - InstallJDK
              - PrepareFolders
              - PreOracleInventory
              - OracleInventory
              - PreInstallWLS
              - InstallWLS
              - PrePatchWLS
              - PatchWLS
              - PreInstallOAS
              - InstallOAS
              - CreateRCU
              - ConfigureOAS
              - RunOAS
          OsRequirements: ...
          AddSwap: ...
          InstallJDK: ...
          PrepareFolders: ...
          PreOracleInventory: ...
          OracleInventory: ...
          PreInstallWLS: ...
          InstallWLS: ...
          PrePatchWLS: ...
          PatchWLS: ...
          InstallOAS: ...
          CreateRCU:
            commands:
              cmd00:
                command: echo 'Create RCU' >> /tmp/OASsetup.log
              cmd01_01:
                command: !Join 
                  - ''
                  - - sudo -u oracle sh -c '(echo "
                    - !Ref RcuSysDBPassword
                    - '"; echo "'
                    - !Ref RcuSchemasDBPassword
                    - '") > /home/oracle/rcu_password.dat'''
              cmd02_01:
                command: !Join 
                  - ''
                  - - 'sudo -u oracle '
                    - !FindInMap 
                      - TemplateParams
                      - paths
                      - OracleHome
                    - '/oracle_common/bin/rcu '
                    - '-silent '
                    - '-createRepository '
                    - '-schemaPrefix '
                    - !Ref RcuDBPrefix
                    - ' '
                    - '-useSamePasswordForAllSchemaUsers true '
                    - '-connectString '
                    - Fn::Sub:
                      - "${RDSEndpointURL}:${RDSEndpointPort}:ORCL"
                      - {RDSEndpointURL: !GetAtt OASRDSInstance.Endpoint.Address, RDSEndpointPort: !GetAtt OASRDSInstance.Endpoint.Port}
                    - ' '
                    - '-dbUser '
                    - !Ref RcuSysDBUser
                    - ' '
                    - '-databaseType ORACLE '
                    - '-dbRole Normal '
                    - '-honorOMF '
                    - >-
                      -component STB -component MDS -component WLS -component OPSS
                      -component BIPLATFORM -component IAU -component IAU_APPEND
                      -component IAU_VIEWER 
                    - '-f < /home/oracle/rcu_password.dat'
              cmd03_01:
                command: rm /home/oracle/rcu_password.dat
          ConfigureOAS: ...
          RunOAS: ...
      Properties:
        IamInstanceProfile: dev-k12-oas-InstanceRole
        ImageId: !FindInMap 
          - AWSRegionArch2AMI
          - !Ref 'AWS::Region'
          - !FindInMap 
            - AWSInstanceType2Arch
            - !Ref InstanceType
            - Arch
        InstanceType: !Ref InstanceType
        BlockDeviceMappings:
          - DeviceName: /dev/xvda
            Ebs:
              VolumeSize: 25
              VolumeType: gp2
        NetworkInterfaces:
          - AssociatePublicIpAddress: false
            DeviceIndex: '0'
            GroupSet:
              - !Ref OASSecurityGroup
            SubnetId: subnet-aaaaaaaaaaaaaaaa
        KeyName: !Ref KeyName
        Tags:
        - Key: "Name"
          Value: !Ref "AWS::StackName"
        UserData: !Base64 
          'Fn::Join':
            - ''
            - - |
                #!/bin/bash -xe
              - |
                yum update -y aws-cfn-bootstrap
              - |
                # Install the files and packages from the metadata
              - '/opt/aws/bin/cfn-init -v '
              - '         --stack '
              - !Ref 'AWS::StackName'
              - '         --resource OASInstance '
              - '         --configsets InstallAndRun '
              - '         --region '
              - !Ref 'AWS::Region'
              - |+

              - |
                # Signal the status from cfn-init
              - '/opt/aws/bin/cfn-signal -e $? '
              - '         --stack '
              - !Ref 'AWS::StackName'
              - '         --resource OASInstance '
              - '         --region '
              - !Ref 'AWS::Region'
              - |+

      CreationPolicy:
        ResourceSignal:
          Timeout: PT45M
    OASSecurityGroup: ...
    OASLoadBalancerSG: ...
    OASTargetGroup: ...
    OASLoadBalancer: ...
    OASHttpLoadBalancerListener: ...
    OASLoadBalancerListener: ...
    PrivateDNSRecord: ...
...

What should I do?

Thanks

Upvotes: 0

Views: 244

Answers (1)

M. Gleria
M. Gleria

Reputation: 513

Well, I found a workaround.

I replace !Sub with !Join.

This is what I had:

- Fn::Sub:
  - "${RDSEndpointURL}:${RDSEndpointPort}:ORCL"
  - {RDSEndpointURL: !GetAtt OASRDSInstance.Endpoint.Address, RDSEndpointPort: !GetAtt OASRDSInstance.Endpoint.Port}

And this is the replacement:

- !Join 
  - ''
  - - !GetAtt OASRDSInstance.Endpoint.Address
    - ':'
    - !GetAtt OASRDSInstance.Endpoint.Port
    - ':'
    - ${self:custom.RDSDbName}

However, I would like to know if there is a better way.

Upvotes: 0

Related Questions