From f1ac66b9ca78377425c64849f31dfcfb2e05e6ac Mon Sep 17 00:00:00 2001 From: goodrum Date: Wed, 28 Jun 2017 09:26:44 -0500 Subject: [PATCH] * Release 1.5.0 with support for OnCommand Cloud Manager 3.3.0 (#3) ** aws_standalone ADD: Berksfile for cookbook resolution UPDATE: Files::occm-role-policy to include updated IAM requirements for OCCM 3.3.0 UPDATE: Script::bootstrap.sh to install the ChefDK client and use the Berksfile to package the cookbooks and dependencies. UPDATE: Templates::create_ontap.json.tpl to include variable to set the ontap_write_speed UPDATE: Main.tf to streamline resource idempotence and deployment UPDATE: Output.tf variable outputs UPDATE: templates.tf to include changes in setting the write_speed UPDATE: variables.tf formatting and defaults. ** aws_standalone_full ADD: Berksfile for cookbook resolution UPDATE: Files::occm-role-policy to include updated IAM requirements for OCCM 3.3.0 UPDATE: Script::bootstrap.sh to install the ChefDK client and use the Berksfile to package the cookbooks and dependencies. UPDATE: Templates::create_ontap.json.tpl to include variable to set the ontap_write_speed UPDATE: Main.tf to streamline resource idempotence and deployment UPDATE: Output.tf variable outputs UPDATE: templates.tf to include changes in setting the write_speed UPDATE: variables.tf formatting and defaults. --- .gitignore | 3 + CHANGELOG.md | 30 +++ aws_standalone/README.md | 134 ++++++---- aws_standalone/files/Berksfile | 11 + aws_standalone/files/occm-role-policy.json | 197 ++++++++------ aws_standalone/main.tf | 214 +++++++++------ aws_standalone/output.tf | 14 +- aws_standalone/scripts/bootstrap.sh | 25 +- aws_standalone/templates.tf | 21 +- .../templates/create_ontap.json.tpl | 3 +- aws_standalone/variables.tf | 70 +++-- aws_standalone_full/README.md | 146 +++++----- aws_standalone_full/files/Berksfile | 11 + .../files/occm-role-policy.json | 197 ++++++++------ aws_standalone_full/main.tf | 251 +++++++++++------- aws_standalone_full/output.tf | 22 +- aws_standalone_full/scripts/bootstrap.sh | 25 +- aws_standalone_full/templates.tf | 25 +- .../templates/create_ontap.json.tpl | 3 +- aws_standalone_full/variables.tf | 75 ++++-- 20 files changed, 939 insertions(+), 538 deletions(-) create mode 100644 .gitignore create mode 100644 CHANGELOG.md create mode 100644 aws_standalone/files/Berksfile create mode 100644 aws_standalone_full/files/Berksfile diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ee93d0c --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ + +*/*.tfvars +*/*.tfstate* \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..e70d007 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,30 @@ +# aws_standalone Terraform CHANGELOG + +This file is used to list changes made in each version of the aws_standalone Terraform. + + +## v1.5.0 + +- aws_standalone + - ADD: Berksfile for cookbook resolution + - UPDATE: Files::occm-role-policy to include updated IAM requirements for OCCM 3.3.0 + - UPDATE: Script::bootstrap.sh to install the ChefDK client and use the Berksfile to package the cookbooks and dependencies. + - UPDATE: Templates::create_ontap.json.tpl to include variable to set the ontap_write_speed + - UPDATE: Main.tf to streamline resource idempotence and deployment + - UPDATE: Output.tf variable outputs + - UPDATE: templates.tf to include changes in setting the write_speed + - UPDATE: variables.tf formatting and defaults. + +- aws_standalone_full + ADD: Berksfile for cookbook resolution + UPDATE: Files::occm-role-policy to include updated IAM requirements for OCCM 3.3.0 + UPDATE: Script::bootstrap.sh to install the ChefDK client and use the Berksfile to package the cookbooks and dependencies. + UPDATE: Templates::create_ontap.json.tpl to include variable to set the ontap_write_speed + UPDATE: Main.tf to streamline resource idempotence and deployment + UPDATE: Output.tf variable outputs + UPDATE: templates.tf to include changes in setting the write_speed + UPDATE: variables.tf formatting and defaults. + +## v1.0.0 + +- Initial release with support for deployment and setup of OnCommand Cloud Manager and the creation and deletion of ONTAP Cloud for AWS systems diff --git a/aws_standalone/README.md b/aws_standalone/README.md index 50af002..0ba9878 100644 --- a/aws_standalone/README.md +++ b/aws_standalone/README.md @@ -13,21 +13,14 @@ _Note: On `terraform destroy`, the associated ONTAP Cloud system deployed will b - [ONTAP Cloud charges and AWS fees](#ontap-cloud-charges-and-aws-fees) - [NetApp and Amazon Marketplace registration](#netapp-and-amazon-marketplace-registration) - [Tools and versions](#tools-and-versions) +- [Usage](#usage) + - [Before you begin](#before-you-begin) + - [Terraform Commands](#terraform-commands) + - [Re-running the provisioning effort and changes](#re-running-the-provisioning-effort-and-changes) - [Resources](#resources) - [Variables](#variables) - - [AWS Variables](#aws-variables) - - [OnCommand Cloud Manager Variables](#oncommand-cloud-manager-variables) - - [ONTAP Cloud for AWS](#ontap-cloud-for-aws) - [Terraform Configuration Files](#terraform-configuration-files) - - [Files](#files) - - [Scripts](#scripts) - - [Templates](#templates) - - [Default Variable Values](#default-variable-values) - [CHEF Solo integration](#chef-solo-integration) - - [Run_Lists and Attributes](#run_lists-and-attributes) -- [Usage](#usage) - - [Before you begin](#before-you-begin) - - [Re-running the provisioning effort and changes](#re-running-the-provisioning-effort-and-changes) - [Contribute](#contribute) - [License & Authors](#license-&-authors) @@ -40,8 +33,8 @@ This Terraform template will deploy cloud instances and resources into your Amaz ### NetApp and Amazon Marketplace registration Prior running this template, you will need to ensure that your AWS account has subscribed to the official ONTAP Cloud for AWS and OnCommand Cloud Manager images: -* Visit the [official page for OnCommand Cloud Manager in the AWS Marketplace](https://aws.amazon.com/marketplace/pp/B018REK8QG]) for more information. -* Visit the [official page for ONTAP Cloud in the AWS Marketplace](https://aws.amazon.com/marketplace/pp/B011KEZ734]) for more information. +* Visit the [official page for OnCommand Cloud Manager in the AWS Marketplace](https://aws.amazon.com/marketplace/pp/B018REK8QG) for more information. +* Visit the [official page for ONTAP Cloud in the AWS Marketplace](https://aws.amazon.com/marketplace/pp/B011KEZ734) for more information. ### Tools and versions @@ -49,7 +42,38 @@ Prior running this template, you will need to ensure that your AWS account has s - Chef Solo 12.5+ - Terraform v0.9.2+ -### Resources +## Usage +### Before you begin +--- +Verify your meet these requirements +- [Terraform v0.9.2+](https://www.terraform.io/downloads.html) installed on your local machine +- You have an active and valid AWS account with an Identity and Access Management user credentials. More information found [in the official AWS documentation](http://docs.aws.amazon.com/cli/latest/userguide/cli-chap-getting-started.html). +- You have registered for access to the OnCommand Cloud Manager and ONTAP Cloud AMI
Simply go to each of the below links and register + - [OnCommand Cloud Manager](https://aws.amazon.com/marketplace/pp/B018REK8QG) + - [ONTAP Cloud for AWS](https://aws.amazon.com/marketplace/pp/B011KEZ734) + +### Terraform Commands +--- +- `terraform plan`: Execute the planned output to verify the current desired infrastructure state +- `terraform apply`: Run the configuration using the supplied variables. +- `terraform destroy`: Execute the destruction sequence to remove all resources. +- `terraform taint`: Mark a resource for recreation. All child dependent resources will be reset and redeployed as well. + +### Re-running the provisioning effort and changes +--- +All host configurations have been place in custom resources using the Terraform `null_resource` operator. This allows for easy re-application of templates and services. All of the configurations are designed to set the desired state and only update when the existing configuration does not match. Only if a specific resource is marked for destruction, will the destroy triggers enact. + +#### Configuration Resources +--- +- `null_resource.ontap_cloud`: Manages the configuration of OnCommand Cloud Manager and the ONTAP Cloud system + +#### Redeploying an instance +--- +If you mark an instance for redeployment, the associated configuration resource will be marked as well. The deletion of a host will trigger clean-up resources if defined. + +Since the ONTAP Cloud system can be added or removed outside of this infrastructure, the process to reset the OnCommand Cloud Manager host will delete the existing ONTAP Cloud system and force a redeployment. This action will also cause the Peritus Test Case host to rerun its configuration to ensure that everything connects. + +## Resources This Terraform will create the following resources: - AWS Identity Access Management (IAM) Policy - AWS Identity Access Management (IAM) Profile @@ -58,40 +82,52 @@ This Terraform will create the following resources: - AWS EC2 Instance using OnCommand Cloud Manager marketplace image - NetApp ONTAP Cloud for AWS instance with 1TB of storage -### Variables +## Variables _NOTE: properties in bold are required_ +#### Configuration Variables +| Variable | Description | Default Value | +| ------------- |------------- |------------- | +| **`owner_name`** | Your Username to identify your infrastructure. | | +| `converge` | Setting this variable on subsquent runs will force a reload of the configuration and re-apply the configurations. Changing this value will notify the provisioning resources to reconverge their configurations. You can override the value from the command line by running `terraform apply -var converge=true`

_Note: Once changed, the value is preserved so the next time the `terraform apply` command is run, the value will revert to the default._| false | + #### AWS Variables -| Variable | Description | -| ------------- |-------------| -| **`aws_profile`** | Identifies the AWS Shared Credentials File profile name. More information found [in the official AWS documentation](http://docs.aws.amazon.com/cli/latest/userguide/cli-chap-getting-started.html).| -| **`key_name`** | Existing AWS KeyPair name. Must match the KeyPair referenced in `key_file_path`.| -| **`key_file_path`** | Local file path to the SSH key selected as the `aws_keyname`.| -| **`region:`** | AWS region to which the systems will be deployed.| -| **`subnet_id`** | AWS Subnet to which the systems will be deployed. Must exist in your region.| +| Variable | Description | Default Value | +| ------------- |------------- |------------- | +| `aws_profile` | Identifies the AWS Shared Credentials File profile name. More information found [in the official AWS documentation](http://docs.aws.amazon.com/cli/latest/userguide/cli-chap-getting-started.html).| default | +| `region:` | AWS region to which the systems will be deployed.| us-east-1 | +| **`subnet_id`** | AWS Subnet to which the systems will be deployed. Must exist in your region.| | +| **`key_name`** | Existing AWS KeyPair name. Must match the KeyPair referenced in `key_file_path`.| | +| **`key_file_path`** | Local file path to the SSH key selected as the `aws_keyname`.| | #### OnCommand Cloud Manager Variables -| Variable | Description | -| ------------- |-------------| -| **`occm_email`**| The email address to register as the Cloud Admin for the new OnCommand Cloud Manager server.| -| **`occm_password`**| OnCommand Cloud Manager Admin password.| -| **`company_name`**| Your company name to which the OnCommand Cloud manager system will be registered.| -| `occm_amis`| This is a reference variable and does not need to be set. List of the OnCommand Cloud Manager AMIs per region.| +| Variable | Description | Default Value | +| ------------- |------------- |------------- | +| **`occm_email`**| The email address to register as the Cloud Admin for the new OnCommand Cloud Manager server.| | +| **`occm_password`**| OnCommand Cloud Manager Admin password.| | +| **`company_name`**| Your company name to which the OnCommand Cloud manager system will be registered.| | +| `occm_amis`| This is a reference variable and does not need to be set. List of the OnCommand Cloud Manager AMIs per region.| Automatically selected based on region | #### ONTAP Cloud for AWS -| Variable | Description | -| ------------- |-------------| -| **`ontap_name`**| New ONTAP Cloud Name.| -| **`ontap_password`**| New ONTAP Cloud password for Admin.| -| `ontap_size`| Size of the Aggregate: Pick One - 100GB, 500GB, 1TB, 2TB, 4TB, 8TB. Default = '1TB'.| -| `ontap_instance`| AWS Instance type for ONTAP Cloud instance. Note: must be a supported size for the selected license type". Default = 'm4.xlarge'.| -| `license_type`| ONTAP Cloud license type. Supported values are ['cot-explore-paygo', 'cot-standard-paygo', 'cot-premium-paygo']. Default value is 'cot-explore-paygo'| +| Variable | Description | Default Value | +| ------------- |------------- |------------- | +| `ontap_name`| New ONTAP Cloud Name.| demolab | +| `ontap_password`| New ONTAP Cloud password for Admin.| netapp123 | +| `ontap_size`| Size of the Aggregate: Pick One - 100GB, 500GB, 1TB, 2TB, 4TB, 8TB. | 500GB | +| `ontap_instance`| AWS Instance type for ONTAP Cloud instance. Note: must be a supported size for the selected license type". Default = 'm4.xlarge'.| m4.xlarge | +| `license_type`| ONTAP Cloud license type. Supported values are ['cot-explore-paygo', 'cot-standard-paygo', 'cot-premium-paygo']. | cot-explore-paygo | +| `write_speed`| Sets the ONTAP Cloud write speed. 'normal' is standard with high consistency guarantee, while 'high' will increase write performance at the risk of potential data loss in the event of a failure. | normal | + ### Terraform Configuration Files ``` ├── aws_standalone/ │ ├── files +│ │ ├── occm-ec2-role.json +│ │ ├── occm-role-policy.json +│ │ ├── solo.rb +│ │ ├── Berksfile │ ├── scripts │ │ ├── check_server_health.sh │ │ ├── bootstrap.sh @@ -102,7 +138,10 @@ _NOTE: properties in bold are required_ │ │ │ ├── occm │ │ │ │ ├── admin_credentials.json.tpl │ │ │ │ ├── ontap_credentials.json.tpl -│ ├── terraform.tfvars +│ ├── main.tf +│ ├── output.tf +│ ├── README.md +│ ├── variables.tf ``` #### Files @@ -110,11 +149,12 @@ _NOTE: properties in bold are required_ - `files/occm-ec2-role.json`: Default role model for IAM EC2 Role used by OnCommand Cloud manager - `files/occm-role-policy.json`: Creates a new IAM policy used by OnCommand Cloud Manager's IAM EC2 Role and sets valid permissions for the system. - `files/solo.rb`: Configures CHEF Solo defaults for bootstrapping purposes. +- `files/Berksfile`: Berkshelf configuration file to identify cookbooks and dependencies. #### Scripts --- - `scripts/check_server_health.sh`: Forces Terraform to wait for the OnCommand Cloud Manager system services to be fully up prior to provisioning. This solves a race condition where SSH responds faster than the services have time to complete first-boot. -- `scripts/bootstrap.sh`: Executes the installation of Git, downloads the Chef Client, Clones the CHEF cookbooks, and triggers the CHEF Solo command to self-bootstrap. +- `scripts/bootstrap.sh`: Executes the installation of Git, downloads the Chef Client and ChefDK, uses Berkshelf to package the CHEF cookbooks, and triggers the CHEF Solo command to self-bootstrap. #### Templates --- @@ -128,6 +168,7 @@ _NOTE: properties in bold are required_ Create a new file called `terraform.tfvars` to include the variable name and the value to which to assign. This file can be used to preserve the values of the Terraform variables but is explicitly not included in source code control as per the included .gitignore file. ``` +owner_name = "Jeremy Goodrum" aws_profile = "exosphere" key_name = "terraform" key_file_path = "~/Downloads/terraform.pem" @@ -149,25 +190,6 @@ This Terraform template requires the use of the [ONTAP Cloud CHEF Cookbook](gith #### Run_Lists and Attributes Once the OnCommand Cloud Manager has booted and passed the server_health tests, the remote provisioners will transfer the files and start the bootstap process. The current list of supported node attributes can be found at the [ONTAP Cloud CHEF Cookbook](github.com/exospheredata/netapp_ontap_cloud) repository. The values for these can be added or removed in the `create_ontap.json.tpl` file in the templates directory. -## Usage -### Before you begin -Verify your meet these requirements -- [Terraform v0.9.2+](https://www.terraform.io/downloads.html) installed on your local machine -- You have an active and valid AWS account with an Identity and Access Management user credentials. More information found [in the official AWS documentation](http://docs.aws.amazon.com/cli/latest/userguide/cli-chap-getting-started.html). -- You have registered for access to the OnCommand Cloud Manager and ONTAP Cloud AMI - - Simply go to each of the below links and register - - [OnCommand Cloud Manager](https://aws.amazon.com/marketplace/pp/B018REK8QG) - - [ONTAP Cloud for AWS](https://aws.amazon.com/marketplace/pp/B011KEZ734) - - -### Re-running the provisioning effort and changes -Since the ONTAP Cloud system can be added or removed outside of this infrastructure, the provisioner for this resource was moved to use the null_resource method and outside of the instance creation. This means that if you need to re-run the configuration, you will only need to `taint` the resource as such: -``` -terraform taint null_resource.ontap_cloud -``` - -The above command will force the system to run the provisioner once again. The process will idempodently execute the run_list provided in the `create_ontap.json.tpl` under recipes. - ## Contribute - Fork it - Create your feature branch (git checkout -b my-new-feature) diff --git a/aws_standalone/files/Berksfile b/aws_standalone/files/Berksfile new file mode 100644 index 0000000..bf523d7 --- /dev/null +++ b/aws_standalone/files/Berksfile @@ -0,0 +1,11 @@ +# Berksfile +# +# maintainer:: Exosphere Data, LLC +# maintainer_email:: chef@exospheredata.com +# +# Copyright:: 2017, Exosphere Data, LLC, All Rights Reserved. +# + +source 'https://supermarket.chef.io' + +cookbook 'netapp_ontap_cloud', git: 'https://github.com/exospheredata/netapp_ontap_cloud.git' diff --git a/aws_standalone/files/occm-role-policy.json b/aws_standalone/files/occm-role-policy.json index 8f6d790..a4b23d3 100644 --- a/aws_standalone/files/occm-role-policy.json +++ b/aws_standalone/files/occm-role-policy.json @@ -1,87 +1,112 @@ { - "Version": "2012-10-17", - "Statement": [ - { - "Effect": "Allow", - "Action": [ - "ec2:DescribeInstances", - "ec2:DescribeInstanceStatus", - "ec2:RunInstances", - "ec2:ModifyInstanceAttribute", - "ec2:DescribeRouteTables", - "ec2:DescribeImages", - "ec2:CreateTags", - "ec2:CreateVolume", - "ec2:DescribeVolumes", - "ec2:ModifyVolumeAttribute", - "ec2:DeleteVolume", - "ec2:CreateSecurityGroup", - "ec2:DeleteSecurityGroup", - "ec2:DescribeSecurityGroups", - "ec2:RevokeSecurityGroupEgress", - "ec2:AuthorizeSecurityGroupEgress", - "ec2:AuthorizeSecurityGroupIngress", - "ec2:CreateNetworkInterface", - "ec2:DescribeNetworkInterfaces", - "ec2:DeleteNetworkInterface", - "ec2:ModifyNetworkInterfaceAttribute", - "ec2:DescribeSubnets", - "ec2:DescribeVpcs", - "ec2:DescribeDhcpOptions", - "ec2:CreateSnapshot", - "ec2:DeleteSnapshot", - "ec2:DescribeSnapshots", - "ec2:GetConsoleOutput", - "ec2:DescribeKeyPairs", - "ec2:DescribeRegions", - "ec2:DeleteTags", - "ec2:DescribeTags", - "cloudformation:CreateStack", - "cloudformation:DeleteStack", - "cloudformation:DescribeStacks", - "cloudformation:DescribeStackEvents", - "cloudformation:ValidateTemplate", - "iam:PassRole", - "iam:CreateRole", - "iam:DeleteRole", - "iam:PutRolePolicy", - "iam:CreateInstanceProfile", - "iam:DeleteRolePolicy", - "iam:AddRoleToInstanceProfile", - "iam:RemoveRoleFromInstanceProfile", - "iam:DeleteInstanceProfile", - "kms:List*", - "kms:Describe*" - ], - "Resource": "*" - }, - { - "Effect": "Allow", - "Action": [ - "ec2:StartInstances", - "ec2:StopInstances", - "ec2:TerminateInstances", - "ec2:AttachVolume", - "ec2:DetachVolume" - ], - "Condition": { - "StringLike": { - "ec2:ResourceTag/WorkingEnvironment": "*" - } - }, - "Resource": [ - "arn:aws:ec2:*:*:instance/*" - ] - }, - { - "Effect": "Allow", - "Action": [ - "ec2:AttachVolume", - "ec2:DetachVolume" - ], - "Resource": [ - "arn:aws:ec2:*:*:volume/*" - ] - } - ] -} \ No newline at end of file + "Version": "2012-10-17", + "Statement": [{ + "Effect": "Allow", + "Action": [ + "iam:ListInstanceProfiles", + "iam:CreateRole", + "iam:DeleteRole", + "iam:PutRolePolicy", + "iam:CreateInstanceProfile", + "iam:DeleteRolePolicy", + "iam:AddRoleToInstanceProfile", + "iam:RemoveRoleFromInstanceProfile", + "iam:DeleteInstanceProfile", + "ec2:ModifyVolumeAttribute", + "sts:DecodeAuthorizationMessage", + "ec2:DescribeImages", + "ec2:DescribeRouteTables", + "ec2:DescribeInstances", + "iam:PassRole", + "ec2:DescribeInstanceStatus", + "ec2:RunInstances", + "ec2:ModifyInstanceAttribute", + "ec2:CreateTags", + "ec2:CreateVolume", + "ec2:DescribeVolumes", + "ec2:DeleteVolume", + "ec2:CreateSecurityGroup", + "ec2:DeleteSecurityGroup", + "ec2:DescribeSecurityGroups", + "ec2:RevokeSecurityGroupEgress", + "ec2:AuthorizeSecurityGroupEgress", + "ec2:AuthorizeSecurityGroupIngress", + "ec2:RevokeSecurityGroupIngress", + "ec2:CreateNetworkInterface", + "ec2:DescribeNetworkInterfaces", + "ec2:DeleteNetworkInterface", + "ec2:ModifyNetworkInterfaceAttribute", + "ec2:DescribeSubnets", + "ec2:DescribeVpcs", + "ec2:DescribeDhcpOptions", + "ec2:CreateSnapshot", + "ec2:DeleteSnapshot", + "ec2:DescribeSnapshots", + "ec2:StopInstances", + "ec2:GetConsoleOutput", + "ec2:DescribeKeyPairs", + "ec2:DescribeRegions", + "ec2:DeleteTags", + "ec2:DescribeTags", + "cloudformation:CreateStack", + "cloudformation:DeleteStack", + "cloudformation:DescribeStacks", + "cloudformation:DescribeStackEvents", + "cloudformation:ValidateTemplate", + "s3:GetObject", + "s3:ListBucket", + "s3:ListAllMyBuckets", + "s3:GetBucketTagging", + "s3:GetBucketLocation", + "s3:CreateBucket", + "kms:List*", + "kms:Describe*", + "ec2:AssociateIamInstanceProfile", + "ec2:DescribeIamInstanceProfileAssociations", + "ec2:DisassociateIamInstanceProfile" + ], + "Resource": "*" + }, + { + "Sid": "fabricPoolPolicy", + "Effect": "Allow", + "Action": [ + "s3:DeleteBucket", + "s3:GetLifecycleConfiguration", + "s3:PutLifecycleConfiguration", + "s3:PutBucketTagging", + "s3:ListBucketVersions" + ], + "Resource": [ + "arn:aws:s3:::fabric-pool*" + ] + }, + { + "Effect": "Allow", + "Action": [ + "ec2:StartInstances", + "ec2:TerminateInstances", + "ec2:AttachVolume", + "ec2:DetachVolume" + ], + "Condition": { + "StringLike": { + "ec2:ResourceTag/WorkingEnvironment": "*" + } + }, + "Resource": [ + "arn:aws:ec2:*:*:instance/*" + ] + }, + { + "Effect": "Allow", + "Action": [ + "ec2:AttachVolume", + "ec2:DetachVolume" + ], + "Resource": [ + "arn:aws:ec2:*:*:volume/*" + ] + } + ] +} diff --git a/aws_standalone/main.tf b/aws_standalone/main.tf index fb38e33..841f978 100644 --- a/aws_standalone/main.tf +++ b/aws_standalone/main.tf @@ -8,18 +8,18 @@ Create a new IAM Role that can be assigned to the OnCommand Cloud Manager EC2 instance and provide access controls to the connected AWS account. */ resource "aws_iam_role" "occm_ec2_role" { - name = "occm_ec2_role" - description = "Grants access to services required by NetApp's OnCommand Cloud Manager" - assume_role_policy = "${file("files/occm-ec2-role.json")}" + name = "occm_instance_profile_${replace(lower(var.owner_name)," ","_")}" + description = "Grants access to services required by NetApp's OnCommand Cloud Manager" + assume_role_policy = "${file("${path.module}/files/occm-ec2-role.json")}" } /* EC2 Instance Profile based on the provided role */ resource "aws_iam_instance_profile" "occm_instance_profile" { - name = "occm_instance_profile" - role = "${aws_iam_role.occm_ec2_role.id}" - depends_on = [ + name = "occm_instance_profile_${replace(lower(var.owner_name)," ","_")}" + role = "${aws_iam_role.occm_ec2_role.id}" + depends_on = [ "aws_iam_role.occm_ec2_role" ] } @@ -27,14 +27,14 @@ resource "aws_iam_instance_profile" "occm_instance_profile" { /* Default policy document for privileges requireed by OnCommand Cloud Manager */ -resource "aws_iam_role_policy" "role_policy" { - name = "occm_instance_role_policy" +resource "aws_iam_role_policy" "occm_role_policy" { + name = "occm_instance_profile_${replace(lower(var.owner_name)," ","_")}" role = "${aws_iam_role.occm_ec2_role.id}" - depends_on = [ + depends_on = [ "aws_iam_role.occm_ec2_role" ] - policy = "${file("files/occm-role-policy.json")}" + policy = "${file("${path.module}/files/occm-role-policy.json")}" } /* @@ -42,9 +42,9 @@ New Security group granting Web access and SSH access to the OnCommand Cloud Man allow all outgoing traffic. */ resource "aws_security_group" "occm_access" { - name = "occm_access" - description = "Allow all inbound traffic on ports 80, 443, and 22." - vpc_id = "${data.aws_subnet.selected.vpc_id}" + name = "occm_access_${replace(lower(var.owner_name)," ","_")}" + description = "Allow all inbound traffic on ports 80, 443, and 22." + vpc_id = "${data.aws_subnet.selected.vpc_id}" ingress { from_port = 80 @@ -76,7 +76,8 @@ resource "aws_security_group" "occm_access" { tags { Name = "OnCommand Cloud Manager Access", - Created_By = "Terraform" + "Deployed Using" = "Terraform", + "Designed by" = "www.exospheredata.com" } } @@ -86,25 +87,25 @@ Launch a new AWS Marketplace instance of Netapp's OnCommand Cloud Manager and as created EC2 Instance Profile. */ resource "aws_instance" "OCCM" { - ami = "${lookup(var.occm_amis, var.region)}" - instance_type = "t2.medium" - subnet_id = "${data.aws_subnet.selected.id}" - vpc_security_group_ids = ["${aws_security_group.occm_access.id}"] - key_name = "${var.key_name}" + depends_on = [ + "aws_iam_role_policy.occm_role_policy", + "aws_iam_role.occm_ec2_role", + "aws_security_group.occm_access" + ] + ami = "${lookup(var.occm_amis, var.region)}" + instance_type = "t2.medium" + subnet_id = "${data.aws_subnet.selected.id}" + vpc_security_group_ids = ["${aws_security_group.occm_access.id}"] + key_name = "${var.key_name}" associate_public_ip_address = "true" - iam_instance_profile = "${aws_iam_instance_profile.occm_instance_profile.id}" + iam_instance_profile = "${aws_iam_instance_profile.occm_instance_profile.id}" tags { Name = "OnCommand Cloud Manager", + "Owned By" = "${var.owner_name}", "Deployed Using" = "Terraform", "Provisioned Using" = "CHEF", "Designed by" = "www.exospheredata.com" } - depends_on = [ - "aws_iam_role_policy.role_policy", - "aws_iam_role.occm_ec2_role", - "aws_iam_role_policy.role_policy", - "aws_security_group.occm_access" - ] /* Establish a connection to the OnCommand Cloud Manager system using @@ -123,31 +124,21 @@ resource "aws_instance" "OCCM" { to SSH long before the service is online. */ provisioner "remote-exec" { - inline = [ - "mkdir -p /tmp" - ] + inline = [ + "mkdir -p /tmp/" + ] } provisioner "file" { - source = "./scripts/check_server_health.sh" + source = "${path.module}/scripts/check_server_health.sh" destination = "/tmp/check_server_health.sh" } provisioner "remote-exec" { - inline = [ - "chmod +x /tmp/check_server_health.sh", - "/tmp/check_server_health.sh", - "echo The Instance is ready to be provisioned" - ] + inline = [ + "chmod +x /tmp/check_server_health.sh", + "/tmp/check_server_health.sh", + "echo The Instance is ready to be provisioned" + ] } -} - -resource "null_resource" "ontap_cloud" { - depends_on = [ - "aws_iam_role_policy.role_policy", - "aws_iam_role.occm_ec2_role", - "aws_iam_role_policy.role_policy", - "aws_instance.OCCM" - ] - /* Establish a connection to the OnCommand Cloud Manager system using ssh and the private key file provided. @@ -163,81 +154,156 @@ resource "null_resource" "ontap_cloud" { private_key = "${file("${var.key_file_path}")}" timeout = "60m" } + /* + =========== + These steps will only be run when the terraform destroy command is sent + =========== + The following will only run on a destroy of the environment and needs to be run + to properly destroy the ONTAP Cloud instance. + */ provisioner "remote-exec" { - inline = [ - "rm -rf /tmp/chef", - "mkdir -p /tmp/chef/data_bags/occm" - ] + when = "destroy" + inline = [ + "rm -rf /tmp/chef", + "rm -rf /tmp/cookbooks.tar.gz", + "mkdir -p /tmp/chef/data_bags/occm", + "mkdir -p /tmp/ontap_cloud_cookbooks" + ] } + + /* + Create archive of the cookbooks and dependencies. Upon creation, upload the file to the server and then remove the local copy. + + the path_root variable tells the system to look at the top level of the modules and not in the module path. + */ provisioner "file" { - source = "./files/solo.rb" - destination = "/tmp/chef/solo.rb" + when = "destroy" + source = "${path.module}/files/Berksfile" + destination = "/tmp/ontap_cloud_cookbooks/Berksfile" } + + /* + Send all interpolated files to the remote server + */ provisioner "file" { - source = "./scripts/bootstrap.sh" - destination = "/tmp/chef/bootstrap.sh" + when = "destroy" + source = "${path.module}/files/solo.rb" + destination = "/tmp/chef/solo.rb" } provisioner "file" { - content = "${data.template_file.create_ontap.rendered}" + when = "destroy" + content = "${data.template_file.destroy_ontap.rendered}" destination = "/tmp/chef/dna.json" } + provisioner "file" { + when = "destroy" + source = "${path.module}/scripts/bootstrap.sh" + destination = "/tmp/chef/bootstrap.sh" + } /* Setup the CHEF Data bags */ provisioner "file" { + when = "destroy" content = "${data.template_file.admin_credentials.rendered}" destination = "/tmp/chef/data_bags/occm/admin_credentials.json" } - provisioner "file" { - content = "${data.template_file.ontap_credentials.rendered}" - destination = "/tmp/chef/data_bags/occm/${var.ontap_name}.json" - } + /* + Execute Bootstrap script to apply CHEF configuration and setup. + */ provisioner "remote-exec" { + when = "destroy" inline = [ "chmod +x /tmp/chef/bootstrap.sh", "sudo /tmp/chef/bootstrap.sh", ] } +} + +/* +Deploy ONTAP Cloud system and configuration via CHEF +*/ +resource "null_resource" "ontap_cloud" { + triggers { + occm_id = "${aws_instance.OCCM.id}", + converge = "${var.converge}" + } + depends_on = [ + "aws_iam_role_policy.occm_role_policy", + "aws_iam_role.occm_ec2_role", + "aws_instance.OCCM" + ] /* - The following will only run on a destroy of the environment and needs to be run - to properly destroy the ONTAP Cloud instance. + Establish a connection to the OnCommand Cloud Manager system using ssh and the private + key file provided. + + The deployment process of an ONTAP Cloud system can take upwards of 25+ minutes depending + on the state of the AWS Region. We are setting a 60 minute timeout on this connection + due to this potential length. + */ + connection { + host = "${aws_instance.OCCM.0.public_ip}" + type = "ssh" + user = "ec2-user" # OCCM Default username in AWS EC2 instances + private_key = "${file("${var.key_file_path}")}" + timeout = "60m" + } + + /* + =========== + These steps will only be run when the terraform apply command is sent + =========== + */ provisioner "remote-exec" { - when = "destroy" inline = [ "rm -rf /tmp/chef", - "mkdir -p /tmp/chef/data_bags/occm" + "rm -rf /tmp/ontap_cloud_cookbooks", + "mkdir -p /tmp/chef/data_bags/occm", + "mkdir -p /tmp/ontap_cloud_cookbooks" ] } + /* - Setup the CHEF Data bags + Send all interpolated files to the remote server */ provisioner "file" { - when = "destroy" - content = "${data.template_file.admin_credentials.rendered}" - destination = "/tmp/chef/data_bags/occm/admin_credentials.json" + source = "${path.module}/files/Berksfile" + destination = "/tmp/ontap_cloud_cookbooks/Berksfile" } provisioner "file" { - when = "destroy" - source = "./files/solo.rb" + source = "${path.module}/files/solo.rb" destination = "/tmp/chef/solo.rb" } provisioner "file" { - when = "destroy" - source = "./scripts/bootstrap.sh" + content = "${data.template_file.create_ontap.rendered}" + destination = "/tmp/chef/dna.json" + } + provisioner "file" { + source = "${path.module}/scripts/bootstrap.sh" destination = "/tmp/chef/bootstrap.sh" } + + /* + Setup the CHEF Data bags + */ provisioner "file" { - when = "destroy" - content = "${data.template_file.destroy_ontap.rendered}" - destination = "/tmp/chef/dna.json" + content = "${data.template_file.admin_credentials.rendered}" + destination = "/tmp/chef/data_bags/occm/admin_credentials.json" + } + provisioner "file" { + content = "${data.template_file.ontap_credentials.rendered}" + destination = "/tmp/chef/data_bags/occm/${var.ontap_name}.json" } + + /* + Execute Bootstrap script to apply CHEF configuration and setup. + */ provisioner "remote-exec" { - when = "destroy" inline = [ "chmod +x /tmp/chef/bootstrap.sh", "sudo /tmp/chef/bootstrap.sh", diff --git a/aws_standalone/output.tf b/aws_standalone/output.tf index b168a84..8a8446c 100644 --- a/aws_standalone/output.tf +++ b/aws_standalone/output.tf @@ -1,9 +1,19 @@ /* Output Variables */ -output "CloudManager-Public-Url" { +output "cloudmanager_public_url" { value = "https://${aws_instance.OCCM.0.public_ip}/occmui/" } -output "CloudManager-Private-Url" { + +output "cloudmanager_public_ip" { + value = "${aws_instance.OCCM.0.public_ip}" +} + + +output "cloudmanager_private_url" { value = "https://${aws_instance.OCCM.0.private_ip}/occmui/" } + +output "cloudmanager_private_ip" { + value = "${aws_instance.OCCM.0.private_ip}" +} diff --git a/aws_standalone/scripts/bootstrap.sh b/aws_standalone/scripts/bootstrap.sh index 6d6d822..2ce8238 100644 --- a/aws_standalone/scripts/bootstrap.sh +++ b/aws_standalone/scripts/bootstrap.sh @@ -14,6 +14,17 @@ if ! exists chef-solo; then curl -L https://www.opscode.com/chef/install.sh | bash fi +if ! exists chef; then + wget -nv https://packages.chef.io/files/stable/chefdk/1.5.0/el/7/chefdk-1.5.0-1.el7.x86_64.rpm + yum install -y chefdk-1.5.0-1.el7.x86_64.rpm +fi + +location=${PWD} +cd /tmp/ontap_cloud_cookbooks && \ + berks package --berksfile=Berksfile && \ + mv cookbooks-*.tar.gz /tmp/cookbooks.tar.gz +cd $location + echo "Remove existing chef files and configurations" rm -rf /var/chef/cookbooks /var/chef/data_bags /var/chef/solo.rb /var/chef/dna.json @@ -21,20 +32,8 @@ echo "Setup the repositories" mkdir -p /var/chef/cookbooks /var/chef/data_bags chmod -R 777 /var/chef -location=${PWD} -cd /var/chef/cookbooks -git clone https://github.com/exospheredata/netapp_ontap_cloud.git > /dev/null 2>&1 -cd netapp_ontap_cloud - -echo 'Clean up files not required for CHEF actions' -rm -rf tasks -rm -rf test -rm -rf spec -rm -rf terraform -cd $location - mv /tmp/chef/* /var/chef/ rm -rf /tmp/chef echo "Start the CHEF Client and configuration bootstrap" -`which chef-solo` -c /var/chef/solo.rb -j /var/chef/dna.json -L /var/chef/client.log -l info +`which chef-solo` --recipe-url /tmp/cookbooks.tar.gz -c /var/chef/solo.rb -j /var/chef/dna.json -l info diff --git a/aws_standalone/templates.tf b/aws_standalone/templates.tf index 8252428..5386acb 100644 --- a/aws_standalone/templates.tf +++ b/aws_standalone/templates.tf @@ -5,24 +5,33 @@ data "aws_subnet" "selected" { id = "${var.subnet_id}" } +/* +Create the data_bag object to contain the OnCommand Cloud Manager credentials +*/ data "template_file" "admin_credentials" { - template = "${file("templates/data_bags/occm/admin_credentials.json.tpl")}" + template = "${file("${path.module}/templates/data_bags/occm/admin_credentials.json.tpl")}" vars { occm_email = "${var.occm_email}" occm_password = "${var.occm_password}" } } +/* +Create the data_bag object to contain the ONTAP Cloud credentials +*/ data "template_file" "ontap_credentials" { - template = "${file("templates/data_bags/occm/ontap_credentials.json.tpl")}" + template = "${file("${path.module}/templates/data_bags/occm/ontap_credentials.json.tpl")}" vars { ontap_name = "${var.ontap_name}" svm_password = "${var.ontap_password}" } } +/* +Create the JSON attributes file for use when creating ONTAP Cloud systems via CHEF +*/ data "template_file" "create_ontap" { - template = "${file("templates/create_ontap.json.tpl")}" + template = "${file("${path.module}/templates/create_ontap.json.tpl")}" vars { company_name = "${var.company_name}" ontap_name = "${var.ontap_name}" @@ -32,11 +41,15 @@ data "template_file" "create_ontap" { vpc_id = "${data.aws_subnet.selected.vpc_id}" region = "${var.region}" subnet_id = "${data.aws_subnet.selected.id}" + write_speed = "${lower(var.ontap_write_speed)}" } } +/* +Create the JSON attributes file for use when deleting ONTAP Cloud systems via CHEF +*/ data "template_file" "destroy_ontap" { - template = "${file("templates/destroy_ontap.json.tpl")}" + template = "${file("${path.module}/templates/destroy_ontap.json.tpl")}" vars { ontap_name = "${var.ontap_name}" } diff --git a/aws_standalone/templates/create_ontap.json.tpl b/aws_standalone/templates/create_ontap.json.tpl index 65c8b21..f0eda3b 100644 --- a/aws_standalone/templates/create_ontap.json.tpl +++ b/aws_standalone/templates/create_ontap.json.tpl @@ -8,7 +8,8 @@ "name": "${ontap_name}", "size": "${ontap_size}", "instance_type": "${ontap_instance}", - "license_type": "${license_type}" + "license_type": "${license_type}", + "write_speed": "${write_speed}" } }, "aws": { diff --git a/aws_standalone/variables.tf b/aws_standalone/variables.tf index 91055a1..6fe83e5 100644 --- a/aws_standalone/variables.tf +++ b/aws_standalone/variables.tf @@ -1,5 +1,8 @@ -variable "aws_profile" { - description = "The aws credentials file profile name." +/* +Mandatory Variables +*/ +variable "owner_name" { + description = "Your Username to identify your infrastructure" } variable "key_name" { @@ -10,66 +13,95 @@ variable "key_file_path" { description = "Location of the local private key file for the EC2 instance." } +variable "converge" { + description = "When set to 'true', the configuration resources will all re-apply to their hosts." + default = "false" +} +/* +AWS specific +*/ +variable "aws_profile" { + description = "The aws credentials file profile name." + default = "default" +} + variable "region" { description = "AWS region to which the systems will be deployed." + default = "us-east-1" } variable "subnet_id" { description = "AWS Subnet to which the systems will be deployed. Must exist in your region." } +/* +OnCommand Cloud Manager specific +*/ variable "occm_email" { description = "Email address (username) for OnCommand Cloud Manager instance" + default = "netapp@peritus.lab" } variable "occm_password" { description = "Administrative password for OnCommand Cloud Manager instance" + default = "peritus" } variable "company_name" { description = "Your company name to which the OnCommand Cloud manager system will be registered" + default = "Peritus Lab" } variable "occm_amis" { type = "map" description = "List of the OnCommand Cloud Manager AMIs per region." default = { - "ap-south-1" = "ami-08443567" - "eu-west-2" = "ami-6f73660b" - "eu-west-1" = "ami-8dd7f2eb" - "ap-northeast-2" = "ami-1e61b070" - "ap-northeast-1" = "ami-21abeb46" - "sa-east-1" = "ami-b0c3a7dc" - "ca-central-1" = "ami-f8b8059c" - "ap-southeast-1" = "ami-432e9a20" - "ap-southeast-2" = "ami-d8aaacbb" - "eu-central-1" = "ami-b7c20ad8" - "us-east-1" = "ami-6c65a27a" - "us-east-2" = "ami-4811342d" - "us-west-1" = "ami-e63a6686" - "us-west-2" = "ami-68e96c08" + "ap-south-1" = "ami-c2bdc2ad" + "eu-west-2" = "ami-fba8bf9f" + "eu-west-1" = "ami-bf9986d9" + "ap-northeast-2" = "ami-2e8d5240" + "ap-northeast-1" = "ami-8e979ee9" + "sa-east-1" = "ami-982843f4" + "ca-central-1" = "ami-38e9565c" + "ap-southeast-1" = "ami-b89c1edb" + "ap-southeast-2" = "ami-cb3322a8" + "eu-central-1" = "ami-975bfff8" + "us-east-1" = "ami-392c0a2f" + "us-east-2" = "ami-98a98ffd" + "us-west-1" = "ami-379ebc57" + "us-west-2" = "ami-0258537b" } } +/* +ONTAP Cloud specific +*/ variable "ontap_name" { description = "New ONTAP Cloud Name" + default = "demolab" } variable "ontap_password" { description = "New ONTAP Cloud password for Admin" + default = "netapp123" } variable "ontap_size" { description = "Size of the Aggregate: Pick One - 100GB, 500GB, 1TB, 2TB, 4TB, 8TB" - default = "1TB" + default = "500GB" } variable "ontap_instance" { description = "AWS Instance type for ONTAP Cloud instance. If not set, the default is 'm4.xlarge'. Note: must be a supported size for the selected license type" - default = "m4.xlarge" + default = "m4.xlarge" } variable "license_type" { description = "ONTAP Cloud license type. Supported values are [cot-explore-paygo, cot-standard-paygo, cot-premium-paygo]. Default value is cot-explore-paygo" - default = "cot-explore-paygo" + default = "cot-explore-paygo" +} + +variable "ontap_write_speed" { + description = "Sets the ONTAP Cloud write speed. 'Normal' is standard with high consistency guarantee, while 'high' will increase write performance at the risk of potential data loss in the event of a failure." + default = "normal" } diff --git a/aws_standalone_full/README.md b/aws_standalone_full/README.md index 7284b7e..b8b013d 100644 --- a/aws_standalone_full/README.md +++ b/aws_standalone_full/README.md @@ -13,21 +13,14 @@ _Note: On `terraform destroy`, the associated ONTAP Cloud system deployed will b - [ONTAP Cloud charges and AWS fees](#ontap-cloud-charges-and-aws-fees) - [NetApp and Amazon Marketplace registration](#netapp-and-amazon-marketplace-registration) - [Tools and versions](#tools-and-versions) - - [Resources](#resources) - - [Variables](#variables) - - [AWS Variables](#aws-variables) - - [OnCommand Cloud Manager Variables](#oncommand-cloud-manager-variables) - - [ONTAP Cloud for AWS](#ontap-cloud-for-aws) - - [Terraform Configuration Files](#terraform-configuration-files) - - [Files](#files) - - [Scripts](#scripts) - - [Templates](#templates) - - [Default Variable Values](#default-variable-values) - - [CHEF Solo integration](#chef-solo-integration) - - [Run_Lists and Attributes](#run_lists-and-attributes) - [Usage](#usage) - [Before you begin](#before-you-begin) + - [Terraform Commands](#terraform-commands) - [Re-running the provisioning effort and changes](#re-running-the-provisioning-effort-and-changes) +- [Resources](#resources) +- [Variables](#variables) + - [Terraform Configuration Files](#terraform-configuration-files) + - [CHEF Solo integration](#chef-solo-integration) - [Contribute](#contribute) - [License & Authors](#license-&-authors) @@ -40,8 +33,8 @@ This Terraform template will deploy cloud instances and resources into your Amaz ### NetApp and Amazon Marketplace registration Prior running this template, you will need to ensure that your AWS account has subscribed to the official ONTAP Cloud for AWS and OnCommand Cloud Manager images: -* Visit the [official page for OnCommand Cloud Manager in the AWS Marketplace](https://aws.amazon.com/marketplace/pp/B018REK8QG]) for more information. -* Visit the [official page for ONTAP Cloud in the AWS Marketplace](https://aws.amazon.com/marketplace/pp/B011KEZ734]) for more information. +* Visit the [official page for OnCommand Cloud Manager in the AWS Marketplace](https://aws.amazon.com/marketplace/pp/B018REK8QG) for more information. +* Visit the [official page for ONTAP Cloud in the AWS Marketplace](https://aws.amazon.com/marketplace/pp/B011KEZ734) for more information. ### Tools and versions @@ -49,7 +42,38 @@ Prior running this template, you will need to ensure that your AWS account has s - Chef Solo 12.5+ - Terraform v0.9.2+ -### Resources +## Usage +### Before you begin +--- +Verify your meet these requirements +- [Terraform v0.9.2+](https://www.terraform.io/downloads.html) installed on your local machine +- You have an active and valid AWS account with an Identity and Access Management user credentials. More information found [in the official AWS documentation](http://docs.aws.amazon.com/cli/latest/userguide/cli-chap-getting-started.html). +- You have registered for access to the OnCommand Cloud Manager and ONTAP Cloud AMI
Simply go to each of the below links and register + - [OnCommand Cloud Manager](https://aws.amazon.com/marketplace/pp/B018REK8QG) + - [ONTAP Cloud for AWS](https://aws.amazon.com/marketplace/pp/B011KEZ734) + +### Terraform Commands +--- +- `terraform plan`: Execute the planned output to verify the current desired infrastructure state +- `terraform apply`: Run the configuration using the supplied variables. +- `terraform destroy`: Execute the destruction sequence to remove all resources. +- `terraform taint`: Mark a resource for recreation. All child dependent resources will be reset and redeployed as well. + +### Re-running the provisioning effort and changes +--- +All host configurations have been place in custom resources using the Terraform `null_resource` operator. This allows for easy re-application of templates and services. All of the configurations are designed to set the desired state and only update when the existing configuration does not match. Only if a specific resource is marked for destruction, will the destroy triggers enact. + +#### Configuration Resources +--- +- `null_resource.ontap_cloud`: Manages the configuration of OnCommand Cloud Manager and the ONTAP Cloud system + +#### Redeploying an instance +--- +If you mark an instance for redeployment, the associated configuration resource will be marked as well. The deletion of a host will trigger clean-up resources if defined. + +Since the ONTAP Cloud system can be added or removed outside of this infrastructure, the process to reset the OnCommand Cloud Manager host will delete the existing ONTAP Cloud system and force a redeployment. This action will also cause the Peritus Test Case host to rerun its configuration to ensure that everything connects. + +## Resources This Terraform will create the following resources: - AWS Identity Access Management (IAM) Policy - AWS Identity Access Management (IAM) Profile @@ -60,41 +84,54 @@ This Terraform will create the following resources: - AWS Virtual Private Cloud (VPC) Route Table and Route to IGW - AWS Virtual Private Cloud (VPC) Security Group - AWS EC2 Instance using OnCommand Cloud Manager marketplace image -- NetApp ONTAP Cloud for AWS instance with 1TB of storage +- NetApp ONTAP Cloud for AWS instance with 500GB of storage -### Variables +## Variables _NOTE: properties in bold are required_ +#### Configuration Variables +| Variable | Description | Default Value | +| ------------- |------------- |------------- | +| **`owner_name`** | Your Username to identify your infrastructure. | | +| `converge` | Setting this variable on subsquent runs will force a reload of the configuration and re-apply the configurations. Changing this value will notify the provisioning resources to reconverge their configurations. You can override the value from the command line by running `terraform apply -var converge=true`

_Note: Once changed, the value is preserved so the next time the `terraform apply` command is run, the value will revert to the default._| false | + #### AWS Variables -| Variable | Description | -| ------------- |-------------| -| **`aws_profile`** | Identifies the AWS Shared Credentials File profile name. More information found [in the official AWS documentation](http://docs.aws.amazon.com/cli/latest/userguide/cli-chap-getting-started.html).| -| **`key_name`** | Existing AWS KeyPair name. Must match the KeyPair referenced in `key_file_path`.| -| **`key_file_path`** | Local file path to the SSH key selected as the `aws_keyname`.| -| **`region:`** | AWS region to which the systems will be deployed.| +| Variable | Description | Default Value | +| ------------- |------------- |------------- | +| `aws_profile` | Identifies the AWS Shared Credentials File profile name. More information found [in the official AWS documentation](http://docs.aws.amazon.com/cli/latest/userguide/cli-chap-getting-started.html).| default | +| `region:` | AWS region to which the systems will be deployed.| us-east-1 | +| `vpc_cidr` | CIDR notation for the new VPC. | 10.100.0.0/16 | +| **`key_name`** | Existing AWS KeyPair name. Must match the KeyPair referenced in `key_file_path`.| | +| **`key_file_path`** | Local file path to the SSH key selected as the `aws_keyname`.| | #### OnCommand Cloud Manager Variables -| Variable | Description | -| ------------- |-------------| -| **`occm_email`**| The email address to register as the Cloud Admin for the new OnCommand Cloud Manager server.| -| **`occm_password`**| OnCommand Cloud Manager Admin password.| -| **`company_name`**| Your company name to which the OnCommand Cloud manager system will be registered.| -| `occm_amis`| This is a reference variable and does not need to be set. List of the OnCommand Cloud Manager AMIs per region.| +| Variable | Description | Default Value | +| ------------- |------------- |------------- | +| **`occm_email`**| The email address to register as the Cloud Admin for the new OnCommand Cloud Manager server.| | +| **`occm_password`**| OnCommand Cloud Manager Admin password.| | +| **`company_name`**| Your company name to which the OnCommand Cloud manager system will be registered.| | +| `occm_amis`| This is a reference variable and does not need to be set. List of the OnCommand Cloud Manager AMIs per region.| Automatically selected based on region | #### ONTAP Cloud for AWS -| Variable | Description | -| ------------- |-------------| -| **`ontap_name`**| New ONTAP Cloud Name.| -| **`ontap_password`**| New ONTAP Cloud password for Admin.| -| `ontap_size`| Size of the Aggregate: Pick One - 100GB, 500GB, 1TB, 2TB, 4TB, 8TB. Default = '1TB'.| -| `ontap_instance`| AWS Instance type for ONTAP Cloud instance. Note: must be a supported size for the selected license type". Default = 'm4.xlarge'.| -| `license_type`| ONTAP Cloud license type. Supported values are ['cot-explore-paygo', 'cot-standard-paygo', 'cot-premium-paygo']. Default value is 'cot-explore-paygo'| +| Variable | Description | Default Value | +| ------------- |------------- |------------- | +| `ontap_name`| New ONTAP Cloud Name.| demolab | +| `ontap_password`| New ONTAP Cloud password for Admin.| netapp123 | +| `ontap_size`| Size of the Aggregate: Pick One - 100GB, 500GB, 1TB, 2TB, 4TB, 8TB. | 500GB | +| `ontap_instance`| AWS Instance type for ONTAP Cloud instance. Note: must be a supported size for the selected license type". Default = 'm4.xlarge'.| m4.xlarge | +| `license_type`| ONTAP Cloud license type. Supported values are ['cot-explore-paygo', 'cot-standard-paygo', 'cot-premium-paygo']. | cot-explore-paygo | +| `write_speed`| Sets the ONTAP Cloud write speed. 'normal' is standard with high consistency guarantee, while 'high' will increase write performance at the risk of potential data loss in the event of a failure. | normal | + ### Terraform Configuration Files ``` ├── aws_standalone/ │ ├── files +│ │ ├── occm-ec2-role.json +│ │ ├── occm-role-policy.json +│ │ ├── solo.rb +│ │ ├── Berksfile │ ├── scripts │ │ ├── check_server_health.sh │ │ ├── bootstrap.sh @@ -105,7 +142,10 @@ _NOTE: properties in bold are required_ │ │ │ ├── occm │ │ │ │ ├── admin_credentials.json.tpl │ │ │ │ ├── ontap_credentials.json.tpl -│ ├── terraform.tfvars +│ ├── main.tf +│ ├── output.tf +│ ├── README.md +│ ├── variables.tf ``` #### Files @@ -113,11 +153,12 @@ _NOTE: properties in bold are required_ - `files/occm-ec2-role.json`: Default role model for IAM EC2 Role used by OnCommand Cloud manager - `files/occm-role-policy.json`: Creates a new IAM policy used by OnCommand Cloud Manager's IAM EC2 Role and sets valid permissions for the system. - `files/solo.rb`: Configures CHEF Solo defaults for bootstrapping purposes. +- `files/Berksfile`: Berkshelf configuration file to identify cookbooks and dependencies. #### Scripts --- - `scripts/check_server_health.sh`: Forces Terraform to wait for the OnCommand Cloud Manager system services to be fully up prior to provisioning. This solves a race condition where SSH responds faster than the services have time to complete first-boot. -- `scripts/bootstrap.sh`: Executes the installation of Git, downloads the Chef Client, Clones the CHEF cookbooks, and triggers the CHEF Solo command to self-bootstrap. +- `scripts/bootstrap.sh`: Executes the installation of Git, downloads the Chef Client and ChefDK, uses Berkshelf to package the CHEF cookbooks, and triggers the CHEF Solo command to self-bootstrap. #### Templates --- @@ -131,18 +172,10 @@ _NOTE: properties in bold are required_ Create a new file called `terraform.tfvars` to include the variable name and the value to which to assign. This file can be used to preserve the values of the Terraform variables but is explicitly not included in source code control as per the included .gitignore file. ``` +owner_name = "Jeremy Goodrum" aws_profile = "exosphere" key_name = "terraform" key_file_path = "~/Downloads/terraform.pem" - -region = "us-east-1" - -occm_email = "admin@test.lab" -occm_password = "Netapp123" -company_name = "exospheredata" - -ontap_name = "demolab" -ontap_password = "Netapp123" ``` ### CHEF Solo integration @@ -151,25 +184,6 @@ This Terraform template requires the use of the [ONTAP Cloud CHEF Cookbook](gith #### Run_Lists and Attributes Once the OnCommand Cloud Manager has booted and passed the server_health tests, the remote provisioners will transfer the files and start the bootstap process. The current list of supported node attributes can be found at the [ONTAP Cloud CHEF Cookbook](github.com/exospheredata/netapp_ontap_cloud) repository. The values for these can be added or removed in the `create_ontap.json.tpl` file in the templates directory. -## Usage -### Before you begin -Verify your meet these requirements -- [Terraform v0.9.2+](https://www.terraform.io/downloads.html) installed on your local machine -- You have an active and valid AWS account with an Identity and Access Management user credentials. More information found [in the official AWS documentation](http://docs.aws.amazon.com/cli/latest/userguide/cli-chap-getting-started.html). -- You have registered for access to the OnCommand Cloud Manager and ONTAP Cloud AMI - - Simply go to each of the below links and register - - [OnCommand Cloud Manager](https://aws.amazon.com/marketplace/pp/B018REK8QG) - - [ONTAP Cloud for AWS](https://aws.amazon.com/marketplace/pp/B011KEZ734) - - -### Re-running the provisioning effort and changes -Since the ONTAP Cloud system can be added or removed outside of this infrastructure, the provisioner for this resource was moved to use the null_resource method and outside of the instance creation. This means that if you need to re-run the configuration, you will only need to `taint` the resource as such: -``` -terraform taint null_resource.ontap_cloud -``` - -The above command will force the system to run the provisioner once again. The process will idempodently execute the run_list provided in the `create_ontap.json.tpl` under recipes. - ## Contribute - Fork it - Create your feature branch (git checkout -b my-new-feature) diff --git a/aws_standalone_full/files/Berksfile b/aws_standalone_full/files/Berksfile new file mode 100644 index 0000000..bf523d7 --- /dev/null +++ b/aws_standalone_full/files/Berksfile @@ -0,0 +1,11 @@ +# Berksfile +# +# maintainer:: Exosphere Data, LLC +# maintainer_email:: chef@exospheredata.com +# +# Copyright:: 2017, Exosphere Data, LLC, All Rights Reserved. +# + +source 'https://supermarket.chef.io' + +cookbook 'netapp_ontap_cloud', git: 'https://github.com/exospheredata/netapp_ontap_cloud.git' diff --git a/aws_standalone_full/files/occm-role-policy.json b/aws_standalone_full/files/occm-role-policy.json index 8f6d790..a4b23d3 100644 --- a/aws_standalone_full/files/occm-role-policy.json +++ b/aws_standalone_full/files/occm-role-policy.json @@ -1,87 +1,112 @@ { - "Version": "2012-10-17", - "Statement": [ - { - "Effect": "Allow", - "Action": [ - "ec2:DescribeInstances", - "ec2:DescribeInstanceStatus", - "ec2:RunInstances", - "ec2:ModifyInstanceAttribute", - "ec2:DescribeRouteTables", - "ec2:DescribeImages", - "ec2:CreateTags", - "ec2:CreateVolume", - "ec2:DescribeVolumes", - "ec2:ModifyVolumeAttribute", - "ec2:DeleteVolume", - "ec2:CreateSecurityGroup", - "ec2:DeleteSecurityGroup", - "ec2:DescribeSecurityGroups", - "ec2:RevokeSecurityGroupEgress", - "ec2:AuthorizeSecurityGroupEgress", - "ec2:AuthorizeSecurityGroupIngress", - "ec2:CreateNetworkInterface", - "ec2:DescribeNetworkInterfaces", - "ec2:DeleteNetworkInterface", - "ec2:ModifyNetworkInterfaceAttribute", - "ec2:DescribeSubnets", - "ec2:DescribeVpcs", - "ec2:DescribeDhcpOptions", - "ec2:CreateSnapshot", - "ec2:DeleteSnapshot", - "ec2:DescribeSnapshots", - "ec2:GetConsoleOutput", - "ec2:DescribeKeyPairs", - "ec2:DescribeRegions", - "ec2:DeleteTags", - "ec2:DescribeTags", - "cloudformation:CreateStack", - "cloudformation:DeleteStack", - "cloudformation:DescribeStacks", - "cloudformation:DescribeStackEvents", - "cloudformation:ValidateTemplate", - "iam:PassRole", - "iam:CreateRole", - "iam:DeleteRole", - "iam:PutRolePolicy", - "iam:CreateInstanceProfile", - "iam:DeleteRolePolicy", - "iam:AddRoleToInstanceProfile", - "iam:RemoveRoleFromInstanceProfile", - "iam:DeleteInstanceProfile", - "kms:List*", - "kms:Describe*" - ], - "Resource": "*" - }, - { - "Effect": "Allow", - "Action": [ - "ec2:StartInstances", - "ec2:StopInstances", - "ec2:TerminateInstances", - "ec2:AttachVolume", - "ec2:DetachVolume" - ], - "Condition": { - "StringLike": { - "ec2:ResourceTag/WorkingEnvironment": "*" - } - }, - "Resource": [ - "arn:aws:ec2:*:*:instance/*" - ] - }, - { - "Effect": "Allow", - "Action": [ - "ec2:AttachVolume", - "ec2:DetachVolume" - ], - "Resource": [ - "arn:aws:ec2:*:*:volume/*" - ] - } - ] -} \ No newline at end of file + "Version": "2012-10-17", + "Statement": [{ + "Effect": "Allow", + "Action": [ + "iam:ListInstanceProfiles", + "iam:CreateRole", + "iam:DeleteRole", + "iam:PutRolePolicy", + "iam:CreateInstanceProfile", + "iam:DeleteRolePolicy", + "iam:AddRoleToInstanceProfile", + "iam:RemoveRoleFromInstanceProfile", + "iam:DeleteInstanceProfile", + "ec2:ModifyVolumeAttribute", + "sts:DecodeAuthorizationMessage", + "ec2:DescribeImages", + "ec2:DescribeRouteTables", + "ec2:DescribeInstances", + "iam:PassRole", + "ec2:DescribeInstanceStatus", + "ec2:RunInstances", + "ec2:ModifyInstanceAttribute", + "ec2:CreateTags", + "ec2:CreateVolume", + "ec2:DescribeVolumes", + "ec2:DeleteVolume", + "ec2:CreateSecurityGroup", + "ec2:DeleteSecurityGroup", + "ec2:DescribeSecurityGroups", + "ec2:RevokeSecurityGroupEgress", + "ec2:AuthorizeSecurityGroupEgress", + "ec2:AuthorizeSecurityGroupIngress", + "ec2:RevokeSecurityGroupIngress", + "ec2:CreateNetworkInterface", + "ec2:DescribeNetworkInterfaces", + "ec2:DeleteNetworkInterface", + "ec2:ModifyNetworkInterfaceAttribute", + "ec2:DescribeSubnets", + "ec2:DescribeVpcs", + "ec2:DescribeDhcpOptions", + "ec2:CreateSnapshot", + "ec2:DeleteSnapshot", + "ec2:DescribeSnapshots", + "ec2:StopInstances", + "ec2:GetConsoleOutput", + "ec2:DescribeKeyPairs", + "ec2:DescribeRegions", + "ec2:DeleteTags", + "ec2:DescribeTags", + "cloudformation:CreateStack", + "cloudformation:DeleteStack", + "cloudformation:DescribeStacks", + "cloudformation:DescribeStackEvents", + "cloudformation:ValidateTemplate", + "s3:GetObject", + "s3:ListBucket", + "s3:ListAllMyBuckets", + "s3:GetBucketTagging", + "s3:GetBucketLocation", + "s3:CreateBucket", + "kms:List*", + "kms:Describe*", + "ec2:AssociateIamInstanceProfile", + "ec2:DescribeIamInstanceProfileAssociations", + "ec2:DisassociateIamInstanceProfile" + ], + "Resource": "*" + }, + { + "Sid": "fabricPoolPolicy", + "Effect": "Allow", + "Action": [ + "s3:DeleteBucket", + "s3:GetLifecycleConfiguration", + "s3:PutLifecycleConfiguration", + "s3:PutBucketTagging", + "s3:ListBucketVersions" + ], + "Resource": [ + "arn:aws:s3:::fabric-pool*" + ] + }, + { + "Effect": "Allow", + "Action": [ + "ec2:StartInstances", + "ec2:TerminateInstances", + "ec2:AttachVolume", + "ec2:DetachVolume" + ], + "Condition": { + "StringLike": { + "ec2:ResourceTag/WorkingEnvironment": "*" + } + }, + "Resource": [ + "arn:aws:ec2:*:*:instance/*" + ] + }, + { + "Effect": "Allow", + "Action": [ + "ec2:AttachVolume", + "ec2:DetachVolume" + ], + "Resource": [ + "arn:aws:ec2:*:*:volume/*" + ] + } + ] +} diff --git a/aws_standalone_full/main.tf b/aws_standalone_full/main.tf index 485cf83..78c202c 100644 --- a/aws_standalone_full/main.tf +++ b/aws_standalone_full/main.tf @@ -6,52 +6,55 @@ provider "aws" { /* Create a new AWS VPC */ -resource "aws_vpc" "occm" { - cidr_block = "10.100.0.0/16" +resource "aws_vpc" "lab" { + cidr_block = "${var.vpc_cidr}" enable_dns_hostnames = true tags { Name = "VPC for ONTAP Cloud", + "Owned By" = "${var.owner_name}", "Deployed Using" = "Terraform", "Designed by" = "www.exospheredata.com" } } -resource "aws_subnet" "occm" { - vpc_id = "${aws_vpc.occm.id}" - cidr_block = "10.100.1.0/24" +resource "aws_subnet" "lab" { + vpc_id = "${aws_vpc.lab.id}" + cidr_block = "${cidrsubnet(var.vpc_cidr, 8, 1)}" tags { - Name = "Subnet for ONTAP Cloud", + Name = "Subnet for Infrastructure", + "Owned By" = "${var.owner_name}", "Deployed Using" = "Terraform", "Designed by" = "www.exospheredata.com" } } resource "aws_route_table_association" "main" { - subnet_id = "${aws_subnet.occm.id}" - route_table_id = "${aws_vpc.occm.default_route_table_id}" + subnet_id = "${aws_subnet.lab.id}" + route_table_id = "${aws_vpc.lab.default_route_table_id}" depends_on = [ - "aws_vpc.occm" + "aws_subnet.lab" ] } resource "aws_internet_gateway" "gw" { - vpc_id = "${aws_vpc.occm.id}" + vpc_id = "${aws_vpc.lab.id}" depends_on = [ - "aws_vpc.occm" + "aws_vpc.lab" ] tags { Name = "IGW for ONTAP Cloud VPC", + "Owned By" = "${var.owner_name}", "Deployed Using" = "Terraform", "Designed by" = "www.exospheredata.com" } } resource "aws_route" "igw" { - route_table_id = "${aws_vpc.occm.default_route_table_id}" + route_table_id = "${aws_vpc.lab.default_route_table_id}" destination_cidr_block = "0.0.0.0/0" - gateway_id = "${aws_internet_gateway.gw.id}" + gateway_id = "${aws_internet_gateway.gw.id}" } /* @@ -59,18 +62,18 @@ Create a new IAM Role that can be assigned to the OnCommand Cloud Manager EC2 instance and provide access controls to the connected AWS account. */ resource "aws_iam_role" "occm_ec2_role" { - name = "occm_ec2_role" - description = "Grants access to services required by NetApp's OnCommand Cloud Manager" - assume_role_policy = "${file("files/occm-ec2-role.json")}" + name = "occm_instance_profile_${replace(lower(var.owner_name)," ","_")}" + description = "Grants access to services required by NetApp's OnCommand Cloud Manager" + assume_role_policy = "${file("${path.module}/files/occm-ec2-role.json")}" } /* EC2 Instance Profile based on the provided role */ resource "aws_iam_instance_profile" "occm_instance_profile" { - name = "occm_instance_profile" - role = "${aws_iam_role.occm_ec2_role.id}" - depends_on = [ + name = "occm_instance_profile_${replace(lower(var.owner_name)," ","_")}" + role = "${aws_iam_role.occm_ec2_role.id}" + depends_on = [ "aws_iam_role.occm_ec2_role" ] } @@ -78,14 +81,14 @@ resource "aws_iam_instance_profile" "occm_instance_profile" { /* Default policy document for privileges requireed by OnCommand Cloud Manager */ -resource "aws_iam_role_policy" "role_policy" { - name = "occm_instance_role_policy" +resource "aws_iam_role_policy" "occm_role_policy" { + name = "occm_instance_profile_${replace(lower(var.owner_name)," ","_")}" role = "${aws_iam_role.occm_ec2_role.id}" - depends_on = [ + depends_on = [ "aws_iam_role.occm_ec2_role" ] - policy = "${file("files/occm-role-policy.json")}" + policy = "${file("${path.module}/files/occm-role-policy.json")}" } /* @@ -93,9 +96,12 @@ New Security group granting Web access and SSH access to the OnCommand Cloud Man allow all outgoing traffic. */ resource "aws_security_group" "occm_access" { - name = "occm_access" - description = "Allow all inbound traffic on ports 80, 443, and 22." - vpc_id = "${aws_subnet.occm.vpc_id}" + name = "occm_access_${replace(lower(var.owner_name)," ","_")}" + description = "Allow all inbound traffic on ports 80, 443, and 22." + vpc_id = "${aws_subnet.lab.vpc_id}" + depends_on = [ + "aws_route.igw" + ] ingress { from_port = 80 @@ -127,7 +133,8 @@ resource "aws_security_group" "occm_access" { tags { Name = "OnCommand Cloud Manager Access", - Created_By = "Terraform" + "Deployed Using" = "Terraform", + "Designed by" = "www.exospheredata.com" } } @@ -137,30 +144,30 @@ Launch a new AWS Marketplace instance of Netapp's OnCommand Cloud Manager and as created EC2 Instance Profile. */ resource "aws_instance" "OCCM" { - ami = "${lookup(var.occm_amis, var.region)}" - instance_type = "t2.medium" - subnet_id = "${aws_subnet.occm.id}" - vpc_security_group_ids = ["${aws_security_group.occm_access.id}"] - key_name = "${var.key_name}" + depends_on = [ + "aws_iam_role_policy.occm_role_policy", + "aws_iam_role.occm_ec2_role", + "aws_security_group.occm_access" + ] + ami = "${lookup(var.occm_amis, var.region)}" + instance_type = "t2.medium" + subnet_id = "${aws_subnet.lab.id}" + vpc_security_group_ids = ["${aws_security_group.occm_access.id}"] + key_name = "${var.key_name}" associate_public_ip_address = "true" - iam_instance_profile = "${aws_iam_instance_profile.occm_instance_profile.id}" + iam_instance_profile = "${aws_iam_instance_profile.occm_instance_profile.id}" tags { Name = "OnCommand Cloud Manager", + "Owned By" = "${var.owner_name}", "Deployed Using" = "Terraform", "Provisioned Using" = "CHEF", "Designed by" = "www.exospheredata.com" } - depends_on = [ - "aws_iam_role_policy.role_policy", - "aws_iam_role.occm_ec2_role", - "aws_iam_role_policy.role_policy", - "aws_security_group.occm_access" - ] - + /* Establish a connection to the OnCommand Cloud Manager system using ssh and the private key file provided. - + */ connection { host = "${aws_instance.OCCM.0.public_ip}" type = "ssh" @@ -174,32 +181,21 @@ resource "aws_instance" "OCCM" { to SSH long before the service is online. */ provisioner "remote-exec" { - inline = [ - "mkdir -p /tmp" - ] + inline = [ + "mkdir -p /tmp/" + ] } provisioner "file" { - source = "./scripts/check_server_health.sh" + source = "${path.module}/scripts/check_server_health.sh" destination = "/tmp/check_server_health.sh" } provisioner "remote-exec" { - inline = [ - "chmod +x /tmp/check_server_health.sh", - "/tmp/check_server_health.sh", - "echo The Instance is ready to be provisioned" - ] + inline = [ + "chmod +x /tmp/check_server_health.sh", + "/tmp/check_server_health.sh", + "echo The Instance is ready to be provisioned" + ] } -} - -resource "null_resource" "ontap_cloud" { - depends_on = [ - "aws_iam_role_policy.role_policy", - "aws_iam_role.occm_ec2_role", - "aws_iam_role_policy.role_policy", - "aws_instance.OCCM", - "aws_route.igw" - ] - /* Establish a connection to the OnCommand Cloud Manager system using ssh and the private key file provided. @@ -215,81 +211,156 @@ resource "null_resource" "ontap_cloud" { private_key = "${file("${var.key_file_path}")}" timeout = "60m" } + /* + =========== + These steps will only be run when the terraform destroy command is sent + =========== + The following will only run on a destroy of the environment and needs to be run + to properly destroy the ONTAP Cloud instance. + */ provisioner "remote-exec" { - inline = [ - "rm -rf /tmp/chef", - "mkdir -p /tmp/chef/data_bags/occm" - ] + when = "destroy" + inline = [ + "rm -rf /tmp/chef", + "rm -rf /tmp/cookbooks.tar.gz", + "mkdir -p /tmp/chef/data_bags/occm", + "mkdir -p /tmp/ontap_cloud_cookbooks" + ] } + + /* + Create archive of the cookbooks and dependencies. Upon creation, upload the file to the server and then remove the local copy. + + the path_root variable tells the system to look at the top level of the modules and not in the module path. + */ provisioner "file" { - source = "./files/solo.rb" - destination = "/tmp/chef/solo.rb" + when = "destroy" + source = "${path.module}/files/Berksfile" + destination = "/tmp/ontap_cloud_cookbooks/Berksfile" } + + /* + Send all interpolated files to the remote server + */ provisioner "file" { - source = "./scripts/bootstrap.sh" - destination = "/tmp/chef/bootstrap.sh" + when = "destroy" + source = "${path.module}/files/solo.rb" + destination = "/tmp/chef/solo.rb" } provisioner "file" { - content = "${data.template_file.create_ontap.rendered}" + when = "destroy" + content = "${data.template_file.destroy_ontap.rendered}" destination = "/tmp/chef/dna.json" } + provisioner "file" { + when = "destroy" + source = "${path.module}/scripts/bootstrap.sh" + destination = "/tmp/chef/bootstrap.sh" + } /* Setup the CHEF Data bags */ provisioner "file" { + when = "destroy" content = "${data.template_file.admin_credentials.rendered}" destination = "/tmp/chef/data_bags/occm/admin_credentials.json" } - provisioner "file" { - content = "${data.template_file.ontap_credentials.rendered}" - destination = "/tmp/chef/data_bags/occm/${var.ontap_name}.json" - } + /* + Execute Bootstrap script to apply CHEF configuration and setup. + */ provisioner "remote-exec" { + when = "destroy" inline = [ "chmod +x /tmp/chef/bootstrap.sh", "sudo /tmp/chef/bootstrap.sh", ] } +} + +/* +Deploy ONTAP Cloud system and configuration via CHEF +*/ +resource "null_resource" "ontap_cloud" { + triggers { + occm_id = "${aws_instance.OCCM.id}", + converge = "${var.converge}" + } + depends_on = [ + "aws_iam_role_policy.occm_role_policy", + "aws_iam_role.occm_ec2_role", + "aws_instance.OCCM" + ] /* - The following will only run on a destroy of the environment and needs to be run - to properly destroy the ONTAP Cloud instance. + Establish a connection to the OnCommand Cloud Manager system using ssh and the private + key file provided. + + The deployment process of an ONTAP Cloud system can take upwards of 25+ minutes depending + on the state of the AWS Region. We are setting a 60 minute timeout on this connection + due to this potential length. + */ + connection { + host = "${aws_instance.OCCM.0.public_ip}" + type = "ssh" + user = "ec2-user" # OCCM Default username in AWS EC2 instances + private_key = "${file("${var.key_file_path}")}" + timeout = "60m" + } + + /* + =========== + These steps will only be run when the terraform apply command is sent + =========== + */ provisioner "remote-exec" { - when = "destroy" inline = [ "rm -rf /tmp/chef", - "mkdir -p /tmp/chef/data_bags/occm" + "rm -rf /tmp/ontap_cloud_cookbooks", + "mkdir -p /tmp/chef/data_bags/occm", + "mkdir -p /tmp/ontap_cloud_cookbooks" ] } + /* - Setup the CHEF Data bags + Send all interpolated files to the remote server */ provisioner "file" { - when = "destroy" - content = "${data.template_file.admin_credentials.rendered}" - destination = "/tmp/chef/data_bags/occm/admin_credentials.json" + source = "${path.module}/files/Berksfile" + destination = "/tmp/ontap_cloud_cookbooks/Berksfile" } provisioner "file" { - when = "destroy" - source = "./files/solo.rb" + source = "${path.module}/files/solo.rb" destination = "/tmp/chef/solo.rb" } provisioner "file" { - when = "destroy" - source = "./scripts/bootstrap.sh" + content = "${data.template_file.create_ontap.rendered}" + destination = "/tmp/chef/dna.json" + } + provisioner "file" { + source = "${path.module}/scripts/bootstrap.sh" destination = "/tmp/chef/bootstrap.sh" } + + /* + Setup the CHEF Data bags + */ provisioner "file" { - when = "destroy" - content = "${data.template_file.destroy_ontap.rendered}" - destination = "/tmp/chef/dna.json" + content = "${data.template_file.admin_credentials.rendered}" + destination = "/tmp/chef/data_bags/occm/admin_credentials.json" } + provisioner "file" { + content = "${data.template_file.ontap_credentials.rendered}" + destination = "/tmp/chef/data_bags/occm/${var.ontap_name}.json" + } + + /* + Execute Bootstrap script to apply CHEF configuration and setup. + */ provisioner "remote-exec" { - when = "destroy" inline = [ "chmod +x /tmp/chef/bootstrap.sh", "sudo /tmp/chef/bootstrap.sh", diff --git a/aws_standalone_full/output.tf b/aws_standalone_full/output.tf index b168a84..8fd0af1 100644 --- a/aws_standalone_full/output.tf +++ b/aws_standalone_full/output.tf @@ -1,9 +1,27 @@ /* Output Variables */ -output "CloudManager-Public-Url" { +output "aws_lab_vpc_id" { + value = "${aws_vpc.lab.id}" +} + +output "aws_lab_subnet_id" { + value = "${aws_subnet.lab.id}" +} + +output "cloudmanager_public_url" { value = "https://${aws_instance.OCCM.0.public_ip}/occmui/" } -output "CloudManager-Private-Url" { + +output "cloudmanager_public_ip" { + value = "${aws_instance.OCCM.0.public_ip}" +} + + +output "cloudmanager_private_url" { value = "https://${aws_instance.OCCM.0.private_ip}/occmui/" } + +output "cloudmanager_private_ip" { + value = "${aws_instance.OCCM.0.private_ip}" +} diff --git a/aws_standalone_full/scripts/bootstrap.sh b/aws_standalone_full/scripts/bootstrap.sh index 6d6d822..2ce8238 100644 --- a/aws_standalone_full/scripts/bootstrap.sh +++ b/aws_standalone_full/scripts/bootstrap.sh @@ -14,6 +14,17 @@ if ! exists chef-solo; then curl -L https://www.opscode.com/chef/install.sh | bash fi +if ! exists chef; then + wget -nv https://packages.chef.io/files/stable/chefdk/1.5.0/el/7/chefdk-1.5.0-1.el7.x86_64.rpm + yum install -y chefdk-1.5.0-1.el7.x86_64.rpm +fi + +location=${PWD} +cd /tmp/ontap_cloud_cookbooks && \ + berks package --berksfile=Berksfile && \ + mv cookbooks-*.tar.gz /tmp/cookbooks.tar.gz +cd $location + echo "Remove existing chef files and configurations" rm -rf /var/chef/cookbooks /var/chef/data_bags /var/chef/solo.rb /var/chef/dna.json @@ -21,20 +32,8 @@ echo "Setup the repositories" mkdir -p /var/chef/cookbooks /var/chef/data_bags chmod -R 777 /var/chef -location=${PWD} -cd /var/chef/cookbooks -git clone https://github.com/exospheredata/netapp_ontap_cloud.git > /dev/null 2>&1 -cd netapp_ontap_cloud - -echo 'Clean up files not required for CHEF actions' -rm -rf tasks -rm -rf test -rm -rf spec -rm -rf terraform -cd $location - mv /tmp/chef/* /var/chef/ rm -rf /tmp/chef echo "Start the CHEF Client and configuration bootstrap" -`which chef-solo` -c /var/chef/solo.rb -j /var/chef/dna.json -L /var/chef/client.log -l info +`which chef-solo` --recipe-url /tmp/cookbooks.tar.gz -c /var/chef/solo.rb -j /var/chef/dna.json -l info diff --git a/aws_standalone_full/templates.tf b/aws_standalone_full/templates.tf index b19d90c..67bc73f 100644 --- a/aws_standalone_full/templates.tf +++ b/aws_standalone_full/templates.tf @@ -1,36 +1,49 @@ +/* +Create the data_bag object to contain the OnCommand Cloud Manager credentials +*/ data "template_file" "admin_credentials" { - template = "${file("templates/data_bags/occm/admin_credentials.json.tpl")}" + template = "${file("${path.module}/templates/data_bags/occm/admin_credentials.json.tpl")}" vars { occm_email = "${var.occm_email}" occm_password = "${var.occm_password}" } } +/* +Create the data_bag object to contain the ONTAP Cloud credentials +*/ data "template_file" "ontap_credentials" { - template = "${file("templates/data_bags/occm/ontap_credentials.json.tpl")}" + template = "${file("${path.module}/templates/data_bags/occm/ontap_credentials.json.tpl")}" vars { ontap_name = "${var.ontap_name}" svm_password = "${var.ontap_password}" } } +/* +Create the JSON attributes file for use when creating ONTAP Cloud systems via CHEF +*/ data "template_file" "create_ontap" { - template = "${file("templates/create_ontap.json.tpl")}" + template = "${file("${path.module}/templates/create_ontap.json.tpl")}" vars { company_name = "${var.company_name}" ontap_name = "${var.ontap_name}" ontap_size = "${var.ontap_size}" ontap_instance = "${var.ontap_instance}" license_type = "${var.license_type}" - vpc_id = "${aws_subnet.occm.vpc_id}" + vpc_id = "${aws_subnet.lab.vpc_id}" region = "${var.region}" - subnet_id = "${aws_subnet.occm.id}" + subnet_id = "${aws_subnet.lab.id}" + write_speed = "${lower(var.ontap_write_speed)}" } } +/* +Create the JSON attributes file for use when deleting ONTAP Cloud systems via CHEF +*/ data "template_file" "destroy_ontap" { - template = "${file("templates/destroy_ontap.json.tpl")}" + template = "${file("${path.module}/templates/destroy_ontap.json.tpl")}" vars { ontap_name = "${var.ontap_name}" } diff --git a/aws_standalone_full/templates/create_ontap.json.tpl b/aws_standalone_full/templates/create_ontap.json.tpl index 65c8b21..f0eda3b 100644 --- a/aws_standalone_full/templates/create_ontap.json.tpl +++ b/aws_standalone_full/templates/create_ontap.json.tpl @@ -8,7 +8,8 @@ "name": "${ontap_name}", "size": "${ontap_size}", "instance_type": "${ontap_instance}", - "license_type": "${license_type}" + "license_type": "${license_type}", + "write_speed": "${write_speed}" } }, "aws": { diff --git a/aws_standalone_full/variables.tf b/aws_standalone_full/variables.tf index 62d91fb..322a059 100644 --- a/aws_standalone_full/variables.tf +++ b/aws_standalone_full/variables.tf @@ -1,5 +1,8 @@ -variable "aws_profile" { - description = "The aws credentials file profile name." +/* +Mandatory Variables +*/ +variable "owner_name" { + description = "Your Username to identify your infrastructure" } variable "key_name" { @@ -10,62 +13,96 @@ variable "key_file_path" { description = "Location of the local private key file for the EC2 instance." } +variable "converge" { + description = "When set to 'true', the configuration resources will all re-apply to their hosts." + default = "false" +} +/* +AWS specific +*/ +variable "aws_profile" { + description = "The aws credentials file profile name." + default = "default" +} + variable "region" { description = "AWS region to which the systems will be deployed." + default = "us-east-1" +} + +variable "vpc_cidr" { + description = "Base Network CIDR for the new VPC" + default = "10.100.0.0/16" } +/* +OnCommand Cloud Manager specific +*/ variable "occm_email" { description = "Email address (username) for OnCommand Cloud Manager instance" + default = "netapp@peritus.lab" } variable "occm_password" { description = "Administrative password for OnCommand Cloud Manager instance" + default = "peritus" } variable "company_name" { description = "Your company name to which the OnCommand Cloud manager system will be registered" + default = "Peritus Lab" } variable "occm_amis" { type = "map" description = "List of the OnCommand Cloud Manager AMIs per region." default = { - "ap-south-1" = "ami-08443567" - "eu-west-2" = "ami-6f73660b" - "eu-west-1" = "ami-8dd7f2eb" - "ap-northeast-2" = "ami-1e61b070" - "ap-northeast-1" = "ami-21abeb46" - "sa-east-1" = "ami-b0c3a7dc" - "ca-central-1" = "ami-f8b8059c" - "ap-southeast-1" = "ami-432e9a20" - "ap-southeast-2" = "ami-d8aaacbb" - "eu-central-1" = "ami-b7c20ad8" - "us-east-1" = "ami-6c65a27a" - "us-east-2" = "ami-4811342d" - "us-west-1" = "ami-e63a6686" - "us-west-2" = "ami-68e96c08" + "ap-south-1" = "ami-c2bdc2ad" + "eu-west-2" = "ami-fba8bf9f" + "eu-west-1" = "ami-bf9986d9" + "ap-northeast-2" = "ami-2e8d5240" + "ap-northeast-1" = "ami-8e979ee9" + "sa-east-1" = "ami-982843f4" + "ca-central-1" = "ami-38e9565c" + "ap-southeast-1" = "ami-b89c1edb" + "ap-southeast-2" = "ami-cb3322a8" + "eu-central-1" = "ami-975bfff8" + "us-east-1" = "ami-392c0a2f" + "us-east-2" = "ami-98a98ffd" + "us-west-1" = "ami-379ebc57" + "us-west-2" = "ami-0258537b" } } +/* +ONTAP Cloud specific +*/ variable "ontap_name" { description = "New ONTAP Cloud Name" + default = "demolab" } variable "ontap_password" { description = "New ONTAP Cloud password for Admin" + default = "netapp123" } variable "ontap_size" { description = "Size of the Aggregate: Pick One - 100GB, 500GB, 1TB, 2TB, 4TB, 8TB" - default = "1TB" + default = "500GB" } variable "ontap_instance" { description = "AWS Instance type for ONTAP Cloud instance. If not set, the default is 'm4.xlarge'. Note: must be a supported size for the selected license type" - default = "m4.xlarge" + default = "m4.xlarge" } variable "license_type" { description = "ONTAP Cloud license type. Supported values are [cot-explore-paygo, cot-standard-paygo, cot-premium-paygo]. Default value is cot-explore-paygo" - default = "cot-explore-paygo" + default = "cot-explore-paygo" +} + +variable "ontap_write_speed" { + description = "Sets the ONTAP Cloud write speed. 'Normal' is standard with high consistency guarantee, while 'high' will increase write performance at the risk of potential data loss in the event of a failure." + default = "normal" }