diff --git a/.bumpversion.cfg b/.bumpversion.cfg index 16ea0811..13964c11 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 2.1.0 +current_version = 2.1.1 commit = True message = Bumps version to {new_version} tag = False @@ -20,4 +20,3 @@ replace = Version: {new_version} [bumpversion:file:modules/win-instance/watchmaker-win-instance.template.cfn.yaml] search = Version: {current_version} replace = Version: {new_version} - diff --git a/Makefile b/Makefile index 94643dcd..26cba7d9 100644 --- a/Makefile +++ b/Makefile @@ -1,27 +1,12 @@ -ARCH ?= amd64 -OS ?= $(shell uname -s | tr '[:upper:]' '[:lower:']) -CURL ?= curl --fail -sSL -XARGS ?= xargs -I {} - BIN_DIR ?= ${HOME}/bin PATH := $(BIN_DIR):$(PATH) VERSION ?= $$(grep -E '^current_version' .bumpversion.cfg | sed 's/^.*= //') -MAKEFLAGS += --no-print-directory -SHELL := bash -.SHELLFLAGS := -eu -o pipefail -c -.SUFFIXES: +SHELL := /bin/bash -include $(shell curl -sSL -o .tardigrade-ci "https://raw.githubusercontent.com/plus3it/tardigrade-ci/master/bootstrap/Makefile.bootstrap"; echo .tardigrade-ci) -guard/program/%: - @ which $* > /dev/null || $(MAKE) $*/install - -cfn/%: FIND_CFN ?= find . $(FIND_EXCLUDES) -name '*.template.cfn.*' -type f cfn/version: guard/program/yq cfn/version: $(FIND_CFN) | $(XARGS) bash -c "yq -e '.Metadata.Version | test(\"^$(VERSION)$$\")' {} > /dev/null || (echo '[{}]: BAD/MISSING Cfn Version Metadata'; exit 1)" - -cfn/lint: | guard/program/cfn-lint - $(FIND_CFN) | $(XARGS) cfn-lint -t {} diff --git a/modules/lx-autoscale/README.md b/modules/lx-autoscale/README.md index c621869d..671eaab3 100644 --- a/modules/lx-autoscale/README.md +++ b/modules/lx-autoscale/README.md @@ -3,72 +3,88 @@ This module utilizes the Terraform CloudFormation resource in conjunction with an AWS CloudFormation template to deploy a Watchmaker Linux AutoScaling Group. + +## Requirements + +| Name | Version | +|------|---------| +| terraform | >= 0.12 | + +## Providers + +| Name | Version | +|------|---------| +| aws | n/a | + ## Inputs | Name | Description | Type | Default | Required | -|------|-------------|:----:|:-----:|:-----:| -| AmiDistro | \(Required\) Linux distro of the AMI | string | n/a | yes | -| AmiId | \(Required\) ID of the AMI to launch | string | n/a | yes | -| AppScriptParams | \(Optional\) Parameter string to pass to the application script. Ignored if AppScriptUrl is blank | string | `""` | no | -| AppScriptShell | \(Optional\) Shell with which to execute the application script. Ignored if AppScriptUrl is blank | string | `"bash"` | no | -| AppScriptUrl | \(Optional\) S3 URL to the application script in an S3 bucket \(s3://\). Leave blank to launch without an application script. If specified, an appropriate InstanceRole is required | string | `"null"` | no | -| AppVolumeDevice | \(Optional\) Decision whether to mount an extra EBS volume. Leave as default \("false"\) to launch without an extra application volume | bool | `"false"` | no | -| AppVolumeEncrypted | (Optional) Controls whether the EBS volume will be encrypted. | `bool` | `false` | no | -| AppVolumeMountPath | \(Optional\) Filesystem path to mount the extra app volume. Ignored if AppVolumeDevice is false | string | `"/opt/data"` | no | -| AppVolumeSize | \(Optional\) Size in GB of the EBS volume to create. Ignored if AppVolumeDevice is false | string | `"1"` | no | -| AppVolumeSnapshotId | \(Optional\) EBS Snapshot ID from which to create the AppVolume. "AppVolumeSize" must be equal or greater than the size of the snapshot. Ignored if "AppVolumeDevice" is false | string | `"null"` | no | -| AppVolumeType | \(Optional\) Type of EBS volume to create. Ignored if AppVolumeDevice is false | string | `"gp2"` | no | -| AsgMetrics | \(Optional\) The list of ASG metrics to collect. Must define EnableASGMetricsCollection to enable. Define MetricsCollectionGranularity and leave this option blank to collect all metrics | list(string) | `` | no | -| AsgNotificationTypes | \(Optional\) A list of event types that trigger a notification. Event types can include any of the following types: autoscaling:EC2\_INSTANCE\_LAUNCH, autoscaling:EC2\_INSTANCE\_LAUNCH\_ERROR, autoscaling:EC2\_INSTANCE\_TERMINATE, autoscaling:EC2\_INSTANCE\_TERMINATE\_ERROR, and autoscaling:TEST\_NOTIFICATION. NOTE: Must be defined in conjunction with ASGSNSARN. | list(string) | `` | no | -| AsgSnsArn | \(Optional\) The Amazon Resource Name \(ARN\) of the Amazon Simple Notification Service \(SNS\) topic to send ASG events to. NOTE: Must be defined in conjunction with ASGNotificationTypes. | string | `"null"` | no | -| Capabilities | \(Optional\) A list of capabilities. Valid values: CAPABILITY\_IAM or CAPABILITY\_NAMED\_IAM | list(string) | `` | no | -| CfnEndpointUrl | \(Optional\) URL to the CloudFormation Endpoint. e.g. https://cloudformation.us-east-1.amazonaws.com | string | `"https://cloudformation.us-east-1.amazonaws.com"` | no | -| CloudWatchAgentUrl | \(Optional\) S3 URL to CloudWatch Agent installer. Example: s3://amazoncloudwatch-agent/linux/amd64/latest/AmazonCloudWatchAgent.zip | string | `"null"` | no | -| CloudWatchAppLogs | \(Optional\) List of application log file paths to send to CloudWatch | list(string) | `` | no | -| DesiredCapacity | \(Optional\) Desired number of instances in the Autoscaling Group | string | `"1"` | no | -| DisableRollback | \(Optional\) Set to true to disable rollback of the stack if stack creation failed. Conflicts with OnFailure | string | `"false"` | no | -| EbsOptimized | \(Optional\) Specifies whether the launch configuration is optimized for EBS I/O. This optimization provides dedicated throughput to Amazon EBS and an optimized configuration stack to provide optimal EBS I/O performance. Warning: Stack creation will fail if set to true and the instance type does not support EBS Optimization. See complete list of supported instances here: https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/EBSOptimized.html#ebs-optimization-support | bool | `"false"` | no | -| EnableRepos | \(Optional\) Specify repos to be enabled by yum-config-manager | string | `"null"` | no | -| IamRoleArn | \(Optional\) The ARN of an IAM role that AWS CloudFormation assumes to create the stack. If you don't specify a value, AWS CloudFormation uses the role that was previously associated with the stack. If no role is available, AWS CloudFormation uses a temporary session that is generated from your user credentials | string | `"null"` | no | -| InstanceRole | \(Optional\) IAM instance role to apply to the instance | string | `"null"` | no | -| InstanceTerminationPolicies | \(Optional\) A list of policies that are used to select the instances to terminate. The policies are executed in the order that you list them. | list(string) | `` | no | -| InstanceType | \(Optional\) Amazon EC2 instance type | string | `"t2.micro"` | no | -| KeyPairName | \(Required\) Public/private key pairs allow you to securely connect to your instance after it launches | string | n/a | yes | -| LoadBalancerNames | \(Optional\) Comma-separated string of Classic ELB Names to associate with the Autoscaling Group; conflicts with TargetGroupArns | string | `"null"` | no | -| MaxCapacity | \(Optional\) Maximum number of instances in the Autoscaling Group | string | `"2"` | no | -| MinCapacity | \(Optional\) Minimum number of instances in the Autoscaling Group | string | `"1"` | no | -| Name | \(Required\) Name of CloudFormation Stack | string | n/a | yes | -| NoPublicIp | \(Optional\) Controls whether to assign the instance a public IP. Recommended to leave at true \_unless\_ launching in a public subnet | bool | `"true"` | no | -| NoReboot | \(Optional\) Controls whether to reboot the instance as the last step of cfn-init execution | bool | `"false"` | no | -| NoUpdates | \(Optional\) Controls whether to run yum update during a stack update \(On the initial instance launch, Watchmaker \_always\_ installs updates\) | bool | `"false"` | no | -| NotificationArns | \(Optional\) A list of SNS topic ARNs to publish stack related events | list(string) | `` | no | -| OnFailureAction | \(Optional\) Action to be taken if stack creation fails. This must be one of: DO\_NOTHING, ROLLBACK, or DELETE. Conflicts with DisableRollback | string | `"DO_NOTHING"` | no | -| PatchGroup | \(Optional\) Key value of the Patch Group tag. Controls whether to create a PatchGroup tag that can be leveraged via SSM to auto-update instances. | string | `"null"` | no | -| PolicyBody | \(Optional\) String containing the stack policy body. Conflicts with PolicyUrl | string | `"null"` | no | -| PolicyUrl | \(Optional\) URL to a file containing the stack policy. Conflicts with PolicyBody | string | `"null"` | no | -| PypiIndexUrl | \(Optional\) URL to the PyPi Index | string | `"https://pypi.org/simple"` | no | -| RootVolumeEncrypted | (Optional) Controls whether the root volume will be encrypted. | `bool` | `false` | no | -| RootVolumeSize | \(Optional\) Root Volume Size in GB \*\*NOTE\*\* This value can be set larger than the default \(20GB\) but NOT smaller. If set larger than default value partition will need to be expanded manually. | string | `"20"` | no | -| ScaleDownSchedule | \(Optional\) Scheduled Action in cron-format \(UTC\) to scale down to MinCapacity; ignored if empty or ScaleUpSchedule is unset \(E.g. "0 0 \* \* \*"\) | string | `"null"` | no | -| ScaleUpSchedule | \(Optional\) Scheduled Action in cron-format \(UTC\) to scale up to MaxCapacity; ignored if empty or ScaleDownSchedule is unset \(E.g. "0 10 \* \* Mon-Fri"\) | string | `"null"` | no | -| SecurityGroupIds | \(Required\) List of security groups to apply to the instance | string | n/a | yes | -| StackTags | \(Optional\) A map of tag keys/values to associate with this stack | map(string) | `` | no | -| SubnetIds | \(Required\) List of subnets to associate to the Autoscaling Group | string | n/a | yes | -| TargetGroupArns | \(Optional\) Comma-separated string of Target Group ARNs to associate with the Autoscaling Group; conflicts with LoadBalancerNames | string | `"null"` | no | -| TimeoutInMinutes | \(Optional\) The amount of time that can pass before the stack status becomes CREATE\_FAILED | string | `"30"` | no | -| ToggleCfnInitUpdate | \(Optional\) A/B toggle that forces a change to instance metadata, triggering the cfn-init update sequence | string | `"A"` | no | -| ToggleNewInstances | \(Optional\) A/B toggle that forces a change to instance userdata, triggering new instances via the Autoscale update policy | string | `"A"` | no | -| WatchmakerAdminGroups | \(Optional\) Colon-separated list of domain groups that should have admin permissions on the EC2 instance | string | `"null"` | no | -| WatchmakerAdminUsers | \(Optional\) Colon-separated list of domain users that should have admin permissions on the EC2 instance | string | `"null"` | no | -| WatchmakerConfig | \(Optional\) URL to a Watchmaker config file | string | `"null"` | no | -| WatchmakerEnvironment | \(Optional\) Environment in which the instance is being deployed | string | `"null"` | no | -| WatchmakerExtraArgs | \(Optional\) Additional parameters to be passed to the Watchmaker CLI | string | `"null"` | no | -| WatchmakerOuPath | \(Optional\) DN of the OU to place the instance when joining a domain. If blank and WatchmakerEnvironment enforces a domain join, the instance will be placed in a default container. Leave blank if not joining a domain, or if WatchmakerEnvironment is false | string | `"null"` | no | -| WatchmakerStandaloneUrl | \(Optional\) HTTP/S URL to a Watchmaker standalone executable. The file will be retrieved and used to run Watchmaker, instead of installing Watchmaker from PyPi | string | `"null"` | no | -| WatchmakerVersion | \(Optional\) Watchmaker version to install. When blank \(the default\) the latest version will be installed. Used only when Watchmaker is installed from PyPi | string | `"null"` | no | +|------|-------------|------|---------|:--------:| +| AmiDistro | (Required) Linux distro of the AMI | `string` | n/a | yes | +| AmiId | (Required) ID of the AMI to launch | `string` | n/a | yes | +| KeyPairName | (Required) Public/private key pairs allow you to securely connect to your instance after it launches | `string` | n/a | yes | +| Name | (Required) Name of CloudFormation Stack | `string` | n/a | yes | +| SecurityGroupIds | (Required) List of security groups to apply to the instance | `string` | n/a | yes | +| SubnetIds | (Required) List of subnets to associate to the Autoscaling Group | `string` | n/a | yes | +| AppScriptParams | (Optional) Parameter string to pass to the application script. Ignored if AppScriptUrl is blank | `string` | `""` | no | +| AppScriptShell | (Optional) Shell with which to execute the application script. Ignored if AppScriptUrl is blank | `string` | `"bash"` | no | +| AppScriptUrl | (Optional) S3 URL to the application script in an S3 bucket (s3://). Leave blank to launch without an application script. If specified, an appropriate InstanceRole is required | `string` | `null` | no | +| AppVolumeDevice | (Optional) Decision whether to mount an extra EBS volume. Leave as default ("false") to launch without an extra application volume | `bool` | `false` | no | +| AppVolumeDeviceName | (Optional) Device name to give to the extra EBS volume. Ignored if AppVolumeDevice is false | `string` | `"/dev/xvdf"` | no | +| AppVolumeEncrypted | (Optional) Controls whether the EBS volume will be encrypted | `bool` | `false` | no | +| AppVolumeMountPath | (Optional) Filesystem path to mount the extra app volume. Ignored if AppVolumeDevice is false | `string` | `"/opt/data"` | no | +| AppVolumeSize | (Optional) Size in GB of the EBS volume to create. Ignored if AppVolumeDevice is false | `string` | `"1"` | no | +| AppVolumeSnapshotId | (Optional) EBS Snapshot ID from which to create the AppVolume. "AppVolumeSize" must be equal or greater than the size of the snapshot. Ignored if "AppVolumeDevice" is false | `string` | `null` | no | +| AppVolumeType | (Optional) Type of EBS volume to create. Ignored if AppVolumeDevice is false | `string` | `"gp2"` | no | +| AsgMetrics | (Optional) The list of ASG metrics to collect. Must define EnableASGMetricsCollection to enable. Define MetricsCollectionGranularity and leave this option blank to collect all metrics | `list(string)` | `[]` | no | +| AsgNotificationTypes | (Optional) A list of event types that trigger a notification. Event types can include any of the following types: autoscaling:EC2\_INSTANCE\_LAUNCH, autoscaling:EC2\_INSTANCE\_LAUNCH\_ERROR, autoscaling:EC2\_INSTANCE\_TERMINATE, autoscaling:EC2\_INSTANCE\_TERMINATE\_ERROR, and autoscaling:TEST\_NOTIFICATION. NOTE: Must be defined in conjunction with ASGSNSARN. | `list(string)` | `[]` | no | +| AsgSnsArn | (Optional) The Amazon Resource Name (ARN) of the Amazon Simple Notification Service (SNS) topic to send ASG events to. NOTE: Must be defined in conjunction with ASGNotificationTypes. | `string` | `null` | no | +| Capabilities | (Optional) A list of capabilities. Valid values: CAPABILITY\_IAM or CAPABILITY\_NAMED\_IAM | `list(string)` | `[]` | no | +| CfnEndpointUrl | (Optional) URL to the CloudFormation Endpoint. e.g. https://cloudformation.us-east-1.amazonaws.com | `string` | `"https://cloudformation.us-east-1.amazonaws.com"` | no | +| CloudWatchAgentUrl | (Optional) S3 URL to CloudWatch Agent installer. Example: s3://amazoncloudwatch-agent/linux/amd64/latest/AmazonCloudWatchAgent.zip | `string` | `null` | no | +| CloudWatchAppLogs | (Optional) List of application log file paths to send to CloudWatch | `list(string)` | `[]` | no | +| DesiredCapacity | (Optional) Desired number of instances in the Autoscaling Group | `string` | `"1"` | no | +| DisableRollback | (Optional) Set to true to disable rollback of the stack if stack creation failed. Conflicts with OnFailure | `string` | `false` | no | +| EbsOptimized | (Optional) Specifies whether the launch configuration is optimized for EBS I/O. This optimization provides dedicated throughput to Amazon EBS and an optimized configuration stack to provide optimal EBS I/O performance. Warning: Stack creation will fail if set to true and the instance type does not support EBS Optimization. See complete list of supported instances here: https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/EBSOptimized.html#ebs-optimization-support | `bool` | `false` | no | +| EnableRepos | (Optional) Specify repos to be enabled by yum-config-manager | `string` | `null` | no | +| IamRoleArn | (Optional) The ARN of an IAM role that AWS CloudFormation assumes to create the stack. If you don't specify a value, AWS CloudFormation uses the role that was previously associated with the stack. If no role is available, AWS CloudFormation uses a temporary session that is generated from your user credentials | `string` | `null` | no | +| InstanceRole | (Optional) IAM instance role to apply to the instance | `string` | `null` | no | +| InstanceTerminationPolicies | (Optional) A list of policies that are used to select the instances to terminate. The policies are executed in the order that you list them. | `list(string)` | `[]` | no | +| InstanceType | (Optional) Amazon EC2 instance type | `string` | `"t2.micro"` | no | +| LoadBalancerNames | (Optional) Comma-separated string of Classic ELB Names to associate with the Autoscaling Group; conflicts with TargetGroupArns | `string` | `null` | no | +| MaxCapacity | (Optional) Maximum number of instances in the Autoscaling Group | `string` | `"2"` | no | +| MinCapacity | (Optional) Minimum number of instances in the Autoscaling Group | `string` | `"1"` | no | +| NoPublicIp | (Optional) Controls whether to assign the instance a public IP. Recommended to leave at true _unless_ launching in a public subnet | `bool` | `true` | no | +| NoReboot | (Optional) Controls whether to reboot the instance as the last step of cfn-init execution | `bool` | `false` | no | +| NoUpdates | (Optional) Controls whether to run yum update during a stack update (On the initial instance launch, Watchmaker _always_ installs updates) | `bool` | `false` | no | +| NotificationArns | (Optional) A list of SNS topic ARNs to publish stack related events | `list(string)` | `[]` | no | +| OnFailureAction | (Optional) Action to be taken if stack creation fails. This must be one of: DO\_NOTHING, ROLLBACK, or DELETE. Conflicts with DisableRollback | `string` | `"DO_NOTHING"` | no | +| PatchGroup | (Optional) Key value of the Patch Group tag. Controls whether to create a PatchGroup tag that can be leveraged via SSM to auto-update instances. | `string` | `null` | no | +| PolicyBody | (Optional) String containing the stack policy body. Conflicts with PolicyUrl | `string` | `null` | no | +| PolicyUrl | (Optional) URL to a file containing the stack policy. Conflicts with PolicyBody | `string` | `null` | no | +| PypiIndexUrl | (Optional) URL to the PyPi Index | `string` | `"https://pypi.org/simple"` | no | +| RootVolumeEncrypted | (Optional) Controls whether the root volume will be encrypted | `bool` | `false` | no | +| RootVolumeSize | (Optional) Root Volume Size in GB **NOTE** This value can be set larger than the default (20GB) but NOT smaller. If set larger than default value partition will need to be expanded manually. | `string` | `"20"` | no | +| ScaleDownSchedule | (Optional) Scheduled Action in cron-format (UTC) to scale down to MinCapacity; ignored if empty or ScaleUpSchedule is unset (E.g. "0 0 \* \* \*") | `string` | `null` | no | +| ScaleUpSchedule | (Optional) Scheduled Action in cron-format (UTC) to scale up to MaxCapacity; ignored if empty or ScaleDownSchedule is unset (E.g. "0 10 \* \* Mon-Fri") | `string` | `null` | no | +| StackTags | (Optional) A map of tag keys/values to associate with this stack | `map(string)` | `{}` | no | +| TargetGroupArns | (Optional) Comma-separated string of Target Group ARNs to associate with the Autoscaling Group; conflicts with LoadBalancerNames | `string` | `null` | no | +| TimeoutInMinutes | (Optional) The amount of time that can pass before the stack status becomes CREATE\_FAILED | `string` | `"30"` | no | +| ToggleCfnInitUpdate | (Optional) A/B toggle that forces a change to instance metadata, triggering the cfn-init update sequence | `string` | `"A"` | no | +| ToggleNewInstances | (Optional) A/B toggle that forces a change to instance userdata, triggering new instances via the Autoscale update policy | `string` | `"A"` | no | +| WatchmakerAdminGroups | (Optional) Colon-separated list of domain groups that should have admin permissions on the EC2 instance | `string` | `null` | no | +| WatchmakerAdminUsers | (Optional) Colon-separated list of domain users that should have admin permissions on the EC2 instance | `string` | `null` | no | +| WatchmakerConfig | (Optional) URL to a Watchmaker config file | `string` | `null` | no | +| WatchmakerEnvironment | (Optional) Environment in which the instance is being deployed | `string` | `null` | no | +| WatchmakerExtraArgs | (Optional) Additional parameters to be passed to the Watchmaker CLI | `string` | `null` | no | +| WatchmakerOuPath | (Optional) DN of the OU to place the instance when joining a domain. If blank and WatchmakerEnvironment enforces a domain join, the instance will be placed in a default container. Leave blank if not joining a domain, or if WatchmakerEnvironment is false | `string` | `null` | no | +| WatchmakerStandaloneUrl | (Optional) HTTP/S URL to a Watchmaker standalone executable. The file will be retrieved and used to run Watchmaker, instead of installing Watchmaker from PyPi | `string` | `null` | no | +| WatchmakerVersion | (Optional) Watchmaker version to install. When blank (the default) the latest version will be installed. Used only when Watchmaker is installed from PyPi | `string` | `null` | no | ## Outputs | Name | Description | |------|-------------| | watchmaker-lx-autoscale | CloudFormation stack object for watchmaker-lx-autoscale | + + diff --git a/modules/lx-autoscale/main.tf b/modules/lx-autoscale/main.tf index d7e3b7e8..16604c35 100644 --- a/modules/lx-autoscale/main.tf +++ b/modules/lx-autoscale/main.tf @@ -22,6 +22,7 @@ resource "aws_cloudformation_stack" "watchmaker-lx-autoscale" { AppScriptShell = var.AppScriptShell AppScriptUrl = var.AppScriptUrl AppVolumeDevice = var.AppVolumeDevice + AppVolumeDeviceName = var.AppVolumeDeviceName AppVolumeMountPath = var.AppVolumeMountPath AppVolumeEncrypted = var.AppVolumeEncrypted AppVolumeSize = var.AppVolumeSize diff --git a/modules/lx-autoscale/variables.tf b/modules/lx-autoscale/variables.tf index 70efbb87..7371e53d 100644 --- a/modules/lx-autoscale/variables.tf +++ b/modules/lx-autoscale/variables.tf @@ -113,6 +113,12 @@ variable "AppVolumeDevice" { default = false } +variable "AppVolumeDeviceName" { + type = string + description = "(Optional) Device name to give to the extra EBS volume. Ignored if AppVolumeDevice is false" + default = "/dev/xvdf" +} + variable "AppVolumeEncrypted" { type = bool description = "(Optional) Controls whether the EBS volume will be encrypted" diff --git a/modules/lx-autoscale/watchmaker-lx-autoscale.params.cfn.yaml b/modules/lx-autoscale/watchmaker-lx-autoscale.params.cfn.yaml index 75ca3a5e..fcef446c 100644 --- a/modules/lx-autoscale/watchmaker-lx-autoscale.params.cfn.yaml +++ b/modules/lx-autoscale/watchmaker-lx-autoscale.params.cfn.yaml @@ -10,6 +10,8 @@ ParameterValue: __APPSCRIPTURL__ - ParameterKey: AppVolumeDevice ParameterValue: __APPVOLUMEDEVICE__ +- ParameterKey: AppVolumeDeviceName + ParameterValue: __APPVOLUMEDEVICENAME__ - ParameterKey: AppVolumeEncrypted ParameterValue: __APPVOLUMEENCRYPTED__ - ParameterKey: AppVolumeMountPath diff --git a/modules/lx-autoscale/watchmaker-lx-autoscale.template.cfn.yaml b/modules/lx-autoscale/watchmaker-lx-autoscale.template.cfn.yaml index e629a65e..4990a936 100644 --- a/modules/lx-autoscale/watchmaker-lx-autoscale.template.cfn.yaml +++ b/modules/lx-autoscale/watchmaker-lx-autoscale.template.cfn.yaml @@ -169,6 +169,7 @@ Metadata: default: EC2 Application EBS Volume Parameters: - AppVolumeDevice + - AppVolumeDeviceName - AppVolumeEncrypted - AppVolumeMountPath - AppVolumeSize @@ -207,7 +208,7 @@ Metadata: default: Force Cfn Init Update ToggleNewInstances: default: Force New Instances - Version: 2.1.0 + Version: 2.1.1 Outputs: ScaleDownScheduledAction: Condition: UseScheduledAction @@ -270,6 +271,13 @@ Parameters: Decision whether to mount an extra EBS volume. Leave as default ("false") to launch without an extra application volume Type: String + AppVolumeDeviceName: + AllowedPattern: '/dev/xvd[f-k]' + Default: '/dev/xvdf' + Description: >- + Device name to be given to extra EBS volume. Ignored if "AppVolumeDevice" + is false + Type: String AppVolumeEncrypted: AllowedValues: - 'false' @@ -969,7 +977,7 @@ Resources: VolumeType: gp2 - !If - CreateAppVolume - - DeviceName: /dev/xvdf + - DeviceName: !Ref AppVolumeDeviceName Ebs: DeleteOnTermination: true Encrypted: !Ref AppVolumeEncrypted @@ -1013,13 +1021,12 @@ Resources: #!/bin/bash -xe # Format and mount app volume - APPVOL_DEVICE="$(ls /dev/xvdf /dev/nvme1n1 2> /dev/null || true)" - if [[ -n "$APPVOL_DEVICE" && "${AppVolumeDevice}" == "true" ]] + if [[ "${AppVolumeDevice}" == "true" ]] then MOUNT_VFSTYPE="auto" MOUNT_OPTS="defaults,nofail" - cloud-init-per instance mkfsappvolume mkfs -t ext4 "$APPVOL_DEVICE" - grep -q "$APPVOL_DEVICE" /etc/fstab || printf "%s\t%s\t%s\t%s\t0\t2\n" "$APPVOL_DEVICE" "${AppVolumeMountPath}" "$MOUNT_VFSTYPE" "$MOUNT_OPTS" >> /etc/fstab + cloud-init-per instance mkfsappvolume mkfs -t ext4 "${AppVolumeDeviceName}" + grep -q "${AppVolumeDeviceName}" /etc/fstab || printf "%s\t%s\t%s\t%s\t0\t2\n" "${AppVolumeDeviceName}" "${AppVolumeMountPath}" "$MOUNT_VFSTYPE" "$MOUNT_OPTS" >> /etc/fstab mkdir -p "${AppVolumeMountPath}" mount -a fi diff --git a/modules/lx-instance/README.md b/modules/lx-instance/README.md index 831f527a..42a67db5 100644 --- a/modules/lx-instance/README.md +++ b/modules/lx-instance/README.md @@ -30,6 +30,7 @@ with an AWS CloudFormation template to deploy a Watchmaker Linux Instance. | AppScriptShell | (Optional) Shell with which to execute the application script. Ignored if AppScriptUrl is blank | `string` | `"bash"` | no | | AppScriptUrl | (Optional) S3 URL to the application script in an S3 bucket (s3://). Leave blank to launch without an application script. If specified, an appropriate InstanceRole is required | `string` | `null` | no | | AppVolumeDevice | (Optional) Decision whether to mount an extra EBS volume. Leave as default (false) to launch without an extra application volume | `bool` | `false` | no | +| AppVolumeDeviceName | (Optional) Device name to be given to the extra EBS volume. Ignored if AppVolumeDevice is false | `string` | `"/dev/xvdf"` | no | | AppVolumeEncrypted | (Optional) Controls whether the EBS volume will be encrypted. When KmsKeyId is specified, EBS encryption will be done using that, otherwise encrypted using AWS managed CMK | `bool` | `false` | no | | AppVolumeMountPath | (Optional) Filesystem path to mount the extra app volume. Ignored if AppVolumeDevice is false | `string` | `"/opt/data"` | no | | AppVolumeSize | (Optional) Size in GB of the EBS volume to create. Ignored if AppVolumeDevice is false | `string` | `"1"` | no | diff --git a/modules/lx-instance/main.tf b/modules/lx-instance/main.tf index 4bc6abc0..6032e038 100644 --- a/modules/lx-instance/main.tf +++ b/modules/lx-instance/main.tf @@ -22,6 +22,7 @@ resource "aws_cloudformation_stack" "watchmaker-lx-instance" { AppScriptShell = var.AppScriptShell AppScriptUrl = var.AppScriptUrl AppVolumeDevice = var.AppVolumeDevice + AppVolumeDeviceName = var.AppVolumeDeviceName AppVolumeEncrypted = var.AppVolumeEncrypted AppVolumeMountPath = var.AppVolumeMountPath AppVolumeSize = var.AppVolumeSize diff --git a/modules/lx-instance/variables.tf b/modules/lx-instance/variables.tf index 8941119b..0cbf3cad 100644 --- a/modules/lx-instance/variables.tf +++ b/modules/lx-instance/variables.tf @@ -113,6 +113,12 @@ variable "AppVolumeDevice" { default = false } +variable "AppVolumeDeviceName" { + type = string + description = "(Optional) Device name to be given to the extra EBS volume. Ignored if AppVolumeDevice is false" + default = "/dev/xvdf" +} + variable "AppVolumeEncrypted" { type = bool description = "(Optional) Controls whether the EBS volume will be encrypted. When KmsKeyId is specified, EBS encryption will be done using that, otherwise encrypted using AWS managed CMK" diff --git a/modules/lx-instance/watchmaker-lx-instance.params.cfn.yaml b/modules/lx-instance/watchmaker-lx-instance.params.cfn.yaml index 682f3707..1ded8c2a 100644 --- a/modules/lx-instance/watchmaker-lx-instance.params.cfn.yaml +++ b/modules/lx-instance/watchmaker-lx-instance.params.cfn.yaml @@ -10,6 +10,8 @@ ParameterValue: __APPSCRIPTURL__ - ParameterKey: AppVolumeDevice ParameterValue: __APPVOLUMEDEVICE__ +- ParameterKey: AppVolumeDeviceName + ParameterValue: __APPVOLUMEDEVICENAME__ - ParameterKey: AppVolumeEncrypted ParameterValue: __APPVOLUMEENCRYPTED__ - ParameterKey: AppVolumeMountPath diff --git a/modules/lx-instance/watchmaker-lx-instance.template.cfn.yaml b/modules/lx-instance/watchmaker-lx-instance.template.cfn.yaml index 88abffb9..a982aff8 100644 --- a/modules/lx-instance/watchmaker-lx-instance.template.cfn.yaml +++ b/modules/lx-instance/watchmaker-lx-instance.template.cfn.yaml @@ -142,6 +142,7 @@ Metadata: default: EC2 Application EBS Volume Parameters: - AppVolumeDevice + - AppVolumeDeviceName - AppVolumeEncrypted - AppVolumeMountPath - AppVolumeSize @@ -163,7 +164,7 @@ Metadata: ParameterLabels: ToggleCfnInitUpdate: default: Force Cfn Init Update - Version: 2.1.0 + Version: 2.1.1 Outputs: WatchmakerInstanceId: Description: Instance ID @@ -215,6 +216,13 @@ Parameters: Decision on whether to mount an extra EBS volume. Leave as default ("false") to launch without an extra application volume Type: String + AppVolumeDeviceName: + AllowedPattern: '/dev/xvd[f-k]' + Default: '/dev/xvdf' + Description: >- + Device name to be given to the extra EBS volume. Ignored if + "AppVolumeDevice" is false + Type: String AppVolumeEncrypted: AllowedValues: - 'false' @@ -797,7 +805,7 @@ Resources: VolumeType: gp2 - !If - CreateAppVolume - - DeviceName: /dev/xvdf + - DeviceName: !Ref AppVolumeDeviceName Ebs: DeleteOnTermination: true Encrypted: !Ref AppVolumeEncrypted @@ -867,13 +875,12 @@ Resources: #!/bin/bash -xe # Format and mount app volume - APPVOL_DEVICE="$(ls /dev/xvdf /dev/nvme1n1 2> /dev/null || true)" - if [[ -n "$APPVOL_DEVICE" && "${AppVolumeDevice}" == "true" ]] + if [[ "${AppVolumeDevice}" == "true" ]] then MOUNT_VFSTYPE="auto" MOUNT_OPTS="defaults,nofail" - cloud-init-per instance mkfsappvolume mkfs -t ext4 "$APPVOL_DEVICE" - grep -q "$APPVOL_DEVICE" /etc/fstab || printf "%s\t%s\t%s\t%s\t0\t2\n" "$APPVOL_DEVICE" "${AppVolumeMountPath}" "$MOUNT_VFSTYPE" "$MOUNT_OPTS" >> /etc/fstab + cloud-init-per instance mkfsappvolume mkfs -t ext4 "${AppVolumeDeviceName}" + grep -q "${AppVolumeDeviceName}" /etc/fstab || printf "%s\t%s\t%s\t%s\t0\t2\n" "${AppVolumeDeviceName}" "${AppVolumeMountPath}" "$MOUNT_VFSTYPE" "$MOUNT_OPTS" >> /etc/fstab mkdir -p "${AppVolumeMountPath}" mount -a fi diff --git a/modules/win-autoscale/watchmaker-win-autoscale.template.cfn.yaml b/modules/win-autoscale/watchmaker-win-autoscale.template.cfn.yaml index f4375c55..a77f919e 100644 --- a/modules/win-autoscale/watchmaker-win-autoscale.template.cfn.yaml +++ b/modules/win-autoscale/watchmaker-win-autoscale.template.cfn.yaml @@ -194,7 +194,7 @@ Metadata: default: Force Cfn Init Update ToggleNewInstances: default: Force New Instances - Version: 2.1.0 + Version: 2.1.1 Outputs: ScaleDownScheduledAction: Condition: UseScheduledAction @@ -881,28 +881,24 @@ Resources: - UseWamStandalone - !Sub | # Download watchmaker standalone pkg - [Net.ServicePointManager]::SecurityProtocol = "Ssl3, Tls, Tls11, Tls12" + [Net.ServicePointManager]::SecurityProtocol = "Tls12" (New-Object System.Net.WebClient).DownloadFile("${WatchmakerStandaloneUrl}", "c:\cfn\scripts\watchmaker.exe") - !Sub - | + [Net.ServicePointManager]::SecurityProtocol = "Tls12" $BootstrapUrl = "${WatchmakerBootstrapper}" $PythonUrl = "${PythonInstaller}" $PypiUrl = "${PypiIndexUrl}" - # Get the host $PypiHost="$(([System.Uri]$PypiUrl).Host)" - # Download bootstrap file $BootstrapFile = "${!Env:Temp}\$(${!BootstrapUrl}.split('/')[-1])" (New-Object System.Net.WebClient).DownloadFile("$BootstrapUrl", "$BootstrapFile") - # Install python & "$BootstrapFile" -PythonUrl "$PythonUrl" -Verbose -ErrorAction Stop - # Install setup dependencies python -m pip install --index-url="$PypiUrl" --trusted-host="$PypiHost" --upgrade pip setuptools if (-not $?) { throw 'pip failed to install setup dependencies!' } - # Install watchmaker pip install --index-url="$PypiUrl" --trusted-host="$PypiHost" --upgrade boto3 ${local_WatchmakerPkg} if (-not $?) { throw 'pip failed to install watchmaker!' } diff --git a/modules/win-instance/watchmaker-win-instance.template.cfn.yaml b/modules/win-instance/watchmaker-win-instance.template.cfn.yaml index c63e04f8..544bdae8 100644 --- a/modules/win-instance/watchmaker-win-instance.template.cfn.yaml +++ b/modules/win-instance/watchmaker-win-instance.template.cfn.yaml @@ -148,7 +148,7 @@ Metadata: ParameterLabels: ToggleCfnInitUpdate: default: Force Cfn Init Update - Version: 2.1.0 + Version: 2.1.1 Outputs: WatchmakerInstanceId: Description: Instance ID @@ -701,28 +701,24 @@ Resources: - UseWamStandalone - !Sub | # Download watchmaker standalone pkg - [Net.ServicePointManager]::SecurityProtocol = "Ssl3, Tls, Tls11, Tls12" + [Net.ServicePointManager]::SecurityProtocol = "Tls12" (New-Object System.Net.WebClient).DownloadFile("${WatchmakerStandaloneUrl}", "c:\cfn\scripts\watchmaker.exe") - !Sub - | + [Net.ServicePointManager]::SecurityProtocol = "Tls12" $BootstrapUrl = "${WatchmakerBootstrapper}" $PythonUrl = "${PythonInstaller}" $PypiUrl = "${PypiIndexUrl}" - # Get the host $PypiHost="$(([System.Uri]$PypiUrl).Host)" - # Download bootstrap file $BootstrapFile = "${!Env:Temp}\$(${!BootstrapUrl}.split('/')[-1])" (New-Object System.Net.WebClient).DownloadFile("$BootstrapUrl", "$BootstrapFile") - # Install python & "$BootstrapFile" -PythonUrl "$PythonUrl" -Verbose -ErrorAction Stop - # Install setup dependencies python -m pip install --index-url="$PypiUrl" --trusted-host="$PypiHost" --upgrade pip setuptools if (-not $?) { throw 'pip failed to install setup dependencies!' } - # Install watchmaker pip install --index-url="$PypiUrl" --trusted-host="$PypiHost" --upgrade boto3 ${local_WatchmakerPkg} if (-not $?) { throw 'pip failed to install watchmaker!' } diff --git a/tests/data.tf b/tests/data.tf index 0aff574b..5abdcc9d 100644 --- a/tests/data.tf +++ b/tests/data.tf @@ -3,26 +3,6 @@ data "aws_vpc" "this" { default = "true" } -data "aws_ami" "centos6" { - most_recent = true - owners = ["701759196663"] - - filter { - name = "name" - values = ["*spel-minimal-centos-6*"] - } - - filter { - name = "is-public" - values = ["true"] - } - - filter { - name = "state" - values = ["available"] - } -} - data "aws_ami" "centos7" { most_recent = true owners = ["701759196663"] diff --git a/tests/main.tf b/tests/main.tf index 31767b9b..eae60ebd 100644 --- a/tests/main.tf +++ b/tests/main.tf @@ -6,33 +6,6 @@ resource "aws_sns_topic" "tf-aws-wam" { name = "${local.test_prefix}-topic" } -module "lx-instance-centos6" { - source = "../modules/lx-instance" - - Name = "${local.test_prefix}-lx-instance-centos6" - AmiId = data.aws_ami.centos6.image_id - AmiDistro = "CentOS" - AppVolumeDevice = true - AppVolumeEncrypted = true - AppVolumeSize = "10" - CloudWatchAgentUrl = var.cloudwatch_agent_url_centos - DisableRollback = "true" - EbsOptimized = "false" - InstanceRole = var.instance_role - InstanceType = "t2.medium" - KeyPairName = local.keypair_name - KmsKeyId = local.kmskey_id - NoPublicIp = "false" - OnFailureAction = "" - RootVolumeEncrypted = true - RootVolumeSize = "25" - SecurityGroupIds = local.security_group - SubnetId = var.subnet_id - WatchmakerConfig = var.watchmaker_config - WatchmakerEnvironment = var.watchmaker_env - EnableRepos = "epel" -} - module "lx-instance-centos7" { source = "../modules/lx-instance" @@ -47,7 +20,7 @@ module "lx-instance-centos7" { InstanceType = "t3.medium" KeyPairName = local.keypair_name NoPublicIp = "false" - OnFailureAction = "" + OnFailureAction = null RootVolumeSize = "25" SecurityGroupIds = local.security_group SubnetId = var.subnet_id @@ -56,35 +29,6 @@ module "lx-instance-centos7" { EnableRepos = "epel" } -module "lx-autoscale-centos6" { - source = "../modules/lx-autoscale" - - Name = "${local.test_prefix}-lx-autoscale-centos6" - AmiId = data.aws_ami.centos6.image_id - AmiDistro = "CentOS" - AppVolumeDevice = true - AppVolumeEncrypted = true - AppVolumeSize = "10" - AsgMetrics = var.AsgMetrics - AsgNotificationTypes = var.AsgNotificationTypes - AsgSnsArn = aws_sns_topic.tf-aws-wam.arn - CloudWatchAgentUrl = var.cloudwatch_agent_url_centos - DisableRollback = "true" - EbsOptimized = "false" - InstanceRole = var.instance_role - InstanceType = "t2.medium" - KeyPairName = local.keypair_name - NoPublicIp = "false" - OnFailureAction = "" - RootVolumeEncrypted = true - RootVolumeSize = "25" - SecurityGroupIds = local.security_group - SubnetIds = var.subnet_id - WatchmakerConfig = var.watchmaker_config - WatchmakerEnvironment = var.watchmaker_env - EnableRepos = "epel" -} - module "lx-autoscale-centos7" { source = "../modules/lx-autoscale" @@ -102,7 +46,7 @@ module "lx-autoscale-centos7" { InstanceType = "t3.medium" KeyPairName = local.keypair_name NoPublicIp = "false" - OnFailureAction = "" + OnFailureAction = null RootVolumeSize = "25" SecurityGroupIds = local.security_group SubnetIds = var.subnet_id @@ -126,7 +70,7 @@ module "win-instance-2012R2" { InstanceType = "t3.large" KeyPairName = local.keypair_name NoPublicIp = "false" - OnFailureAction = "" + OnFailureAction = null RootVolumeEncrypted = true RootVolumeSize = "35" SecurityGroupIds = local.security_group @@ -151,7 +95,7 @@ module "win-instance-2016" { KeyPairName = local.keypair_name KmsKeyId = local.kmskey_id NoPublicIp = "false" - OnFailureAction = "" + OnFailureAction = null RootVolumeEncrypted = true RootVolumeSize = "35" SecurityGroupIds = local.security_group @@ -173,7 +117,7 @@ module "win-instance-2019" { InstanceType = "t3.large" KeyPairName = local.keypair_name NoPublicIp = "false" - OnFailureAction = "" + OnFailureAction = null RootVolumeSize = "35" SecurityGroupIds = local.security_group SubnetId = var.subnet_id @@ -198,7 +142,7 @@ module "win-autoscale-2012R2" { InstanceType = "t3.large" KeyPairName = local.keypair_name NoPublicIp = "false" - OnFailureAction = "" + OnFailureAction = null RootVolumeEncrypted = true RootVolumeSize = "35" SecurityGroupIds = local.security_group @@ -224,7 +168,7 @@ module "win-autoscale-2016" { InstanceType = "t3.large" KeyPairName = local.keypair_name NoPublicIp = "false" - OnFailureAction = "" + OnFailureAction = null RootVolumeEncrypted = true RootVolumeSize = "35" SecurityGroupIds = local.security_group @@ -248,7 +192,7 @@ module "win-autoscale-2019" { InstanceType = "t3.large" KeyPairName = local.keypair_name NoPublicIp = "false" - OnFailureAction = "" + OnFailureAction = null RootVolumeSize = "35" SecurityGroupIds = local.security_group SubnetIds = var.subnet_id