0

I am writing CF code to launch ec2 instance, this is what my code looks like:

I am facing these 2 issues:

1) I get this error "Template validation error: Template error: unresolved condition dependency BackupSize in Fn::If"

2) I want to join Parameter Name and from Mappings USERDATA. (The remaining userdata works fine, but this join is not working and just puts the same code in the userdata.

Can anyone help me out please?

AWSTemplateFormatVersion: "2010-09-09"  
Description: "This template should be used to deploy ONLY test servers"  

Mappings:  

    Regions:  
    us-east-1:  
           "AMI": "ami-x"  
           "VPC": "vpc-x"  
           "SUBNET": "subnet-x"  
           "USERDATA": ".example.com"  
           "SHARE": "server1:/share"  
           "SecurityGroups": "sg-x"  
           "SecurityGroups2": "sg-y"  

Parameters:  

      ApplSize:  
      Description: "Please enter application vol. size"  
      Type: "String"  
      BackupSize:  
      Description: "Please enter backup vol. size"  
      Type: "String"  


Resources:  

      EC2Instance:  
      Type: "AWS::EC2::Instance"  
      Properties:  
            ImageId: !FindInMap [Regions, !Ref "AWS::Region", AMI]  
            InstanceType: !Ref InstanceType  
            SubnetId: !FindInMap [Regions, !Ref "AWS::Region", SUBNET]  
            SecurityGroupIds:  
                - !FindInMap [Regions, !Ref "AWS::Region", SecurityGroups]  
                - !FindInMap [Regions, !Ref "AWS::Region", SecurityGroups2]  
            BlockDeviceMappings:  
                -   
                 DeviceName : "/dev/sda1"  
                 Ebs:  
                    VolumeSize: "20"  
                    VolumeType: gp2  
                -  
                 DeviceName : "/dev/sde"  
                 Ebs:  
                    VolumeSize: !Ref ApplSize  
                    VolumeType: gp2  
                -  
                 DeviceName : "/dev/sdc"  
                 Ebs:  
                    VolumeSize: "5"  
                    VolumeType: gp2  

                - Fn::If:  
                   - BackupSize  
                   -   
                     DeviceName : "/dev/sdg"  
                     Ebs:  
                       VolumeSize: !Ref BackupSize  
                       VolumeType: gp2  
                   - !Ref "AWS::NoValue"  

      UserData:   
              Fn::Base64: !Sub |  
                #!/bin/bash  
                NEW_HOSTNAME=Fn::Join: [ " ", [ !Ref Name, Fn::FindInMap: 
                                    [Regions, !Ref "AWS::Region", USERDATA] ] ]  
                hostname $NEW_HOSTNAME  
                myshortname=`hostname -s`  

I expect the template to create Backup volume if I put any value in the parameter, and if I leave backupsize value blank, it should not create this disk.

Alex Harvey
  • 14,494
  • 5
  • 61
  • 97
david bob
  • 71
  • 3
  • 9
  • You'll have to provide your actual template with the formatting corrected (must be valid YAML) because I can't reproduce what you're seeing. – Alex Harvey Feb 05 '19 at 07:53
  • Here: https://ufile.io/2liuv – david bob Feb 05 '19 at 11:27
  • Ok I agree that your template in that file is the same as the one above. And, as I said, it's an invalid template. Indentation is wrong everywhere. You will need to give us the real one that yields `Template validation error: Template error: unresolved condition dependency BackupSize in Fn::If`. – Alex Harvey Feb 05 '19 at 12:09
  • And after fixing the indentation problems, the template then yields, `Unresolved resource dependencies [InstanceType] in the Resources block of the template`. – Alex Harvey Feb 05 '19 at 12:13

3 Answers3

0

The various versions of the template presented all have basic formatting problems. The latest version (attached in a comment below this answer):

▶ aws cloudformation validate-template --template-body file://cloudformation.yml 
An error occurred (ValidationError) when calling the ValidateTemplate operation: [/Mappings/Regions] 'null' values are not allowed in templates

The formatting problems include duplicate keys, incorrect indentation, etc. These problems can't be detected by simply checking if the file is valid YAML. It can be valid YAML and still be invalid for Cloudformation. You need to use the validate-template command as I showed above.

After fixing up the various issues in the provided template (including the new version), I was unable to reproduce an error about

unresolved condition dependency BackupSize in Fn::If

What you have in Fn::If looks ok to me.

As for how to interpolate Fn::Join in the UserData:

  1. I would consider refactoring so that complex logic lies outside of Cloudformation. For instance, you could pass the hostname as a separate parameter.

  2. If you really want to do it this way you can do it like this:

UserData:
  Fn::Base64: !Sub
    - |
      #!/bin/bash
      NEWHOSTNAME=${newhostname}
      hostname $NEW_HOSTNAME
      myshortname=`hostname -s`
    - newhostname: !Join ["", ["foo", "bar"]]
Alex Harvey
  • 14,494
  • 5
  • 61
  • 97
  • I have like 100 line of bash code, do I have to put quote around all the lines? But what about that dependency issue? I have uploaded the code which had instance type as well, below is the link for it. https://ufile.io/bwoti – david bob Feb 05 '19 at 21:56
  • I will use point 1 as the solution, forget about the previous reply, I have posted the code again with all details, hope that helps – david bob Feb 05 '19 at 23:46
  • Bro., I really appreciate your help. I managed to fix that issue with If condition, now I am trying to work on that UserData part. Will upload the code soon – david bob Feb 06 '19 at 08:54
  • I figured out the UserData part as well, I edited the correct code above The only challenge now is how to add another variable apart from url, I guess this is something Dev people would know – david bob Feb 07 '19 at 00:14
0
AWSTemplateFormatVersion: "2010-09-09"  
Description: "This template should be used to deploy ONLY test servers"  

Mappings:  

    Regions:  
    us-east-1:  
           "AMI": "ami-x"  
           "VPC": "vpc-x"  
           "SUBNET": "subnet-x"  
           "USERDATA": ".example.com"  
           "SHARE": "server1:/share"  
           "SecurityGroups": "sg-x"  
           "SecurityGroups2": "sg-y"  

Parameters:  

      ApplSize:  
        Description: "Please enter application vol. size"  
        Type: "String"  
      BackupSize:
        Description: "Please enter backup vol. size"
        Type: "String"
      VaultSize:
        Description: "Please enter secret vol. size"
        Type: "String"
      InstanceType:
        Description: "Please select the instance type"
        Type: "String"
      Name:
        Description: "Please mention server name"
        Type: "String"
      CustomerName:
        Description: "Please mention customer name"
        Type: "String"
      Url:
        Description: "Please mention url without the domain name"
        Type: "String"


Conditions:
    BackupVol: !Equals [!Ref BackupSize, ""]


Resources:  

      EC2Instance:  
      Type: "AWS::EC2::Instance"  
      Properties:  
            ImageId: !FindInMap [Regions, !Ref "AWS::Region", AMI]  
            InstanceType: !Ref InstanceType  
            SubnetId: !FindInMap [Regions, !Ref "AWS::Region", SUBNET]  
            SecurityGroupIds:  
                - !FindInMap [Regions, !Ref "AWS::Region", SecurityGroups]  
                - !FindInMap [Regions, !Ref "AWS::Region", SecurityGroups2]  
            BlockDeviceMappings:  
                -   
                 DeviceName : "/dev/sda1"  
                 Ebs:  
                    VolumeSize: "20"  
                    VolumeType: gp2  
                -  
                 DeviceName : "/dev/sde"  
                 Ebs:  
                    VolumeSize: !Ref ApplSize  
                    VolumeType: gp2  
                -  
                 DeviceName : "/dev/sdc"  
                 Ebs:  
                    VolumeSize: "5"  
                    VolumeType: gp2  

               - Fn::If:
                   - BackupVol
                   - !Ref "AWS::NoValue"
                   - DeviceName : "/dev/sdg"
                     Ebs:
                       VolumeSize: !Ref BackupSize
                       VolumeType: gp2  

      UserData: 
              Fn::Base64: !Sub
               - |+
                  #!/bin/bash -xe
                  NEW_HOSTNAME=${test}
               - test: 
                    Fn::FindInMap: [Regions, !Ref "AWS::Region", Name] 
Alex Harvey
  • 14,494
  • 5
  • 61
  • 97
david bob
  • 71
  • 3
  • 9
  • This is also an invalid template. If you contact me on Linked In, I will help get to the bottom of why the templates you're pasting in here are invalid. – Alex Harvey Feb 07 '19 at 10:40
0

Simple ans..first condition of IF should be a CONDITIONS..Create a conditions block and use that in IF... Example:

Conditions: mycondition: blah blah

IF [mycondition: blah1, blah2]