Creating an EC2 in AWS via Cloud Formation

This blog post explains how to create (β€œspin up” in the cool lingo πŸ™‚ ) an EC2 in AWS using Cloud Formation. I will attempt to explain each line or section of code before the code itself. The complete cloud formation template is available at the end of this post. This template is written in JSON. It could also have been done in YAML.

This is the opening curly brace. Just make sure you have one at the end to close it out. Strongly suggest using a JSON formatter and syntax checker.

{

These lines identify the AWS template format version and a description tag for documentation purposes

    "AWSTemplateFormatVersion":"2010-09-09",
    "Description":"Linux EC2 to test with",

The parameters section contains the parameters that will be passed from my Jenkins job to this cloud formation template. Each of these can have a type, default value, and description.

    "Parameters":{
        "CFstackname":{
            "Type":"String"
        },
        "AppID":{
            "Type":"String",
            "Default":"ABC",
            "Description":"Name of the application. Default=ABC"
        },
        "Role":{
            "Type":"String",
            "Default":"App",
            "Description":"Enter the Role name. Default=App"
        },
        "UserID":{
            "Type":"String",
            "Description":"Enter the userid of the owner(s)"
        }
    },

This next section specifies the resources that are to be created by this cloud formation template.

    "Resources":{

The type of the resource to be created is an EC2 instance

        "EC2Instance":{
            "Type":"AWS::EC2::Instance",

This section contains the properties to describe the resource.

            "Properties":{

This parameter specifies the instance type which in this case is a t3 small

                "InstanceType":"t3.small",

The DisableApiTermination attribute controls whether the instance can be terminated using the console, CLI, or API. While writing this blog post I did learn that the DisableApiTermination attribute does not prevent Amazon EC2 Auto Scaling from terminating an instance. Just a useful piece of information.

                "DisableApiTermination":"false",

This specifies the network interfaces. The AssociatePublicIpAddress is set to false in this case. The subnet ID is your subnet i.e. logical subdivision of an IP network. The group set contains the security groups that you want to be attached to this EC2 instance. These need to be predefined.

                "NetworkInterfaces":[
                    {
                        "AssociatePublicIpAddress":"false",
                        "DeviceIndex":"0",
                        "SubnetId":"my-subnet-01",
                        "GroupSet":[
                            "sg-for-me-01",
                            "sg-for-me-02"
                        ]
                    }
                ],

This next parameter specifies the Amazon machine image (AMI) that you wish to use to create this instance. In my case, I had a pre-created AMI that I was using as it was already encrypted with my KMS key

                "ImageId":"ami-dean-01",

Here I’m specifying the block devices (disks) to be associated with this machine. The volume size is specified in gigabytes. Storage is deleted when the EC2 is terminated. The disk is to be encrypted with the KMS key specified

                "BlockDeviceMappings":[
                    {
                        "DeviceName":"/dev/sda1",
                        "Ebs":{
                            "VolumeSize":"100",
                            "DeleteOnTermination":true,
                            "VolumeType":"gp2",
                            "Encrypted":"true",
                            "KmsKeyId":"my magical KMS key"
                        }
                    }
                ],

These are the tags that are to be associated with this EC2. Some of them are from the parameters of the top of the template. This is a free form to the extent that you can specify any tag string as the key and any value as the value.

                "Tags":[
                    {
                        "Key":"UserID",
                        "Value":"xyz01"
                    },
                    {
                        "Key":"Name",
                        "Value":"My Linux Machine"
                    },
                    {
                        "Key":"Role",
                        "Value":"App"
                    }

Close all the curly braces or else bad things will happen πŸ™‚

 
                ]
            }
        }
    },

This section is the outputs that I am expecting. The first is the instance id, followed by the Availability Zone (AZ) and the private IP

    "Outputs":{
        "InstanceId":{
            "Description":"InstanceId of the newly created EC2 instance",
            "Value":{
                "Ref":"EC2Instance"
            }
        },
        "AZ":{
            "Description":"Availability Zone of the newly created EC2 instance",
            "Value":{
                "Fn::GetAtt":[
                    "EC2Instance",
                    "AvailabilityZone"
                ]
            }
        },
        "PrivateIP":{
            "Description":"PrivateIP of the newly created EC2 instance",
            "Value":{
                "Fn::GetAtt":[
                    "EC2Instance",
                    "PrivateIp"
                ]
            }
        }
    }
}

Complete cloud formation template

{
    "AWSTemplateFormatVersion":"2010-09-09",
    "Description":"Linux EC2 to test with",
    "Parameters":{
        "CFstackname":{
            "Type":"String"
        },
        "AppID":{
            "Type":"String",
            "Default":"ABC",
            "Description":"Name of the application. Default=ABC"
        },
        "Role":{
            "Type":"String",
            "Default":"App",
            "Description":"Enter the Role name. Default=App"
        },
        "UserID":{
            "Type":"String",
            "Description":"Enter the userid of the owner(s)"
        }
    },
    "Resources":{
        "EC2Instance":{
            "Type":"AWS::EC2::Instance",
            "Properties":{
                "InstanceType":"t3.small",
                "DisableApiTermination":"false",
                "NetworkInterfaces":[
                    {
                        "AssociatePublicIpAddress":"false",
                        "DeviceIndex":"0",
                        "SubnetId":"my-subnet-01",
                        "GroupSet":[
                            "sg-for-me-01",
                            "sg-for-me-02"
                        ]
                    }
                ],
                "ImageId":"ami-dean-01",
                "BlockDeviceMappings":[
                    {
                        "DeviceName":"/dev/sda1",
                        "Ebs":{
                            "VolumeSize":"100",
                            "DeleteOnTermination":true,
                            "VolumeType":"gp2",
                            "Encrypted":"true",
                            "KmsKeyId":"my magical KMS key"
                        }
                    }
                ],
                "Tags":[
                    {
                        "Key":"UserID",
                        "Value":"xyz01"
                    },
                    {
                        "Key":"Name",
                        "Value":"My Linux Machine"
                    },
                    {
                        "Key":"Role",
                        "Value":"App"
                    }
 
                ]
            }
        }
    },
    "Outputs":{
        "InstanceId":{
            "Description":"InstanceId of the newly created EC2 instance",
            "Value":{
                "Ref":"EC2Instance"
            }
        },
        "AZ":{
            "Description":"Availability Zone of the newly created EC2 instance",
            "Value":{
                "Fn::GetAtt":[
                    "EC2Instance",
                    "AvailabilityZone"
                ]
            }
        },
        "PrivateIP":{
            "Description":"PrivateIP of the newly created EC2 instance",
            "Value":{
                "Fn::GetAtt":[
                    "EC2Instance",
                    "PrivateIp"
                ]
            }
        }
    }
}

ORA-31604: invalid transform NAME parameter “MODIFY” for object type PROCACT_INSTANCE in function ADD_TRANSFORM

While performing an import data pump operation into an Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 – 64bit Production we encountered the below error:

Connected to: Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production
With the Partitioning, Real Application Clusters, Automatic Storage Management, OLAP,
Data Mining and Real Application Testing options
Master table "SYS"."SYS_IMPORT_FULL_15" successfully loaded/unloaded
Starting "SYS"."SYS_IMPORT_FULL_15":  "/******** AS SYSDBA" directory=exp_dir dumpfile=resolvecode.dmp remap_table=myuser.accounting_codes:accounting_codes_prod 
Processing object type TABLE_EXPORT/TABLE/PROCACT_INSTANCE
ORA-39126: Worker unexpected fatal error in KUPW$WORKER.LOAD_MD_TRANSFORMS [] 
ORA-31604: invalid transform NAME parameter "MODIFY" for object type PROCACT_INSTANCE in function ADD_TRANSFORM
ORA-06512: at "SYS.DBMS_SYS_ERROR", line 86
ORA-06512: at "SYS.KUPW$WORKER", line 9710

This issue is documented on Oracle support at

Impdp Fails With ORA-39126 ORA-31604 Iinvalid Transform NAME Parameter "MODIFY" For Object Type PROCACT_INSTANCE in function ADD_TRANSFORM (Doc ID 1596495.1)

The solution is to change the import data pump command from:

impdp \'/ as sysdba \' dumpfile=resolvecode.dmp directory=exp_dir remap_table=myuser.accounting_codes:accounting_codes_prod 

to:

impdp \'/ as sysdba \' dumpfile=resolvecode.dmp directory=exp_dir remap_table=myuser.accounting_codes:accounting_codes_prod exclude=PROCACT_INSTANCE

The use of the exclude=PROCACT_SYSTEM will exclude the resource manager objects such as resource plans and groups.

There is also a patch available, but the addition of exclude=PROCACT_INSTANCE solved my issue faster than patching.