opsworks parameters and resources in the cloudformation template

188 views Asked by At

I'm working on a cloudformation template that has many parameters, like the ID of the elastic file system and the DNS of the MountTarget. I want to retreive these parameters from the existing resources, but if they are not already created I want to create them in the template :

{
  "AWSTemplateFormatVersion": "2010-09-09",
  "Description": "AWS CloudFormation Template : Stack OpsWorks Slave pour deployer les instances script",


  "Mappings": {

    "Region2Principal": {

      "us-east-1": {
        "EC2Principal": "ec2.amazonaws.com",
        "OpsWorksPrincipal": "opsworks.amazonaws.com"
      },

      "us-west-2": {
        "EC2Principal": "ec2.amazonaws.com",
        "OpsWorksPrincipal": "opsworks.amazonaws.com"
      },

      "us-west-1": {
        "EC2Principal": "ec2.amazonaws.com",
        "OpsWorksPrincipal": "opsworks.amazonaws.com"
      },

      "eu-west-1": {
        "EC2Principal": "ec2.amazonaws.com",
        "OpsWorksPrincipal": "opsworks.amazonaws.com"
      }
    },

    "AWSInstanceType2Arch" : {

           "t1.micro"    : { "Arch" : "PV64"   },
           "t2.micro"    : { "Arch" : "HVM64"  },
           "m1.small"    : { "Arch" : "PV64"   },
           "m1.large"    : { "Arch" : "PV64"   },
           "m4.large"    : { "Arch" : "HVM64"  },
           "m4.xlarge"   : { "Arch" : "HVM64"  },
           "m4.2xlarge"  : { "Arch" : "HVM64"  },
           "m4.4xlarge"  : { "Arch" : "HVM64"  },
           "m4.10xlarge" : { "Arch" : "HVM64"  },
           "m4.16xlarge" : { "Arch" : "HVM64"  },
           "c3.large"    : { "Arch" : "HVM64"  },
           "c3.xlarge"   : { "Arch" : "HVM64"  },
           "c3.2xlarge"  : { "Arch" : "HVM64"  },
           "c3.4xlarge"  : { "Arch" : "HVM64"  },
           "c3.8xlarge"  : { "Arch" : "HVM64"  },
           "c4.large"    : { "Arch" : "HVM64"    },
           "c4.xlarge"   : { "Arch" : "HVM64"  },
           "c4.2xlarge"  : { "Arch" : "HVM64"  },
           "c4.4xlarge"  : { "Arch" : "HVM64"  },
           "c4.8xlarge"  : { "Arch" : "HVM64"  }
    },

    "AWSRegionArch2AMI" : {

      "us-east-1" : { "PV64" : "ami-5fb8c835", "HVM64" : "ami-60b6c60a" },
      "us-west-1" : { "PV64" : "ami-56ea8636", "HVM64" : "ami-d5ea86b5" },
      "eu-west-1" : { "PV64" : "ami-95e33ce6", "HVM64" : "ami-bff32ccc" },
      "us-west-2" : { "PV64" : "ami-d93622b8", "HVM64" : "ami-f0091d91" }
    }

  },


  "Parameters": {

    "OpsWorksStackColor": {
        "Description": "RGB Color to use for OpsWorks Stack",
        "Type": "String",
        "Default": "rgb(38, 146, 168)"
    },

    "Region" : {
        "Type":"String",
        "Description": "Region location of the template resources",
        "Default": "eu-west-1",
        "AllowedValues" : [ "us-east-1", "us-west-1", "us-west-2", "eu-west-1" ]
    },

    "SecurityGroupIds": {
        "Description": "Security groups that can be used to access the EC2 instances, do not select more than 5 SG",
        "Type": "List<AWS::EC2::SecurityGroup::Id>",
        "ConstraintDescription": "must be list of EC2 security group ids"
    },

    "VpcId": {
        "Type": "AWS::EC2::VPC::Id",
        "Description": "VPC associated with the provided subnets",
        "Default": "vpc-69e3320c",
        "ConstraintDescription": "must be an existing VPC ID"
    },

    "SubnetId": {
        "Type": "String",
        "Default": "subnet-6820eb31",
        "ConstraintDescription": "must be an existing subnet ID"
    },

    "InstanceType": {
        "Type": "String",
        "Default": "c3.large",
        "AllowedValues" : ["t2.micro", "m1.small", "m1.large","m4.large","m4.xlarge","m4.2xlarge","m4.4xlarge","m4.10xlarge","m4.16xlarge","c4.large" , "c4.xlarge" ,"c4.2xlarge" , "c4.4xlarge","c4.8xlarge" , "c3.large" , "c3.xlarge", "c3.2xlarge", "c3.4xlarge" ,"c3.8xlarge"],
        "ConstraintDescription": "must be a valid EC2 instance type"
    },

    "KeyPairName": {
        "Type": "AWS::EC2::KeyPair::KeyName",
        "Default": "test-generic-ec2",
        "ConstraintDescription": "must be the name of an existing EC2 KeyPair"
    },

    "CookbookS3" : {
        "Type": "String",
        "Default": "https://s3-eu-west-1.amazonaws.com/mybucket.test.cookbooks/cookbook-v1.tar.gz",
        "ConstraintDescription": "the Url to the cookbook"
    },

    "CookbookS3AccessID": {
        "Type": "String",
        "ConstraintDescription": "username to the appropriate IAM access key ID"
    },

    "CookbookS3AccessKey": {
        "Type": "String",
        "NoEcho" : "true",
        "ConstraintDescription": "password to the appropriate IAM secret access key"
    },

    "MountPoint" : {
        "Description" : "The Linux mount point for the EFS volume",
        "Type": "String",
        "MinLength": "1",
        "Default": "efs-file-appli-tmp"
    },

    "MountPointDNS" : {
        "Description" : "Mount target DNS name",
        "Type" : "String",
        "Default" : "eu-west-1a.fs-c2388dc0b.efs.eu-west-1.amazonaws.com"
    },

    "FileSystem" : {
        "Description" :"The Id of the FileSystem",
        "Type": "String",
        "Default": "fs-c2388dc0b"
    },

    "NewRelicLicence" : {
        "Description": "The licence key of newrelic",
        "Type": "String"
    },

    "Environnement" : {
        "Description": "The Environnement variable ",
        "Type": "String",
        "Default": "test",
        "AllowedValues" : ["dev", "test", "int", "prod"]
    }

  },

  "Conditions" : {
    "CreateProdResources" : { "Fn::Not" : [{  "Fn::Equals" : [ {"Ref" : "Environnement"},"test" ] }] }
  },

  "Resources": {

    "MyStack": {
        "Type": "AWS::OpsWorks::Stack",
        "Properties": {
         "AgentVersion" : "LATEST",
         "Name": { "Ref": "AWS::StackName" },
         "Attributes": { "Color": { "Ref": "OpsWorksStackColor" } },
         "ChefConfiguration": {},
         "ConfigurationManager": { "Name": "Chef", "Version": "12" },
         "CustomCookbooksSource": {
           "Type": "s3",
           "Password" : { "Ref": "CookbookS3AccessKey" },
           "Username" : { "Ref": "CookbookS3AccessID" },
           "Url": { "Ref": "CookbookS3" }
         },
         "CustomJson":  { 

                          "mount" : { "mountdir" : {
                            "default" : { "dirname" : { "Ref" : "MountPoint" } } }
                          },
                          "mountadd" : { "mountdns" : {
                            "default" : { "mdns" : { "Ref" : "MountPointDNS" }}}
                          }


         },
         "DefaultInstanceProfileArn": { "Fn::GetAtt": [ "OpsWorksInstanceProfile","Arn" ] },
         "DefaultOs": "Ubuntu 14.04 LTS",
         "DefaultRootDeviceType": "ebs",
         "DefaultSshKeyName": { "Ref": "KeyPairName" },
         "DefaultSubnetId" : {"Ref" : "SubnetId" },
         "ServiceRoleArn": { "Fn::GetAtt": ["OpsWorksServiceRole", "Arn"] },
         "UseCustomCookbooks": true,
         "UseOpsworksSecurityGroups" : true,
         "VpcId" : { "Ref" : "VpcId" }
        }
    },

    "MyLayer": {
        "Type": "AWS::OpsWorks::Layer",
        "DependsOn" : "OpsWorksServiceRole",
        "Properties": {
         "AutoAssignElasticIps" : false,
         "AutoAssignPublicIps" : true,
         "CustomRecipes" : {
           "Setup"     : ["cassandra-php-driver::setup","awscli::setup","crontab::setup","prometheus-server::setup","awslogs::setup","newrelic::php_agent","settings::setup"],
           "Configure" : ["cassandra-php-driver::configure","security::configure","settings::default"],
           "Deploy": ["imports::deploy"]
        },
         "CustomSecurityGroupIds" : { "Ref" : "SecurityGroupIds" },
         "EnableAutoHealing" : true,
         "InstallUpdatesOnBoot": false,
         "LifecycleEventConfiguration": {
           "ShutdownEventConfiguration": {
           "DelayUntilElbConnectionsDrained": false,
           "ExecutionTimeout": 120 }
         },
         "Name": "script-node",
         "Shortname" : "node",
         "StackId": { "Ref": "MyStack" },
         "Type": "custom",
         "UseEbsOptimizedInstances": true,
         "VolumeConfigurations": [ {
           "Iops": 10000,
           "MountPoint": "/dev/sda1",
           "NumberOfDisks": 1,
           "Size": 20,
           "VolumeType": "gp2"
         }]
      }
    },

    "OpsWorksServiceRole": {
        "Type": "AWS::IAM::Role",
        "Properties": {
         "AssumeRolePolicyDocument": {
          "Version" : "2012-10-17",
          "Statement": [ {
            "Effect": "Allow",
            "Principal": { "Service": [ { "Fn::FindInMap": [ "Region2Principal",{ "Ref": "AWS::Region" },"OpsWorksPrincipal" ] } ] },
                             "Action" : [ "sts:AssumeRole" ]
          } ]
            },
         "Path": "/",
         "Policies": [ {
          "PolicyName": "opsworks-service",
          "PolicyDocument": {
          "Version" : "2012-10-17",
          "Statement": [ {
            "Effect": "Allow",
            "Action": "*",
            "Resource": "*"
            } ]
          }
          } ]
        }
    },

    "OpsWorksInstanceRole": {
        "Type": "AWS::IAM::Role",
        "Properties": {
         "AssumeRolePolicyDocument": {
          "Version" : "2012-10-17",
          "Statement": [ {
              "Effect": "Allow",
              "Principal": { "Service" : [ { "Fn::FindInMap": [ "Region2Principal", { "Ref": "AWS::Region" },"EC2Principal" ] } ] },
                             "Action"  : [ "sts:AssumeRole" ]
          }]
         },
         "Path": "/",
         "Policies": [{
          "PolicyName": "aws-opsworks-instance",
          "PolicyDocument": {
            "Statement": [{
              "Effect": "Allow",
              "Action": "*",
              "Resource": "*"
            }]
          }
         }]
        }
    },

    "OpsWorksInstanceProfile": {
        "Type": "AWS::IAM::InstanceProfile",
        "Properties": {
         "Path": "/",
         "Roles": [ { "Ref": "OpsWorksInstanceRole" } ]
      }
    },

    "MyInstance": {
        "Type": "AWS::OpsWorks::Instance",
        "Properties": {
         "Hostname": "Script",
         "RootDeviceType": "ebs",
         "StackId": {"Ref": "MyStack"},
         "LayerIds": [{"Ref": "MyLayer"}],
         "InstanceType": {"Ref" : "InstanceType"}
        }
    },

    "MyApp": {
        "Type": "AWS::OpsWorks::App",
        "Properties": {
         "AppSource" : {
          "Type" : "git",
          "Url" : "git://github.com:globlW/My-imports.git",
          "Revision" : "develop"
         },
         "Description": "Dataimport and connectors",
         "Name" : "app-Imports",
         "Shortname" : "app_imports",
         "StackId" : {"Ref": "MyStack"},
         "Type" : "other"
        }
    },

    "MyFileSystem" : {
        "Type" : "AWS::EFS::FileSystem",
        "Condition" : "CreateProdResources",
        "Properties" : {
         "FileSystemTags" : [{
          "Key" : "Name",
          "Value" : {"Ref" : "MountPoint"}
         }]
        }
    },

    "MountTarget": {
        "Type": "AWS::EFS::MountTarget",
        "Condition" : "CreateProdResources",
        "Properties": {
         "FileSystemId": { "Ref": "MyFileSystem" },
          "SubnetId": { "Ref": "SubnetId" },
          "SecurityGroups": [ { "Ref": "SecurityGroupIds" } ]
        }
    }

  }




}

As you see, I use often the { "Ref" : "FileSystem" } , { "Ref" : "MountPointDNS" } and { "Ref" : "MountPoint" }, I specially need them in the CustomJson. The problem is how to link the parameters with the recent created resources and how to name them ? can I give the same name so that I can always get a value to customjson ? I hope my issue is clear. Thank you

1

There are 1 answers

0
wjordan On BEST ANSWER

It is possible to conditionally use an existing resource using Condition Functions. See the Conditionally use an existing resource example in the documentation, which demonstrates the following pattern:

Parameters: 
  ExistingResource: 
    Description: An existing resource (optional).
    Default: NONE
    Type: String
Conditions: 
  CreateNewResource: !Equals [!Ref ExistingResource, NONE]
Resources: 
  NewResource:
    Condition: CreateNewResource
    Type: # Resource type
    Properties: # Resource properties
Outputs:
  ResourceId:
    Description: Reference to either a newly-created or existing resource.
    Value: !If [CreateNewResource, !Ref NewResource, !Ref ExistingResource]