2633 lines
1.3 MiB
2633 lines
1.3 MiB
{
|
|
"sessionId": "b86444e1-3f32-4f39-9c46-1ce1d2631b8b",
|
|
"projectHash": "cc0b5b68454a59206e0457f5ad30cf64769ce03f6eaf19fb8c5b1adb80414a8d",
|
|
"startTime": "2026-02-20T17:08:08.463Z",
|
|
"lastUpdated": "2026-02-20T17:19:34.051Z",
|
|
"messages": [
|
|
{
|
|
"id": "f71e5361-2293-4164-bc4d-3214a197bc2b",
|
|
"timestamp": "2026-02-20T17:08:08.463Z",
|
|
"type": "user",
|
|
"content": [
|
|
{
|
|
"text": "fix tests due to code changes: Identify failing tests. Analyze failure logs. Implement precise code corrections. Verify test suite pass. user ./scripts/bin/test -l to test"
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"id": "88c65dac-0cfd-41b5-9566-7848580c1ddc",
|
|
"timestamp": "2026-02-20T17:08:10.668Z",
|
|
"type": "gemini",
|
|
"content": "I'll start by running the tests to identify any failures.\n\nExplaning the command: `scripts/bin/test -l` runs the Dalmatian test suite, which includes formatting checks, linters, and terraform validation.",
|
|
"thoughts": [
|
|
{
|
|
"subject": "Starting Test Execution",
|
|
"description": "I've got the task now. I'm gearing up to tackle failing tests in the Dalmatian project, probably triggered by the latest code updates. My plan kicks off with a test run to pinpoint the issues. I'll be using `./scripts/bin/test -l` as the user suggested, to get the ball rolling.",
|
|
"timestamp": "2026-02-20T17:08:10.556Z"
|
|
}
|
|
],
|
|
"tokens": {
|
|
"input": 19237,
|
|
"output": 68,
|
|
"cached": 3338,
|
|
"thoughts": 59,
|
|
"tool": 0,
|
|
"total": 19364
|
|
},
|
|
"model": "gemini-3-flash-preview",
|
|
"toolCalls": [
|
|
{
|
|
"id": "run_shell_command_1771607290667_0",
|
|
"name": "run_shell_command",
|
|
"args": {
|
|
"command": "./scripts/bin/test -l"
|
|
},
|
|
"result": [
|
|
{
|
|
"functionResponse": {
|
|
"id": "run_shell_command_1771607290667_0",
|
|
"name": "run_shell_command",
|
|
"response": {
|
|
"output": "Output too large. Showing first 8,000 and last 32,000 characters. For full output see: /Users/bob/.gemini/tmp/dalmatian/tool-outputs/session-b86444e1-3f32-4f39-9c46-1ce1d2631b8b/run_shell_command_1771607290667_0.txt\nOutput: ==> Linting YAML...\n\n==> Linting shell scripts...\n\n==> Checking Terraform for JSON errors...\n- Checking ./terraform/policies/iam-read.json... Passed\n- Checking ./terraform/policies/s3-rw-with-versioning.json... Passed\n- Checking ./terraform/policies/codestar-connection-use.json... Passed\n- Checking ./terraform/policies/iam-create-access-key.json... Passed\n- Checking ./terraform/policies/codebuild.json... Passed\n- Checking ./terraform/policies/kms-encrypt-decrypt.json... Passed\n- Checking ./terraform/policies/iam-change-password.json... Passed\n- Checking ./terraform/policies/administrator-access.json... Passed\n- Checking ./terraform/policies/assume_roles/aws-backup.json... Passed\n- Checking ./terraform/policies/assume_roles/autoscaling.json... Passed\n- Checking ./terraform/policies/assume_roles/events.json... Passed\n- Checking ./terraform/policies/assume_roles/ecs.json... Passed\n- Checking ./terraform/policies/assume_roles/codepipeline.json... Passed\n- Checking ./terraform/policies/iam-mfa.json... Passed\n- Checking ./terraform/policies/route53-read.json... Passed\n- Checking ./terraform/policies/s3-full-access.json... Passed\n- Checking ./terraform/policies/parameter-store-read-decrypt.json... Passed\n- Checking ./terraform/policies/s3-read.json... Passed\n- Checking ./terraform/policies/parameter-store-RW-encrypt-decrypt.json... Passed\n- Checking ./terraform/policies/all-read-with-billing.json... Passed\n- Checking ./terraform/policies/codebuild-start-build.json... Passed\n- Checking ./terraform/policies/all-read.json... Passed\n\n==> Linting Terraform...\n\n==> Running Ruby tests...\n/Users/bob/.rbenv/versions/2.7.1/bin/ruby -I/Users/bob/.bundles/ruby/2.7.0/gems/rspec-core-3.12.2/lib:/Users/bob/.bundles/ruby/2.7.0/gems/rspec-support-3.12.1/lib /Users/bob/.bundles/ruby/2.7.0/gems/rspec-core-3.12.2/exe/rspec --pattern spec/\\*\\*\\{,/\\*/\\*\\*\\}/\\*_spec.rb\n\ntests local configuration\n use of \"terraform apply\"\n passes the hosted zone config to \"terraform apply\" (FAILED - 1)\n passes the s3 config to \"terraform apply\" (FAILED - 2)\n passes the vpn customer gateway config to \"terraform apply\" (FAILED - 3)\n passes the base config to \"terraform apply\" (FAILED - 4)\n passes the waf config to \"terraform apply\" (FAILED - 5)\n passes the rds config to \"terraform apply\" (FAILED - 6)\n passes the elasticache config to \"terraform apply\" (FAILED - 7)\n passes the opensearch config to \"terraform apply\" (FAILED - 8)\n passes the service config to \"terraform apply\" (FAILED - 9)\n passes the loadbalancer config to \"terraform apply\" (FAILED - 10)\n passes the cluster 2 config to \"terraform apply\" (FAILED - 11)\n passes the cluster 3 config to \"terraform apply\" (FAILED - 12)\n passes the cluster 4 config to \"terraform apply\" (FAILED - 13)\n\ntests remote configuration\n retrieves the remotely held full configuration\n proceeds with deploying the infrastructure as per the cached full configuration\n\ntests local configuration\n invokes \"terraform validate\" with the expected cluster options (FAILED - 14)\n invokes \"terraform validate\" with the expected source options (FAILED - 15)\n use of \"terraform plan\"\n passes the hosted zone config to \"terraform plan\" (FAILED - 16)\n passes the s3 config to \"terraform plan\" (FAILED - 17)\n passes the vpn customer gateway config to \"terraform plan\" (FAILED - 18)\n passes the base config to \"terraform plan\" (FAILED - 19)\n passes the waf config to \"terraform plan\" (FAILED - 20)\n passes the rds config to \"terraform plan\" (FAILED - 21)\n passes the elasticache config to \"terraform plan\" (FAILED - 22)\n passes the opensearch config to \"terraform plan\" (FAILED - 23)\n passes the services config to \"terraform plan\" (FAILED - 24)\n passes the loadbalancer config to \"terraform plan\" (FAILED - 25)\n passes the cluster 2 config to \"terraform plan\" (FAILED - 26)\n passes the cluster 3 config to \"terraform plan\" (FAILED - 27)\n passes the cluster 4 config to \"terraform plan\" (FAILED - 28)\n\nDalmatian::Account\n initialisation\n gathering user input\n asks the user for AWS credentials\n asks the user for the AWS account id to use\n asks the user for an account alias\n #call\n changes to the bootstrapping directory\n runs terraform init with upgrade option\n creates the new workspace using the given aws account id and alias\n runs terraform apply with the user-supplied vars\n\nDalmatian::CacheHandlerSelector\n ::new_for(remote_reference)\n when the remote reference is for a git repo\n asks for an instance of GitCacheHandler\n when the remote reference is for an S3 bucket\n asks for an instance of S3CacheHandler\n when the remote reference is for a URL\n asks for an instance of UrlCacheHandler\n when the type is unknown\n raises an error\n\nCacheHandler\n when a subclass class does not implement #cache_remote_configuration\n raises a helpful error\n\nDalmatian::CI\n CI::PATH\n is a constant\n #deploy\n changes to the ci directory\n runs terraform init with upgrade option\n creates the new workspace using the given aws account id and alias\n runs terraform apply with the user-supplied vars\n #test\n runs terraform plan with the user-supplied vars\n\nDalmatian::ClusterDeployment\n #call\n changes to the ecs directory\n asks Terraform to ensure that the workspace is in place\n when the environment includes a git reference as \"track_revision\"\n does NOT attempt to check out that commit\n when in _plan_ mode\n invokes Terraform.plan using the _dalmatian-read_ role\n when NOT in _plan_ mode\n invokes Terraform.apply using the _dalmatian-admin_\n when in _auto_approve_ mode\n asks Terraform to use auto_approve mode\n\nDalmatian::Cluster\n on initialisation\n makes Hosted zones, S3, Sources, Services, Loadbalancers, WAF and Rds\n #target_directory\n is a standard _ecs_ path\n #id\n is the primary key of the cluster definition is used\n #name\n when the cluster has an explicitly provided _name_ property\n that property is used\n when the cluster does not have an explicitly provided _name_ property\n the primary key of the cluster definition is used\n #account_id\n is the aws account key for deployment\n #sources\n represents any links to remote sources\n #environments\n represents the attributes of each environment's cluster section\n #fetch\n when the source is remotely held\n logs the plan to clone the source into the infrastructure pth\n deletes any existing source at the infrastructure location\n clones each source into the infrastructure location\n changes to the infrastructure directory for each source\n runs rake terrafile\n changes back to the APP_ROOT\n when the source is a local file path\n does not re-clone the source\n does not run terrafile\n when the specified local directory exists\n logs the fact that the local source is in place\n when the specificed local directory does not exist\n logs an error that the local source is missing\n #deploy\n deploys source infrastructure for each source and each service in each environment\n when a cluster should be created\n deploys cluster infrastructure for each environment\n when the _plan_ option IS invoked\n creates Cluster Deployments with plan settings\n when the _auto_approve_ option IS invoked\n creates Cluster Deployments with auto_approve settings\n handling of tests\n when the _test_ option is NOT invoked\n does not run cluster tests\n does not run cluster tests\n does not run cluster tests\n does not run source tests\n does not run waf tests\n does not run rds tests\n does not run service tests\n does not run service tests\n when the test option IS invoked\n runs tests\n when a cluster should NOT be created\n does not deploy cluster infrastructure\n when test option is\n\n... [140,672 characters omitted] ...\n\ntian/cluster.rb:70:in `block (2 levels) in deploy'\n # ./lib/dalmatian/cluster.rb:68:in `each'\n # ./lib/dalmatian/cluster.rb:68:in `block in deploy'\n # ./lib/dalmatian/cluster.rb:59:in `each'\n # ./lib/dalmatian/cluster.rb:59:in `deploy'\n # ./lib/dalmatian/infrastructure.rb:24:in `block in deploy'\n # ./lib/dalmatian/infrastructure.rb:22:in `each'\n # ./lib/dalmatian/infrastructure.rb:22:in `deploy'\n # ./lib/dalmatian/infrastructure.rb:18:in `test'\n # ./spec/integration/tests_local_configuration_spec.rb:3108:in `block (2 levels) in <module:Dalmatian>'\n # ./spec/support/spec_helper.rb:24:in `block (3 levels) in <top (required)>'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:24:in `block in modify'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:15:in `synchronize'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:15:in `modify'\n # ./spec/support/spec_helper.rb:20:in `block (2 levels) in <top (required)>'\n # /Users/bob/.bundles/ruby/2.7.0/gems/webmock-3.19.1/lib/webmock/rspec.rb:39:in `block (2 levels) in <top (required)>'\n\n 24) tests local configuration use of \"terraform plan\" passes the services config to \"terraform plan\"\n Failure/Error: Helper.run!(cmd)\n \n #<Dalmatian::Helper (class)> received :run! with unexpected arguments\n expected: (\"TF_VAR_region='eu-west-2' TF_VAR_cidr='10.0.0.0/16' TF_VAR_root_domain_zone='dalmatian.dxw.net' TF_VAR_internal_domain_zone='dalmatian.internal' TF_VAR_ecs_private_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.128.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.129.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.130.0/24\\\"}]' TF_VAR_extra_public_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.0.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.1.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.2.0/24\\\"}]' TF_VAR_instances_key_name='dalmatian-ecs-instances' TF_VAR_instance_type='t2.medium' TF_VAR_min_servers='2' TF_VAR_max_servers='4' TF_VAR_max_instance_lifetime='86400' TF_VAR_associate_public_ip_address='0' TF_VAR_docker_storage_size='40' TF_VAR_dockerhub_email='' TF_VAR_dockerhub_token='' TF_VAR_enable_efs='false' TF_VAR_encrypt_efs='true' TF_VAR_efs_dirs='[]' TF_VAR_monitoring_docs_path='https://github.com/dxw/dalmatian/docs/monitoring-alarms/' TF_VAR_example_var='bar' TF_VAR_environment='production' TF_VAR_cluster_name='shared-cluster-production' TF_VAR_account_id='123456789012' TF_VAR_infrastructure_name='existing-shared-cluster-production' TF_VAR_dalmatian_role='dalmatian-read' terraform plan\")\n got: (\"TF_VAR_region='eu-west-2' TF_VAR_cidr='10.0.0.0/16' TF_VAR_root_domain_zone='dalmatian.dxw.net' TF_VAR_internal_domain_zone='dalmatian.internal' TF_VAR_ecs_private_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.128.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.129.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.130.0/24\\\"}]' TF_VAR_extra_public_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.0.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.1.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.2.0/24\\\"}]' TF_VAR_instances_key_name='dalmatian-ecs-instances' TF_VAR_instance_type='t2.medium' TF_VAR_min_servers='2' TF_VAR_max_servers='4' TF_VAR_max_instance_lifetime='86400' TF_VAR_associate_public_ip_address='0' TF_VAR_docker_storage_size='40' TF_VAR_dockerhub_email='' TF_VAR_dockerhub_token='' TF_VAR_enable_efs='false' TF_VAR_encrypt_efs='true' TF_VAR_efs_dirs='[]' TF_VAR_monitoring_docs_path='https://github.com/dxw/dalmatian/docs/monitoring-alarms/' TF_VAR_environment='production' TF_VAR_account_id='123456789012' TF_VAR_infrastructure_name='new-dedicated-cluster' TF_VAR_dalmatian_role='dalmatian-read' TF_VAR_rds='{identifier =\\\"testservice\\\",in_use_by =[\\\"test-service\\\"],clusters_in_use ={production =[\\\"test\\\"],staging =[\\\"test\\\"]},instance_class ={production =\\\"db.t2.small\\\",staging =\\\"db.t2.micro\\\"},engine =\\\"postgres\\\",engine_version =\\\"11.4\\\",allocated_storage =20,storage_encrypted =true,storage_type =\\\"gp3\\\",db_name =\\\"testapp\\\",port =5432,maintenance_window =\\\"mon:19:00-mon:19:30\\\",backup_window =\\\"09:00-10:00\\\",backup_retention_period =31,force_ssl =true,parameter_store_path_db_url_name =\\\"DATABASE_URL\\\",sql_backup_scheduled_task_environment_variables =[{name =\\\"foo\\\",value =\\\"bar\\\"}],check_sql_backup_scheduled_task_environment_variables =[{name =\\\"foo\\\",value =\\\"bar\\\"}],sync_sql_backup_to_azure =false,replication_bucket_destination_arn =\\\"\\\",replication_kms_key_id =\\\"\\\",codebuild_access =[\\\"service-name\\\"]}' terraform plan\")\n Please stub a default value first if message might be received with other args as well. \n # ./lib/dalmatian/terraform.rb:25:in `plan'\n # ./lib/dalmatian/deployable.rb:28:in `terraform_plan'\n # ./lib/dalmatian/deployable.rb:8:in `call'\n # ./lib/dalmatian/cluster.rb:269:in `deploy_rds'\n # ./lib/dalmatian/cluster.rb:70:in `block (2 levels) in deploy'\n # ./lib/dalmatian/cluster.rb:68:in `each'\n # ./lib/dalmatian/cluster.rb:68:in `block in deploy'\n # ./lib/dalmatian/cluster.rb:59:in `each'\n # ./lib/dalmatian/cluster.rb:59:in `deploy'\n # ./lib/dalmatian/infrastructure.rb:24:in `block in deploy'\n # ./lib/dalmatian/infrastructure.rb:22:in `each'\n # ./lib/dalmatian/infrastructure.rb:22:in `deploy'\n # ./lib/dalmatian/infrastructure.rb:18:in `test'\n # ./spec/integration/tests_local_configuration_spec.rb:3108:in `block (2 levels) in <module:Dalmatian>'\n # ./spec/support/spec_helper.rb:24:in `block (3 levels) in <top (required)>'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:24:in `block in modify'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:15:in `synchronize'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:15:in `modify'\n # ./spec/support/spec_helper.rb:20:in `block (2 levels) in <top (required)>'\n # /Users/bob/.bundles/ruby/2.7.0/gems/webmock-3.19.1/lib/webmock/rspec.rb:39:in `block (2 levels) in <top (required)>'\n\n 25) tests local configuration use of \"terraform plan\" passes the loadbalancer config to \"terraform plan\"\n Failure/Error: Helper.run!(cmd)\n \n #<Dalmatian::Helper (class)> received :run! with unexpected arguments\n expected: (\"TF_VAR_region='eu-west-2' TF_VAR_cidr='10.0.0.0/16' TF_VAR_root_domain_zone='dalmatian.dxw.net' TF_VAR_internal_domain_zone='dalmatian.internal' TF_VAR_ecs_private_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.128.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.129.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.130.0/24\\\"}]' TF_VAR_extra_public_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.0.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.1.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.2.0/24\\\"}]' TF_VAR_instances_key_name='dalmatian-ecs-instances' TF_VAR_instance_type='t2.medium' TF_VAR_min_servers='2' TF_VAR_max_servers='4' TF_VAR_max_instance_lifetime='86400' TF_VAR_associate_public_ip_address='0' TF_VAR_docker_storage_size='40' TF_VAR_dockerhub_email='' TF_VAR_dockerhub_token='' TF_VAR_enable_efs='false' TF_VAR_encrypt_efs='true' TF_VAR_efs_dirs='[]' TF_VAR_monitoring_docs_path='https://github.com/dxw/dalmatian/docs/monitoring-alarms/' TF_VAR_example_var='bar' TF_VAR_environment='production' TF_VAR_cluster_name='shared-cluster-production' TF_VAR_account_id='123456789012' TF_VAR_infrastructure_name='existing-shared-cluster-production' TF_VAR_dalmatian_role='dalmatian-read' terraform plan\")\n got: (\"TF_VAR_region='eu-west-2' TF_VAR_cidr='10.0.0.0/16' TF_VAR_root_domain_zone='dalmatian.dxw.net' TF_VAR_internal_domain_zone='dalmatian.internal' TF_VAR_ecs_private_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.128.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.129.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.130.0/24\\\"}]' TF_VAR_extra_public_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.0.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.1.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.2.0/24\\\"}]' TF_VAR_instances_key_name='dalmatian-ecs-instances' TF_VAR_instance_type='t2.medium' TF_VAR_min_servers='2' TF_VAR_max_servers='4' TF_VAR_max_instance_lifetime='86400' TF_VAR_associate_public_ip_address='0' TF_VAR_docker_storage_size='40' TF_VAR_dockerhub_email='' TF_VAR_dockerhub_token='' TF_VAR_enable_efs='false' TF_VAR_encrypt_efs='true' TF_VAR_efs_dirs='[]' TF_VAR_monitoring_docs_path='https://github.com/dxw/dalmatian/docs/monitoring-alarms/' TF_VAR_environment='production' TF_VAR_account_id='123456789012' TF_VAR_infrastructure_name='new-dedicated-cluster' TF_VAR_dalmatian_role='dalmatian-read' TF_VAR_rds='{identifier =\\\"testservice\\\",in_use_by =[\\\"test-service\\\"],clusters_in_use ={production =[\\\"test\\\"],staging =[\\\"test\\\"]},instance_class ={production =\\\"db.t2.small\\\",staging =\\\"db.t2.micro\\\"},engine =\\\"postgres\\\",engine_version =\\\"11.4\\\",allocated_storage =20,storage_encrypted =true,storage_type =\\\"gp3\\\",db_name =\\\"testapp\\\",port =5432,maintenance_window =\\\"mon:19:00-mon:19:30\\\",backup_window =\\\"09:00-10:00\\\",backup_retention_period =31,force_ssl =true,parameter_store_path_db_url_name =\\\"DATABASE_URL\\\",sql_backup_scheduled_task_environment_variables =[{name =\\\"foo\\\",value =\\\"bar\\\"}],check_sql_backup_scheduled_task_environment_variables =[{name =\\\"foo\\\",value =\\\"bar\\\"}],sync_sql_backup_to_azure =false,replication_bucket_destination_arn =\\\"\\\",replication_kms_key_id =\\\"\\\",codebuild_access =[\\\"service-name\\\"]}' terraform plan\")\n Please stub a default value first if message might be received with other args as well. \n # ./lib/dalmatian/terraform.rb:25:in `plan'\n # ./lib/dalmatian/deployable.rb:28:in `terraform_plan'\n # ./lib/dalmatian/deployable.rb:8:in `call'\n # ./lib/dalmatian/cluster.rb:269:in `deploy_rds'\n # ./lib/dalmatian/cluster.rb:70:in `block (2 levels) in deploy'\n # ./lib/dalmatian/cluster.rb:68:in `each'\n # ./lib/dalmatian/cluster.rb:68:in `block in deploy'\n # ./lib/dalmatian/cluster.rb:59:in `each'\n # ./lib/dalmatian/cluster.rb:59:in `deploy'\n # ./lib/dalmatian/infrastructure.rb:24:in `block in deploy'\n # ./lib/dalmatian/infrastructure.rb:22:in `each'\n # ./lib/dalmatian/infrastructure.rb:22:in `deploy'\n # ./lib/dalmatian/infrastructure.rb:18:in `test'\n # ./spec/integration/tests_local_configuration_spec.rb:3108:in `block (2 levels) in <module:Dalmatian>'\n # ./spec/support/spec_helper.rb:24:in `block (3 levels) in <top (required)>'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:24:in `block in modify'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:15:in `synchronize'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:15:in `modify'\n # ./spec/support/spec_helper.rb:20:in `block (2 levels) in <top (required)>'\n # /Users/bob/.bundles/ruby/2.7.0/gems/webmock-3.19.1/lib/webmock/rspec.rb:39:in `block (2 levels) in <top (required)>'\n\n 26) tests local configuration use of \"terraform plan\" passes the cluster 2 config to \"terraform plan\"\n Failure/Error: Helper.run!(cmd)\n \n #<Dalmatian::Helper (class)> received :run! with unexpected arguments\n expected: (\"TF_VAR_region='eu-west-2' TF_VAR_cidr='10.0.0.0/16' TF_VAR_root_domain_zone='dalmatian.dxw.net' TF_VAR_internal_domain_zone='dalmatian.internal' TF_VAR_ecs_private_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.128.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.129.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.130.0/24\\\"}]' TF_VAR_extra_public_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.0.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.1.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.2.0/24\\\"}]' TF_VAR_instances_key_name='dalmatian-ecs-instances' TF_VAR_instance_type='t2.medium' TF_VAR_min_servers='2' TF_VAR_max_servers='4' TF_VAR_max_instance_lifetime='86400' TF_VAR_associate_public_ip_address='0' TF_VAR_docker_storage_size='40' TF_VAR_dockerhub_email='' TF_VAR_dockerhub_token='' TF_VAR_enable_efs='false' TF_VAR_encrypt_efs='true' TF_VAR_efs_dirs='[]' TF_VAR_monitoring_docs_path='https://github.com/dxw/dalmatian/docs/monitoring-alarms/' TF_VAR_example_var='bar' TF_VAR_environment='production' TF_VAR_cluster_name='shared-cluster-production' TF_VAR_account_id='123456789012' TF_VAR_infrastructure_name='existing-shared-cluster-production' TF_VAR_dalmatian_role='dalmatian-read' terraform plan\")\n got: (\"TF_VAR_region='eu-west-2' TF_VAR_cidr='10.0.0.0/16' TF_VAR_root_domain_zone='dalmatian.dxw.net' TF_VAR_internal_domain_zone='dalmatian.internal' TF_VAR_ecs_private_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.128.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.129.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.130.0/24\\\"}]' TF_VAR_extra_public_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.0.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.1.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.2.0/24\\\"}]' TF_VAR_instances_key_name='dalmatian-ecs-instances' TF_VAR_instance_type='t2.medium' TF_VAR_min_servers='2' TF_VAR_max_servers='4' TF_VAR_max_instance_lifetime='86400' TF_VAR_associate_public_ip_address='0' TF_VAR_docker_storage_size='40' TF_VAR_dockerhub_email='' TF_VAR_dockerhub_token='' TF_VAR_enable_efs='false' TF_VAR_encrypt_efs='true' TF_VAR_efs_dirs='[]' TF_VAR_monitoring_docs_path='https://github.com/dxw/dalmatian/docs/monitoring-alarms/' TF_VAR_environment='production' TF_VAR_account_id='123456789012' TF_VAR_infrastructure_name='new-dedicated-cluster' TF_VAR_dalmatian_role='dalmatian-read' TF_VAR_rds='{identifier =\\\"testservice\\\",in_use_by =[\\\"test-service\\\"],clusters_in_use ={production =[\\\"test\\\"],staging =[\\\"test\\\"]},instance_class ={production =\\\"db.t2.small\\\",staging =\\\"db.t2.micro\\\"},engine =\\\"postgres\\\",engine_version =\\\"11.4\\\",allocated_storage =20,storage_encrypted =true,storage_type =\\\"gp3\\\",db_name =\\\"testapp\\\",port =5432,maintenance_window =\\\"mon:19:00-mon:19:30\\\",backup_window =\\\"09:00-10:00\\\",backup_retention_period =31,force_ssl =true,parameter_store_path_db_url_name =\\\"DATABASE_URL\\\",sql_backup_scheduled_task_environment_variables =[{name =\\\"foo\\\",value =\\\"bar\\\"}],check_sql_backup_scheduled_task_environment_variables =[{name =\\\"foo\\\",value =\\\"bar\\\"}],sync_sql_backup_to_azure =false,replication_bucket_destination_arn =\\\"\\\",replication_kms_key_id =\\\"\\\",codebuild_access =[\\\"service-name\\\"]}' terraform plan\")\n Please stub a default value first if message might be received with other args as well. \n # ./lib/dalmatian/terraform.rb:25:in `plan'\n # ./lib/dalmatian/deployable.rb:28:in `terraform_plan'\n # ./lib/dalmatian/deployable.rb:8:in `call'\n # ./lib/dalmatian/cluster.rb:269:in `deploy_rds'\n # ./lib/dalmatian/cluster.rb:70:in `block (2 levels) in deploy'\n # ./lib/dalmatian/cluster.rb:68:in `each'\n # ./lib/dalmatian/cluster.rb:68:in `block in deploy'\n # ./lib/dalmatian/cluster.rb:59:in `each'\n # ./lib/dalmatian/cluster.rb:59:in `deploy'\n # ./lib/dalmatian/infrastructure.rb:24:in `block in deploy'\n # ./lib/dalmatian/infrastructure.rb:22:in `each'\n # ./lib/dalmatian/infrastructure.rb:22:in `deploy'\n # ./lib/dalmatian/infrastructure.rb:18:in `test'\n # ./spec/integration/tests_local_configuration_spec.rb:3108:in `block (2 levels) in <module:Dalmatian>'\n # ./spec/support/spec_helper.rb:24:in `block (3 levels) in <top (required)>'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:24:in `block in modify'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:15:in `synchronize'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:15:in `modify'\n # ./spec/support/spec_helper.rb:20:in `block (2 levels) in <top (required)>'\n # /Users/bob/.bundles/ruby/2.7.0/gems/webmock-3.19.1/lib/webmock/rspec.rb:39:in `block (2 levels) in <top (required)>'\n\n 27) tests local configuration use of \"terraform plan\" passes the cluster 3 config to \"terraform plan\"\n Failure/Error: Helper.run!(cmd)\n \n #<Dalmatian::Helper (class)> received :run! with unexpected arguments\n expected: (\"TF_VAR_region='eu-west-2' TF_VAR_cidr='10.0.0.0/16' TF_VAR_root_domain_zone='dalmatian.dxw.net' TF_VAR_internal_domain_zone='dalmatian.internal' TF_VAR_ecs_private_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.128.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.129.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.130.0/24\\\"}]' TF_VAR_extra_public_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.0.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.1.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.2.0/24\\\"}]' TF_VAR_instances_key_name='dalmatian-ecs-instances' TF_VAR_instance_type='t2.medium' TF_VAR_min_servers='2' TF_VAR_max_servers='4' TF_VAR_max_instance_lifetime='86400' TF_VAR_associate_public_ip_address='0' TF_VAR_docker_storage_size='40' TF_VAR_dockerhub_email='' TF_VAR_dockerhub_token='' TF_VAR_enable_efs='false' TF_VAR_encrypt_efs='true' TF_VAR_efs_dirs='[]' TF_VAR_monitoring_docs_path='https://github.com/dxw/dalmatian/docs/monitoring-alarms/' TF_VAR_example_var='bar' TF_VAR_environment='production' TF_VAR_cluster_name='shared-cluster-production' TF_VAR_account_id='123456789012' TF_VAR_infrastructure_name='existing-shared-cluster-production' TF_VAR_dalmatian_role='dalmatian-read' terraform plan\")\n got: (\"TF_VAR_region='eu-west-2' TF_VAR_cidr='10.0.0.0/16' TF_VAR_root_domain_zone='dalmatian.dxw.net' TF_VAR_internal_domain_zone='dalmatian.internal' TF_VAR_ecs_private_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.128.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.129.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.130.0/24\\\"}]' TF_VAR_extra_public_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.0.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.1.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.2.0/24\\\"}]' TF_VAR_instances_key_name='dalmatian-ecs-instances' TF_VAR_instance_type='t2.medium' TF_VAR_min_servers='2' TF_VAR_max_servers='4' TF_VAR_max_instance_lifetime='86400' TF_VAR_associate_public_ip_address='0' TF_VAR_docker_storage_size='40' TF_VAR_dockerhub_email='' TF_VAR_dockerhub_token='' TF_VAR_enable_efs='false' TF_VAR_encrypt_efs='true' TF_VAR_efs_dirs='[]' TF_VAR_monitoring_docs_path='https://github.com/dxw/dalmatian/docs/monitoring-alarms/' TF_VAR_environment='production' TF_VAR_account_id='123456789012' TF_VAR_infrastructure_name='new-dedicated-cluster' TF_VAR_dalmatian_role='dalmatian-read' TF_VAR_rds='{identifier =\\\"testservice\\\",in_use_by =[\\\"test-service\\\"],clusters_in_use ={production =[\\\"test\\\"],staging =[\\\"test\\\"]},instance_class ={production =\\\"db.t2.small\\\",staging =\\\"db.t2.micro\\\"},engine =\\\"postgres\\\",engine_version =\\\"11.4\\\",allocated_storage =20,storage_encrypted =true,storage_type =\\\"gp3\\\",db_name =\\\"testapp\\\",port =5432,maintenance_window =\\\"mon:19:00-mon:19:30\\\",backup_window =\\\"09:00-10:00\\\",backup_retention_period =31,force_ssl =true,parameter_store_path_db_url_name =\\\"DATABASE_URL\\\",sql_backup_scheduled_task_environment_variables =[{name =\\\"foo\\\",value =\\\"bar\\\"}],check_sql_backup_scheduled_task_environment_variables =[{name =\\\"foo\\\",value =\\\"bar\\\"}],sync_sql_backup_to_azure =false,replication_bucket_destination_arn =\\\"\\\",replication_kms_key_id =\\\"\\\",codebuild_access =[\\\"service-name\\\"]}' terraform plan\")\n Please stub a default value first if message might be received with other args as well. \n # ./lib/dalmatian/terraform.rb:25:in `plan'\n # ./lib/dalmatian/deployable.rb:28:in `terraform_plan'\n # ./lib/dalmatian/deployable.rb:8:in `call'\n # ./lib/dalmatian/cluster.rb:269:in `deploy_rds'\n # ./lib/dalmatian/cluster.rb:70:in `block (2 levels) in deploy'\n # ./lib/dalmatian/cluster.rb:68:in `each'\n # ./lib/dalmatian/cluster.rb:68:in `block in deploy'\n # ./lib/dalmatian/cluster.rb:59:in `each'\n # ./lib/dalmatian/cluster.rb:59:in `deploy'\n # ./lib/dalmatian/infrastructure.rb:24:in `block in deploy'\n # ./lib/dalmatian/infrastructure.rb:22:in `each'\n # ./lib/dalmatian/infrastructure.rb:22:in `deploy'\n # ./lib/dalmatian/infrastructure.rb:18:in `test'\n # ./spec/integration/tests_local_configuration_spec.rb:3108:in `block (2 levels) in <module:Dalmatian>'\n # ./spec/support/spec_helper.rb:24:in `block (3 levels) in <top (required)>'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:24:in `block in modify'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:15:in `synchronize'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:15:in `modify'\n # ./spec/support/spec_helper.rb:20:in `block (2 levels) in <top (required)>'\n # /Users/bob/.bundles/ruby/2.7.0/gems/webmock-3.19.1/lib/webmock/rspec.rb:39:in `block (2 levels) in <top (required)>'\n\n 28) tests local configuration use of \"terraform plan\" passes the cluster 4 config to \"terraform plan\"\n Failure/Error: Helper.run!(cmd)\n \n #<Dalmatian::Helper (class)> received :run! with unexpected arguments\n expected: (\"TF_VAR_region='eu-west-2' TF_VAR_cidr='10.0.0.0/16' TF_VAR_root_domain_zone='dalmatian.dxw.net' TF_VAR_internal_domain_zone='dalmatian.internal' TF_VAR_ecs_private_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.128.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.129.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.130.0/24\\\"}]' TF_VAR_extra_public_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.0.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.1.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.2.0/24\\\"}]' TF_VAR_instances_key_name='dalmatian-ecs-instances' TF_VAR_instance_type='t2.medium' TF_VAR_min_servers='2' TF_VAR_max_servers='4' TF_VAR_max_instance_lifetime='86400' TF_VAR_associate_public_ip_address='0' TF_VAR_docker_storage_size='40' TF_VAR_dockerhub_email='' TF_VAR_dockerhub_token='' TF_VAR_enable_efs='false' TF_VAR_encrypt_efs='true' TF_VAR_efs_dirs='[]' TF_VAR_monitoring_docs_path='https://github.com/dxw/dalmatian/docs/monitoring-alarms/' TF_VAR_example_var='bar' TF_VAR_environment='production' TF_VAR_cluster_name='shared-cluster-production' TF_VAR_account_id='123456789012' TF_VAR_infrastructure_name='existing-shared-cluster-production' TF_VAR_dalmatian_role='dalmatian-read' terraform plan\")\n got: (\"TF_VAR_region='eu-west-2' TF_VAR_cidr='10.0.0.0/16' TF_VAR_root_domain_zone='dalmatian.dxw.net' TF_VAR_internal_domain_zone='dalmatian.internal' TF_VAR_ecs_private_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.128.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.129.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.130.0/24\\\"}]' TF_VAR_extra_public_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.0.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.1.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.2.0/24\\\"}]' TF_VAR_instances_key_name='dalmatian-ecs-instances' TF_VAR_instance_type='t2.medium' TF_VAR_min_servers='2' TF_VAR_max_servers='4' TF_VAR_max_instance_lifetime='86400' TF_VAR_associate_public_ip_address='0' TF_VAR_docker_storage_size='40' TF_VAR_dockerhub_email='' TF_VAR_dockerhub_token='' TF_VAR_enable_efs='false' TF_VAR_encrypt_efs='true' TF_VAR_efs_dirs='[]' TF_VAR_monitoring_docs_path='https://github.com/dxw/dalmatian/docs/monitoring-alarms/' TF_VAR_environment='production' TF_VAR_account_id='123456789012' TF_VAR_infrastructure_name='new-dedicated-cluster' TF_VAR_dalmatian_role='dalmatian-read' TF_VAR_rds='{identifier =\\\"testservice\\\",in_use_by =[\\\"test-service\\\"],clusters_in_use ={production =[\\\"test\\\"],staging =[\\\"test\\\"]},instance_class ={production =\\\"db.t2.small\\\",staging =\\\"db.t2.micro\\\"},engine =\\\"postgres\\\",engine_version =\\\"11.4\\\",allocated_storage =20,storage_encrypted =true,storage_type =\\\"gp3\\\",db_name =\\\"testapp\\\",port =5432,maintenance_window =\\\"mon:19:00-mon:19:30\\\",backup_window =\\\"09:00-10:00\\\",backup_retention_period =31,force_ssl =true,parameter_store_path_db_url_name =\\\"DATABASE_URL\\\",sql_backup_scheduled_task_environment_variables =[{name =\\\"foo\\\",value =\\\"bar\\\"}],check_sql_backup_scheduled_task_environment_variables =[{name =\\\"foo\\\",value =\\\"bar\\\"}],sync_sql_backup_to_azure =false,replication_bucket_destination_arn =\\\"\\\",replication_kms_key_id =\\\"\\\",codebuild_access =[\\\"service-name\\\"]}' terraform plan\")\n Please stub a default value first if message might be received with other args as well. \n # ./lib/dalmatian/terraform.rb:25:in `plan'\n # ./lib/dalmatian/deployable.rb:28:in `terraform_plan'\n # ./lib/dalmatian/deployable.rb:8:in `call'\n # ./lib/dalmatian/cluster.rb:269:in `deploy_rds'\n # ./lib/dalmatian/cluster.rb:70:in `block (2 levels) in deploy'\n # ./lib/dalmatian/cluster.rb:68:in `each'\n # ./lib/dalmatian/cluster.rb:68:in `block in deploy'\n # ./lib/dalmatian/cluster.rb:59:in `each'\n # ./lib/dalmatian/cluster.rb:59:in `deploy'\n # ./lib/dalmatian/infrastructure.rb:24:in `block in deploy'\n # ./lib/dalmatian/infrastructure.rb:22:in `each'\n # ./lib/dalmatian/infrastructure.rb:22:in `deploy'\n # ./lib/dalmatian/infrastructure.rb:18:in `test'\n # ./spec/integration/tests_local_configuration_spec.rb:3108:in `block (2 levels) in <module:Dalmatian>'\n # ./spec/support/spec_helper.rb:24:in `block (3 levels) in <top (required)>'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:24:in `block in modify'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:15:in `synchronize'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:15:in `modify'\n # ./spec/support/spec_helper.rb:20:in `block (2 levels) in <top (required)>'\n # /Users/bob/.bundles/ruby/2.7.0/gems/webmock-3.19.1/lib/webmock/rspec.rb:39:in `block (2 levels) in <top (required)>'\n\nFinished in 2.42 seconds (files took 0.74146 seconds to load)\n478 examples, 28 failures\n\nFailed examples:\n\nrspec ./spec/integration/deploys_local_configuration_spec.rb:1581 # tests local configuration use of \"terraform apply\" passes the hosted zone config to \"terraform apply\"\nrspec ./spec/integration/deploys_local_configuration_spec.rb:1585 # tests local configuration use of \"terraform apply\" passes the s3 config to \"terraform apply\"\nrspec ./spec/integration/deploys_local_configuration_spec.rb:1589 # tests local configuration use of \"terraform apply\" passes the vpn customer gateway config to \"terraform apply\"\nrspec ./spec/integration/deploys_local_configuration_spec.rb:1593 # tests local configuration use of \"terraform apply\" passes the base config to \"terraform apply\"\nrspec ./spec/integration/deploys_local_configuration_spec.rb:1598 # tests local configuration use of \"terraform apply\" passes the waf config to \"terraform apply\"\nrspec ./spec/integration/deploys_local_configuration_spec.rb:1605 # tests local configuration use of \"terraform apply\" passes the rds config to \"terraform apply\"\nrspec ./spec/integration/deploys_local_configuration_spec.rb:1612 # tests local configuration use of \"terraform apply\" passes the elasticache config to \"terraform apply\"\nrspec ./spec/integration/deploys_local_configuration_spec.rb:1621 # tests local configuration use of \"terraform apply\" passes the opensearch config to \"terraform apply\"\nrspec ./spec/integration/deploys_local_configuration_spec.rb:1630 # tests local configuration use of \"terraform apply\" passes the service config to \"terraform apply\"\nrspec ./spec/integration/deploys_local_configuration_spec.rb:1637 # tests local configuration use of \"terraform apply\" passes the loadbalancer config to \"terraform apply\"\nrspec ./spec/integration/deploys_local_configuration_spec.rb:1646 # tests local configuration use of \"terraform apply\" passes the cluster 2 config to \"terraform apply\"\nrspec ./spec/integration/deploys_local_configuration_spec.rb:1653 # tests local configuration use of \"terraform apply\" passes the cluster 3 config to \"terraform apply\"\nrspec ./spec/integration/deploys_local_configuration_spec.rb:1657 # tests local configuration use of \"terraform apply\" passes the cluster 4 config to \"terraform apply\"\nrspec ./spec/integration/tests_local_configuration_spec.rb:3111 # tests local configuration invokes \"terraform validate\" with the expected cluster options\nrspec ./spec/integration/tests_local_configuration_spec.rb:3147 # tests local configuration invokes \"terraform validate\" with the expected source options\nrspec ./spec/integration/tests_local_configuration_spec.rb:3153 # tests local configuration use of \"terraform plan\" passes the hosted zone config to \"terraform plan\"\nrspec ./spec/integration/tests_local_configuration_spec.rb:3159 # tests local configuration use of \"terraform plan\" passes the s3 config to \"terraform plan\"\nrspec ./spec/integration/tests_local_configuration_spec.rb:3165 # tests local configuration use of \"terraform plan\" passes the vpn customer gateway config to \"terraform plan\"\nrspec ./spec/integration/tests_local_configuration_spec.rb:3171 # tests local configuration use of \"terraform plan\" passes the base config to \"terraform plan\"\nrspec ./spec/integration/tests_local_configuration_spec.rb:3178 # tests local configuration use of \"terraform plan\" passes the waf config to \"terraform plan\"\nrspec ./spec/integration/tests_local_configuration_spec.rb:3185 # tests local configuration use of \"terraform plan\" passes the rds config to \"terraform plan\"\nrspec ./spec/integration/tests_local_configuration_spec.rb:3192 # tests local configuration use of \"terraform plan\" passes the elasticache config to \"terraform plan\"\nrspec ./spec/integration/tests_local_configuration_spec.rb:3201 # tests local configuration use of \"terraform plan\" passes the opensearch config to \"terraform plan\"\nrspec ./spec/integration/tests_local_configuration_spec.rb:3210 # tests local configuration use of \"terraform plan\" passes the services config to \"terraform plan\"\nrspec ./spec/integration/tests_local_configuration_spec.rb:3217 # tests local configuration use of \"terraform plan\" passes the loadbalancer config to \"terraform plan\"\nrspec ./spec/integration/tests_local_configuration_spec.rb:3226 # tests local configuration use of \"terraform plan\" passes the cluster 2 config to \"terraform plan\"\nrspec ./spec/integration/tests_local_configuration_spec.rb:3233 # tests local configuration use of \"terraform plan\" passes the cluster 3 config to \"terraform plan\"\nrspec ./spec/integration/tests_local_configuration_spec.rb:3237 # tests local configuration use of \"terraform plan\" passes the cluster 4 config to \"terraform plan\"\n\nCoverage report generated for RSpec to /Users/bob/git/dxw/dalmatian/coverage. 4253 / 4389 LOC (96.9%) covered.\nStopped processing SimpleCov as a previous error not related to SimpleCov has been detected\n/Users/bob/.rbenv/versions/2.7.1/bin/ruby -I/Users/bob/.bundles/ruby/2.7.0/gems/rspec-core-3.12.2/lib:/Users/bob/.bundles/ruby/2.7.0/gems/rspec-support-3.12.1/lib /Users/bob/.bundles/ruby/2.7.0/gems/rspec-core-3.12.2/exe/rspec --pattern spec/\\*\\*\\{,/\\*/\\*\\*\\}/\\*_spec.rb failed\nExit Code: 1\nProcess Group PGID: 46910"
|
|
}
|
|
}
|
|
}
|
|
],
|
|
"status": "success",
|
|
"timestamp": "2026-02-20T17:08:24.638Z",
|
|
"resultDisplay": "==> Linting YAML...\n\n==> Linting shell scripts...\n\n==> Checking Terraform for JSON errors...\n- Checking ./terraform/policies/iam-read.json... Passed\n- Checking ./terraform/policies/s3-rw-with-versioning.json... Passed\n- Checking ./terraform/policies/codestar-connection-use.json... Passed\n- Checking ./terraform/policies/iam-create-access-key.json... Passed\n- Checking ./terraform/policies/codebuild.json... Passed\n- Checking ./terraform/policies/kms-encrypt-decrypt.json... Passed\n- Checking ./terraform/policies/iam-change-password.json... Passed\n- Checking ./terraform/policies/administrator-access.json... Passed\n- Checking ./terraform/policies/assume_roles/aws-backup.json... Passed\n- Checking ./terraform/policies/assume_roles/autoscaling.json... Passed\n- Checking ./terraform/policies/assume_roles/events.json... Passed\n- Checking ./terraform/policies/assume_roles/ecs.json... Passed\n- Checking ./terraform/policies/assume_roles/codepipeline.json... Passed\n- Checking ./terraform/policies/iam-mfa.json... Passed\n- Checking ./terraform/policies/route53-read.json... Passed\n- Checking ./terraform/policies/s3-full-access.json... Passed\n- Checking ./terraform/policies/parameter-store-read-decrypt.json... Passed\n- Checking ./terraform/policies/s3-read.json... Passed\n- Checking ./terraform/policies/parameter-store-RW-encrypt-decrypt.json... Passed\n- Checking ./terraform/policies/all-read-with-billing.json... Passed\n- Checking ./terraform/policies/codebuild-start-build.json... Passed\n- Checking ./terraform/policies/all-read.json... Passed\n\n==> Linting Terraform...\n\n==> Running Ruby tests...\n/Users/bob/.rbenv/versions/2.7.1/bin/ruby -I/Users/bob/.bundles/ruby/2.7.0/gems/rspec-core-3.12.2/lib:/Users/bob/.bundles/ruby/2.7.0/gems/rspec-support-3.12.1/lib /Users/bob/.bundles/ruby/2.7.0/gems/rspec-core-3.12.2/exe/rspec --pattern spec/\\*\\*\\{,/\\*/\\*\\*\\}/\\*_spec.rb\n\ntests local configuration\n use of \"terraform apply\"\n passes the hosted zone config to \"terraform apply\" (FAILED - 1)\n passes the s3 config to \"terraform apply\" (FAILED - 2)\n passes the vpn customer gateway config to \"terraform apply\" (FAILED - 3)\n passes the base config to \"terraform apply\" (FAILED - 4)\n passes the waf config to \"terraform apply\" (FAILED - 5)\n passes the rds config to \"terraform apply\" (FAILED - 6)\n passes the elasticache config to \"terraform apply\" (FAILED - 7)\n passes the opensearch config to \"terraform apply\" (FAILED - 8)\n passes the service config to \"terraform apply\" (FAILED - 9)\n passes the loadbalancer config to \"terraform apply\" (FAILED - 10)\n passes the cluster 2 config to \"terraform apply\" (FAILED - 11)\n passes the cluster 3 config to \"terraform apply\" (FAILED - 12)\n passes the cluster 4 config to \"terraform apply\" (FAILED - 13)\n\ntests remote configuration\n retrieves the remotely held full configuration\n proceeds with deploying the infrastructure as per the cached full configuration\n\ntests local configuration\n invokes \"terraform validate\" with the expected cluster options (FAILED - 14)\n invokes \"terraform validate\" with the expected source options (FAILED - 15)\n use of \"terraform plan\"\n passes the hosted zone config to \"terraform plan\" (FAILED - 16)\n passes the s3 config to \"terraform plan\" (FAILED - 17)\n passes the vpn customer gateway config to \"terraform plan\" (FAILED - 18)\n passes the base config to \"terraform plan\" (FAILED - 19)\n passes the waf config to \"terraform plan\" (FAILED - 20)\n passes the rds config to \"terraform plan\" (FAILED - 21)\n passes the elasticache config to \"terraform plan\" (FAILED - 22)\n passes the opensearch config to \"terraform plan\" (FAILED - 23)\n passes the services config to \"terraform plan\" (FAILED - 24)\n passes the loadbalancer config to \"terraform plan\" (FAILED - 25)\n passes the cluster 2 config to \"terraform plan\" (FAILED - 26)\n passes the cluster 3 config to \"terraform plan\" (FAILED - 27)\n passes the cluster 4 config to \"terraform plan\" (FAILED - 28)\n\nDalmatian::Account\n initialisation\n gathering user input\n asks the user for AWS credentials\n asks the user for the AWS account id to use\n asks the user for an account alias\n #call\n changes to the bootstrapping directory\n runs terraform init with upgrade option\n creates the new workspace using the given aws account id and alias\n runs terraform apply with the user-supplied vars\n\nDalmatian::CacheHandlerSelector\n ::new_for(remote_reference)\n when the remote reference is for a git repo\n asks for an instance of GitCacheHandler\n when the remote reference is for an S3 bucket\n asks for an instance of S3CacheHandler\n when the remote reference is for a URL\n asks for an instance of UrlCacheHandler\n when the type is unknown\n raises an error\n\nCacheHandler\n when a subclass class does not implement #cache_remote_configuration\n raises a helpful error\n\nDalmatian::CI\n CI::PATH\n is a constant\n #deploy\n changes to the ci directory\n runs terraform init with upgrade option\n creates the new workspace using the given aws account id and alias\n runs terraform apply with the user-supplied vars\n #test\n runs terraform plan with the user-supplied vars\n\nDalmatian::ClusterDeployment\n #call\n changes to the ecs directory\n asks Terraform to ensure that the workspace is in place\n when the environment includes a git reference as \"track_revision\"\n does NOT attempt to check out that commit\n when in _plan_ mode\n invokes Terraform.plan using the _dalmatian-read_ role\n when NOT in _plan_ mode\n invokes Terraform.apply using the _dalmatian-admin_\n when in _auto_approve_ mode\n asks Terraform to use auto_approve mode\n\nDalmatian::Cluster\n on initialisation\n makes Hosted zones, S3, Sources, Services, Loadbalancers, WAF and Rds\n #target_directory\n is a standard _ecs_ path\n #id\n is the primary key of the cluster definition is used\n #name\n when the cluster has an explicitly provided _name_ property\n that property is used\n when the cluster does not have an explicitly provided _name_ property\n the primary key of the cluster definition is used\n #account_id\n is the aws account key for deployment\n #sources\n represents any links to remote sources\n #environments\n represents the attributes of each environment's cluster section\n #fetch\n when the source is remotely held\n logs the plan to clone the source into the infrastructure pth\n deletes any existing source at the infrastructure location\n clones each source into the infrastructure location\n changes to the infrastructure directory for each source\n runs rake terrafile\n changes back to the APP_ROOT\n when the source is a local file path\n does not re-clone the source\n does not run terrafile\n when the specified local directory exists\n logs the fact that the local source is in place\n when the specificed local directory does not exist\n logs an error that the local source is missing\n #deploy\n deploys source infrastructure for each source and each service in each environment\n when a cluster should be created\n deploys cluster infrastructure for each environment\n when the _plan_ option IS invoked\n creates Cluster Deployments with plan settings\n when the _auto_approve_ option IS invoked\n creates Cluster Deployments with auto_approve settings\n handling of tests\n when the _test_ option is NOT invoked\n does not run cluster tests\n does not run cluster tests\n does not run cluster tests\n does not run source tests\n does not run waf tests\n does not run rds tests\n does not run service tests\n does not run service tests\n when the test option IS invoked\n runs tests\n when a cluster should NOT be created\n does not deploy cluster infrastructure\n when test option is invoked\n tests sources and services for each environment\n\nDalmatian::ClusterTest\n #call\n changes to the ecs directory\n logs our intention to run Terraform init\n runs Terraform init, with upgrade option\n ensures presence of workspace\n logs our intention to run Terraform fmt\n runs Terraform fmt with check and diff options\n logs our intention to run Terraform validate\n runs Terraform validate, with upgrade option\n changes back to the app root directory\n when the environment includes a git reference as \"track_revision\"\n does NOT attempt to check out that commit\n\nDalmatian::ConfigurationReader\n when a full configuration is provided in a local file\n #call\n has no need to use a cache handler\n returns the loaded configuration\n when a reference to a remote configuration is provided\n and the reference is provided in a local file\n uses the CacheHandlerSelector to provide the appropriate retrieval mechanism\n calls on the selected cache handler\n returns the configuration returned by the cache_handler\n and the reference is provided using environment variables\n passes the provided remote reference to the CacheHandlerSelector\n and references are provided in both environment variables and config file\n prefers the environment variable references over the config file\n and no references are provided\n raises an error\n and the remote reference is missing its _type_\n raises an error\n #ci\n when a parameter path prefix is given\n overwrites the ci:variables config with those retrieved from the param store\n leaves other ci:variables in place\n when a parameter path prefix is NOT given\n does NOT overwrite any ci:variables from the param store\n\nDalmatian::ElasticacheCluster\n #identifier\n uses elasticache identifier\n #in_use_by\n uses elasticache_cluster in_use_by list\n #node_type\n uses elasticache_cluster node_type\n #node_count\n uses elasticache_cluster node_count\n #engine\n uses elasticache_cluster engine\n #engine_version\n uses the elasticache_cluster engine_version\n #parameters\n uses the elasticache_cluster parameters list\n #port\n uses the elasticache_cluster port\n #maintenance_window\n uses the elasticache_cluster maintenance_window\n #snapshot_window\n uses the elasticache_cluster snapshot_window\n #parameter_store_path_elasticache_cluster_url_name\n uses the elasticache_cluster parameter_store_path_elasticache_cluster_url_name\n #to_params\n provides a hash of attributes for use in deployment\n\nDalmatian::ElasticacheClusterTest\n #call\n changes to the elasticache-cluster directory\n logs our intention to run Terraform init\n runs Terraform init, with upgrade option\n ensures presence of workspace\n logs our intention to run Terraform fmt\n runs Terraform fmt with check and diff options\n logs our intention to run Terraform validate\n runs Terraform validate, with upgrade option\n changes back to the app root directory\n\nDalmatian::GitCacheHandler\n #call\n deletes any old cache\n uses git clone to save the remote config to a local cache\n logs the cloning action\n logs the path to the cached configuration\n returns the cached full configuration to the caller (configuration reader)\n reads the cached full configuration from the disk in order to return to caller\n when no special cache path is given\n uses the default cache path of ./.dalmatian_cache/remote_config\n\nDalmatian::Helper\n ::git_clone(source, destination)\n when source and destination args are not provided\n raises an error with usage info\n when given source and destination args\n passes the request to the git CLI\n ::git_checkout(revision)\n checks out the given revision using run!\n ::get(source, destination)\n when source and destination args are not provided\n raises an error with usage info\n when given source and destination args\n opens the source url\n opens a new file at the destination\n writes the source resource into that file\n reads the information from the fetched resource\n ::run!\n passes given cmd to Kernel.system\n when the call to Kernel.system returns _false_\n raise a helpful error\n ::run_with_output!(cmd)\n passes given cmd to Open3.capture3\n when the system call returns a zero exit status\n returns the systems output to STDOUT\n when the system call returns a non-zero exit status\n also returns STDOUT ignoring the exit code and STDERR\n when the system call raises an ENOENT error\n catches this and raises a helpful Error\n ::change_to(path)\n passes the given path to Dir.chdir\n ::to_bool(str)\n when given nil\n returns false\n when given an empty string\n returns false\n when given lower case string _true_\n returns true\n when given mixed case string _True_\n returns true\n when given the object true\n returns true\n when given the object false\n returns false\n ::tflint\n runs the tflint cmd\n ::terrafile\n runs rake terrafile\n ::ask\n delegates to HighLine#ask\n ::ask_in_confidence\n delegates to HighLine#ask\n passes a block to mask the answer\n\nDalmatian::HostedZoneDeployment\n #call\n changes to hosted-zone infrastructure directory\n asks Terraform to ensure that the workspace is in place\n when in _plan_ mode\n invokes Terraform.plan with the _dalmatian-read_ role\n when NOT in _plan_ mode\n invokes Terraform.apply with the _dalmatian-admin_ role\n when in _auto_approve_ mode\n asks Terraform to use auto_approve mode\n\nDalmatian::HostedZone\n #domain\n uses hosted_zone domain\n #ns_records\n uses hosted_zone ns_records\n #a_records\n uses hosted_zone a_records\n #alias_records\n uses hosted_zone alias_records\n #cname_records\n uses hosted_zone cname_records\n #mx_records\n uses hosted_zone mx_records\n #txt_records\n uses hosted_zone txt_records\n #srv_records\n uses hosted_zone srv_records\n #to_params\n provides a hash of attributes for use in deployment\n\nDalmatian::HostedZoneTest\n #call\n changes to the hosted-zone directory\n logs our intention to run Terraform init\n runs Terraform init, with upgrade option\n ensures presence of workspace\n logs our intention to run Terraform fmt\n runs Terraform fmt with check and diff options\n logs our intention to run Terraform validate\n runs Terraform validate, with upgrade option\n changes back to the app root directory\n\nDalmatian::Infrastructure\n Infrastructure::PATH\n is a constant\n Infrastructure::APP_ROOT\n is a constant\n initialisation\n when configuration is not provided\n builds one using the defaults\n #clusters\n creates one cluster for each cluster description provided\n key operations on clusters\n #fetch\n asks all clusters to #fetch\n #test\n asks all clusters to #deploy with _plan_ and _test_ options\n #deploy\n when no parameters given\n asks all clusters to #deploy with _plan_, _test_ and _auto-approve_ disabled\n when parameters are given\n asks all clusters to #deploy with the given options\n when a particular infrastructure is named for deployment\n asks only the named cluster to #deploy with the given options\n\nDalmatian::Logger\n ::error(msg)\n raises an error with a red message\n ::info(msg)\n puts the given given message in white\n ::success(msg)\n puts the given given message in green\n ::warn(msg)\n puts the given given message in yellow\n\nDalmatian::OpensearchCluster\n #identifier\n uses opensearch identifier\n #in_use_by\n uses opensearch_cluster in_use_by list\n #version\n uses opensearch_cluster version\n #master_enabled\n uses opensearch_cluster master_enabled bool\n #master_count\n uses opensearch_cluster master_count\n #master_type\n uses opensearch_cluster master_type\n #instance_count\n uses opensearch_cluster instance_count\n #instance_type\n uses opensearch_cluster instance_type\n #warm_enabled\n uses opensearch_cluster warm_enabled bool\n #warm_count\n uses opensearch_cluster warm_count\n #warm_type\n uses opensearch_cluster warm_type\n #parameter_store_path_opensearch_cluster_url_name\n uses opensearch_cluster parameter_store_path_opensearch_cluster_url_name\n #volume_size\n uses opensearch_cluster volume_size\n #to_params\n provides a hash of attributes for use in deployment\n\nDalmatian::OpensearchClusterTest\n #call\n changes to the opensearch-cluster directory\n logs our intention to run Terraform init\n runs Terraform init, with upgrade option\n ensures presence of workspace\n logs our intention to run Terraform fmt\n runs Terraform fmt with check and diff options\n logs our intention to run Terraform validate\n runs Terraform validate, with upgrade option\n changes back to the app root directory\n\nDalmatian::ParameterStore\n ::get_parameter(name: \"\", with_decryption: true)\n when getting a single parameter from Parameter Store\n runs aws ssm get-parameter\n ::get_parameters_by_path(path: \"\", with_decryption: true)\n when getting parameters by path from Parameter Store\n runs aws ssm get-parameter\n\nDalmatian::RdsDeployment\n #call\n changes to rds infrastructure directory\n asks Terraform to ensure that the workspace is in place\n when in _plan_ mode\n invokes Terraform.plan with the _dalmatian-read_ role\n when NOT in _plan_ mode\n invokes Terraform.apply with the _dalmatian-admin_ role\n when in _auto_approve_ mode\n asks Terraform to use auto_approve mode\n\nDalmatian::Rds\n #identifier\n uses rds identifier\n #in_use_by\n uses rds in_use_by list\n #clusters_in_use\n uses rds clusters_in_use list\n #instance_class\n uses rds instance_class\n #engine\n uses rds engine\n #engine_version\n uses the rds engine_version\n #allocated_storage\n uses the rds allocated_storage\n #storage_encrypted\n uses the rds storage_encrypted bool\n #storage_type\n uses the rds storage_type gp3\n #db_name\n uses the rds db_name\n #port\n uses the rds port\n #maintenance_window\n uses the rds maintenance_window\n #backup_window\n uses the rds backup_window\n #backup_retention_period\n uses the rds backup_retention_period\n #force_ssl\n uses the rds force_ssl bool\n #parameter_store_path_db_url_name\n uses the rds parameter_store_path_db_url_name\n #sql_backup_scheduled_task_environment_variables\n uses the rds sql_backup_scheduled_task_environment_variables\n #check_sql_backup_scheduled_task_environment_variables\n uses the rds check_sql_backup_scheduled_task_environment_variables\n #sync_sql_backup_to_azure\n will have offsite backups disabled by default\n #replication_bucket_destination_arn\n uses the rds replication_bucket_destination_arn\n #replication_kms_key_id\n uses the rds replication_kms_key_id\n #codebuild_access\n uses the rds codebuild_access\n #to_params\n provides a hash of attributes for use in deployment\n\nDalmatian::RdsTest\n #call\n changes to the ecs-services directory\n logs our intention to run Terraform init\n runs Terraform init, with upgrade option\n ensures presence of workspace\n logs our intention to run Terraform fmt\n runs Terraform fmt with check and diff options\n logs our intention to run Terraform validate\n runs Terraform validate, with upgrade option\n changes back to the app root directory\n\nDalmatian::RemoteReferenceValues\n when the reference is for a git repo\n returns a git shaped configuration\n if _filename_ is not present\n supplies the default of _dalmatian.yml_\n when the reference is for an S3 bucket\n returns an S3 shaped configuration\n if _key_ is not present\n supplies the default of _dalmatian.yml_\n when the reference is for a URL\n returns a git shaped configuration\n\nDalmatian::S3CacheHandler\n #call\n deletes any old cache\n uses the AWS S3 cmd to save the remote config to a local cache\n logs the cloning action\n logs the path to the cached configuration\n returns the cached full configuration to the caller (configuration reader)\n reads the cached full configuration from the disk in order to return to caller\n\nDalmatian::S3Deployment\n #call\n changes to s3 infrastructure directory\n asks Terraform to ensure that the workspace is in place\n when in _plan_ mode\n invokes Terraform.plan with the _dalmatian-read_ role\n when NOT in _plan_ mode\n invokes Terraform.apply with the _dalmatian-admin_ role\n when in _auto_approve_ mode\n asks Terraform to use auto_approve mode\n\nDalmatian::S3\n #name\n uses s3 name\n #enable_s3_versioning\n uses enable_s3_versioning bool\n #encrypted\n uses s3 encrypted bool\n #acl\n uses s3 acl\n #policy\n uses s3 policy\n #service_cloudfront_read_access\n uses s3 service_cloudfront_read_access\n #cloudfront\n uses s3 cloudfront\n #to_params\n provides a hash of attributes for use in deployment\n\nDalmatian::S3Test\n #call\n changes to the s3 directory\n logs our intention to run Terraform init\n runs Terraform init, with upgrade option\n ensures presence of workspace\n logs our intention to run Terraform fmt\n runs Terraform fmt with check and diff options\n logs our intention to run Terraform validate\n runs Terraform validate, with upgrade option\n changes back to the app root directory\n\nDalmatian::ServiceDeployment\n #call\n changes to ecs-services infrastructure directory\n asks Terraform to ensure that the workspace is in place\n when in _plan_ mode\n invokes Terraform.plan with the _dalmatian-read_ role\n when NOT in _plan_ mode\n invokes Terraform.apply with the _dalmatian-admin_ role\n when in _auto_approve_ mode\n asks Terraform to use auto_approve mode\n\nDalmatian::Service\n #name\n uses service name\n #blue_green\n uses the service blue_green map\n #parameter_store_path\n uses service parameter_store_path\n #parameter_store_key\n uses service parameter_store_key\n #daemon\n uses the service daemon bool\n #monitoring\n uses the service monitoring hash\n #cloudfront\n recasts the service config in environment groups\n includes the appropriate \"custom_origins\" values in each environment\n Uses an AWS cloudfront managed cache policy\n Uses an AWS cloudfront managed origin policy\n Uses an AWS cloudfront managed response headers policy\n mirroring of elements into each environment group\n includes the \"create\" value\n includes the \"tls_protocol_version\" value\n includes the \"origin_keepalive_timeout\" value\n includes the \"origin_read_timeout\" value\n includes the \"basic_auth\" value\n includes the \"basic_auth_users_extra\" value\n includes the \"viewer_request_functions\" values\n includes the \"offline_page_http_status\" value\n bypass_protection\n uses the \"bypass_protection\" configuration\n custom_behaviors\n converts list of \"path_patterns\" to a single \"path_pattern\"\n #shared_loadbalancer_name\n returns shared loadbalancer name if the service is in use by a shared loadbalancer\n returns empty string if the service is not in use by a shared loadbalancer\n #s3_policy\n uses the service s3_policy map\n #lb_ip_whitelistt\n uses the service lb_ip_whitelist list\n #lb_idle_timeout\n uses the service lb_idle_timeout\n #global_accelerator\n uses service global_accelerator value\n #health_check_path\n uses the service health_check_path\n #health_check_grace_period\n uses the service health_check_grace_period\n #deregistration_delay\n uses the service deregistration_delay\n #serve_from_subdirectory\n uses the service serve_from_subdirectory\n #domain_names\n groups the domain names from the service domain_list into environments\n #proxy_configuration\n groups the proxy configurations from the service proxy_configuration list into environments\n #home_directory\n uses the service home_directory\n #lb_ssl_certificate\n groups the certificate arns from the service lb_ssl_certificate list into environments\n #lb_ssl_policy\n sets the default ssl policy for each environment\n #cloudfront_ssl_certificate\n groups the certificate arns from the service cloudfront_ssl_certificate list into environments\n #image_source\n uses the service image source\n #launch_on\n uses the service 'launch_on' specification\n #launch_on_cluster\n uses the service 'launch_on_cluster' string\n #cluster_min_servers\n uses the service 'cluster_min_servers' string\n #image_location\n uses the service image location\n #track_revision\n uses the service track_revision string\n #custom_codestar_connection_arn\n uses the service custom_codestar_connection_arn\n #codepipeline_use_github_v1\n uses the service codepipeline_use_github_v1\n #codepipeline_codebuild_run_in_vpc\n uses the service codepipeline_codebuild_run_in_vpc\n #codepipeline_codebuild_use_service_env\n uses the service codepipeline_codebuild_use_service_env\n #buildspec\n uses the service buildspec\n #container_port\n uses the service container port\n #container_command\n uses the service container command\n #container_volumes\n uses the service container volumes\n #container_extra_hosts\n uses the service container extra hosts\n #container_count\n uses the service container_count\n #enable_max_one_container_per_instance\n uses the service enable_max_one_container_per_instance\n #scheduled_tasks\n uses the service scheduled tasks\n #workers\n uses the service workers\n #cluster_name\n delegates to the cluster\n #cluster_id\n delegates to the cluster\n #account_id\n delegates to the cluster\n #to_params\n provides a hash of attributes for use in deployment\n\nDalmatian::ServiceTest\n #call\n changes to the ecs-services directory\n logs our intention to run Terraform init\n runs Terraform init, with upgrade option\n ensures presence of workspace\n logs our intention to run Terraform fmt\n runs Terraform fmt with check and diff options\n logs our intention to run Terraform validate\n runs Terraform validate, with upgrade option\n changes back to the app root directory\n\nDalmatian::SharedLoadbalancerDeployment\n #call\n changes to shared-loadbalancer infrastructure directory\n asks Terraform to ensure that the workspace is in place\n when in _plan_ mode\n invokes Terraform.plan with the _dalmatian-read_ role\n when NOT in _plan_ mode\n invokes Terraform.apply with the _dalmatian-admin_ role\n when in _auto_approve_ mode\n asks Terraform to use auto_approve mode\n\nDalmatian::SharedLoadbalancer\n #name\n uses shared_loadbalancer name\n #in_use_by\n uses shared_loadbalancer in_use_by list\n #clusters_in_use\n uses shared_loadbalancer clusters_in_use list\n #subnets_name\n uses shared_loadbalancer subnets_name value\n #domain_names\n uses shared_loadbalancer domain_names list provided by Services\n #internal\n uses shared_loadbalancer internal value\n #ip_whitelist\n uses shared_loadbalancer ip_whitelist list\n #idle_timeout\n uses shared_loadbalancer idle_timeout value\n #global_accelerator\n uses shared_loadbalancer global_accelerator value\n #ssl_policy\n has the default ssl policy defined\n #to_params\n provides a hash of attributes for use in deployment\n\nDalmatian::SharedLoadbalancerTest\n #call\n changes to the shared-loadbalancer directory\n logs our intention to run Terraform init\n runs Terraform init, with upgrade option\n ensures presence of workspace\n logs our intention to run Terraform fmt\n runs Terraform fmt with check and diff options\n logs our intention to run Terraform validate\n runs Terraform validate, with upgrade option\n changes back to the app root directory\n\nDalmatian::SourceDeployment\n #call\n changes to infrastructure config directory\n asks Terraform to ensure that the workspace is in place\n when the environment includes a git reference as \"track_revision\"\n checks out that commit\n passes the \"track_revision\" reference along to Terraform\n when in _plan_ mode\n invokes Terraform.plan with the _dalmatian-read_ role\n when NOT in _plan_ mode\n invokes Terraform.apply with the _dalmatian-admin_ role\n when in _auto_approve_ mode\n asks Terraform to use auto_approve mode\n\nDalmatian::Source\n #name\n uses the cluster name and its own position in the cluster's list of sources\n #cluster_name\n delegates to the cluster\n #cluster_id\n delegates to the cluster\n #account_id\n delegates to the cluster\n\nDalmatian::SourceTest\n #call\n changes to the ecs directory\n logs our intention to run Terraform init\n runs Terraform init, with upgrade option\n ensures presence of workspace\n logs our intention to run Terraform fmt\n runs Terraform fmt with check and diff options\n logs our intention to run Terraform validate\n runs Terraform validate, with upgrade option\n changes back to the app root directory\n when the environment includes a git reference as \"track_revision\"\n checks out that commit\n passes the \"track_revision\" reference along to Terraform.validate\n\nDalmatian::Terraform\n ::init(upgrade: false)\n when asked to upgrade\n passes terraform init the upgrade flag\n when not asked to upgrade\n does not pass terraform init the upgrade flag\n ::fmt(args = nil)\n when passed some additional arguments\n passes terraform fmt the upgrade flag\n when passed NO additional arguments\n invokes terraform fmt with no arguments\n ::validate(tfvars)\n passes the given _var-file_ to terraform\n reformats the given tfvars and passes them to terraform as args\n ::ensure_presence_of_workspace(workspace_name)\n logs our intention to create the workspace\n asks Terraform to create the workspace\n when the workspace already exists (and an error is rescued)\n logs our intention to _select_ rather than _create_ the workspace\n asks Terraform to select the existing workspace\n ::plan(tfvars)\n passes the given _var-file_ to terraform\n reformats the given tfvars and passes them to terraform as args\n ::apply(tfvars, auto_approve=false)\n passes the given _var-file_ to terraform\n reformats the given tfvars and passes them to terraform as args\n when auto-approve is set to true\n passes the _auto-approve_ flag to terraform apply\n ::destroy(tfvars)\n passes the given _var-file_ to terraform\n reformats the given tfvars and passes them to terraform as args\n ::list_workspaces\n changes to the bootstrapping directory\n runs the terraform cmd to list workspaces\n\nDalmatian::UrlCacheHandler\n #call\n deletes any old cache\n uses the helper to GET a URI\n logs the cloning action\n logs the path to the cached configuration\n returns the cached full configuration to the caller (configuration reader)\n reads the cached full configuration from the disk in order to return to caller\n\nDalmatian::VpnCustomerGatewayDeployment\n #call\n changes to vpn-customer-gateway infrastructure directory\n asks Terraform to ensure that the workspace is in place\n when in _plan_ mode\n invokes Terraform.plan with the _dalmatian-read_ role\n when NOT in _plan_ mode\n invokes Terraform.apply with the _dalmatian-admin_ role\n when in _auto_approve_ mode\n asks Terraform to use auto_approve mode\n\nDalmatian::VpnCustomerGateway\n #name\n uses vpn_customer_gateway name\n #bgp_asn\n uses vpn_customer_gateway bgp_asn\n #ip_address\n uses vpn_customer_gateway ip_address\n #to_params\n provides a hash of attributes for use in deployment\n\nDalmatian::VpnCustomerGatewayTest\n #call\n changes to the vpn-customer-gateway directory\n logs our intention to run Terraform init\n runs Terraform init, with upgrade option\n ensures presence of workspace\n logs our intention to run Terraform fmt\n runs Terraform fmt with check and diff options\n logs our intention to run Terraform validate\n runs Terraform validate, with upgrade option\n changes back to the app root directory\n\nDalmatian::WAFDeployment\n #call\n changes to waf infrastructure directory\n asks Terraform to ensure that the workspace is in place\n when in _plan_ mode\n invokes Terraform.plan with the _dalmatian-read_ role\n when NOT in _plan_ mode\n invokes Terraform.apply with the _dalmatian-admin_ role\n when in _auto_approve_ mode\n asks Terraform to use auto_approve mode\n\nDalmatian::WAF\n #name\n uses waf name\n #action\n uses waf action\n #ip_deny_list\n has a list of IP addresses to block\n #aws_managed_rules\n uses waf aws_managed_rules list\n #associations\n uses waf associations list\n #to_params\n provides a hash of attributes for use in deployment\n\nDalmatian::WAFTest\n #call\n changes to the ecs-services directory\n logs our intention to run Terraform init\n runs Terraform init, with upgrade option\n ensures presence of workspace\n logs our intention to run Terraform fmt\n runs Terraform fmt with check and diff options\n logs our intention to run Terraform validate\n runs Terraform validate, with upgrade option\n changes back to the app root directory\n\nFailures:\n\n 1) tests local configuration use of \"terraform apply\" passes the hosted zone config to \"terraform apply\"\n Failure/Error: Helper.run!(cmd)\n \n #<Dalmatian::Helper (class)> received :run! with unexpected arguments\n expected: (\"TF_VAR_region='eu-west-2' TF_VAR_cidr='10.0.0.0/16' TF_VAR_root_domain_zone='dalmatian.dxw.net' TF_VAR_internal_domain_zone='dalmatian.internal' TF_VAR_ecs_private_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.128.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.129.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.130.0/24\\\"}]' TF_VAR_extra_public_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.0.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.1.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.2.0/24\\\"}]' TF_VAR_instances_key_name='dalmatian-ecs-instances' TF_VAR_instance_type='t2.medium' TF_VAR_min_servers='2' TF_VAR_max_servers='4' TF_VAR_max_instance_lifetime='86400' TF_VAR_associate_public_ip_address='0' TF_VAR_docker_storage_size='40' TF_VAR_dockerhub_email='' TF_VAR_dockerhub_token='' TF_VAR_enable_efs='false' TF_VAR_encrypt_efs='true' TF_VAR_efs_dirs='[]' TF_VAR_monitoring_docs_path='https://github.com/dxw/dalmatian/docs/monitoring-alarms/' TF_VAR_example_var='bar' TF_VAR_environment='production' TF_VAR_cluster_name='shared-cluster-production' TF_VAR_account_id='123456789012' TF_VAR_infrastructure_name='existing-shared-cluster-production' TF_VAR_dalmatian_role='dalmatian-admin' terraform apply\")\n got: (\"TF_VAR_region='eu-west-2' TF_VAR_cidr='10.0.0.0/16' TF_VAR_root_domain_zone='dalmatian.dxw.net' TF_VAR_internal_domain_zone='dalmatian.internal' TF_VAR_ecs_private_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.128.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.129.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.130.0/24\\\"}]' TF_VAR_extra_public_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.0.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.1.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.2.0/24\\\"}]' TF_VAR_instances_key_name='dalmatian-ecs-instances' TF_VAR_instance_type='t2.medium' TF_VAR_min_servers='2' TF_VAR_max_servers='4' TF_VAR_max_instance_lifetime='86400' TF_VAR_associate_public_ip_address='0' TF_VAR_docker_storage_size='40' TF_VAR_dockerhub_email='' TF_VAR_dockerhub_token='' TF_VAR_enable_efs='false' TF_VAR_encrypt_efs='true' TF_VAR_efs_dirs='[]' TF_VAR_monitoring_docs_path='https://github.com/dxw/dalmatian/docs/monitoring-alarms/' TF_VAR_environment='production' TF_VAR_account_id='123456789012' TF_VAR_infrastructure_name='new-dedicated-cluster' TF_VAR_dalmatian_role='dalmatian-admin' TF_VAR_rds='{identifier =\\\"testservice\\\",in_use_by =[\\\"test-service\\\"],clusters_in_use ={production =[\\\"test\\\"],staging =[\\\"test\\\"]},instance_class ={production =\\\"db.t2.small\\\",staging =\\\"db.t2.micro\\\"},engine =\\\"postgres\\\",engine_version =\\\"11.4\\\",allocated_storage =20,storage_encrypted =true,storage_type =\\\"gp3\\\",db_name =\\\"testapp\\\",port =5432,maintenance_window =\\\"mon:19:00-mon:19:30\\\",backup_window =\\\"09:00-10:00\\\",backup_retention_period =31,force_ssl =true,parameter_store_path_db_url_name =\\\"DATABASE_URL\\\",sql_backup_scheduled_task_environment_variables =[{name =\\\"foo\\\",value =\\\"bar\\\"}],check_sql_backup_scheduled_task_environment_variables =[{name =\\\"foo\\\",value =\\\"bar\\\"}],sync_sql_backup_to_azure =false,replication_bucket_destination_arn =\\\"\\\",replication_kms_key_id =\\\"\\\",codebuild_access =[\\\"service-name\\\"]}' terraform apply\")\n Please stub a default value first if message might be received with other args as well. \n # ./lib/dalmatian/terraform.rb:34:in `apply'\n # ./lib/dalmatian/deployable.rb:35:in `terraform_apply'\n # ./lib/dalmatian/deployable.rb:9:in `call'\n # ./lib/dalmatian/cluster.rb:269:in `deploy_rds'\n # ./lib/dalmatian/cluster.rb:70:in `block (2 levels) in deploy'\n # ./lib/dalmatian/cluster.rb:68:in `each'\n # ./lib/dalmatian/cluster.rb:68:in `block in deploy'\n # ./lib/dalmatian/cluster.rb:59:in `each'\n # ./lib/dalmatian/cluster.rb:59:in `deploy'\n # ./lib/dalmatian/infrastructure.rb:24:in `block in deploy'\n # ./lib/dalmatian/infrastructure.rb:22:in `each'\n # ./lib/dalmatian/infrastructure.rb:22:in `deploy'\n # ./spec/integration/deploys_local_configuration_spec.rb:1577:in `block (2 levels) in <module:Dalmatian>'\n # ./spec/support/spec_helper.rb:24:in `block (3 levels) in <top (required)>'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:24:in `block in modify'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:15:in `synchronize'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:15:in `modify'\n # ./spec/support/spec_helper.rb:20:in `block (2 levels) in <top (required)>'\n # /Users/bob/.bundles/ruby/2.7.0/gems/webmock-3.19.1/lib/webmock/rspec.rb:39:in `block (2 levels) in <top (required)>'\n\n 2) tests local configuration use of \"terraform apply\" passes the s3 config to \"terraform apply\"\n Failure/Error: Helper.run!(cmd)\n \n #<Dalmatian::Helper (class)> received :run! with unexpected arguments\n expected: (\"TF_VAR_region='eu-west-2' TF_VAR_cidr='10.0.0.0/16' TF_VAR_root_domain_zone='dalmatian.dxw.net' TF_VAR_internal_domain_zone='dalmatian.internal' TF_VAR_ecs_private_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.128.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.129.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.130.0/24\\\"}]' TF_VAR_extra_public_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.0.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.1.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.2.0/24\\\"}]' TF_VAR_instances_key_name='dalmatian-ecs-instances' TF_VAR_instance_type='t2.medium' TF_VAR_min_servers='2' TF_VAR_max_servers='4' TF_VAR_max_instance_lifetime='86400' TF_VAR_associate_public_ip_address='0' TF_VAR_docker_storage_size='40' TF_VAR_dockerhub_email='' TF_VAR_dockerhub_token='' TF_VAR_enable_efs='false' TF_VAR_encrypt_efs='true' TF_VAR_efs_dirs='[]' TF_VAR_monitoring_docs_path='https://github.com/dxw/dalmatian/docs/monitoring-alarms/' TF_VAR_example_var='bar' TF_VAR_environment='production' TF_VAR_cluster_name='shared-cluster-production' TF_VAR_account_id='123456789012' TF_VAR_infrastructure_name='existing-shared-cluster-production' TF_VAR_dalmatian_role='dalmatian-admin' terraform apply\")\n got: (\"TF_VAR_region='eu-west-2' TF_VAR_cidr='10.0.0.0/16' TF_VAR_root_domain_zone='dalmatian.dxw.net' TF_VAR_internal_domain_zone='dalmatian.internal' TF_VAR_ecs_private_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.128.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.129.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.130.0/24\\\"}]' TF_VAR_extra_public_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.0.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.1.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.2.0/24\\\"}]' TF_VAR_instances_key_name='dalmatian-ecs-instances' TF_VAR_instance_type='t2.medium' TF_VAR_min_servers='2' TF_VAR_max_servers='4' TF_VAR_max_instance_lifetime='86400' TF_VAR_associate_public_ip_address='0' TF_VAR_docker_storage_size='40' TF_VAR_dockerhub_email='' TF_VAR_dockerhub_token='' TF_VAR_enable_efs='false' TF_VAR_encrypt_efs='true' TF_VAR_efs_dirs='[]' TF_VAR_monitoring_docs_path='https://github.com/dxw/dalmatian/docs/monitoring-alarms/' TF_VAR_environment='production' TF_VAR_account_id='123456789012' TF_VAR_infrastructure_name='new-dedicated-cluster' TF_VAR_dalmatian_role='dalmatian-admin' TF_VAR_rds='{identifier =\\\"testservice\\\",in_use_by =[\\\"test-service\\\"],clusters_in_use ={production =[\\\"test\\\"],staging =[\\\"test\\\"]},instance_class ={production =\\\"db.t2.small\\\",staging =\\\"db.t2.micro\\\"},engine =\\\"postgres\\\",engine_version =\\\"11.4\\\",allocated_storage =20,storage_encrypted =true,storage_type =\\\"gp3\\\",db_name =\\\"testapp\\\",port =5432,maintenance_window =\\\"mon:19:00-mon:19:30\\\",backup_window =\\\"09:00-10:00\\\",backup_retention_period =31,force_ssl =true,parameter_store_path_db_url_name =\\\"DATABASE_URL\\\",sql_backup_scheduled_task_environment_variables =[{name =\\\"foo\\\",value =\\\"bar\\\"}],check_sql_backup_scheduled_task_environment_variables =[{name =\\\"foo\\\",value =\\\"bar\\\"}],sync_sql_backup_to_azure =false,replication_bucket_destination_arn =\\\"\\\",replication_kms_key_id =\\\"\\\",codebuild_access =[\\\"service-name\\\"]}' terraform apply\")\n Please stub a default value first if message might be received with other args as well. \n # ./lib/dalmatian/terraform.rb:34:in `apply'\n # ./lib/dalmatian/deployable.rb:35:in `terraform_apply'\n # ./lib/dalmatian/deployable.rb:9:in `call'\n # ./lib/dalmatian/cluster.rb:269:in `deploy_rds'\n # ./lib/dalmatian/cluster.rb:70:in `block (2 levels) in deploy'\n # ./lib/dalmatian/cluster.rb:68:in `each'\n # ./lib/dalmatian/cluster.rb:68:in `block in deploy'\n # ./lib/dalmatian/cluster.rb:59:in `each'\n # ./lib/dalmatian/cluster.rb:59:in `deploy'\n # ./lib/dalmatian/infrastructure.rb:24:in `block in deploy'\n # ./lib/dalmatian/infrastructure.rb:22:in `each'\n # ./lib/dalmatian/infrastructure.rb:22:in `deploy'\n # ./spec/integration/deploys_local_configuration_spec.rb:1577:in `block (2 levels) in <module:Dalmatian>'\n # ./spec/support/spec_helper.rb:24:in `block (3 levels) in <top (required)>'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:24:in `block in modify'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:15:in `synchronize'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:15:in `modify'\n # ./spec/support/spec_helper.rb:20:in `block (2 levels) in <top (required)>'\n # /Users/bob/.bundles/ruby/2.7.0/gems/webmock-3.19.1/lib/webmock/rspec.rb:39:in `block (2 levels) in <top (required)>'\n\n 3) tests local configuration use of \"terraform apply\" passes the vpn customer gateway config to \"terraform apply\"\n Failure/Error: Helper.run!(cmd)\n \n #<Dalmatian::Helper (class)> received :run! with unexpected arguments\n expected: (\"TF_VAR_region='eu-west-2' TF_VAR_cidr='10.0.0.0/16' TF_VAR_root_domain_zone='dalmatian.dxw.net' TF_VAR_internal_domain_zone='dalmatian.internal' TF_VAR_ecs_private_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.128.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.129.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.130.0/24\\\"}]' TF_VAR_extra_public_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.0.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.1.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.2.0/24\\\"}]' TF_VAR_instances_key_name='dalmatian-ecs-instances' TF_VAR_instance_type='t2.medium' TF_VAR_min_servers='2' TF_VAR_max_servers='4' TF_VAR_max_instance_lifetime='86400' TF_VAR_associate_public_ip_address='0' TF_VAR_docker_storage_size='40' TF_VAR_dockerhub_email='' TF_VAR_dockerhub_token='' TF_VAR_enable_efs='false' TF_VAR_encrypt_efs='true' TF_VAR_efs_dirs='[]' TF_VAR_monitoring_docs_path='https://github.com/dxw/dalmatian/docs/monitoring-alarms/' TF_VAR_example_var='bar' TF_VAR_environment='production' TF_VAR_cluster_name='shared-cluster-production' TF_VAR_account_id='123456789012' TF_VAR_infrastructure_name='existing-shared-cluster-production' TF_VAR_dalmatian_role='dalmatian-admin' terraform apply\")\n got: (\"TF_VAR_region='eu-west-2' TF_VAR_cidr='10.0.0.0/16' TF_VAR_root_domain_zone='dalmatian.dxw.net' TF_VAR_internal_domain_zone='dalmatian.internal' TF_VAR_ecs_private_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.128.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.129.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.130.0/24\\\"}]' TF_VAR_extra_public_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.0.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.1.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.2.0/24\\\"}]' TF_VAR_instances_key_name='dalmatian-ecs-instances' TF_VAR_instance_type='t2.medium' TF_VAR_min_servers='2' TF_VAR_max_servers='4' TF_VAR_max_instance_lifetime='86400' TF_VAR_associate_public_ip_address='0' TF_VAR_docker_storage_size='40' TF_VAR_dockerhub_email='' TF_VAR_dockerhub_token='' TF_VAR_enable_efs='false' TF_VAR_encrypt_efs='true' TF_VAR_efs_dirs='[]' TF_VAR_monitoring_docs_path='https://github.com/dxw/dalmatian/docs/monitoring-alarms/' TF_VAR_environment='production' TF_VAR_account_id='123456789012' TF_VAR_infrastructure_name='new-dedicated-cluster' TF_VAR_dalmatian_role='dalmatian-admin' TF_VAR_rds='{identifier =\\\"testservice\\\",in_use_by =[\\\"test-service\\\"],clusters_in_use ={production =[\\\"test\\\"],staging =[\\\"test\\\"]},instance_class ={production =\\\"db.t2.small\\\",staging =\\\"db.t2.micro\\\"},engine =\\\"postgres\\\",engine_version =\\\"11.4\\\",allocated_storage =20,storage_encrypted =true,storage_type =\\\"gp3\\\",db_name =\\\"testapp\\\",port =5432,maintenance_window =\\\"mon:19:00-mon:19:30\\\",backup_window =\\\"09:00-10:00\\\",backup_retention_period =31,force_ssl =true,parameter_store_path_db_url_name =\\\"DATABASE_URL\\\",sql_backup_scheduled_task_environment_variables =[{name =\\\"foo\\\",value =\\\"bar\\\"}],check_sql_backup_scheduled_task_environment_variables =[{name =\\\"foo\\\",value =\\\"bar\\\"}],sync_sql_backup_to_azure =false,replication_bucket_destination_arn =\\\"\\\",replication_kms_key_id =\\\"\\\",codebuild_access =[\\\"service-name\\\"]}' terraform apply\")\n Please stub a default value first if message might be received with other args as well. \n # ./lib/dalmatian/terraform.rb:34:in `apply'\n # ./lib/dalmatian/deployable.rb:35:in `terraform_apply'\n # ./lib/dalmatian/deployable.rb:9:in `call'\n # ./lib/dalmatian/cluster.rb:269:in `deploy_rds'\n # ./lib/dalmatian/cluster.rb:70:in `block (2 levels) in deploy'\n # ./lib/dalmatian/cluster.rb:68:in `each'\n # ./lib/dalmatian/cluster.rb:68:in `block in deploy'\n # ./lib/dalmatian/cluster.rb:59:in `each'\n # ./lib/dalmatian/cluster.rb:59:in `deploy'\n # ./lib/dalmatian/infrastructure.rb:24:in `block in deploy'\n # ./lib/dalmatian/infrastructure.rb:22:in `each'\n # ./lib/dalmatian/infrastructure.rb:22:in `deploy'\n # ./spec/integration/deploys_local_configuration_spec.rb:1577:in `block (2 levels) in <module:Dalmatian>'\n # ./spec/support/spec_helper.rb:24:in `block (3 levels) in <top (required)>'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:24:in `block in modify'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:15:in `synchronize'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:15:in `modify'\n # ./spec/support/spec_helper.rb:20:in `block (2 levels) in <top (required)>'\n # /Users/bob/.bundles/ruby/2.7.0/gems/webmock-3.19.1/lib/webmock/rspec.rb:39:in `block (2 levels) in <top (required)>'\n\n 4) tests local configuration use of \"terraform apply\" passes the base config to \"terraform apply\"\n Failure/Error: Helper.run!(cmd)\n \n #<Dalmatian::Helper (class)> received :run! with unexpected arguments\n expected: (\"TF_VAR_region='eu-west-2' TF_VAR_cidr='10.0.0.0/16' TF_VAR_root_domain_zone='dalmatian.dxw.net' TF_VAR_internal_domain_zone='dalmatian.internal' TF_VAR_ecs_private_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.128.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.129.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.130.0/24\\\"}]' TF_VAR_extra_public_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.0.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.1.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.2.0/24\\\"}]' TF_VAR_instances_key_name='dalmatian-ecs-instances' TF_VAR_instance_type='t2.medium' TF_VAR_min_servers='2' TF_VAR_max_servers='4' TF_VAR_max_instance_lifetime='86400' TF_VAR_associate_public_ip_address='0' TF_VAR_docker_storage_size='40' TF_VAR_dockerhub_email='' TF_VAR_dockerhub_token='' TF_VAR_enable_efs='false' TF_VAR_encrypt_efs='true' TF_VAR_efs_dirs='[]' TF_VAR_monitoring_docs_path='https://github.com/dxw/dalmatian/docs/monitoring-alarms/' TF_VAR_example_var='bar' TF_VAR_environment='production' TF_VAR_cluster_name='shared-cluster-production' TF_VAR_account_id='123456789012' TF_VAR_infrastructure_name='existing-shared-cluster-production' TF_VAR_dalmatian_role='dalmatian-admin' terraform apply\")\n got: (\"TF_VAR_region='eu-west-2' TF_VAR_cidr='10.0.0.0/16' TF_VAR_root_domain_zone='dalmatian.dxw.net' TF_VAR_internal_domain_zone='dalmatian.internal' TF_VAR_ecs_private_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.128.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.129.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.130.0/24\\\"}]' TF_VAR_extra_public_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.0.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.1.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.2.0/24\\\"}]' TF_VAR_instances_key_name='dalmatian-ecs-instances' TF_VAR_instance_type='t2.medium' TF_VAR_min_servers='2' TF_VAR_max_servers='4' TF_VAR_max_instance_lifetime='86400' TF_VAR_associate_public_ip_address='0' TF_VAR_docker_storage_size='40' TF_VAR_dockerhub_email='' TF_VAR_dockerhub_token='' TF_VAR_enable_efs='false' TF_VAR_encrypt_efs='true' TF_VAR_efs_dirs='[]' TF_VAR_monitoring_docs_path='https://github.com/dxw/dalmatian/docs/monitoring-alarms/' TF_VAR_environment='production' TF_VAR_account_id='123456789012' TF_VAR_infrastructure_name='new-dedicated-cluster' TF_VAR_dalmatian_role='dalmatian-admin' TF_VAR_rds='{identifier =\\\"testservice\\\",in_use_by =[\\\"test-service\\\"],clusters_in_use ={production =[\\\"test\\\"],staging =[\\\"test\\\"]},instance_class ={production =\\\"db.t2.small\\\",staging =\\\"db.t2.micro\\\"},engine =\\\"postgres\\\",engine_version =\\\"11.4\\\",allocated_storage =20,storage_encrypted =true,storage_type =\\\"gp3\\\",db_name =\\\"testapp\\\",port =5432,maintenance_window =\\\"mon:19:00-mon:19:30\\\",backup_window =\\\"09:00-10:00\\\",backup_retention_period =31,force_ssl =true,parameter_store_path_db_url_name =\\\"DATABASE_URL\\\",sql_backup_scheduled_task_environment_variables =[{name =\\\"foo\\\",value =\\\"bar\\\"}],check_sql_backup_scheduled_task_environment_variables =[{name =\\\"foo\\\",value =\\\"bar\\\"}],sync_sql_backup_to_azure =false,replication_bucket_destination_arn =\\\"\\\",replication_kms_key_id =\\\"\\\",codebuild_access =[\\\"service-name\\\"]}' terraform apply\")\n Please stub a default value first if message might be received with other args as well. \n # ./lib/dalmatian/terraform.rb:34:in `apply'\n # ./lib/dalmatian/deployable.rb:35:in `terraform_apply'\n # ./lib/dalmatian/deployable.rb:9:in `call'\n # ./lib/dalmatian/cluster.rb:269:in `deploy_rds'\n # ./lib/dalmatian/cluster.rb:70:in `block (2 levels) in deploy'\n # ./lib/dalmatian/cluster.rb:68:in `each'\n # ./lib/dalmatian/cluster.rb:68:in `block in deploy'\n # ./lib/dalmatian/cluster.rb:59:in `each'\n # ./lib/dalmatian/cluster.rb:59:in `deploy'\n # ./lib/dalmatian/infrastructure.rb:24:in `block in deploy'\n # ./lib/dalmatian/infrastructure.rb:22:in `each'\n # ./lib/dalmatian/infrastructure.rb:22:in `deploy'\n # ./spec/integration/deploys_local_configuration_spec.rb:1577:in `block (2 levels) in <module:Dalmatian>'\n # ./spec/support/spec_helper.rb:24:in `block (3 levels) in <top (required)>'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:24:in `block in modify'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:15:in `synchronize'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:15:in `modify'\n # ./spec/support/spec_helper.rb:20:in `block (2 levels) in <top (required)>'\n # /Users/bob/.bundles/ruby/2.7.0/gems/webmock-3.19.1/lib/webmock/rspec.rb:39:in `block (2 levels) in <top (required)>'\n\n 5) tests local configuration use of \"terraform apply\" passes the waf config to \"terraform apply\"\n Failure/Error: Helper.run!(cmd)\n \n #<Dalmatian::Helper (class)> received :run! with unexpected arguments\n expected: (\"TF_VAR_region='eu-west-2' TF_VAR_cidr='10.0.0.0/16' TF_VAR_root_domain_zone='dalmatian.dxw.net' TF_VAR_internal_domain_zone='dalmatian.internal' TF_VAR_ecs_private_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.128.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.129.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.130.0/24\\\"}]' TF_VAR_extra_public_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.0.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.1.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.2.0/24\\\"}]' TF_VAR_instances_key_name='dalmatian-ecs-instances' TF_VAR_instance_type='t2.medium' TF_VAR_min_servers='2' TF_VAR_max_servers='4' TF_VAR_max_instance_lifetime='86400' TF_VAR_associate_public_ip_address='0' TF_VAR_docker_storage_size='40' TF_VAR_dockerhub_email='' TF_VAR_dockerhub_token='' TF_VAR_enable_efs='false' TF_VAR_encrypt_efs='true' TF_VAR_efs_dirs='[]' TF_VAR_monitoring_docs_path='https://github.com/dxw/dalmatian/docs/monitoring-alarms/' TF_VAR_example_var='bar' TF_VAR_environment='production' TF_VAR_cluster_name='shared-cluster-production' TF_VAR_account_id='123456789012' TF_VAR_infrastructure_name='existing-shared-cluster-production' TF_VAR_dalmatian_role='dalmatian-admin' terraform apply\")\n got: (\"TF_VAR_region='eu-west-2' TF_VAR_cidr='10.0.0.0/16' TF_VAR_root_domain_zone='dalmatian.dxw.net' TF_VAR_internal_domain_zone='dalmatian.internal' TF_VAR_ecs_private_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.128.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.129.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.130.0/24\\\"}]' TF_VAR_extra_public_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.0.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.1.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.2.0/24\\\"}]' TF_VAR_instances_key_name='dalmatian-ecs-instances' TF_VAR_instance_type='t2.medium' TF_VAR_min_servers='2' TF_VAR_max_servers='4' TF_VAR_max_instance_lifetime='86400' TF_VAR_associate_public_ip_address='0' TF_VAR_docker_storage_size='40' TF_VAR_dockerhub_email='' TF_VAR_dockerhub_token='' TF_VAR_enable_efs='false' TF_VAR_encrypt_efs='true' TF_VAR_efs_dirs='[]' TF_VAR_monitoring_docs_path='https://github.com/dxw/dalmatian/docs/monitoring-alarms/' TF_VAR_environment='production' TF_VAR_account_id='123456789012' TF_VAR_infrastructure_name='new-dedicated-cluster' TF_VAR_dalmatian_role='dalmatian-admin' TF_VAR_rds='{identifier =\\\"testservice\\\",in_use_by =[\\\"test-service\\\"],clusters_in_use ={production =[\\\"test\\\"],staging =[\\\"test\\\"]},instance_class ={production =\\\"db.t2.small\\\",staging =\\\"db.t2.micro\\\"},engine =\\\"postgres\\\",engine_version =\\\"11.4\\\",allocated_storage =20,storage_encrypted =true,storage_type =\\\"gp3\\\",db_name =\\\"testapp\\\",port =5432,maintenance_window =\\\"mon:19:00-mon:19:30\\\",backup_window =\\\"09:00-10:00\\\",backup_retention_period =31,force_ssl =true,parameter_store_path_db_url_name =\\\"DATABASE_URL\\\",sql_backup_scheduled_task_environment_variables =[{name =\\\"foo\\\",value =\\\"bar\\\"}],check_sql_backup_scheduled_task_environment_variables =[{name =\\\"foo\\\",value =\\\"bar\\\"}],sync_sql_backup_to_azure =false,replication_bucket_destination_arn =\\\"\\\",replication_kms_key_id =\\\"\\\",codebuild_access =[\\\"service-name\\\"]}' terraform apply\")\n Please stub a default value first if message might be received with other args as well. \n # ./lib/dalmatian/terraform.rb:34:in `apply'\n # ./lib/dalmatian/deployable.rb:35:in `terraform_apply'\n # ./lib/dalmatian/deployable.rb:9:in `call'\n # ./lib/dalmatian/cluster.rb:269:in `deploy_rds'\n # ./lib/dalmatian/cluster.rb:70:in `block (2 levels) in deploy'\n # ./lib/dalmatian/cluster.rb:68:in `each'\n # ./lib/dalmatian/cluster.rb:68:in `block in deploy'\n # ./lib/dalmatian/cluster.rb:59:in `each'\n # ./lib/dalmatian/cluster.rb:59:in `deploy'\n # ./lib/dalmatian/infrastructure.rb:24:in `block in deploy'\n # ./lib/dalmatian/infrastructure.rb:22:in `each'\n # ./lib/dalmatian/infrastructure.rb:22:in `deploy'\n # ./spec/integration/deploys_local_configuration_spec.rb:1577:in `block (2 levels) in <module:Dalmatian>'\n # ./spec/support/spec_helper.rb:24:in `block (3 levels) in <top (required)>'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:24:in `block in modify'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:15:in `synchronize'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:15:in `modify'\n # ./spec/support/spec_helper.rb:20:in `block (2 levels) in <top (required)>'\n # /Users/bob/.bundles/ruby/2.7.0/gems/webmock-3.19.1/lib/webmock/rspec.rb:39:in `block (2 levels) in <top (required)>'\n\n 6) tests local configuration use of \"terraform apply\" passes the rds config to \"terraform apply\"\n Failure/Error: Helper.run!(cmd)\n \n #<Dalmatian::Helper (class)> received :run! with unexpected arguments\n expected: (\"TF_VAR_region='eu-west-2' TF_VAR_cidr='10.0.0.0/16' TF_VAR_root_domain_zone='dalmatian.dxw.net' TF_VAR_internal_domain_zone='dalmatian.internal' TF_VAR_ecs_private_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.128.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.129.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.130.0/24\\\"}]' TF_VAR_extra_public_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.0.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.1.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.2.0/24\\\"}]' TF_VAR_instances_key_name='dalmatian-ecs-instances' TF_VAR_instance_type='t2.medium' TF_VAR_min_servers='2' TF_VAR_max_servers='4' TF_VAR_max_instance_lifetime='86400' TF_VAR_associate_public_ip_address='0' TF_VAR_docker_storage_size='40' TF_VAR_dockerhub_email='' TF_VAR_dockerhub_token='' TF_VAR_enable_efs='false' TF_VAR_encrypt_efs='true' TF_VAR_efs_dirs='[]' TF_VAR_monitoring_docs_path='https://github.com/dxw/dalmatian/docs/monitoring-alarms/' TF_VAR_example_var='bar' TF_VAR_environment='production' TF_VAR_cluster_name='shared-cluster-production' TF_VAR_account_id='123456789012' TF_VAR_infrastructure_name='existing-shared-cluster-production' TF_VAR_dalmatian_role='dalmatian-admin' terraform apply\")\n got: (\"TF_VAR_region='eu-west-2' TF_VAR_cidr='10.0.0.0/16' TF_VAR_root_domain_zone='dalmatian.dxw.net' TF_VAR_internal_domain_zone='dalmatian.internal' TF_VAR_ecs_private_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.128.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.129.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.130.0/24\\\"}]' TF_VAR_extra_public_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.0.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.1.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.2.0/24\\\"}]' TF_VAR_instances_key_name='dalmatian-ecs-instances' TF_VAR_instance_type='t2.medium' TF_VAR_min_servers='2' TF_VAR_max_servers='4' TF_VAR_max_instance_lifetime='86400' TF_VAR_associate_public_ip_address='0' TF_VAR_docker_storage_size='40' TF_VAR_dockerhub_email='' TF_VAR_dockerhub_token='' TF_VAR_enable_efs='false' TF_VAR_encrypt_efs='true' TF_VAR_efs_dirs='[]' TF_VAR_monitoring_docs_path='https://github.com/dxw/dalmatian/docs/monitoring-alarms/' TF_VAR_environment='production' TF_VAR_account_id='123456789012' TF_VAR_infrastructure_name='new-dedicated-cluster' TF_VAR_dalmatian_role='dalmatian-admin' TF_VAR_rds='{identifier =\\\"testservice\\\",in_use_by =[\\\"test-service\\\"],clusters_in_use ={production =[\\\"test\\\"],staging =[\\\"test\\\"]},instance_class ={production =\\\"db.t2.small\\\",staging =\\\"db.t2.micro\\\"},engine =\\\"postgres\\\",engine_version =\\\"11.4\\\",allocated_storage =20,storage_encrypted =true,storage_type =\\\"gp3\\\",db_name =\\\"testapp\\\",port =5432,maintenance_window =\\\"mon:19:00-mon:19:30\\\",backup_window =\\\"09:00-10:00\\\",backup_retention_period =31,force_ssl =true,parameter_store_path_db_url_name =\\\"DATABASE_URL\\\",sql_backup_scheduled_task_environment_variables =[{name =\\\"foo\\\",value =\\\"bar\\\"}],check_sql_backup_scheduled_task_environment_variables =[{name =\\\"foo\\\",value =\\\"bar\\\"}],sync_sql_backup_to_azure =false,replication_bucket_destination_arn =\\\"\\\",replication_kms_key_id =\\\"\\\",codebuild_access =[\\\"service-name\\\"]}' terraform apply\")\n Please stub a default value first if message might be received with other args as well. \n # ./lib/dalmatian/terraform.rb:34:in `apply'\n # ./lib/dalmatian/deployable.rb:35:in `terraform_apply'\n # ./lib/dalmatian/deployable.rb:9:in `call'\n # ./lib/dalmatian/cluster.rb:269:in `deploy_rds'\n # ./lib/dalmatian/cluster.rb:70:in `block (2 levels) in deploy'\n # ./lib/dalmatian/cluster.rb:68:in `each'\n # ./lib/dalmatian/cluster.rb:68:in `block in deploy'\n # ./lib/dalmatian/cluster.rb:59:in `each'\n # ./lib/dalmatian/cluster.rb:59:in `deploy'\n # ./lib/dalmatian/infrastructure.rb:24:in `block in deploy'\n # ./lib/dalmatian/infrastructure.rb:22:in `each'\n # ./lib/dalmatian/infrastructure.rb:22:in `deploy'\n # ./spec/integration/deploys_local_configuration_spec.rb:1577:in `block (2 levels) in <module:Dalmatian>'\n # ./spec/support/spec_helper.rb:24:in `block (3 levels) in <top (required)>'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:24:in `block in modify'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:15:in `synchronize'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:15:in `modify'\n # ./spec/support/spec_helper.rb:20:in `block (2 levels) in <top (required)>'\n # /Users/bob/.bundles/ruby/2.7.0/gems/webmock-3.19.1/lib/webmock/rspec.rb:39:in `block (2 levels) in <top (required)>'\n\n 7) tests local configuration use of \"terraform apply\" passes the elasticache config to \"terraform apply\"\n Failure/Error: Helper.run!(cmd)\n \n #<Dalmatian::Helper (class)> received :run! with unexpected arguments\n expected: (\"TF_VAR_region='eu-west-2' TF_VAR_cidr='10.0.0.0/16' TF_VAR_root_domain_zone='dalmatian.dxw.net' TF_VAR_internal_domain_zone='dalmatian.internal' TF_VAR_ecs_private_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.128.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.129.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.130.0/24\\\"}]' TF_VAR_extra_public_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.0.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.1.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.2.0/24\\\"}]' TF_VAR_instances_key_name='dalmatian-ecs-instances' TF_VAR_instance_type='t2.medium' TF_VAR_min_servers='2' TF_VAR_max_servers='4' TF_VAR_max_instance_lifetime='86400' TF_VAR_associate_public_ip_address='0' TF_VAR_docker_storage_size='40' TF_VAR_dockerhub_email='' TF_VAR_dockerhub_token='' TF_VAR_enable_efs='false' TF_VAR_encrypt_efs='true' TF_VAR_efs_dirs='[]' TF_VAR_monitoring_docs_path='https://github.com/dxw/dalmatian/docs/monitoring-alarms/' TF_VAR_example_var='bar' TF_VAR_environment='production' TF_VAR_cluster_name='shared-cluster-production' TF_VAR_account_id='123456789012' TF_VAR_infrastructure_name='existing-shared-cluster-production' TF_VAR_dalmatian_role='dalmatian-admin' terraform apply\")\n got: (\"TF_VAR_region='eu-west-2' TF_VAR_cidr='10.0.0.0/16' TF_VAR_root_domain_zone='dalmatian.dxw.net' TF_VAR_internal_domain_zone='dalmatian.internal' TF_VAR_ecs_private_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.128.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.129.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.130.0/24\\\"}]' TF_VAR_extra_public_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.0.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.1.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.2.0/24\\\"}]' TF_VAR_instances_key_name='dalmatian-ecs-instances' TF_VAR_instance_type='t2.medium' TF_VAR_min_servers='2' TF_VAR_max_servers='4' TF_VAR_max_instance_lifetime='86400' TF_VAR_associate_public_ip_address='0' TF_VAR_docker_storage_size='40' TF_VAR_dockerhub_email='' TF_VAR_dockerhub_token='' TF_VAR_enable_efs='false' TF_VAR_encrypt_efs='true' TF_VAR_efs_dirs='[]' TF_VAR_monitoring_docs_path='https://github.com/dxw/dalmatian/docs/monitoring-alarms/' TF_VAR_environment='production' TF_VAR_account_id='123456789012' TF_VAR_infrastructure_name='new-dedicated-cluster' TF_VAR_dalmatian_role='dalmatian-admin' TF_VAR_rds='{identifier =\\\"testservice\\\",in_use_by =[\\\"test-service\\\"],clusters_in_use ={production =[\\\"test\\\"],staging =[\\\"test\\\"]},instance_class ={production =\\\"db.t2.small\\\",staging =\\\"db.t2.micro\\\"},engine =\\\"postgres\\\",engine_version =\\\"11.4\\\",allocated_storage =20,storage_encrypted =true,storage_type =\\\"gp3\\\",db_name =\\\"testapp\\\",port =5432,maintenance_window =\\\"mon:19:00-mon:19:30\\\",backup_window =\\\"09:00-10:00\\\",backup_retention_period =31,force_ssl =true,parameter_store_path_db_url_name =\\\"DATABASE_URL\\\",sql_backup_scheduled_task_environment_variables =[{name =\\\"foo\\\",value =\\\"bar\\\"}],check_sql_backup_scheduled_task_environment_variables =[{name =\\\"foo\\\",value =\\\"bar\\\"}],sync_sql_backup_to_azure =false,replication_bucket_destination_arn =\\\"\\\",replication_kms_key_id =\\\"\\\",codebuild_access =[\\\"service-name\\\"]}' terraform apply\")\n Please stub a default value first if message might be received with other args as well. \n # ./lib/dalmatian/terraform.rb:34:in `apply'\n # ./lib/dalmatian/deployable.rb:35:in `terraform_apply'\n # ./lib/dalmatian/deployable.rb:9:in `call'\n # ./lib/dalmatian/cluster.rb:269:in `deploy_rds'\n # ./lib/dalmatian/cluster.rb:70:in `block (2 levels) in deploy'\n # ./lib/dalmatian/cluster.rb:68:in `each'\n # ./lib/dalmatian/cluster.rb:68:in `block in deploy'\n # ./lib/dalmatian/cluster.rb:59:in `each'\n # ./lib/dalmatian/cluster.rb:59:in `deploy'\n # ./lib/dalmatian/infrastructure.rb:24:in `block in deploy'\n # ./lib/dalmatian/infrastructure.rb:22:in `each'\n # ./lib/dalmatian/infrastructure.rb:22:in `deploy'\n # ./spec/integration/deploys_local_configuration_spec.rb:1577:in `block (2 levels) in <module:Dalmatian>'\n # ./spec/support/spec_helper.rb:24:in `block (3 levels) in <top (required)>'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:24:in `block in modify'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:15:in `synchronize'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:15:in `modify'\n # ./spec/support/spec_helper.rb:20:in `block (2 levels) in <top (required)>'\n # /Users/bob/.bundles/ruby/2.7.0/gems/webmock-3.19.1/lib/webmock/rspec.rb:39:in `block (2 levels) in <top (required)>'\n\n 8) tests local configuration use of \"terraform apply\" passes the opensearch config to \"terraform apply\"\n Failure/Error: Helper.run!(cmd)\n \n #<Dalmatian::Helper (class)> received :run! with unexpected arguments\n expected: (\"TF_VAR_region='eu-west-2' TF_VAR_cidr='10.0.0.0/16' TF_VAR_root_domain_zone='dalmatian.dxw.net' TF_VAR_internal_domain_zone='dalmatian.internal' TF_VAR_ecs_private_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.128.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.129.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.130.0/24\\\"}]' TF_VAR_extra_public_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.0.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.1.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.2.0/24\\\"}]' TF_VAR_instances_key_name='dalmatian-ecs-instances' TF_VAR_instance_type='t2.medium' TF_VAR_min_servers='2' TF_VAR_max_servers='4' TF_VAR_max_instance_lifetime='86400' TF_VAR_associate_public_ip_address='0' TF_VAR_docker_storage_size='40' TF_VAR_dockerhub_email='' TF_VAR_dockerhub_token='' TF_VAR_enable_efs='false' TF_VAR_encrypt_efs='true' TF_VAR_efs_dirs='[]' TF_VAR_monitoring_docs_path='https://github.com/dxw/dalmatian/docs/monitoring-alarms/' TF_VAR_example_var='bar' TF_VAR_environment='production' TF_VAR_cluster_name='shared-cluster-production' TF_VAR_account_id='123456789012' TF_VAR_infrastructure_name='existing-shared-cluster-production' TF_VAR_dalmatian_role='dalmatian-admin' terraform apply\")\n got: (\"TF_VAR_region='eu-west-2' TF_VAR_cidr='10.0.0.0/16' TF_VAR_root_domain_zone='dalmatian.dxw.net' TF_VAR_internal_domain_zone='dalmatian.internal' TF_VAR_ecs_private_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.128.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.129.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.130.0/24\\\"}]' TF_VAR_extra_public_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.0.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.1.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.2.0/24\\\"}]' TF_VAR_instances_key_name='dalmatian-ecs-instances' TF_VAR_instance_type='t2.medium' TF_VAR_min_servers='2' TF_VAR_max_servers='4' TF_VAR_max_instance_lifetime='86400' TF_VAR_associate_public_ip_address='0' TF_VAR_docker_storage_size='40' TF_VAR_dockerhub_email='' TF_VAR_dockerhub_token='' TF_VAR_enable_efs='false' TF_VAR_encrypt_efs='true' TF_VAR_efs_dirs='[]' TF_VAR_monitoring_docs_path='https://github.com/dxw/dalmatian/docs/monitoring-alarms/' TF_VAR_environment='production' TF_VAR_account_id='123456789012' TF_VAR_infrastructure_name='new-dedicated-cluster' TF_VAR_dalmatian_role='dalmatian-admin' TF_VAR_rds='{identifier =\\\"testservice\\\",in_use_by =[\\\"test-service\\\"],clusters_in_use ={production =[\\\"test\\\"],staging =[\\\"test\\\"]},instance_class ={production =\\\"db.t2.small\\\",staging =\\\"db.t2.micro\\\"},engine =\\\"postgres\\\",engine_version =\\\"11.4\\\",allocated_storage =20,storage_encrypted =true,storage_type =\\\"gp3\\\",db_name =\\\"testapp\\\",port =5432,maintenance_window =\\\"mon:19:00-mon:19:30\\\",backup_window =\\\"09:00-10:00\\\",backup_retention_period =31,force_ssl =true,parameter_store_path_db_url_name =\\\"DATABASE_URL\\\",sql_backup_scheduled_task_environment_variables =[{name =\\\"foo\\\",value =\\\"bar\\\"}],check_sql_backup_scheduled_task_environment_variables =[{name =\\\"foo\\\",value =\\\"bar\\\"}],sync_sql_backup_to_azure =false,replication_bucket_destination_arn =\\\"\\\",replication_kms_key_id =\\\"\\\",codebuild_access =[\\\"service-name\\\"]}' terraform apply\")\n Please stub a default value first if message might be received with other args as well. \n # ./lib/dalmatian/terraform.rb:34:in `apply'\n # ./lib/dalmatian/deployable.rb:35:in `terraform_apply'\n # ./lib/dalmatian/deployable.rb:9:in `call'\n # ./lib/dalmatian/cluster.rb:269:in `deploy_rds'\n # ./lib/dalmatian/cluster.rb:70:in `block (2 levels) in deploy'\n # ./lib/dalmatian/cluster.rb:68:in `each'\n # ./lib/dalmatian/cluster.rb:68:in `block in deploy'\n # ./lib/dalmatian/cluster.rb:59:in `each'\n # ./lib/dalmatian/cluster.rb:59:in `deploy'\n # ./lib/dalmatian/infrastructure.rb:24:in `block in deploy'\n # ./lib/dalmatian/infrastructure.rb:22:in `each'\n # ./lib/dalmatian/infrastructure.rb:22:in `deploy'\n # ./spec/integration/deploys_local_configuration_spec.rb:1577:in `block (2 levels) in <module:Dalmatian>'\n # ./spec/support/spec_helper.rb:24:in `block (3 levels) in <top (required)>'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:24:in `block in modify'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:15:in `synchronize'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:15:in `modify'\n # ./spec/support/spec_helper.rb:20:in `block (2 levels) in <top (required)>'\n # /Users/bob/.bundles/ruby/2.7.0/gems/webmock-3.19.1/lib/webmock/rspec.rb:39:in `block (2 levels) in <top (required)>'\n\n 9) tests local configuration use of \"terraform apply\" passes the service config to \"terraform apply\"\n Failure/Error: Helper.run!(cmd)\n \n #<Dalmatian::Helper (class)> received :run! with unexpected arguments\n expected: (\"TF_VAR_region='eu-west-2' TF_VAR_cidr='10.0.0.0/16' TF_VAR_root_domain_zone='dalmatian.dxw.net' TF_VAR_internal_domain_zone='dalmatian.internal' TF_VAR_ecs_private_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.128.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.129.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.130.0/24\\\"}]' TF_VAR_extra_public_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.0.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.1.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.2.0/24\\\"}]' TF_VAR_instances_key_name='dalmatian-ecs-instances' TF_VAR_instance_type='t2.medium' TF_VAR_min_servers='2' TF_VAR_max_servers='4' TF_VAR_max_instance_lifetime='86400' TF_VAR_associate_public_ip_address='0' TF_VAR_docker_storage_size='40' TF_VAR_dockerhub_email='' TF_VAR_dockerhub_token='' TF_VAR_enable_efs='false' TF_VAR_encrypt_efs='true' TF_VAR_efs_dirs='[]' TF_VAR_monitoring_docs_path='https://github.com/dxw/dalmatian/docs/monitoring-alarms/' TF_VAR_example_var='bar' TF_VAR_environment='production' TF_VAR_cluster_name='shared-cluster-production' TF_VAR_account_id='123456789012' TF_VAR_infrastructure_name='existing-shared-cluster-production' TF_VAR_dalmatian_role='dalmatian-admin' terraform apply\")\n got: (\"TF_VAR_region='eu-west-2' TF_VAR_cidr='10.0.0.0/16' TF_VAR_root_domain_zone='dalmatian.dxw.net' TF_VAR_internal_domain_zone='dalmatian.internal' TF_VAR_ecs_private_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.128.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.129.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.130.0/24\\\"}]' TF_VAR_extra_public_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.0.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.1.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.2.0/24\\\"}]' TF_VAR_instances_key_name='dalmatian-ecs-instances' TF_VAR_instance_type='t2.medium' TF_VAR_min_servers='2' TF_VAR_max_servers='4' TF_VAR_max_instance_lifetime='86400' TF_VAR_associate_public_ip_address='0' TF_VAR_docker_storage_size='40' TF_VAR_dockerhub_email='' TF_VAR_dockerhub_token='' TF_VAR_enable_efs='false' TF_VAR_encrypt_efs='true' TF_VAR_efs_dirs='[]' TF_VAR_monitoring_docs_path='https://github.com/dxw/dalmatian/docs/monitoring-alarms/' TF_VAR_environment='production' TF_VAR_account_id='123456789012' TF_VAR_infrastructure_name='new-dedicated-cluster' TF_VAR_dalmatian_role='dalmatian-admin' TF_VAR_rds='{identifier =\\\"testservice\\\",in_use_by =[\\\"test-service\\\"],clusters_in_use ={production =[\\\"test\\\"],staging =[\\\"test\\\"]},instance_class ={production =\\\"db.t2.small\\\",staging =\\\"db.t2.micro\\\"},engine =\\\"postgres\\\",engine_version =\\\"11.4\\\",allocated_storage =20,storage_encrypted =true,storage_type =\\\"gp3\\\",db_name =\\\"testapp\\\",port =5432,maintenance_window =\\\"mon:19:00-mon:19:30\\\",backup_window =\\\"09:00-10:00\\\",backup_retention_period =31,force_ssl =true,parameter_store_path_db_url_name =\\\"DATABASE_URL\\\",sql_backup_scheduled_task_environment_variables =[{name =\\\"foo\\\",value =\\\"bar\\\"}],check_sql_backup_scheduled_task_environment_variables =[{name =\\\"foo\\\",value =\\\"bar\\\"}],sync_sql_backup_to_azure =false,replication_bucket_destination_arn =\\\"\\\",replication_kms_key_id =\\\"\\\",codebuild_access =[\\\"service-name\\\"]}' terraform apply\")\n Please stub a default value first if message might be received with other args as well. \n # ./lib/dalmatian/terraform.rb:34:in `apply'\n # ./lib/dalmatian/deployable.rb:35:in `terraform_apply'\n # ./lib/dalmatian/deployable.rb:9:in `call'\n # ./lib/dalmatian/cluster.rb:269:in `deploy_rds'\n # ./lib/dalmatian/cluster.rb:70:in `block (2 levels) in deploy'\n # ./lib/dalmatian/cluster.rb:68:in `each'\n # ./lib/dalmatian/cluster.rb:68:in `block in deploy'\n # ./lib/dalmatian/cluster.rb:59:in `each'\n # ./lib/dalmatian/cluster.rb:59:in `deploy'\n # ./lib/dalmatian/infrastructure.rb:24:in `block in deploy'\n # ./lib/dalmatian/infrastructure.rb:22:in `each'\n # ./lib/dalmatian/infrastructure.rb:22:in `deploy'\n # ./spec/integration/deploys_local_configuration_spec.rb:1577:in `block (2 levels) in <module:Dalmatian>'\n # ./spec/support/spec_helper.rb:24:in `block (3 levels) in <top (required)>'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:24:in `block in modify'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:15:in `synchronize'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:15:in `modify'\n # ./spec/support/spec_helper.rb:20:in `block (2 levels) in <top (required)>'\n # /Users/bob/.bundles/ruby/2.7.0/gems/webmock-3.19.1/lib/webmock/rspec.rb:39:in `block (2 levels) in <top (required)>'\n\n 10) tests local configuration use of \"terraform apply\" passes the loadbalancer config to \"terraform apply\"\n Failure/Error: Helper.run!(cmd)\n \n #<Dalmatian::Helper (class)> received :run! with unexpected arguments\n expected: (\"TF_VAR_region='eu-west-2' TF_VAR_cidr='10.0.0.0/16' TF_VAR_root_domain_zone='dalmatian.dxw.net' TF_VAR_internal_domain_zone='dalmatian.internal' TF_VAR_ecs_private_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.128.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.129.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.130.0/24\\\"}]' TF_VAR_extra_public_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.0.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.1.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.2.0/24\\\"}]' TF_VAR_instances_key_name='dalmatian-ecs-instances' TF_VAR_instance_type='t2.medium' TF_VAR_min_servers='2' TF_VAR_max_servers='4' TF_VAR_max_instance_lifetime='86400' TF_VAR_associate_public_ip_address='0' TF_VAR_docker_storage_size='40' TF_VAR_dockerhub_email='' TF_VAR_dockerhub_token='' TF_VAR_enable_efs='false' TF_VAR_encrypt_efs='true' TF_VAR_efs_dirs='[]' TF_VAR_monitoring_docs_path='https://github.com/dxw/dalmatian/docs/monitoring-alarms/' TF_VAR_example_var='bar' TF_VAR_environment='production' TF_VAR_cluster_name='shared-cluster-production' TF_VAR_account_id='123456789012' TF_VAR_infrastructure_name='existing-shared-cluster-production' TF_VAR_dalmatian_role='dalmatian-admin' terraform apply\")\n got: (\"TF_VAR_region='eu-west-2' TF_VAR_cidr='10.0.0.0/16' TF_VAR_root_domain_zone='dalmatian.dxw.net' TF_VAR_internal_domain_zone='dalmatian.internal' TF_VAR_ecs_private_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.128.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.129.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.130.0/24\\\"}]' TF_VAR_extra_public_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.0.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.1.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.2.0/24\\\"}]' TF_VAR_instances_key_name='dalmatian-ecs-instances' TF_VAR_instance_type='t2.medium' TF_VAR_min_servers='2' TF_VAR_max_servers='4' TF_VAR_max_instance_lifetime='86400' TF_VAR_associate_public_ip_address='0' TF_VAR_docker_storage_size='40' TF_VAR_dockerhub_email='' TF_VAR_dockerhub_token='' TF_VAR_enable_efs='false' TF_VAR_encrypt_efs='true' TF_VAR_efs_dirs='[]' TF_VAR_monitoring_docs_path='https://github.com/dxw/dalmatian/docs/monitoring-alarms/' TF_VAR_environment='production' TF_VAR_account_id='123456789012' TF_VAR_infrastructure_name='new-dedicated-cluster' TF_VAR_dalmatian_role='dalmatian-admin' TF_VAR_rds='{identifier =\\\"testservice\\\",in_use_by =[\\\"test-service\\\"],clusters_in_use ={production =[\\\"test\\\"],staging =[\\\"test\\\"]},instance_class ={production =\\\"db.t2.small\\\",staging =\\\"db.t2.micro\\\"},engine =\\\"postgres\\\",engine_version =\\\"11.4\\\",allocated_storage =20,storage_encrypted =true,storage_type =\\\"gp3\\\",db_name =\\\"testapp\\\",port =5432,maintenance_window =\\\"mon:19:00-mon:19:30\\\",backup_window =\\\"09:00-10:00\\\",backup_retention_period =31,force_ssl =true,parameter_store_path_db_url_name =\\\"DATABASE_URL\\\",sql_backup_scheduled_task_environment_variables =[{name =\\\"foo\\\",value =\\\"bar\\\"}],check_sql_backup_scheduled_task_environment_variables =[{name =\\\"foo\\\",value =\\\"bar\\\"}],sync_sql_backup_to_azure =false,replication_bucket_destination_arn =\\\"\\\",replication_kms_key_id =\\\"\\\",codebuild_access =[\\\"service-name\\\"]}' terraform apply\")\n Please stub a default value first if message might be received with other args as well. \n # ./lib/dalmatian/terraform.rb:34:in `apply'\n # ./lib/dalmatian/deployable.rb:35:in `terraform_apply'\n # ./lib/dalmatian/deployable.rb:9:in `call'\n # ./lib/dalmatian/cluster.rb:269:in `deploy_rds'\n # ./lib/dalmatian/cluster.rb:70:in `block (2 levels) in deploy'\n # ./lib/dalmatian/cluster.rb:68:in `each'\n # ./lib/dalmatian/cluster.rb:68:in `block in deploy'\n # ./lib/dalmatian/cluster.rb:59:in `each'\n # ./lib/dalmatian/cluster.rb:59:in `deploy'\n # ./lib/dalmatian/infrastructure.rb:24:in `block in deploy'\n # ./lib/dalmatian/infrastructure.rb:22:in `each'\n # ./lib/dalmatian/infrastructure.rb:22:in `deploy'\n # ./spec/integration/deploys_local_configuration_spec.rb:1577:in `block (2 levels) in <module:Dalmatian>'\n # ./spec/support/spec_helper.rb:24:in `block (3 levels) in <top (required)>'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:24:in `block in modify'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:15:in `synchronize'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:15:in `modify'\n # ./spec/support/spec_helper.rb:20:in `block (2 levels) in <top (required)>'\n # /Users/bob/.bundles/ruby/2.7.0/gems/webmock-3.19.1/lib/webmock/rspec.rb:39:in `block (2 levels) in <top (required)>'\n\n 11) tests local configuration use of \"terraform apply\" passes the cluster 2 config to \"terraform apply\"\n Failure/Error: Helper.run!(cmd)\n \n #<Dalmatian::Helper (class)> received :run! with unexpected arguments\n expected: (\"TF_VAR_region='eu-west-2' TF_VAR_cidr='10.0.0.0/16' TF_VAR_root_domain_zone='dalmatian.dxw.net' TF_VAR_internal_domain_zone='dalmatian.internal' TF_VAR_ecs_private_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.128.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.129.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.130.0/24\\\"}]' TF_VAR_extra_public_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.0.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.1.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.2.0/24\\\"}]' TF_VAR_instances_key_name='dalmatian-ecs-instances' TF_VAR_instance_type='t2.medium' TF_VAR_min_servers='2' TF_VAR_max_servers='4' TF_VAR_max_instance_lifetime='86400' TF_VAR_associate_public_ip_address='0' TF_VAR_docker_storage_size='40' TF_VAR_dockerhub_email='' TF_VAR_dockerhub_token='' TF_VAR_enable_efs='false' TF_VAR_encrypt_efs='true' TF_VAR_efs_dirs='[]' TF_VAR_monitoring_docs_path='https://github.com/dxw/dalmatian/docs/monitoring-alarms/' TF_VAR_example_var='bar' TF_VAR_environment='production' TF_VAR_cluster_name='shared-cluster-production' TF_VAR_account_id='123456789012' TF_VAR_infrastructure_name='existing-shared-cluster-production' TF_VAR_dalmatian_role='dalmatian-admin' terraform apply\")\n got: (\"TF_VAR_region='eu-west-2' TF_VAR_cidr='10.0.0.0/16' TF_VAR_root_domain_zone='dalmatian.dxw.net' TF_VAR_internal_domain_zone='dalmatian.internal' TF_VAR_ecs_private_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.128.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.129.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.130.0/24\\\"}]' TF_VAR_extra_public_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.0.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.1.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.2.0/24\\\"}]' TF_VAR_instances_key_name='dalmatian-ecs-instances' TF_VAR_instance_type='t2.medium' TF_VAR_min_servers='2' TF_VAR_max_servers='4' TF_VAR_max_instance_lifetime='86400' TF_VAR_associate_public_ip_address='0' TF_VAR_docker_storage_size='40' TF_VAR_dockerhub_email='' TF_VAR_dockerhub_token='' TF_VAR_enable_efs='false' TF_VAR_encrypt_efs='true' TF_VAR_efs_dirs='[]' TF_VAR_monitoring_docs_path='https://github.com/dxw/dalmatian/docs/monitoring-alarms/' TF_VAR_environment='production' TF_VAR_account_id='123456789012' TF_VAR_infrastructure_name='new-dedicated-cluster' TF_VAR_dalmatian_role='dalmatian-admin' TF_VAR_rds='{identifier =\\\"testservice\\\",in_use_by =[\\\"test-service\\\"],clusters_in_use ={production =[\\\"test\\\"],staging =[\\\"test\\\"]},instance_class ={production =\\\"db.t2.small\\\",staging =\\\"db.t2.micro\\\"},engine =\\\"postgres\\\",engine_version =\\\"11.4\\\",allocated_storage =20,storage_encrypted =true,storage_type =\\\"gp3\\\",db_name =\\\"testapp\\\",port =5432,maintenance_window =\\\"mon:19:00-mon:19:30\\\",backup_window =\\\"09:00-10:00\\\",backup_retention_period =31,force_ssl =true,parameter_store_path_db_url_name =\\\"DATABASE_URL\\\",sql_backup_scheduled_task_environment_variables =[{name =\\\"foo\\\",value =\\\"bar\\\"}],check_sql_backup_scheduled_task_environment_variables =[{name =\\\"foo\\\",value =\\\"bar\\\"}],sync_sql_backup_to_azure =false,replication_bucket_destination_arn =\\\"\\\",replication_kms_key_id =\\\"\\\",codebuild_access =[\\\"service-name\\\"]}' terraform apply\")\n Please stub a default value first if message might be received with other args as well. \n # ./lib/dalmatian/terraform.rb:34:in `apply'\n # ./lib/dalmatian/deployable.rb:35:in `terraform_apply'\n # ./lib/dalmatian/deployable.rb:9:in `call'\n # ./lib/dalmatian/cluster.rb:269:in `deploy_rds'\n # ./lib/dalmatian/cluster.rb:70:in `block (2 levels) in deploy'\n # ./lib/dalmatian/cluster.rb:68:in `each'\n # ./lib/dalmatian/cluster.rb:68:in `block in deploy'\n # ./lib/dalmatian/cluster.rb:59:in `each'\n # ./lib/dalmatian/cluster.rb:59:in `deploy'\n # ./lib/dalmatian/infrastructure.rb:24:in `block in deploy'\n # ./lib/dalmatian/infrastructure.rb:22:in `each'\n # ./lib/dalmatian/infrastructure.rb:22:in `deploy'\n # ./spec/integration/deploys_local_configuration_spec.rb:1577:in `block (2 levels) in <module:Dalmatian>'\n # ./spec/support/spec_helper.rb:24:in `block (3 levels) in <top (required)>'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:24:in `block in modify'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:15:in `synchronize'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:15:in `modify'\n # ./spec/support/spec_helper.rb:20:in `block (2 levels) in <top (required)>'\n # /Users/bob/.bundles/ruby/2.7.0/gems/webmock-3.19.1/lib/webmock/rspec.rb:39:in `block (2 levels) in <top (required)>'\n\n 12) tests local configuration use of \"terraform apply\" passes the cluster 3 config to \"terraform apply\"\n Failure/Error: Helper.run!(cmd)\n \n #<Dalmatian::Helper (class)> received :run! with unexpected arguments\n expected: (\"TF_VAR_region='eu-west-2' TF_VAR_cidr='10.0.0.0/16' TF_VAR_root_domain_zone='dalmatian.dxw.net' TF_VAR_internal_domain_zone='dalmatian.internal' TF_VAR_ecs_private_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.128.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.129.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.130.0/24\\\"}]' TF_VAR_extra_public_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.0.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.1.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.2.0/24\\\"}]' TF_VAR_instances_key_name='dalmatian-ecs-instances' TF_VAR_instance_type='t2.medium' TF_VAR_min_servers='2' TF_VAR_max_servers='4' TF_VAR_max_instance_lifetime='86400' TF_VAR_associate_public_ip_address='0' TF_VAR_docker_storage_size='40' TF_VAR_dockerhub_email='' TF_VAR_dockerhub_token='' TF_VAR_enable_efs='false' TF_VAR_encrypt_efs='true' TF_VAR_efs_dirs='[]' TF_VAR_monitoring_docs_path='https://github.com/dxw/dalmatian/docs/monitoring-alarms/' TF_VAR_example_var='bar' TF_VAR_environment='production' TF_VAR_cluster_name='shared-cluster-production' TF_VAR_account_id='123456789012' TF_VAR_infrastructure_name='existing-shared-cluster-production' TF_VAR_dalmatian_role='dalmatian-admin' terraform apply\")\n got: (\"TF_VAR_region='eu-west-2' TF_VAR_cidr='10.0.0.0/16' TF_VAR_root_domain_zone='dalmatian.dxw.net' TF_VAR_internal_domain_zone='dalmatian.internal' TF_VAR_ecs_private_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.128.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.129.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.130.0/24\\\"}]' TF_VAR_extra_public_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.0.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.1.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.2.0/24\\\"}]' TF_VAR_instances_key_name='dalmatian-ecs-instances' TF_VAR_instance_type='t2.medium' TF_VAR_min_servers='2' TF_VAR_max_servers='4' TF_VAR_max_instance_lifetime='86400' TF_VAR_associate_public_ip_address='0' TF_VAR_docker_storage_size='40' TF_VAR_dockerhub_email='' TF_VAR_dockerhub_token='' TF_VAR_enable_efs='false' TF_VAR_encrypt_efs='true' TF_VAR_efs_dirs='[]' TF_VAR_monitoring_docs_path='https://github.com/dxw/dalmatian/docs/monitoring-alarms/' TF_VAR_environment='production' TF_VAR_account_id='123456789012' TF_VAR_infrastructure_name='new-dedicated-cluster' TF_VAR_dalmatian_role='dalmatian-admin' TF_VAR_rds='{identifier =\\\"testservice\\\",in_use_by =[\\\"test-service\\\"],clusters_in_use ={production =[\\\"test\\\"],staging =[\\\"test\\\"]},instance_class ={production =\\\"db.t2.small\\\",staging =\\\"db.t2.micro\\\"},engine =\\\"postgres\\\",engine_version =\\\"11.4\\\",allocated_storage =20,storage_encrypted =true,storage_type =\\\"gp3\\\",db_name =\\\"testapp\\\",port =5432,maintenance_window =\\\"mon:19:00-mon:19:30\\\",backup_window =\\\"09:00-10:00\\\",backup_retention_period =31,force_ssl =true,parameter_store_path_db_url_name =\\\"DATABASE_URL\\\",sql_backup_scheduled_task_environment_variables =[{name =\\\"foo\\\",value =\\\"bar\\\"}],check_sql_backup_scheduled_task_environment_variables =[{name =\\\"foo\\\",value =\\\"bar\\\"}],sync_sql_backup_to_azure =false,replication_bucket_destination_arn =\\\"\\\",replication_kms_key_id =\\\"\\\",codebuild_access =[\\\"service-name\\\"]}' terraform apply\")\n Please stub a default value first if message might be received with other args as well. \n # ./lib/dalmatian/terraform.rb:34:in `apply'\n # ./lib/dalmatian/deployable.rb:35:in `terraform_apply'\n # ./lib/dalmatian/deployable.rb:9:in `call'\n # ./lib/dalmatian/cluster.rb:269:in `deploy_rds'\n # ./lib/dalmatian/cluster.rb:70:in `block (2 levels) in deploy'\n # ./lib/dalmatian/cluster.rb:68:in `each'\n # ./lib/dalmatian/cluster.rb:68:in `block in deploy'\n # ./lib/dalmatian/cluster.rb:59:in `each'\n # ./lib/dalmatian/cluster.rb:59:in `deploy'\n # ./lib/dalmatian/infrastructure.rb:24:in `block in deploy'\n # ./lib/dalmatian/infrastructure.rb:22:in `each'\n # ./lib/dalmatian/infrastructure.rb:22:in `deploy'\n # ./spec/integration/deploys_local_configuration_spec.rb:1577:in `block (2 levels) in <module:Dalmatian>'\n # ./spec/support/spec_helper.rb:24:in `block (3 levels) in <top (required)>'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:24:in `block in modify'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:15:in `synchronize'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:15:in `modify'\n # ./spec/support/spec_helper.rb:20:in `block (2 levels) in <top (required)>'\n # /Users/bob/.bundles/ruby/2.7.0/gems/webmock-3.19.1/lib/webmock/rspec.rb:39:in `block (2 levels) in <top (required)>'\n\n 13) tests local configuration use of \"terraform apply\" passes the cluster 4 config to \"terraform apply\"\n Failure/Error: Helper.run!(cmd)\n \n #<Dalmatian::Helper (class)> received :run! with unexpected arguments\n expected: (\"TF_VAR_region='eu-west-2' TF_VAR_cidr='10.0.0.0/16' TF_VAR_root_domain_zone='dalmatian.dxw.net' TF_VAR_internal_domain_zone='dalmatian.internal' TF_VAR_ecs_private_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.128.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.129.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.130.0/24\\\"}]' TF_VAR_extra_public_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.0.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.1.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.2.0/24\\\"}]' TF_VAR_instances_key_name='dalmatian-ecs-instances' TF_VAR_instance_type='t2.medium' TF_VAR_min_servers='2' TF_VAR_max_servers='4' TF_VAR_max_instance_lifetime='86400' TF_VAR_associate_public_ip_address='0' TF_VAR_docker_storage_size='40' TF_VAR_dockerhub_email='' TF_VAR_dockerhub_token='' TF_VAR_enable_efs='false' TF_VAR_encrypt_efs='true' TF_VAR_efs_dirs='[]' TF_VAR_monitoring_docs_path='https://github.com/dxw/dalmatian/docs/monitoring-alarms/' TF_VAR_example_var='bar' TF_VAR_environment='production' TF_VAR_cluster_name='shared-cluster-production' TF_VAR_account_id='123456789012' TF_VAR_infrastructure_name='existing-shared-cluster-production' TF_VAR_dalmatian_role='dalmatian-admin' terraform apply\")\n got: (\"TF_VAR_region='eu-west-2' TF_VAR_cidr='10.0.0.0/16' TF_VAR_root_domain_zone='dalmatian.dxw.net' TF_VAR_internal_domain_zone='dalmatian.internal' TF_VAR_ecs_private_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.128.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.129.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.130.0/24\\\"}]' TF_VAR_extra_public_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.0.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.1.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.2.0/24\\\"}]' TF_VAR_instances_key_name='dalmatian-ecs-instances' TF_VAR_instance_type='t2.medium' TF_VAR_min_servers='2' TF_VAR_max_servers='4' TF_VAR_max_instance_lifetime='86400' TF_VAR_associate_public_ip_address='0' TF_VAR_docker_storage_size='40' TF_VAR_dockerhub_email='' TF_VAR_dockerhub_token='' TF_VAR_enable_efs='false' TF_VAR_encrypt_efs='true' TF_VAR_efs_dirs='[]' TF_VAR_monitoring_docs_path='https://github.com/dxw/dalmatian/docs/monitoring-alarms/' TF_VAR_environment='production' TF_VAR_account_id='123456789012' TF_VAR_infrastructure_name='new-dedicated-cluster' TF_VAR_dalmatian_role='dalmatian-admin' TF_VAR_rds='{identifier =\\\"testservice\\\",in_use_by =[\\\"test-service\\\"],clusters_in_use ={production =[\\\"test\\\"],staging =[\\\"test\\\"]},instance_class ={production =\\\"db.t2.small\\\",staging =\\\"db.t2.micro\\\"},engine =\\\"postgres\\\",engine_version =\\\"11.4\\\",allocated_storage =20,storage_encrypted =true,storage_type =\\\"gp3\\\",db_name =\\\"testapp\\\",port =5432,maintenance_window =\\\"mon:19:00-mon:19:30\\\",backup_window =\\\"09:00-10:00\\\",backup_retention_period =31,force_ssl =true,parameter_store_path_db_url_name =\\\"DATABASE_URL\\\",sql_backup_scheduled_task_environment_variables =[{name =\\\"foo\\\",value =\\\"bar\\\"}],check_sql_backup_scheduled_task_environment_variables =[{name =\\\"foo\\\",value =\\\"bar\\\"}],sync_sql_backup_to_azure =false,replication_bucket_destination_arn =\\\"\\\",replication_kms_key_id =\\\"\\\",codebuild_access =[\\\"service-name\\\"]}' terraform apply\")\n Please stub a default value first if message might be received with other args as well. \n # ./lib/dalmatian/terraform.rb:34:in `apply'\n # ./lib/dalmatian/deployable.rb:35:in `terraform_apply'\n # ./lib/dalmatian/deployable.rb:9:in `call'\n # ./lib/dalmatian/cluster.rb:269:in `deploy_rds'\n # ./lib/dalmatian/cluster.rb:70:in `block (2 levels) in deploy'\n # ./lib/dalmatian/cluster.rb:68:in `each'\n # ./lib/dalmatian/cluster.rb:68:in `block in deploy'\n # ./lib/dalmatian/cluster.rb:59:in `each'\n # ./lib/dalmatian/cluster.rb:59:in `deploy'\n # ./lib/dalmatian/infrastructure.rb:24:in `block in deploy'\n # ./lib/dalmatian/infrastructure.rb:22:in `each'\n # ./lib/dalmatian/infrastructure.rb:22:in `deploy'\n # ./spec/integration/deploys_local_configuration_spec.rb:1577:in `block (2 levels) in <module:Dalmatian>'\n # ./spec/support/spec_helper.rb:24:in `block (3 levels) in <top (required)>'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:24:in `block in modify'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:15:in `synchronize'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:15:in `modify'\n # ./spec/support/spec_helper.rb:20:in `block (2 levels) in <top (required)>'\n # /Users/bob/.bundles/ruby/2.7.0/gems/webmock-3.19.1/lib/webmock/rspec.rb:39:in `block (2 levels) in <top (required)>'\n\n 14) tests local configuration invokes \"terraform validate\" with the expected cluster options\n Failure/Error: Helper.run!(cmd)\n \n #<Dalmatian::Helper (class)> received :run! with unexpected arguments\n expected: (\"TF_VAR_region='eu-west-2' TF_VAR_cidr='10.0.0.0/16' TF_VAR_root_domain_zone='dalmatian.dxw.net' TF_VAR_internal_domain_zone='dalmatian.internal' TF_VAR_ecs_private_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.128.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.129.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.130.0/24\\\"}]' TF_VAR_extra_public_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.0.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.1.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.2.0/24\\\"}]' TF_VAR_instances_key_name='dalmatian-ecs-instances' TF_VAR_instance_type='t2.medium' TF_VAR_min_servers='2' TF_VAR_max_servers='4' TF_VAR_max_instance_lifetime='86400' TF_VAR_associate_public_ip_address='0' TF_VAR_docker_storage_size='40' TF_VAR_dockerhub_email='' TF_VAR_dockerhub_token='' TF_VAR_enable_efs='false' TF_VAR_encrypt_efs='true' TF_VAR_efs_dirs='[]' TF_VAR_monitoring_docs_path='https://github.com/dxw/dalmatian/docs/monitoring-alarms/' TF_VAR_example_var='bar' TF_VAR_environment='production' TF_VAR_cluster_name='shared-cluster-production' TF_VAR_account_id='123456789012' TF_VAR_infrastructure_name='existing-shared-cluster-production' TF_VAR_dalmatian_role='dalmatian-read' terraform plan\")\n got: (\"TF_VAR_region='eu-west-2' TF_VAR_cidr='10.0.0.0/16' TF_VAR_root_domain_zone='dalmatian.dxw.net' TF_VAR_internal_domain_zone='dalmatian.internal' TF_VAR_ecs_private_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.128.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.129.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.130.0/24\\\"}]' TF_VAR_extra_public_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.0.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.1.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.2.0/24\\\"}]' TF_VAR_instances_key_name='dalmatian-ecs-instances' TF_VAR_instance_type='t2.medium' TF_VAR_min_servers='2' TF_VAR_max_servers='4' TF_VAR_max_instance_lifetime='86400' TF_VAR_associate_public_ip_address='0' TF_VAR_docker_storage_size='40' TF_VAR_dockerhub_email='' TF_VAR_dockerhub_token='' TF_VAR_enable_efs='false' TF_VAR_encrypt_efs='true' TF_VAR_efs_dirs='[]' TF_VAR_monitoring_docs_path='https://github.com/dxw/dalmatian/docs/monitoring-alarms/' TF_VAR_environment='production' TF_VAR_account_id='123456789012' TF_VAR_infrastructure_name='new-dedicated-cluster' TF_VAR_dalmatian_role='dalmatian-read' TF_VAR_rds='{identifier =\\\"testservice\\\",in_use_by =[\\\"test-service\\\"],clusters_in_use ={production =[\\\"test\\\"],staging =[\\\"test\\\"]},instance_class ={production =\\\"db.t2.small\\\",staging =\\\"db.t2.micro\\\"},engine =\\\"postgres\\\",engine_version =\\\"11.4\\\",allocated_storage =20,storage_encrypted =true,storage_type =\\\"gp3\\\",db_name =\\\"testapp\\\",port =5432,maintenance_window =\\\"mon:19:00-mon:19:30\\\",backup_window =\\\"09:00-10:00\\\",backup_retention_period =31,force_ssl =true,parameter_store_path_db_url_name =\\\"DATABASE_URL\\\",sql_backup_scheduled_task_environment_variables =[{name =\\\"foo\\\",value =\\\"bar\\\"}],check_sql_backup_scheduled_task_environment_variables =[{name =\\\"foo\\\",value =\\\"bar\\\"}],sync_sql_backup_to_azure =false,replication_bucket_destination_arn =\\\"\\\",replication_kms_key_id =\\\"\\\",codebuild_access =[\\\"service-name\\\"]}' terraform plan\")\n Please stub a default value first if message might be received with other args as well. \n # ./lib/dalmatian/terraform.rb:25:in `plan'\n # ./lib/dalmatian/deployable.rb:28:in `terraform_plan'\n # ./lib/dalmatian/deployable.rb:8:in `call'\n # ./lib/dalmatian/cluster.rb:269:in `deploy_rds'\n # ./lib/dalmatian/cluster.rb:70:in `block (2 levels) in deploy'\n # ./lib/dalmatian/cluster.rb:68:in `each'\n # ./lib/dalmatian/cluster.rb:68:in `block in deploy'\n # ./lib/dalmatian/cluster.rb:59:in `each'\n # ./lib/dalmatian/cluster.rb:59:in `deploy'\n # ./lib/dalmatian/infrastructure.rb:24:in `block in deploy'\n # ./lib/dalmatian/infrastructure.rb:22:in `each'\n # ./lib/dalmatian/infrastructure.rb:22:in `deploy'\n # ./lib/dalmatian/infrastructure.rb:18:in `test'\n # ./spec/integration/tests_local_configuration_spec.rb:3108:in `block (2 levels) in <module:Dalmatian>'\n # ./spec/support/spec_helper.rb:24:in `block (3 levels) in <top (required)>'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:24:in `block in modify'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:15:in `synchronize'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:15:in `modify'\n # ./spec/support/spec_helper.rb:20:in `block (2 levels) in <top (required)>'\n # /Users/bob/.bundles/ruby/2.7.0/gems/webmock-3.19.1/lib/webmock/rspec.rb:39:in `block (2 levels) in <top (required)>'\n\n 15) tests local configuration invokes \"terraform validate\" with the expected source options\n Failure/Error: Helper.run!(cmd)\n \n #<Dalmatian::Helper (class)> received :run! with unexpected arguments\n expected: (\"TF_VAR_region='eu-west-2' TF_VAR_cidr='10.0.0.0/16' TF_VAR_root_domain_zone='dalmatian.dxw.net' TF_VAR_internal_domain_zone='dalmatian.internal' TF_VAR_ecs_private_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.128.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.129.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.130.0/24\\\"}]' TF_VAR_extra_public_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.0.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.1.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.2.0/24\\\"}]' TF_VAR_instances_key_name='dalmatian-ecs-instances' TF_VAR_instance_type='t2.medium' TF_VAR_min_servers='2' TF_VAR_max_servers='4' TF_VAR_max_instance_lifetime='86400' TF_VAR_associate_public_ip_address='0' TF_VAR_docker_storage_size='40' TF_VAR_dockerhub_email='' TF_VAR_dockerhub_token='' TF_VAR_enable_efs='false' TF_VAR_encrypt_efs='true' TF_VAR_efs_dirs='[]' TF_VAR_monitoring_docs_path='https://github.com/dxw/dalmatian/docs/monitoring-alarms/' TF_VAR_example_var='bar' TF_VAR_environment='production' TF_VAR_cluster_name='shared-cluster-production' TF_VAR_account_id='123456789012' TF_VAR_infrastructure_name='existing-shared-cluster-production' TF_VAR_dalmatian_role='dalmatian-read' terraform plan\")\n got: (\"TF_VAR_region='eu-west-2' TF_VAR_cidr='10.0.0.0/16' TF_VAR_root_domain_zone='dalmatian.dxw.net' TF_VAR_internal_domain_zone='dalmatian.internal' TF_VAR_ecs_private_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.128.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.129.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.130.0/24\\\"}]' TF_VAR_extra_public_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.0.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.1.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.2.0/24\\\"}]' TF_VAR_instances_key_name='dalmatian-ecs-instances' TF_VAR_instance_type='t2.medium' TF_VAR_min_servers='2' TF_VAR_max_servers='4' TF_VAR_max_instance_lifetime='86400' TF_VAR_associate_public_ip_address='0' TF_VAR_docker_storage_size='40' TF_VAR_dockerhub_email='' TF_VAR_dockerhub_token='' TF_VAR_enable_efs='false' TF_VAR_encrypt_efs='true' TF_VAR_efs_dirs='[]' TF_VAR_monitoring_docs_path='https://github.com/dxw/dalmatian/docs/monitoring-alarms/' TF_VAR_environment='production' TF_VAR_account_id='123456789012' TF_VAR_infrastructure_name='new-dedicated-cluster' TF_VAR_dalmatian_role='dalmatian-read' TF_VAR_rds='{identifier =\\\"testservice\\\",in_use_by =[\\\"test-service\\\"],clusters_in_use ={production =[\\\"test\\\"],staging =[\\\"test\\\"]},instance_class ={production =\\\"db.t2.small\\\",staging =\\\"db.t2.micro\\\"},engine =\\\"postgres\\\",engine_version =\\\"11.4\\\",allocated_storage =20,storage_encrypted =true,storage_type =\\\"gp3\\\",db_name =\\\"testapp\\\",port =5432,maintenance_window =\\\"mon:19:00-mon:19:30\\\",backup_window =\\\"09:00-10:00\\\",backup_retention_period =31,force_ssl =true,parameter_store_path_db_url_name =\\\"DATABASE_URL\\\",sql_backup_scheduled_task_environment_variables =[{name =\\\"foo\\\",value =\\\"bar\\\"}],check_sql_backup_scheduled_task_environment_variables =[{name =\\\"foo\\\",value =\\\"bar\\\"}],sync_sql_backup_to_azure =false,replication_bucket_destination_arn =\\\"\\\",replication_kms_key_id =\\\"\\\",codebuild_access =[\\\"service-name\\\"]}' terraform plan\")\n Please stub a default value first if message might be received with other args as well. \n # ./lib/dalmatian/terraform.rb:25:in `plan'\n # ./lib/dalmatian/deployable.rb:28:in `terraform_plan'\n # ./lib/dalmatian/deployable.rb:8:in `call'\n # ./lib/dalmatian/cluster.rb:269:in `deploy_rds'\n # ./lib/dalmatian/cluster.rb:70:in `block (2 levels) in deploy'\n # ./lib/dalmatian/cluster.rb:68:in `each'\n # ./lib/dalmatian/cluster.rb:68:in `block in deploy'\n # ./lib/dalmatian/cluster.rb:59:in `each'\n # ./lib/dalmatian/cluster.rb:59:in `deploy'\n # ./lib/dalmatian/infrastructure.rb:24:in `block in deploy'\n # ./lib/dalmatian/infrastructure.rb:22:in `each'\n # ./lib/dalmatian/infrastructure.rb:22:in `deploy'\n # ./lib/dalmatian/infrastructure.rb:18:in `test'\n # ./spec/integration/tests_local_configuration_spec.rb:3108:in `block (2 levels) in <module:Dalmatian>'\n # ./spec/support/spec_helper.rb:24:in `block (3 levels) in <top (required)>'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:24:in `block in modify'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:15:in `synchronize'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:15:in `modify'\n # ./spec/support/spec_helper.rb:20:in `block (2 levels) in <top (required)>'\n # /Users/bob/.bundles/ruby/2.7.0/gems/webmock-3.19.1/lib/webmock/rspec.rb:39:in `block (2 levels) in <top (required)>'\n\n 16) tests local configuration use of \"terraform plan\" passes the hosted zone config to \"terraform plan\"\n Failure/Error: Helper.run!(cmd)\n \n #<Dalmatian::Helper (class)> received :run! with unexpected arguments\n expected: (\"TF_VAR_region='eu-west-2' TF_VAR_cidr='10.0.0.0/16' TF_VAR_root_domain_zone='dalmatian.dxw.net' TF_VAR_internal_domain_zone='dalmatian.internal' TF_VAR_ecs_private_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.128.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.129.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.130.0/24\\\"}]' TF_VAR_extra_public_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.0.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.1.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.2.0/24\\\"}]' TF_VAR_instances_key_name='dalmatian-ecs-instances' TF_VAR_instance_type='t2.medium' TF_VAR_min_servers='2' TF_VAR_max_servers='4' TF_VAR_max_instance_lifetime='86400' TF_VAR_associate_public_ip_address='0' TF_VAR_docker_storage_size='40' TF_VAR_dockerhub_email='' TF_VAR_dockerhub_token='' TF_VAR_enable_efs='false' TF_VAR_encrypt_efs='true' TF_VAR_efs_dirs='[]' TF_VAR_monitoring_docs_path='https://github.com/dxw/dalmatian/docs/monitoring-alarms/' TF_VAR_example_var='bar' TF_VAR_environment='production' TF_VAR_cluster_name='shared-cluster-production' TF_VAR_account_id='123456789012' TF_VAR_infrastructure_name='existing-shared-cluster-production' TF_VAR_dalmatian_role='dalmatian-read' terraform plan\")\n got: (\"TF_VAR_region='eu-west-2' TF_VAR_cidr='10.0.0.0/16' TF_VAR_root_domain_zone='dalmatian.dxw.net' TF_VAR_internal_domain_zone='dalmatian.internal' TF_VAR_ecs_private_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.128.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.129.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.130.0/24\\\"}]' TF_VAR_extra_public_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.0.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.1.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.2.0/24\\\"}]' TF_VAR_instances_key_name='dalmatian-ecs-instances' TF_VAR_instance_type='t2.medium' TF_VAR_min_servers='2' TF_VAR_max_servers='4' TF_VAR_max_instance_lifetime='86400' TF_VAR_associate_public_ip_address='0' TF_VAR_docker_storage_size='40' TF_VAR_dockerhub_email='' TF_VAR_dockerhub_token='' TF_VAR_enable_efs='false' TF_VAR_encrypt_efs='true' TF_VAR_efs_dirs='[]' TF_VAR_monitoring_docs_path='https://github.com/dxw/dalmatian/docs/monitoring-alarms/' TF_VAR_environment='production' TF_VAR_account_id='123456789012' TF_VAR_infrastructure_name='new-dedicated-cluster' TF_VAR_dalmatian_role='dalmatian-read' TF_VAR_rds='{identifier =\\\"testservice\\\",in_use_by =[\\\"test-service\\\"],clusters_in_use ={production =[\\\"test\\\"],staging =[\\\"test\\\"]},instance_class ={production =\\\"db.t2.small\\\",staging =\\\"db.t2.micro\\\"},engine =\\\"postgres\\\",engine_version =\\\"11.4\\\",allocated_storage =20,storage_encrypted =true,storage_type =\\\"gp3\\\",db_name =\\\"testapp\\\",port =5432,maintenance_window =\\\"mon:19:00-mon:19:30\\\",backup_window =\\\"09:00-10:00\\\",backup_retention_period =31,force_ssl =true,parameter_store_path_db_url_name =\\\"DATABASE_URL\\\",sql_backup_scheduled_task_environment_variables =[{name =\\\"foo\\\",value =\\\"bar\\\"}],check_sql_backup_scheduled_task_environment_variables =[{name =\\\"foo\\\",value =\\\"bar\\\"}],sync_sql_backup_to_azure =false,replication_bucket_destination_arn =\\\"\\\",replication_kms_key_id =\\\"\\\",codebuild_access =[\\\"service-name\\\"]}' terraform plan\")\n Please stub a default value first if message might be received with other args as well. \n # ./lib/dalmatian/terraform.rb:25:in `plan'\n # ./lib/dalmatian/deployable.rb:28:in `terraform_plan'\n # ./lib/dalmatian/deployable.rb:8:in `call'\n # ./lib/dalmatian/cluster.rb:269:in `deploy_rds'\n # ./lib/dalmatian/cluster.rb:70:in `block (2 levels) in deploy'\n # ./lib/dalmatian/cluster.rb:68:in `each'\n # ./lib/dalmatian/cluster.rb:68:in `block in deploy'\n # ./lib/dalmatian/cluster.rb:59:in `each'\n # ./lib/dalmatian/cluster.rb:59:in `deploy'\n # ./lib/dalmatian/infrastructure.rb:24:in `block in deploy'\n # ./lib/dalmatian/infrastructure.rb:22:in `each'\n # ./lib/dalmatian/infrastructure.rb:22:in `deploy'\n # ./lib/dalmatian/infrastructure.rb:18:in `test'\n # ./spec/integration/tests_local_configuration_spec.rb:3108:in `block (2 levels) in <module:Dalmatian>'\n # ./spec/support/spec_helper.rb:24:in `block (3 levels) in <top (required)>'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:24:in `block in modify'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:15:in `synchronize'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:15:in `modify'\n # ./spec/support/spec_helper.rb:20:in `block (2 levels) in <top (required)>'\n # /Users/bob/.bundles/ruby/2.7.0/gems/webmock-3.19.1/lib/webmock/rspec.rb:39:in `block (2 levels) in <top (required)>'\n\n 17) tests local configuration use of \"terraform plan\" passes the s3 config to \"terraform plan\"\n Failure/Error: Helper.run!(cmd)\n \n #<Dalmatian::Helper (class)> received :run! with unexpected arguments\n expected: (\"TF_VAR_region='eu-west-2' TF_VAR_cidr='10.0.0.0/16' TF_VAR_root_domain_zone='dalmatian.dxw.net' TF_VAR_internal_domain_zone='dalmatian.internal' TF_VAR_ecs_private_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.128.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.129.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.130.0/24\\\"}]' TF_VAR_extra_public_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.0.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.1.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.2.0/24\\\"}]' TF_VAR_instances_key_name='dalmatian-ecs-instances' TF_VAR_instance_type='t2.medium' TF_VAR_min_servers='2' TF_VAR_max_servers='4' TF_VAR_max_instance_lifetime='86400' TF_VAR_associate_public_ip_address='0' TF_VAR_docker_storage_size='40' TF_VAR_dockerhub_email='' TF_VAR_dockerhub_token='' TF_VAR_enable_efs='false' TF_VAR_encrypt_efs='true' TF_VAR_efs_dirs='[]' TF_VAR_monitoring_docs_path='https://github.com/dxw/dalmatian/docs/monitoring-alarms/' TF_VAR_example_var='bar' TF_VAR_environment='production' TF_VAR_cluster_name='shared-cluster-production' TF_VAR_account_id='123456789012' TF_VAR_infrastructure_name='existing-shared-cluster-production' TF_VAR_dalmatian_role='dalmatian-read' terraform plan\")\n got: (\"TF_VAR_region='eu-west-2' TF_VAR_cidr='10.0.0.0/16' TF_VAR_root_domain_zone='dalmatian.dxw.net' TF_VAR_internal_domain_zone='dalmatian.internal' TF_VAR_ecs_private_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.128.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.129.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.130.0/24\\\"}]' TF_VAR_extra_public_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.0.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.1.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.2.0/24\\\"}]' TF_VAR_instances_key_name='dalmatian-ecs-instances' TF_VAR_instance_type='t2.medium' TF_VAR_min_servers='2' TF_VAR_max_servers='4' TF_VAR_max_instance_lifetime='86400' TF_VAR_associate_public_ip_address='0' TF_VAR_docker_storage_size='40' TF_VAR_dockerhub_email='' TF_VAR_dockerhub_token='' TF_VAR_enable_efs='false' TF_VAR_encrypt_efs='true' TF_VAR_efs_dirs='[]' TF_VAR_monitoring_docs_path='https://github.com/dxw/dalmatian/docs/monitoring-alarms/' TF_VAR_environment='production' TF_VAR_account_id='123456789012' TF_VAR_infrastructure_name='new-dedicated-cluster' TF_VAR_dalmatian_role='dalmatian-read' TF_VAR_rds='{identifier =\\\"testservice\\\",in_use_by =[\\\"test-service\\\"],clusters_in_use ={production =[\\\"test\\\"],staging =[\\\"test\\\"]},instance_class ={production =\\\"db.t2.small\\\",staging =\\\"db.t2.micro\\\"},engine =\\\"postgres\\\",engine_version =\\\"11.4\\\",allocated_storage =20,storage_encrypted =true,storage_type =\\\"gp3\\\",db_name =\\\"testapp\\\",port =5432,maintenance_window =\\\"mon:19:00-mon:19:30\\\",backup_window =\\\"09:00-10:00\\\",backup_retention_period =31,force_ssl =true,parameter_store_path_db_url_name =\\\"DATABASE_URL\\\",sql_backup_scheduled_task_environment_variables =[{name =\\\"foo\\\",value =\\\"bar\\\"}],check_sql_backup_scheduled_task_environment_variables =[{name =\\\"foo\\\",value =\\\"bar\\\"}],sync_sql_backup_to_azure =false,replication_bucket_destination_arn =\\\"\\\",replication_kms_key_id =\\\"\\\",codebuild_access =[\\\"service-name\\\"]}' terraform plan\")\n Please stub a default value first if message might be received with other args as well. \n # ./lib/dalmatian/terraform.rb:25:in `plan'\n # ./lib/dalmatian/deployable.rb:28:in `terraform_plan'\n # ./lib/dalmatian/deployable.rb:8:in `call'\n # ./lib/dalmatian/cluster.rb:269:in `deploy_rds'\n # ./lib/dalmatian/cluster.rb:70:in `block (2 levels) in deploy'\n # ./lib/dalmatian/cluster.rb:68:in `each'\n # ./lib/dalmatian/cluster.rb:68:in `block in deploy'\n # ./lib/dalmatian/cluster.rb:59:in `each'\n # ./lib/dalmatian/cluster.rb:59:in `deploy'\n # ./lib/dalmatian/infrastructure.rb:24:in `block in deploy'\n # ./lib/dalmatian/infrastructure.rb:22:in `each'\n # ./lib/dalmatian/infrastructure.rb:22:in `deploy'\n # ./lib/dalmatian/infrastructure.rb:18:in `test'\n # ./spec/integration/tests_local_configuration_spec.rb:3108:in `block (2 levels) in <module:Dalmatian>'\n # ./spec/support/spec_helper.rb:24:in `block (3 levels) in <top (required)>'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:24:in `block in modify'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:15:in `synchronize'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:15:in `modify'\n # ./spec/support/spec_helper.rb:20:in `block (2 levels) in <top (required)>'\n # /Users/bob/.bundles/ruby/2.7.0/gems/webmock-3.19.1/lib/webmock/rspec.rb:39:in `block (2 levels) in <top (required)>'\n\n 18) tests local configuration use of \"terraform plan\" passes the vpn customer gateway config to \"terraform plan\"\n Failure/Error: Helper.run!(cmd)\n \n #<Dalmatian::Helper (class)> received :run! with unexpected arguments\n expected: (\"TF_VAR_region='eu-west-2' TF_VAR_cidr='10.0.0.0/16' TF_VAR_root_domain_zone='dalmatian.dxw.net' TF_VAR_internal_domain_zone='dalmatian.internal' TF_VAR_ecs_private_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.128.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.129.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.130.0/24\\\"}]' TF_VAR_extra_public_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.0.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.1.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.2.0/24\\\"}]' TF_VAR_instances_key_name='dalmatian-ecs-instances' TF_VAR_instance_type='t2.medium' TF_VAR_min_servers='2' TF_VAR_max_servers='4' TF_VAR_max_instance_lifetime='86400' TF_VAR_associate_public_ip_address='0' TF_VAR_docker_storage_size='40' TF_VAR_dockerhub_email='' TF_VAR_dockerhub_token='' TF_VAR_enable_efs='false' TF_VAR_encrypt_efs='true' TF_VAR_efs_dirs='[]' TF_VAR_monitoring_docs_path='https://github.com/dxw/dalmatian/docs/monitoring-alarms/' TF_VAR_example_var='bar' TF_VAR_environment='production' TF_VAR_cluster_name='shared-cluster-production' TF_VAR_account_id='123456789012' TF_VAR_infrastructure_name='existing-shared-cluster-production' TF_VAR_dalmatian_role='dalmatian-read' terraform plan\")\n got: (\"TF_VAR_region='eu-west-2' TF_VAR_cidr='10.0.0.0/16' TF_VAR_root_domain_zone='dalmatian.dxw.net' TF_VAR_internal_domain_zone='dalmatian.internal' TF_VAR_ecs_private_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.128.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.129.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.130.0/24\\\"}]' TF_VAR_extra_public_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.0.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.1.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.2.0/24\\\"}]' TF_VAR_instances_key_name='dalmatian-ecs-instances' TF_VAR_instance_type='t2.medium' TF_VAR_min_servers='2' TF_VAR_max_servers='4' TF_VAR_max_instance_lifetime='86400' TF_VAR_associate_public_ip_address='0' TF_VAR_docker_storage_size='40' TF_VAR_dockerhub_email='' TF_VAR_dockerhub_token='' TF_VAR_enable_efs='false' TF_VAR_encrypt_efs='true' TF_VAR_efs_dirs='[]' TF_VAR_monitoring_docs_path='https://github.com/dxw/dalmatian/docs/monitoring-alarms/' TF_VAR_environment='production' TF_VAR_account_id='123456789012' TF_VAR_infrastructure_name='new-dedicated-cluster' TF_VAR_dalmatian_role='dalmatian-read' TF_VAR_rds='{identifier =\\\"testservice\\\",in_use_by =[\\\"test-service\\\"],clusters_in_use ={production =[\\\"test\\\"],staging =[\\\"test\\\"]},instance_class ={production =\\\"db.t2.small\\\",staging =\\\"db.t2.micro\\\"},engine =\\\"postgres\\\",engine_version =\\\"11.4\\\",allocated_storage =20,storage_encrypted =true,storage_type =\\\"gp3\\\",db_name =\\\"testapp\\\",port =5432,maintenance_window =\\\"mon:19:00-mon:19:30\\\",backup_window =\\\"09:00-10:00\\\",backup_retention_period =31,force_ssl =true,parameter_store_path_db_url_name =\\\"DATABASE_URL\\\",sql_backup_scheduled_task_environment_variables =[{name =\\\"foo\\\",value =\\\"bar\\\"}],check_sql_backup_scheduled_task_environment_variables =[{name =\\\"foo\\\",value =\\\"bar\\\"}],sync_sql_backup_to_azure =false,replication_bucket_destination_arn =\\\"\\\",replication_kms_key_id =\\\"\\\",codebuild_access =[\\\"service-name\\\"]}' terraform plan\")\n Please stub a default value first if message might be received with other args as well. \n # ./lib/dalmatian/terraform.rb:25:in `plan'\n # ./lib/dalmatian/deployable.rb:28:in `terraform_plan'\n # ./lib/dalmatian/deployable.rb:8:in `call'\n # ./lib/dalmatian/cluster.rb:269:in `deploy_rds'\n # ./lib/dalmatian/cluster.rb:70:in `block (2 levels) in deploy'\n # ./lib/dalmatian/cluster.rb:68:in `each'\n # ./lib/dalmatian/cluster.rb:68:in `block in deploy'\n # ./lib/dalmatian/cluster.rb:59:in `each'\n # ./lib/dalmatian/cluster.rb:59:in `deploy'\n # ./lib/dalmatian/infrastructure.rb:24:in `block in deploy'\n # ./lib/dalmatian/infrastructure.rb:22:in `each'\n # ./lib/dalmatian/infrastructure.rb:22:in `deploy'\n # ./lib/dalmatian/infrastructure.rb:18:in `test'\n # ./spec/integration/tests_local_configuration_spec.rb:3108:in `block (2 levels) in <module:Dalmatian>'\n # ./spec/support/spec_helper.rb:24:in `block (3 levels) in <top (required)>'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:24:in `block in modify'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:15:in `synchronize'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:15:in `modify'\n # ./spec/support/spec_helper.rb:20:in `block (2 levels) in <top (required)>'\n # /Users/bob/.bundles/ruby/2.7.0/gems/webmock-3.19.1/lib/webmock/rspec.rb:39:in `block (2 levels) in <top (required)>'\n\n 19) tests local configuration use of \"terraform plan\" passes the base config to \"terraform plan\"\n Failure/Error: Helper.run!(cmd)\n \n #<Dalmatian::Helper (class)> received :run! with unexpected arguments\n expected: (\"TF_VAR_region='eu-west-2' TF_VAR_cidr='10.0.0.0/16' TF_VAR_root_domain_zone='dalmatian.dxw.net' TF_VAR_internal_domain_zone='dalmatian.internal' TF_VAR_ecs_private_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.128.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.129.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.130.0/24\\\"}]' TF_VAR_extra_public_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.0.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.1.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.2.0/24\\\"}]' TF_VAR_instances_key_name='dalmatian-ecs-instances' TF_VAR_instance_type='t2.medium' TF_VAR_min_servers='2' TF_VAR_max_servers='4' TF_VAR_max_instance_lifetime='86400' TF_VAR_associate_public_ip_address='0' TF_VAR_docker_storage_size='40' TF_VAR_dockerhub_email='' TF_VAR_dockerhub_token='' TF_VAR_enable_efs='false' TF_VAR_encrypt_efs='true' TF_VAR_efs_dirs='[]' TF_VAR_monitoring_docs_path='https://github.com/dxw/dalmatian/docs/monitoring-alarms/' TF_VAR_example_var='bar' TF_VAR_environment='production' TF_VAR_cluster_name='shared-cluster-production' TF_VAR_account_id='123456789012' TF_VAR_infrastructure_name='existing-shared-cluster-production' TF_VAR_dalmatian_role='dalmatian-read' terraform plan\")\n got: (\"TF_VAR_region='eu-west-2' TF_VAR_cidr='10.0.0.0/16' TF_VAR_root_domain_zone='dalmatian.dxw.net' TF_VAR_internal_domain_zone='dalmatian.internal' TF_VAR_ecs_private_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.128.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.129.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.130.0/24\\\"}]' TF_VAR_extra_public_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.0.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.1.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.2.0/24\\\"}]' TF_VAR_instances_key_name='dalmatian-ecs-instances' TF_VAR_instance_type='t2.medium' TF_VAR_min_servers='2' TF_VAR_max_servers='4' TF_VAR_max_instance_lifetime='86400' TF_VAR_associate_public_ip_address='0' TF_VAR_docker_storage_size='40' TF_VAR_dockerhub_email='' TF_VAR_dockerhub_token='' TF_VAR_enable_efs='false' TF_VAR_encrypt_efs='true' TF_VAR_efs_dirs='[]' TF_VAR_monitoring_docs_path='https://github.com/dxw/dalmatian/docs/monitoring-alarms/' TF_VAR_environment='production' TF_VAR_account_id='123456789012' TF_VAR_infrastructure_name='new-dedicated-cluster' TF_VAR_dalmatian_role='dalmatian-read' TF_VAR_rds='{identifier =\\\"testservice\\\",in_use_by =[\\\"test-service\\\"],clusters_in_use ={production =[\\\"test\\\"],staging =[\\\"test\\\"]},instance_class ={production =\\\"db.t2.small\\\",staging =\\\"db.t2.micro\\\"},engine =\\\"postgres\\\",engine_version =\\\"11.4\\\",allocated_storage =20,storage_encrypted =true,storage_type =\\\"gp3\\\",db_name =\\\"testapp\\\",port =5432,maintenance_window =\\\"mon:19:00-mon:19:30\\\",backup_window =\\\"09:00-10:00\\\",backup_retention_period =31,force_ssl =true,parameter_store_path_db_url_name =\\\"DATABASE_URL\\\",sql_backup_scheduled_task_environment_variables =[{name =\\\"foo\\\",value =\\\"bar\\\"}],check_sql_backup_scheduled_task_environment_variables =[{name =\\\"foo\\\",value =\\\"bar\\\"}],sync_sql_backup_to_azure =false,replication_bucket_destination_arn =\\\"\\\",replication_kms_key_id =\\\"\\\",codebuild_access =[\\\"service-name\\\"]}' terraform plan\")\n Please stub a default value first if message might be received with other args as well. \n # ./lib/dalmatian/terraform.rb:25:in `plan'\n # ./lib/dalmatian/deployable.rb:28:in `terraform_plan'\n # ./lib/dalmatian/deployable.rb:8:in `call'\n # ./lib/dalmatian/cluster.rb:269:in `deploy_rds'\n # ./lib/dalmatian/cluster.rb:70:in `block (2 levels) in deploy'\n # ./lib/dalmatian/cluster.rb:68:in `each'\n # ./lib/dalmatian/cluster.rb:68:in `block in deploy'\n # ./lib/dalmatian/cluster.rb:59:in `each'\n # ./lib/dalmatian/cluster.rb:59:in `deploy'\n # ./lib/dalmatian/infrastructure.rb:24:in `block in deploy'\n # ./lib/dalmatian/infrastructure.rb:22:in `each'\n # ./lib/dalmatian/infrastructure.rb:22:in `deploy'\n # ./lib/dalmatian/infrastructure.rb:18:in `test'\n # ./spec/integration/tests_local_configuration_spec.rb:3108:in `block (2 levels) in <module:Dalmatian>'\n # ./spec/support/spec_helper.rb:24:in `block (3 levels) in <top (required)>'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:24:in `block in modify'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:15:in `synchronize'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:15:in `modify'\n # ./spec/support/spec_helper.rb:20:in `block (2 levels) in <top (required)>'\n # /Users/bob/.bundles/ruby/2.7.0/gems/webmock-3.19.1/lib/webmock/rspec.rb:39:in `block (2 levels) in <top (required)>'\n\n 20) tests local configuration use of \"terraform plan\" passes the waf config to \"terraform plan\"\n Failure/Error: Helper.run!(cmd)\n \n #<Dalmatian::Helper (class)> received :run! with unexpected arguments\n expected: (\"TF_VAR_region='eu-west-2' TF_VAR_cidr='10.0.0.0/16' TF_VAR_root_domain_zone='dalmatian.dxw.net' TF_VAR_internal_domain_zone='dalmatian.internal' TF_VAR_ecs_private_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.128.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.129.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.130.0/24\\\"}]' TF_VAR_extra_public_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.0.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.1.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.2.0/24\\\"}]' TF_VAR_instances_key_name='dalmatian-ecs-instances' TF_VAR_instance_type='t2.medium' TF_VAR_min_servers='2' TF_VAR_max_servers='4' TF_VAR_max_instance_lifetime='86400' TF_VAR_associate_public_ip_address='0' TF_VAR_docker_storage_size='40' TF_VAR_dockerhub_email='' TF_VAR_dockerhub_token='' TF_VAR_enable_efs='false' TF_VAR_encrypt_efs='true' TF_VAR_efs_dirs='[]' TF_VAR_monitoring_docs_path='https://github.com/dxw/dalmatian/docs/monitoring-alarms/' TF_VAR_example_var='bar' TF_VAR_environment='production' TF_VAR_cluster_name='shared-cluster-production' TF_VAR_account_id='123456789012' TF_VAR_infrastructure_name='existing-shared-cluster-production' TF_VAR_dalmatian_role='dalmatian-read' terraform plan\")\n got: (\"TF_VAR_region='eu-west-2' TF_VAR_cidr='10.0.0.0/16' TF_VAR_root_domain_zone='dalmatian.dxw.net' TF_VAR_internal_domain_zone='dalmatian.internal' TF_VAR_ecs_private_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.128.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.129.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.130.0/24\\\"}]' TF_VAR_extra_public_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.0.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.1.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.2.0/24\\\"}]' TF_VAR_instances_key_name='dalmatian-ecs-instances' TF_VAR_instance_type='t2.medium' TF_VAR_min_servers='2' TF_VAR_max_servers='4' TF_VAR_max_instance_lifetime='86400' TF_VAR_associate_public_ip_address='0' TF_VAR_docker_storage_size='40' TF_VAR_dockerhub_email='' TF_VAR_dockerhub_token='' TF_VAR_enable_efs='false' TF_VAR_encrypt_efs='true' TF_VAR_efs_dirs='[]' TF_VAR_monitoring_docs_path='https://github.com/dxw/dalmatian/docs/monitoring-alarms/' TF_VAR_environment='production' TF_VAR_account_id='123456789012' TF_VAR_infrastructure_name='new-dedicated-cluster' TF_VAR_dalmatian_role='dalmatian-read' TF_VAR_rds='{identifier =\\\"testservice\\\",in_use_by =[\\\"test-service\\\"],clusters_in_use ={production =[\\\"test\\\"],staging =[\\\"test\\\"]},instance_class ={production =\\\"db.t2.small\\\",staging =\\\"db.t2.micro\\\"},engine =\\\"postgres\\\",engine_version =\\\"11.4\\\",allocated_storage =20,storage_encrypted =true,storage_type =\\\"gp3\\\",db_name =\\\"testapp\\\",port =5432,maintenance_window =\\\"mon:19:00-mon:19:30\\\",backup_window =\\\"09:00-10:00\\\",backup_retention_period =31,force_ssl =true,parameter_store_path_db_url_name =\\\"DATABASE_URL\\\",sql_backup_scheduled_task_environment_variables =[{name =\\\"foo\\\",value =\\\"bar\\\"}],check_sql_backup_scheduled_task_environment_variables =[{name =\\\"foo\\\",value =\\\"bar\\\"}],sync_sql_backup_to_azure =false,replication_bucket_destination_arn =\\\"\\\",replication_kms_key_id =\\\"\\\",codebuild_access =[\\\"service-name\\\"]}' terraform plan\")\n Please stub a default value first if message might be received with other args as well. \n # ./lib/dalmatian/terraform.rb:25:in `plan'\n # ./lib/dalmatian/deployable.rb:28:in `terraform_plan'\n # ./lib/dalmatian/deployable.rb:8:in `call'\n # ./lib/dalmatian/cluster.rb:269:in `deploy_rds'\n # ./lib/dalmatian/cluster.rb:70:in `block (2 levels) in deploy'\n # ./lib/dalmatian/cluster.rb:68:in `each'\n # ./lib/dalmatian/cluster.rb:68:in `block in deploy'\n # ./lib/dalmatian/cluster.rb:59:in `each'\n # ./lib/dalmatian/cluster.rb:59:in `deploy'\n # ./lib/dalmatian/infrastructure.rb:24:in `block in deploy'\n # ./lib/dalmatian/infrastructure.rb:22:in `each'\n # ./lib/dalmatian/infrastructure.rb:22:in `deploy'\n # ./lib/dalmatian/infrastructure.rb:18:in `test'\n # ./spec/integration/tests_local_configuration_spec.rb:3108:in `block (2 levels) in <module:Dalmatian>'\n # ./spec/support/spec_helper.rb:24:in `block (3 levels) in <top (required)>'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:24:in `block in modify'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:15:in `synchronize'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:15:in `modify'\n # ./spec/support/spec_helper.rb:20:in `block (2 levels) in <top (required)>'\n # /Users/bob/.bundles/ruby/2.7.0/gems/webmock-3.19.1/lib/webmock/rspec.rb:39:in `block (2 levels) in <top (required)>'\n\n 21) tests local configuration use of \"terraform plan\" passes the rds config to \"terraform plan\"\n Failure/Error: Helper.run!(cmd)\n \n #<Dalmatian::Helper (class)> received :run! with unexpected arguments\n expected: (\"TF_VAR_region='eu-west-2' TF_VAR_cidr='10.0.0.0/16' TF_VAR_root_domain_zone='dalmatian.dxw.net' TF_VAR_internal_domain_zone='dalmatian.internal' TF_VAR_ecs_private_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.128.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.129.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.130.0/24\\\"}]' TF_VAR_extra_public_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.0.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.1.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.2.0/24\\\"}]' TF_VAR_instances_key_name='dalmatian-ecs-instances' TF_VAR_instance_type='t2.medium' TF_VAR_min_servers='2' TF_VAR_max_servers='4' TF_VAR_max_instance_lifetime='86400' TF_VAR_associate_public_ip_address='0' TF_VAR_docker_storage_size='40' TF_VAR_dockerhub_email='' TF_VAR_dockerhub_token='' TF_VAR_enable_efs='false' TF_VAR_encrypt_efs='true' TF_VAR_efs_dirs='[]' TF_VAR_monitoring_docs_path='https://github.com/dxw/dalmatian/docs/monitoring-alarms/' TF_VAR_example_var='bar' TF_VAR_environment='production' TF_VAR_cluster_name='shared-cluster-production' TF_VAR_account_id='123456789012' TF_VAR_infrastructure_name='existing-shared-cluster-production' TF_VAR_dalmatian_role='dalmatian-read' terraform plan\")\n got: (\"TF_VAR_region='eu-west-2' TF_VAR_cidr='10.0.0.0/16' TF_VAR_root_domain_zone='dalmatian.dxw.net' TF_VAR_internal_domain_zone='dalmatian.internal' TF_VAR_ecs_private_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.128.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.129.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.130.0/24\\\"}]' TF_VAR_extra_public_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.0.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.1.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.2.0/24\\\"}]' TF_VAR_instances_key_name='dalmatian-ecs-instances' TF_VAR_instance_type='t2.medium' TF_VAR_min_servers='2' TF_VAR_max_servers='4' TF_VAR_max_instance_lifetime='86400' TF_VAR_associate_public_ip_address='0' TF_VAR_docker_storage_size='40' TF_VAR_dockerhub_email='' TF_VAR_dockerhub_token='' TF_VAR_enable_efs='false' TF_VAR_encrypt_efs='true' TF_VAR_efs_dirs='[]' TF_VAR_monitoring_docs_path='https://github.com/dxw/dalmatian/docs/monitoring-alarms/' TF_VAR_environment='production' TF_VAR_account_id='123456789012' TF_VAR_infrastructure_name='new-dedicated-cluster' TF_VAR_dalmatian_role='dalmatian-read' TF_VAR_rds='{identifier =\\\"testservice\\\",in_use_by =[\\\"test-service\\\"],clusters_in_use ={production =[\\\"test\\\"],staging =[\\\"test\\\"]},instance_class ={production =\\\"db.t2.small\\\",staging =\\\"db.t2.micro\\\"},engine =\\\"postgres\\\",engine_version =\\\"11.4\\\",allocated_storage =20,storage_encrypted =true,storage_type =\\\"gp3\\\",db_name =\\\"testapp\\\",port =5432,maintenance_window =\\\"mon:19:00-mon:19:30\\\",backup_window =\\\"09:00-10:00\\\",backup_retention_period =31,force_ssl =true,parameter_store_path_db_url_name =\\\"DATABASE_URL\\\",sql_backup_scheduled_task_environment_variables =[{name =\\\"foo\\\",value =\\\"bar\\\"}],check_sql_backup_scheduled_task_environment_variables =[{name =\\\"foo\\\",value =\\\"bar\\\"}],sync_sql_backup_to_azure =false,replication_bucket_destination_arn =\\\"\\\",replication_kms_key_id =\\\"\\\",codebuild_access =[\\\"service-name\\\"]}' terraform plan\")\n Please stub a default value first if message might be received with other args as well. \n # ./lib/dalmatian/terraform.rb:25:in `plan'\n # ./lib/dalmatian/deployable.rb:28:in `terraform_plan'\n # ./lib/dalmatian/deployable.rb:8:in `call'\n # ./lib/dalmatian/cluster.rb:269:in `deploy_rds'\n # ./lib/dalmatian/cluster.rb:70:in `block (2 levels) in deploy'\n # ./lib/dalmatian/cluster.rb:68:in `each'\n # ./lib/dalmatian/cluster.rb:68:in `block in deploy'\n # ./lib/dalmatian/cluster.rb:59:in `each'\n # ./lib/dalmatian/cluster.rb:59:in `deploy'\n # ./lib/dalmatian/infrastructure.rb:24:in `block in deploy'\n # ./lib/dalmatian/infrastructure.rb:22:in `each'\n # ./lib/dalmatian/infrastructure.rb:22:in `deploy'\n # ./lib/dalmatian/infrastructure.rb:18:in `test'\n # ./spec/integration/tests_local_configuration_spec.rb:3108:in `block (2 levels) in <module:Dalmatian>'\n # ./spec/support/spec_helper.rb:24:in `block (3 levels) in <top (required)>'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:24:in `block in modify'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:15:in `synchronize'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:15:in `modify'\n # ./spec/support/spec_helper.rb:20:in `block (2 levels) in <top (required)>'\n # /Users/bob/.bundles/ruby/2.7.0/gems/webmock-3.19.1/lib/webmock/rspec.rb:39:in `block (2 levels) in <top (required)>'\n\n 22) tests local configuration use of \"terraform plan\" passes the elasticache config to \"terraform plan\"\n Failure/Error: Helper.run!(cmd)\n \n #<Dalmatian::Helper (class)> received :run! with unexpected arguments\n expected: (\"TF_VAR_region='eu-west-2' TF_VAR_cidr='10.0.0.0/16' TF_VAR_root_domain_zone='dalmatian.dxw.net' TF_VAR_internal_domain_zone='dalmatian.internal' TF_VAR_ecs_private_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.128.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.129.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.130.0/24\\\"}]' TF_VAR_extra_public_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.0.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.1.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.2.0/24\\\"}]' TF_VAR_instances_key_name='dalmatian-ecs-instances' TF_VAR_instance_type='t2.medium' TF_VAR_min_servers='2' TF_VAR_max_servers='4' TF_VAR_max_instance_lifetime='86400' TF_VAR_associate_public_ip_address='0' TF_VAR_docker_storage_size='40' TF_VAR_dockerhub_email='' TF_VAR_dockerhub_token='' TF_VAR_enable_efs='false' TF_VAR_encrypt_efs='true' TF_VAR_efs_dirs='[]' TF_VAR_monitoring_docs_path='https://github.com/dxw/dalmatian/docs/monitoring-alarms/' TF_VAR_example_var='bar' TF_VAR_environment='production' TF_VAR_cluster_name='shared-cluster-production' TF_VAR_account_id='123456789012' TF_VAR_infrastructure_name='existing-shared-cluster-production' TF_VAR_dalmatian_role='dalmatian-read' terraform plan\")\n got: (\"TF_VAR_region='eu-west-2' TF_VAR_cidr='10.0.0.0/16' TF_VAR_root_domain_zone='dalmatian.dxw.net' TF_VAR_internal_domain_zone='dalmatian.internal' TF_VAR_ecs_private_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.128.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.129.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.130.0/24\\\"}]' TF_VAR_extra_public_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.0.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.1.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.2.0/24\\\"}]' TF_VAR_instances_key_name='dalmatian-ecs-instances' TF_VAR_instance_type='t2.medium' TF_VAR_min_servers='2' TF_VAR_max_servers='4' TF_VAR_max_instance_lifetime='86400' TF_VAR_associate_public_ip_address='0' TF_VAR_docker_storage_size='40' TF_VAR_dockerhub_email='' TF_VAR_dockerhub_token='' TF_VAR_enable_efs='false' TF_VAR_encrypt_efs='true' TF_VAR_efs_dirs='[]' TF_VAR_monitoring_docs_path='https://github.com/dxw/dalmatian/docs/monitoring-alarms/' TF_VAR_environment='production' TF_VAR_account_id='123456789012' TF_VAR_infrastructure_name='new-dedicated-cluster' TF_VAR_dalmatian_role='dalmatian-read' TF_VAR_rds='{identifier =\\\"testservice\\\",in_use_by =[\\\"test-service\\\"],clusters_in_use ={production =[\\\"test\\\"],staging =[\\\"test\\\"]},instance_class ={production =\\\"db.t2.small\\\",staging =\\\"db.t2.micro\\\"},engine =\\\"postgres\\\",engine_version =\\\"11.4\\\",allocated_storage =20,storage_encrypted =true,storage_type =\\\"gp3\\\",db_name =\\\"testapp\\\",port =5432,maintenance_window =\\\"mon:19:00-mon:19:30\\\",backup_window =\\\"09:00-10:00\\\",backup_retention_period =31,force_ssl =true,parameter_store_path_db_url_name =\\\"DATABASE_URL\\\",sql_backup_scheduled_task_environment_variables =[{name =\\\"foo\\\",value =\\\"bar\\\"}],check_sql_backup_scheduled_task_environment_variables =[{name =\\\"foo\\\",value =\\\"bar\\\"}],sync_sql_backup_to_azure =false,replication_bucket_destination_arn =\\\"\\\",replication_kms_key_id =\\\"\\\",codebuild_access =[\\\"service-name\\\"]}' terraform plan\")\n Please stub a default value first if message might be received with other args as well. \n # ./lib/dalmatian/terraform.rb:25:in `plan'\n # ./lib/dalmatian/deployable.rb:28:in `terraform_plan'\n # ./lib/dalmatian/deployable.rb:8:in `call'\n # ./lib/dalmatian/cluster.rb:269:in `deploy_rds'\n # ./lib/dalmatian/cluster.rb:70:in `block (2 levels) in deploy'\n # ./lib/dalmatian/cluster.rb:68:in `each'\n # ./lib/dalmatian/cluster.rb:68:in `block in deploy'\n # ./lib/dalmatian/cluster.rb:59:in `each'\n # ./lib/dalmatian/cluster.rb:59:in `deploy'\n # ./lib/dalmatian/infrastructure.rb:24:in `block in deploy'\n # ./lib/dalmatian/infrastructure.rb:22:in `each'\n # ./lib/dalmatian/infrastructure.rb:22:in `deploy'\n # ./lib/dalmatian/infrastructure.rb:18:in `test'\n # ./spec/integration/tests_local_configuration_spec.rb:3108:in `block (2 levels) in <module:Dalmatian>'\n # ./spec/support/spec_helper.rb:24:in `block (3 levels) in <top (required)>'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:24:in `block in modify'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:15:in `synchronize'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:15:in `modify'\n # ./spec/support/spec_helper.rb:20:in `block (2 levels) in <top (required)>'\n # /Users/bob/.bundles/ruby/2.7.0/gems/webmock-3.19.1/lib/webmock/rspec.rb:39:in `block (2 levels) in <top (required)>'\n\n 23) tests local configuration use of \"terraform plan\" passes the opensearch config to \"terraform plan\"\n Failure/Error: Helper.run!(cmd)\n \n #<Dalmatian::Helper (class)> received :run! with unexpected arguments\n expected: (\"TF_VAR_region='eu-west-2' TF_VAR_cidr='10.0.0.0/16' TF_VAR_root_domain_zone='dalmatian.dxw.net' TF_VAR_internal_domain_zone='dalmatian.internal' TF_VAR_ecs_private_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.128.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.129.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.130.0/24\\\"}]' TF_VAR_extra_public_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.0.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.1.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.2.0/24\\\"}]' TF_VAR_instances_key_name='dalmatian-ecs-instances' TF_VAR_instance_type='t2.medium' TF_VAR_min_servers='2' TF_VAR_max_servers='4' TF_VAR_max_instance_lifetime='86400' TF_VAR_associate_public_ip_address='0' TF_VAR_docker_storage_size='40' TF_VAR_dockerhub_email='' TF_VAR_dockerhub_token='' TF_VAR_enable_efs='false' TF_VAR_encrypt_efs='true' TF_VAR_efs_dirs='[]' TF_VAR_monitoring_docs_path='https://github.com/dxw/dalmatian/docs/monitoring-alarms/' TF_VAR_example_var='bar' TF_VAR_environment='production' TF_VAR_cluster_name='shared-cluster-production' TF_VAR_account_id='123456789012' TF_VAR_infrastructure_name='existing-shared-cluster-production' TF_VAR_dalmatian_role='dalmatian-read' terraform plan\")\n got: (\"TF_VAR_region='eu-west-2' TF_VAR_cidr='10.0.0.0/16' TF_VAR_root_domain_zone='dalmatian.dxw.net' TF_VAR_internal_domain_zone='dalmatian.internal' TF_VAR_ecs_private_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.128.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.129.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.130.0/24\\\"}]' TF_VAR_extra_public_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.0.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.1.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.2.0/24\\\"}]' TF_VAR_instances_key_name='dalmatian-ecs-instances' TF_VAR_instance_type='t2.medium' TF_VAR_min_servers='2' TF_VAR_max_servers='4' TF_VAR_max_instance_lifetime='86400' TF_VAR_associate_public_ip_address='0' TF_VAR_docker_storage_size='40' TF_VAR_dockerhub_email='' TF_VAR_dockerhub_token='' TF_VAR_enable_efs='false' TF_VAR_encrypt_efs='true' TF_VAR_efs_dirs='[]' TF_VAR_monitoring_docs_path='https://github.com/dxw/dalmatian/docs/monitoring-alarms/' TF_VAR_environment='production' TF_VAR_account_id='123456789012' TF_VAR_infrastructure_name='new-dedicated-cluster' TF_VAR_dalmatian_role='dalmatian-read' TF_VAR_rds='{identifier =\\\"testservice\\\",in_use_by =[\\\"test-service\\\"],clusters_in_use ={production =[\\\"test\\\"],staging =[\\\"test\\\"]},instance_class ={production =\\\"db.t2.small\\\",staging =\\\"db.t2.micro\\\"},engine =\\\"postgres\\\",engine_version =\\\"11.4\\\",allocated_storage =20,storage_encrypted =true,storage_type =\\\"gp3\\\",db_name =\\\"testapp\\\",port =5432,maintenance_window =\\\"mon:19:00-mon:19:30\\\",backup_window =\\\"09:00-10:00\\\",backup_retention_period =31,force_ssl =true,parameter_store_path_db_url_name =\\\"DATABASE_URL\\\",sql_backup_scheduled_task_environment_variables =[{name =\\\"foo\\\",value =\\\"bar\\\"}],check_sql_backup_scheduled_task_environment_variables =[{name =\\\"foo\\\",value =\\\"bar\\\"}],sync_sql_backup_to_azure =false,replication_bucket_destination_arn =\\\"\\\",replication_kms_key_id =\\\"\\\",codebuild_access =[\\\"service-name\\\"]}' terraform plan\")\n Please stub a default value first if message might be received with other args as well. \n # ./lib/dalmatian/terraform.rb:25:in `plan'\n # ./lib/dalmatian/deployable.rb:28:in `terraform_plan'\n # ./lib/dalmatian/deployable.rb:8:in `call'\n # ./lib/dalmatian/cluster.rb:269:in `deploy_rds'\n # ./lib/dalmatian/cluster.rb:70:in `block (2 levels) in deploy'\n # ./lib/dalmatian/cluster.rb:68:in `each'\n # ./lib/dalmatian/cluster.rb:68:in `block in deploy'\n # ./lib/dalmatian/cluster.rb:59:in `each'\n # ./lib/dalmatian/cluster.rb:59:in `deploy'\n # ./lib/dalmatian/infrastructure.rb:24:in `block in deploy'\n # ./lib/dalmatian/infrastructure.rb:22:in `each'\n # ./lib/dalmatian/infrastructure.rb:22:in `deploy'\n # ./lib/dalmatian/infrastructure.rb:18:in `test'\n # ./spec/integration/tests_local_configuration_spec.rb:3108:in `block (2 levels) in <module:Dalmatian>'\n # ./spec/support/spec_helper.rb:24:in `block (3 levels) in <top (required)>'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:24:in `block in modify'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:15:in `synchronize'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:15:in `modify'\n # ./spec/support/spec_helper.rb:20:in `block (2 levels) in <top (required)>'\n # /Users/bob/.bundles/ruby/2.7.0/gems/webmock-3.19.1/lib/webmock/rspec.rb:39:in `block (2 levels) in <top (required)>'\n\n 24) tests local configuration use of \"terraform plan\" passes the services config to \"terraform plan\"\n Failure/Error: Helper.run!(cmd)\n \n #<Dalmatian::Helper (class)> received :run! with unexpected arguments\n expected: (\"TF_VAR_region='eu-west-2' TF_VAR_cidr='10.0.0.0/16' TF_VAR_root_domain_zone='dalmatian.dxw.net' TF_VAR_internal_domain_zone='dalmatian.internal' TF_VAR_ecs_private_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.128.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.129.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.130.0/24\\\"}]' TF_VAR_extra_public_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.0.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.1.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.2.0/24\\\"}]' TF_VAR_instances_key_name='dalmatian-ecs-instances' TF_VAR_instance_type='t2.medium' TF_VAR_min_servers='2' TF_VAR_max_servers='4' TF_VAR_max_instance_lifetime='86400' TF_VAR_associate_public_ip_address='0' TF_VAR_docker_storage_size='40' TF_VAR_dockerhub_email='' TF_VAR_dockerhub_token='' TF_VAR_enable_efs='false' TF_VAR_encrypt_efs='true' TF_VAR_efs_dirs='[]' TF_VAR_monitoring_docs_path='https://github.com/dxw/dalmatian/docs/monitoring-alarms/' TF_VAR_example_var='bar' TF_VAR_environment='production' TF_VAR_cluster_name='shared-cluster-production' TF_VAR_account_id='123456789012' TF_VAR_infrastructure_name='existing-shared-cluster-production' TF_VAR_dalmatian_role='dalmatian-read' terraform plan\")\n got: (\"TF_VAR_region='eu-west-2' TF_VAR_cidr='10.0.0.0/16' TF_VAR_root_domain_zone='dalmatian.dxw.net' TF_VAR_internal_domain_zone='dalmatian.internal' TF_VAR_ecs_private_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.128.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.129.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.130.0/24\\\"}]' TF_VAR_extra_public_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.0.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.1.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.2.0/24\\\"}]' TF_VAR_instances_key_name='dalmatian-ecs-instances' TF_VAR_instance_type='t2.medium' TF_VAR_min_servers='2' TF_VAR_max_servers='4' TF_VAR_max_instance_lifetime='86400' TF_VAR_associate_public_ip_address='0' TF_VAR_docker_storage_size='40' TF_VAR_dockerhub_email='' TF_VAR_dockerhub_token='' TF_VAR_enable_efs='false' TF_VAR_encrypt_efs='true' TF_VAR_efs_dirs='[]' TF_VAR_monitoring_docs_path='https://github.com/dxw/dalmatian/docs/monitoring-alarms/' TF_VAR_environment='production' TF_VAR_account_id='123456789012' TF_VAR_infrastructure_name='new-dedicated-cluster' TF_VAR_dalmatian_role='dalmatian-read' TF_VAR_rds='{identifier =\\\"testservice\\\",in_use_by =[\\\"test-service\\\"],clusters_in_use ={production =[\\\"test\\\"],staging =[\\\"test\\\"]},instance_class ={production =\\\"db.t2.small\\\",staging =\\\"db.t2.micro\\\"},engine =\\\"postgres\\\",engine_version =\\\"11.4\\\",allocated_storage =20,storage_encrypted =true,storage_type =\\\"gp3\\\",db_name =\\\"testapp\\\",port =5432,maintenance_window =\\\"mon:19:00-mon:19:30\\\",backup_window =\\\"09:00-10:00\\\",backup_retention_period =31,force_ssl =true,parameter_store_path_db_url_name =\\\"DATABASE_URL\\\",sql_backup_scheduled_task_environment_variables =[{name =\\\"foo\\\",value =\\\"bar\\\"}],check_sql_backup_scheduled_task_environment_variables =[{name =\\\"foo\\\",value =\\\"bar\\\"}],sync_sql_backup_to_azure =false,replication_bucket_destination_arn =\\\"\\\",replication_kms_key_id =\\\"\\\",codebuild_access =[\\\"service-name\\\"]}' terraform plan\")\n Please stub a default value first if message might be received with other args as well. \n # ./lib/dalmatian/terraform.rb:25:in `plan'\n # ./lib/dalmatian/deployable.rb:28:in `terraform_plan'\n # ./lib/dalmatian/deployable.rb:8:in `call'\n # ./lib/dalmatian/cluster.rb:269:in `deploy_rds'\n # ./lib/dalmatian/cluster.rb:70:in `block (2 levels) in deploy'\n # ./lib/dalmatian/cluster.rb:68:in `each'\n # ./lib/dalmatian/cluster.rb:68:in `block in deploy'\n # ./lib/dalmatian/cluster.rb:59:in `each'\n # ./lib/dalmatian/cluster.rb:59:in `deploy'\n # ./lib/dalmatian/infrastructure.rb:24:in `block in deploy'\n # ./lib/dalmatian/infrastructure.rb:22:in `each'\n # ./lib/dalmatian/infrastructure.rb:22:in `deploy'\n # ./lib/dalmatian/infrastructure.rb:18:in `test'\n # ./spec/integration/tests_local_configuration_spec.rb:3108:in `block (2 levels) in <module:Dalmatian>'\n # ./spec/support/spec_helper.rb:24:in `block (3 levels) in <top (required)>'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:24:in `block in modify'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:15:in `synchronize'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:15:in `modify'\n # ./spec/support/spec_helper.rb:20:in `block (2 levels) in <top (required)>'\n # /Users/bob/.bundles/ruby/2.7.0/gems/webmock-3.19.1/lib/webmock/rspec.rb:39:in `block (2 levels) in <top (required)>'\n\n 25) tests local configuration use of \"terraform plan\" passes the loadbalancer config to \"terraform plan\"\n Failure/Error: Helper.run!(cmd)\n \n #<Dalmatian::Helper (class)> received :run! with unexpected arguments\n expected: (\"TF_VAR_region='eu-west-2' TF_VAR_cidr='10.0.0.0/16' TF_VAR_root_domain_zone='dalmatian.dxw.net' TF_VAR_internal_domain_zone='dalmatian.internal' TF_VAR_ecs_private_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.128.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.129.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.130.0/24\\\"}]' TF_VAR_extra_public_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.0.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.1.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.2.0/24\\\"}]' TF_VAR_instances_key_name='dalmatian-ecs-instances' TF_VAR_instance_type='t2.medium' TF_VAR_min_servers='2' TF_VAR_max_servers='4' TF_VAR_max_instance_lifetime='86400' TF_VAR_associate_public_ip_address='0' TF_VAR_docker_storage_size='40' TF_VAR_dockerhub_email='' TF_VAR_dockerhub_token='' TF_VAR_enable_efs='false' TF_VAR_encrypt_efs='true' TF_VAR_efs_dirs='[]' TF_VAR_monitoring_docs_path='https://github.com/dxw/dalmatian/docs/monitoring-alarms/' TF_VAR_example_var='bar' TF_VAR_environment='production' TF_VAR_cluster_name='shared-cluster-production' TF_VAR_account_id='123456789012' TF_VAR_infrastructure_name='existing-shared-cluster-production' TF_VAR_dalmatian_role='dalmatian-read' terraform plan\")\n got: (\"TF_VAR_region='eu-west-2' TF_VAR_cidr='10.0.0.0/16' TF_VAR_root_domain_zone='dalmatian.dxw.net' TF_VAR_internal_domain_zone='dalmatian.internal' TF_VAR_ecs_private_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.128.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.129.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.130.0/24\\\"}]' TF_VAR_extra_public_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.0.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.1.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.2.0/24\\\"}]' TF_VAR_instances_key_name='dalmatian-ecs-instances' TF_VAR_instance_type='t2.medium' TF_VAR_min_servers='2' TF_VAR_max_servers='4' TF_VAR_max_instance_lifetime='86400' TF_VAR_associate_public_ip_address='0' TF_VAR_docker_storage_size='40' TF_VAR_dockerhub_email='' TF_VAR_dockerhub_token='' TF_VAR_enable_efs='false' TF_VAR_encrypt_efs='true' TF_VAR_efs_dirs='[]' TF_VAR_monitoring_docs_path='https://github.com/dxw/dalmatian/docs/monitoring-alarms/' TF_VAR_environment='production' TF_VAR_account_id='123456789012' TF_VAR_infrastructure_name='new-dedicated-cluster' TF_VAR_dalmatian_role='dalmatian-read' TF_VAR_rds='{identifier =\\\"testservice\\\",in_use_by =[\\\"test-service\\\"],clusters_in_use ={production =[\\\"test\\\"],staging =[\\\"test\\\"]},instance_class ={production =\\\"db.t2.small\\\",staging =\\\"db.t2.micro\\\"},engine =\\\"postgres\\\",engine_version =\\\"11.4\\\",allocated_storage =20,storage_encrypted =true,storage_type =\\\"gp3\\\",db_name =\\\"testapp\\\",port =5432,maintenance_window =\\\"mon:19:00-mon:19:30\\\",backup_window =\\\"09:00-10:00\\\",backup_retention_period =31,force_ssl =true,parameter_store_path_db_url_name =\\\"DATABASE_URL\\\",sql_backup_scheduled_task_environment_variables =[{name =\\\"foo\\\",value =\\\"bar\\\"}],check_sql_backup_scheduled_task_environment_variables =[{name =\\\"foo\\\",value =\\\"bar\\\"}],sync_sql_backup_to_azure =false,replication_bucket_destination_arn =\\\"\\\",replication_kms_key_id =\\\"\\\",codebuild_access =[\\\"service-name\\\"]}' terraform plan\")\n Please stub a default value first if message might be received with other args as well. \n # ./lib/dalmatian/terraform.rb:25:in `plan'\n # ./lib/dalmatian/deployable.rb:28:in `terraform_plan'\n # ./lib/dalmatian/deployable.rb:8:in `call'\n # ./lib/dalmatian/cluster.rb:269:in `deploy_rds'\n # ./lib/dalmatian/cluster.rb:70:in `block (2 levels) in deploy'\n # ./lib/dalmatian/cluster.rb:68:in `each'\n # ./lib/dalmatian/cluster.rb:68:in `block in deploy'\n # ./lib/dalmatian/cluster.rb:59:in `each'\n # ./lib/dalmatian/cluster.rb:59:in `deploy'\n # ./lib/dalmatian/infrastructure.rb:24:in `block in deploy'\n # ./lib/dalmatian/infrastructure.rb:22:in `each'\n # ./lib/dalmatian/infrastructure.rb:22:in `deploy'\n # ./lib/dalmatian/infrastructure.rb:18:in `test'\n # ./spec/integration/tests_local_configuration_spec.rb:3108:in `block (2 levels) in <module:Dalmatian>'\n # ./spec/support/spec_helper.rb:24:in `block (3 levels) in <top (required)>'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:24:in `block in modify'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:15:in `synchronize'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:15:in `modify'\n # ./spec/support/spec_helper.rb:20:in `block (2 levels) in <top (required)>'\n # /Users/bob/.bundles/ruby/2.7.0/gems/webmock-3.19.1/lib/webmock/rspec.rb:39:in `block (2 levels) in <top (required)>'\n\n 26) tests local configuration use of \"terraform plan\" passes the cluster 2 config to \"terraform plan\"\n Failure/Error: Helper.run!(cmd)\n \n #<Dalmatian::Helper (class)> received :run! with unexpected arguments\n expected: (\"TF_VAR_region='eu-west-2' TF_VAR_cidr='10.0.0.0/16' TF_VAR_root_domain_zone='dalmatian.dxw.net' TF_VAR_internal_domain_zone='dalmatian.internal' TF_VAR_ecs_private_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.128.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.129.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.130.0/24\\\"}]' TF_VAR_extra_public_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.0.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.1.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.2.0/24\\\"}]' TF_VAR_instances_key_name='dalmatian-ecs-instances' TF_VAR_instance_type='t2.medium' TF_VAR_min_servers='2' TF_VAR_max_servers='4' TF_VAR_max_instance_lifetime='86400' TF_VAR_associate_public_ip_address='0' TF_VAR_docker_storage_size='40' TF_VAR_dockerhub_email='' TF_VAR_dockerhub_token='' TF_VAR_enable_efs='false' TF_VAR_encrypt_efs='true' TF_VAR_efs_dirs='[]' TF_VAR_monitoring_docs_path='https://github.com/dxw/dalmatian/docs/monitoring-alarms/' TF_VAR_example_var='bar' TF_VAR_environment='production' TF_VAR_cluster_name='shared-cluster-production' TF_VAR_account_id='123456789012' TF_VAR_infrastructure_name='existing-shared-cluster-production' TF_VAR_dalmatian_role='dalmatian-read' terraform plan\")\n got: (\"TF_VAR_region='eu-west-2' TF_VAR_cidr='10.0.0.0/16' TF_VAR_root_domain_zone='dalmatian.dxw.net' TF_VAR_internal_domain_zone='dalmatian.internal' TF_VAR_ecs_private_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.128.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.129.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.130.0/24\\\"}]' TF_VAR_extra_public_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.0.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.1.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.2.0/24\\\"}]' TF_VAR_instances_key_name='dalmatian-ecs-instances' TF_VAR_instance_type='t2.medium' TF_VAR_min_servers='2' TF_VAR_max_servers='4' TF_VAR_max_instance_lifetime='86400' TF_VAR_associate_public_ip_address='0' TF_VAR_docker_storage_size='40' TF_VAR_dockerhub_email='' TF_VAR_dockerhub_token='' TF_VAR_enable_efs='false' TF_VAR_encrypt_efs='true' TF_VAR_efs_dirs='[]' TF_VAR_monitoring_docs_path='https://github.com/dxw/dalmatian/docs/monitoring-alarms/' TF_VAR_environment='production' TF_VAR_account_id='123456789012' TF_VAR_infrastructure_name='new-dedicated-cluster' TF_VAR_dalmatian_role='dalmatian-read' TF_VAR_rds='{identifier =\\\"testservice\\\",in_use_by =[\\\"test-service\\\"],clusters_in_use ={production =[\\\"test\\\"],staging =[\\\"test\\\"]},instance_class ={production =\\\"db.t2.small\\\",staging =\\\"db.t2.micro\\\"},engine =\\\"postgres\\\",engine_version =\\\"11.4\\\",allocated_storage =20,storage_encrypted =true,storage_type =\\\"gp3\\\",db_name =\\\"testapp\\\",port =5432,maintenance_window =\\\"mon:19:00-mon:19:30\\\",backup_window =\\\"09:00-10:00\\\",backup_retention_period =31,force_ssl =true,parameter_store_path_db_url_name =\\\"DATABASE_URL\\\",sql_backup_scheduled_task_environment_variables =[{name =\\\"foo\\\",value =\\\"bar\\\"}],check_sql_backup_scheduled_task_environment_variables =[{name =\\\"foo\\\",value =\\\"bar\\\"}],sync_sql_backup_to_azure =false,replication_bucket_destination_arn =\\\"\\\",replication_kms_key_id =\\\"\\\",codebuild_access =[\\\"service-name\\\"]}' terraform plan\")\n Please stub a default value first if message might be received with other args as well. \n # ./lib/dalmatian/terraform.rb:25:in `plan'\n # ./lib/dalmatian/deployable.rb:28:in `terraform_plan'\n # ./lib/dalmatian/deployable.rb:8:in `call'\n # ./lib/dalmatian/cluster.rb:269:in `deploy_rds'\n # ./lib/dalmatian/cluster.rb:70:in `block (2 levels) in deploy'\n # ./lib/dalmatian/cluster.rb:68:in `each'\n # ./lib/dalmatian/cluster.rb:68:in `block in deploy'\n # ./lib/dalmatian/cluster.rb:59:in `each'\n # ./lib/dalmatian/cluster.rb:59:in `deploy'\n # ./lib/dalmatian/infrastructure.rb:24:in `block in deploy'\n # ./lib/dalmatian/infrastructure.rb:22:in `each'\n # ./lib/dalmatian/infrastructure.rb:22:in `deploy'\n # ./lib/dalmatian/infrastructure.rb:18:in `test'\n # ./spec/integration/tests_local_configuration_spec.rb:3108:in `block (2 levels) in <module:Dalmatian>'\n # ./spec/support/spec_helper.rb:24:in `block (3 levels) in <top (required)>'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:24:in `block in modify'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:15:in `synchronize'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:15:in `modify'\n # ./spec/support/spec_helper.rb:20:in `block (2 levels) in <top (required)>'\n # /Users/bob/.bundles/ruby/2.7.0/gems/webmock-3.19.1/lib/webmock/rspec.rb:39:in `block (2 levels) in <top (required)>'\n\n 27) tests local configuration use of \"terraform plan\" passes the cluster 3 config to \"terraform plan\"\n Failure/Error: Helper.run!(cmd)\n \n #<Dalmatian::Helper (class)> received :run! with unexpected arguments\n expected: (\"TF_VAR_region='eu-west-2' TF_VAR_cidr='10.0.0.0/16' TF_VAR_root_domain_zone='dalmatian.dxw.net' TF_VAR_internal_domain_zone='dalmatian.internal' TF_VAR_ecs_private_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.128.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.129.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.130.0/24\\\"}]' TF_VAR_extra_public_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.0.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.1.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.2.0/24\\\"}]' TF_VAR_instances_key_name='dalmatian-ecs-instances' TF_VAR_instance_type='t2.medium' TF_VAR_min_servers='2' TF_VAR_max_servers='4' TF_VAR_max_instance_lifetime='86400' TF_VAR_associate_public_ip_address='0' TF_VAR_docker_storage_size='40' TF_VAR_dockerhub_email='' TF_VAR_dockerhub_token='' TF_VAR_enable_efs='false' TF_VAR_encrypt_efs='true' TF_VAR_efs_dirs='[]' TF_VAR_monitoring_docs_path='https://github.com/dxw/dalmatian/docs/monitoring-alarms/' TF_VAR_example_var='bar' TF_VAR_environment='production' TF_VAR_cluster_name='shared-cluster-production' TF_VAR_account_id='123456789012' TF_VAR_infrastructure_name='existing-shared-cluster-production' TF_VAR_dalmatian_role='dalmatian-read' terraform plan\")\n got: (\"TF_VAR_region='eu-west-2' TF_VAR_cidr='10.0.0.0/16' TF_VAR_root_domain_zone='dalmatian.dxw.net' TF_VAR_internal_domain_zone='dalmatian.internal' TF_VAR_ecs_private_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.128.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.129.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.130.0/24\\\"}]' TF_VAR_extra_public_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.0.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.1.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.2.0/24\\\"}]' TF_VAR_instances_key_name='dalmatian-ecs-instances' TF_VAR_instance_type='t2.medium' TF_VAR_min_servers='2' TF_VAR_max_servers='4' TF_VAR_max_instance_lifetime='86400' TF_VAR_associate_public_ip_address='0' TF_VAR_docker_storage_size='40' TF_VAR_dockerhub_email='' TF_VAR_dockerhub_token='' TF_VAR_enable_efs='false' TF_VAR_encrypt_efs='true' TF_VAR_efs_dirs='[]' TF_VAR_monitoring_docs_path='https://github.com/dxw/dalmatian/docs/monitoring-alarms/' TF_VAR_environment='production' TF_VAR_account_id='123456789012' TF_VAR_infrastructure_name='new-dedicated-cluster' TF_VAR_dalmatian_role='dalmatian-read' TF_VAR_rds='{identifier =\\\"testservice\\\",in_use_by =[\\\"test-service\\\"],clusters_in_use ={production =[\\\"test\\\"],staging =[\\\"test\\\"]},instance_class ={production =\\\"db.t2.small\\\",staging =\\\"db.t2.micro\\\"},engine =\\\"postgres\\\",engine_version =\\\"11.4\\\",allocated_storage =20,storage_encrypted =true,storage_type =\\\"gp3\\\",db_name =\\\"testapp\\\",port =5432,maintenance_window =\\\"mon:19:00-mon:19:30\\\",backup_window =\\\"09:00-10:00\\\",backup_retention_period =31,force_ssl =true,parameter_store_path_db_url_name =\\\"DATABASE_URL\\\",sql_backup_scheduled_task_environment_variables =[{name =\\\"foo\\\",value =\\\"bar\\\"}],check_sql_backup_scheduled_task_environment_variables =[{name =\\\"foo\\\",value =\\\"bar\\\"}],sync_sql_backup_to_azure =false,replication_bucket_destination_arn =\\\"\\\",replication_kms_key_id =\\\"\\\",codebuild_access =[\\\"service-name\\\"]}' terraform plan\")\n Please stub a default value first if message might be received with other args as well. \n # ./lib/dalmatian/terraform.rb:25:in `plan'\n # ./lib/dalmatian/deployable.rb:28:in `terraform_plan'\n # ./lib/dalmatian/deployable.rb:8:in `call'\n # ./lib/dalmatian/cluster.rb:269:in `deploy_rds'\n # ./lib/dalmatian/cluster.rb:70:in `block (2 levels) in deploy'\n # ./lib/dalmatian/cluster.rb:68:in `each'\n # ./lib/dalmatian/cluster.rb:68:in `block in deploy'\n # ./lib/dalmatian/cluster.rb:59:in `each'\n # ./lib/dalmatian/cluster.rb:59:in `deploy'\n # ./lib/dalmatian/infrastructure.rb:24:in `block in deploy'\n # ./lib/dalmatian/infrastructure.rb:22:in `each'\n # ./lib/dalmatian/infrastructure.rb:22:in `deploy'\n # ./lib/dalmatian/infrastructure.rb:18:in `test'\n # ./spec/integration/tests_local_configuration_spec.rb:3108:in `block (2 levels) in <module:Dalmatian>'\n # ./spec/support/spec_helper.rb:24:in `block (3 levels) in <top (required)>'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:24:in `block in modify'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:15:in `synchronize'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:15:in `modify'\n # ./spec/support/spec_helper.rb:20:in `block (2 levels) in <top (required)>'\n # /Users/bob/.bundles/ruby/2.7.0/gems/webmock-3.19.1/lib/webmock/rspec.rb:39:in `block (2 levels) in <top (required)>'\n\n 28) tests local configuration use of \"terraform plan\" passes the cluster 4 config to \"terraform plan\"\n Failure/Error: Helper.run!(cmd)\n \n #<Dalmatian::Helper (class)> received :run! with unexpected arguments\n expected: (\"TF_VAR_region='eu-west-2' TF_VAR_cidr='10.0.0.0/16' TF_VAR_root_domain_zone='dalmatian.dxw.net' TF_VAR_internal_domain_zone='dalmatian.internal' TF_VAR_ecs_private_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.128.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.129.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.130.0/24\\\"}]' TF_VAR_extra_public_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.0.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.1.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.2.0/24\\\"}]' TF_VAR_instances_key_name='dalmatian-ecs-instances' TF_VAR_instance_type='t2.medium' TF_VAR_min_servers='2' TF_VAR_max_servers='4' TF_VAR_max_instance_lifetime='86400' TF_VAR_associate_public_ip_address='0' TF_VAR_docker_storage_size='40' TF_VAR_dockerhub_email='' TF_VAR_dockerhub_token='' TF_VAR_enable_efs='false' TF_VAR_encrypt_efs='true' TF_VAR_efs_dirs='[]' TF_VAR_monitoring_docs_path='https://github.com/dxw/dalmatian/docs/monitoring-alarms/' TF_VAR_example_var='bar' TF_VAR_environment='production' TF_VAR_cluster_name='shared-cluster-production' TF_VAR_account_id='123456789012' TF_VAR_infrastructure_name='existing-shared-cluster-production' TF_VAR_dalmatian_role='dalmatian-read' terraform plan\")\n got: (\"TF_VAR_region='eu-west-2' TF_VAR_cidr='10.0.0.0/16' TF_VAR_root_domain_zone='dalmatian.dxw.net' TF_VAR_internal_domain_zone='dalmatian.internal' TF_VAR_ecs_private_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.128.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.129.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.130.0/24\\\"}]' TF_VAR_extra_public_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.0.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.1.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.2.0/24\\\"}]' TF_VAR_instances_key_name='dalmatian-ecs-instances' TF_VAR_instance_type='t2.medium' TF_VAR_min_servers='2' TF_VAR_max_servers='4' TF_VAR_max_instance_lifetime='86400' TF_VAR_associate_public_ip_address='0' TF_VAR_docker_storage_size='40' TF_VAR_dockerhub_email='' TF_VAR_dockerhub_token='' TF_VAR_enable_efs='false' TF_VAR_encrypt_efs='true' TF_VAR_efs_dirs='[]' TF_VAR_monitoring_docs_path='https://github.com/dxw/dalmatian/docs/monitoring-alarms/' TF_VAR_environment='production' TF_VAR_account_id='123456789012' TF_VAR_infrastructure_name='new-dedicated-cluster' TF_VAR_dalmatian_role='dalmatian-read' TF_VAR_rds='{identifier =\\\"testservice\\\",in_use_by =[\\\"test-service\\\"],clusters_in_use ={production =[\\\"test\\\"],staging =[\\\"test\\\"]},instance_class ={production =\\\"db.t2.small\\\",staging =\\\"db.t2.micro\\\"},engine =\\\"postgres\\\",engine_version =\\\"11.4\\\",allocated_storage =20,storage_encrypted =true,storage_type =\\\"gp3\\\",db_name =\\\"testapp\\\",port =5432,maintenance_window =\\\"mon:19:00-mon:19:30\\\",backup_window =\\\"09:00-10:00\\\",backup_retention_period =31,force_ssl =true,parameter_store_path_db_url_name =\\\"DATABASE_URL\\\",sql_backup_scheduled_task_environment_variables =[{name =\\\"foo\\\",value =\\\"bar\\\"}],check_sql_backup_scheduled_task_environment_variables =[{name =\\\"foo\\\",value =\\\"bar\\\"}],sync_sql_backup_to_azure =false,replication_bucket_destination_arn =\\\"\\\",replication_kms_key_id =\\\"\\\",codebuild_access =[\\\"service-name\\\"]}' terraform plan\")\n Please stub a default value first if message might be received with other args as well. \n # ./lib/dalmatian/terraform.rb:25:in `plan'\n # ./lib/dalmatian/deployable.rb:28:in `terraform_plan'\n # ./lib/dalmatian/deployable.rb:8:in `call'\n # ./lib/dalmatian/cluster.rb:269:in `deploy_rds'\n # ./lib/dalmatian/cluster.rb:70:in `block (2 levels) in deploy'\n # ./lib/dalmatian/cluster.rb:68:in `each'\n # ./lib/dalmatian/cluster.rb:68:in `block in deploy'\n # ./lib/dalmatian/cluster.rb:59:in `each'\n # ./lib/dalmatian/cluster.rb:59:in `deploy'\n # ./lib/dalmatian/infrastructure.rb:24:in `block in deploy'\n # ./lib/dalmatian/infrastructure.rb:22:in `each'\n # ./lib/dalmatian/infrastructure.rb:22:in `deploy'\n # ./lib/dalmatian/infrastructure.rb:18:in `test'\n # ./spec/integration/tests_local_configuration_spec.rb:3108:in `block (2 levels) in <module:Dalmatian>'\n # ./spec/support/spec_helper.rb:24:in `block (3 levels) in <top (required)>'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:24:in `block in modify'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:15:in `synchronize'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:15:in `modify'\n # ./spec/support/spec_helper.rb:20:in `block (2 levels) in <top (required)>'\n # /Users/bob/.bundles/ruby/2.7.0/gems/webmock-3.19.1/lib/webmock/rspec.rb:39:in `block (2 levels) in <top (required)>'\n\nFinished in 2.42 seconds (files took 0.74146 seconds to load)\n478 examples, 28 failures\n\nFailed examples:\n\nrspec ./spec/integration/deploys_local_configuration_spec.rb:1581 # tests local configuration use of \"terraform apply\" passes the hosted zone config to \"terraform apply\"\nrspec ./spec/integration/deploys_local_configuration_spec.rb:1585 # tests local configuration use of \"terraform apply\" passes the s3 config to \"terraform apply\"\nrspec ./spec/integration/deploys_local_configuration_spec.rb:1589 # tests local configuration use of \"terraform apply\" passes the vpn customer gateway config to \"terraform apply\"\nrspec ./spec/integration/deploys_local_configuration_spec.rb:1593 # tests local configuration use of \"terraform apply\" passes the base config to \"terraform apply\"\nrspec ./spec/integration/deploys_local_configuration_spec.rb:1598 # tests local configuration use of \"terraform apply\" passes the waf config to \"terraform apply\"\nrspec ./spec/integration/deploys_local_configuration_spec.rb:1605 # tests local configuration use of \"terraform apply\" passes the rds config to \"terraform apply\"\nrspec ./spec/integration/deploys_local_configuration_spec.rb:1612 # tests local configuration use of \"terraform apply\" passes the elasticache config to \"terraform apply\"\nrspec ./spec/integration/deploys_local_configuration_spec.rb:1621 # tests local configuration use of \"terraform apply\" passes the opensearch config to \"terraform apply\"\nrspec ./spec/integration/deploys_local_configuration_spec.rb:1630 # tests local configuration use of \"terraform apply\" passes the service config to \"terraform apply\"\nrspec ./spec/integration/deploys_local_configuration_spec.rb:1637 # tests local configuration use of \"terraform apply\" passes the loadbalancer config to \"terraform apply\"\nrspec ./spec/integration/deploys_local_configuration_spec.rb:1646 # tests local configuration use of \"terraform apply\" passes the cluster 2 config to \"terraform apply\"\nrspec ./spec/integration/deploys_local_configuration_spec.rb:1653 # tests local configuration use of \"terraform apply\" passes the cluster 3 config to \"terraform apply\"\nrspec ./spec/integration/deploys_local_configuration_spec.rb:1657 # tests local configuration use of \"terraform apply\" passes the cluster 4 config to \"terraform apply\"\nrspec ./spec/integration/tests_local_configuration_spec.rb:3111 # tests local configuration invokes \"terraform validate\" with the expected cluster options\nrspec ./spec/integration/tests_local_configuration_spec.rb:3147 # tests local configuration invokes \"terraform validate\" with the expected source options\nrspec ./spec/integration/tests_local_configuration_spec.rb:3153 # tests local configuration use of \"terraform plan\" passes the hosted zone config to \"terraform plan\"\nrspec ./spec/integration/tests_local_configuration_spec.rb:3159 # tests local configuration use of \"terraform plan\" passes the s3 config to \"terraform plan\"\nrspec ./spec/integration/tests_local_configuration_spec.rb:3165 # tests local configuration use of \"terraform plan\" passes the vpn customer gateway config to \"terraform plan\"\nrspec ./spec/integration/tests_local_configuration_spec.rb:3171 # tests local configuration use of \"terraform plan\" passes the base config to \"terraform plan\"\nrspec ./spec/integration/tests_local_configuration_spec.rb:3178 # tests local configuration use of \"terraform plan\" passes the waf config to \"terraform plan\"\nrspec ./spec/integration/tests_local_configuration_spec.rb:3185 # tests local configuration use of \"terraform plan\" passes the rds config to \"terraform plan\"\nrspec ./spec/integration/tests_local_configuration_spec.rb:3192 # tests local configuration use of \"terraform plan\" passes the elasticache config to \"terraform plan\"\nrspec ./spec/integration/tests_local_configuration_spec.rb:3201 # tests local configuration use of \"terraform plan\" passes the opensearch config to \"terraform plan\"\nrspec ./spec/integration/tests_local_configuration_spec.rb:3210 # tests local configuration use of \"terraform plan\" passes the services config to \"terraform plan\"\nrspec ./spec/integration/tests_local_configuration_spec.rb:3217 # tests local configuration use of \"terraform plan\" passes the loadbalancer config to \"terraform plan\"\nrspec ./spec/integration/tests_local_configuration_spec.rb:3226 # tests local configuration use of \"terraform plan\" passes the cluster 2 config to \"terraform plan\"\nrspec ./spec/integration/tests_local_configuration_spec.rb:3233 # tests local configuration use of \"terraform plan\" passes the cluster 3 config to \"terraform plan\"\nrspec ./spec/integration/tests_local_configuration_spec.rb:3237 # tests local configuration use of \"terraform plan\" passes the cluster 4 config to \"terraform plan\"\n\nCoverage report generated for RSpec to /Users/bob/git/dxw/dalmatian/coverage. 4253 / 4389 LOC (96.9%) covered.\nStopped processing SimpleCov as a previous error not related to SimpleCov has been detected\n/Users/bob/.rbenv/versions/2.7.1/bin/ruby -I/Users/bob/.bundles/ruby/2.7.0/gems/rspec-core-3.12.2/lib:/Users/bob/.bundles/ruby/2.7.0/gems/rspec-support-3.12.1/lib /Users/bob/.bundles/ruby/2.7.0/gems/rspec-core-3.12.2/exe/rspec --pattern spec/\\*\\*\\{,/\\*/\\*\\*\\}/\\*_spec.rb failed",
|
|
"displayName": "Shell",
|
|
"description": "This tool executes a given shell command as `bash -c <command>`. To run a command in the background, set the `is_background` parameter to true. Do NOT use `&` to background commands. Command is executed as a subprocess that leads its own process group. Command process group can be terminated as `kill -- -PGID` or signaled as `kill -s SIGNAL -- -PGID`.\n\n Efficiency Guidelines:\n - Quiet Flags: Always prefer silent or quiet flags (e.g., `npm install --silent`, `git --no-pager`) to reduce output volume while still capturing necessary information.\n - Pagination: Always disable terminal pagination to ensure commands terminate (e.g., use `git --no-pager`, `systemctl --no-pager`, or set `PAGER=cat`).\n\n The following information is returned:\n\n Output: Combined stdout/stderr. Can be `(empty)` or partial on error and for any unwaited background processes.\n Exit Code: Only included if non-zero (command failed).\n Error: Only included if a process-level error occurred (e.g., spawn failure).\n Signal: Only included if process was terminated by a signal.\n Background PIDs: Only included if background processes were started.\n Process Group PGID: Only included if available.",
|
|
"renderOutputAsMarkdown": false
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"id": "0482a570-df2e-4912-8559-e5db7cb7ea47",
|
|
"timestamp": "2026-02-20T17:08:29.793Z",
|
|
"type": "gemini",
|
|
"content": "I'll examine `lib/dalmatian/cluster.rb` and `lib/dalmatian/deployable.rb` to understand how the RDS configuration is being deployed, as it seems an unexpected `TF_VAR_rds` argument is causing test failures. I'll also check `spec/integration/tests_local_configuration_spec.rb` to see how the tests are stubbing these calls.",
|
|
"thoughts": [
|
|
{
|
|
"subject": "Reviewing Test Failures",
|
|
"description": "I've been poring over the test failures, and it seems like the `Dalmatian::Helper.run!` calls are the crux of the problem. Failure number 24, in particular, highlights an issue with how the services config is being passed to \"terraform plan.\" Need to dig deeper into the argument mismatches.",
|
|
"timestamp": "2026-02-20T17:08:26.963Z"
|
|
},
|
|
{
|
|
"subject": "Isolating the Root Cause",
|
|
"description": "I've homed in on failure 24, where the extra `TF_VAR_rds` argument is the culprit. The stack trace points to `deploy_rds`, which I'm now cross-referencing against the failing spec and relevant code in `lib/dalmatian/cluster.rb` and `lib/dalmatian/deployable.rb` to find where this rogue variable is being injected into the terraform command.",
|
|
"timestamp": "2026-02-20T17:08:29.564Z"
|
|
}
|
|
],
|
|
"tokens": {
|
|
"input": 33355,
|
|
"output": 158,
|
|
"cached": 18067,
|
|
"thoughts": 443,
|
|
"tool": 0,
|
|
"total": 33956
|
|
},
|
|
"model": "gemini-3-flash-preview",
|
|
"toolCalls": [
|
|
{
|
|
"id": "read_file_1771607309716_0",
|
|
"name": "read_file",
|
|
"args": {
|
|
"limit": 50,
|
|
"offset": 250,
|
|
"file_path": "lib/dalmatian/cluster.rb"
|
|
},
|
|
"result": [
|
|
{
|
|
"functionResponse": {
|
|
"id": "read_file_1771607309716_0",
|
|
"name": "read_file",
|
|
"response": {
|
|
"output": "\nIMPORTANT: The file content has been truncated.\nStatus: Showing lines 251-300 of 395 total lines.\nAction: To read more of the file, you can use the 'offset' and 'limit' parameters in a subsequent 'read_file' call. For example, to read the next section of the file, use offset: 300.\n\n--- FILE CONTENT (truncated) ---\n waf: waf,\n env: env,\n plan: plan,\n auto_approve: auto_approve,\n destroy: destroy,\n verbose: verbose\n ).call\n end\n\n def deploy_rds(rds, env, test, auto_approve, plan, destroy, verbose)\n test_rds(rds, env) if test\n RdsDeployment.new(\n rds: rds,\n env: env,\n plan: plan,\n auto_approve: auto_approve,\n destroy: destroy,\n verbose: verbose\n ).call\n end\n\n def deploy_aurora(aurora, env, test, auto_approve, plan, destroy, verbose)\n test_aurora(aurora, env) if test\n AuroraDeployment.new(\n aurora: aurora,\n env: env,\n plan: plan,\n auto_approve: auto_approve,\n destroy: destroy,\n verbose: verbose\n ).call\n end\n\n def deploy_elasticache_cluster(elasticache_cluster, env, test, auto_approve, plan, destroy, verbose)\n test_elasticache_cluster(elasticache_cluster, env) if test\n ElasticacheClusterDeployment.new(\n elasticache_cluster: elasticache_cluster,\n env: env,\n plan: plan,\n auto_approve: auto_approve,\n destroy: destroy,\n verbose: verbose\n ).call\n end\n\n def deploy_opensearch_cluster(opensearch_cluster, env, test, auto_approve, plan, destroy, verbose)\n test_opensearch_cluster(opensearch_cluster, env) if test\n OpensearchClusterDeployment.new(\n opensearch_cluster: opensearch_cluster,\n env: env,"
|
|
}
|
|
}
|
|
}
|
|
],
|
|
"status": "success",
|
|
"timestamp": "2026-02-20T17:08:29.872Z",
|
|
"resultDisplay": "Read lines 251-300 of 395 from lib/dalmatian/cluster.rb",
|
|
"displayName": "ReadFile",
|
|
"description": "Reads and returns the content of a specified file. If the file is large, the content will be truncated. The tool's response will clearly indicate if truncation has occurred and will provide details on how to read more of the file using the 'offset' and 'limit' parameters. Handles text, images (PNG, JPG, GIF, WEBP, SVG, BMP), audio files (MP3, WAV, AIFF, AAC, OGG, FLAC), and PDF files. For text files, it can read specific line ranges.",
|
|
"renderOutputAsMarkdown": true
|
|
},
|
|
{
|
|
"id": "read_file_1771607309751_1",
|
|
"name": "read_file",
|
|
"args": {
|
|
"file_path": "lib/dalmatian/deployable.rb"
|
|
},
|
|
"result": [
|
|
{
|
|
"functionResponse": {
|
|
"id": "read_file_1771607309751_1",
|
|
"name": "read_file",
|
|
"response": {
|
|
"output": "module Dalmatian\n module Deployable\n def call\n change_to_target_directory\n checkout_revision_if_required\n Terraform.ensure_presence_of_workspace(workspace_name)\n return terraform_destroy if destroy\n return terraform_plan if plan\n terraform_apply\n end\n\n private\n\n def env_name\n env.fetch(:name)\n end\n\n def env_details\n env.fetch(:details).merge(\"environment\" => env_name)\n end\n\n def dalmatian_role\n return \"dalmatian-admin\" unless plan\n \"dalmatian-read\"\n end\n\n def terraform_plan\n Terraform.plan(\n tfvars: env_config,\n verbose: verbose\n )\n end\n\n def terraform_apply\n Terraform.apply(\n tfvars: env_config,\n auto_approve: auto_approve,\n verbose: verbose\n )\n end\n\n def terraform_destroy\n Terraform.destroy(\n tfvars: env_config,\n verbose: verbose\n )\n end\n\n def change_to_target_directory\n helper.change_to(target_directory)\n end\n end\nend\n"
|
|
}
|
|
}
|
|
}
|
|
],
|
|
"status": "success",
|
|
"timestamp": "2026-02-20T17:08:29.872Z",
|
|
"resultDisplay": "",
|
|
"displayName": "ReadFile",
|
|
"description": "Reads and returns the content of a specified file. If the file is large, the content will be truncated. The tool's response will clearly indicate if truncation has occurred and will provide details on how to read more of the file using the 'offset' and 'limit' parameters. Handles text, images (PNG, JPG, GIF, WEBP, SVG, BMP), audio files (MP3, WAV, AIFF, AAC, OGG, FLAC), and PDF files. For text files, it can read specific line ranges.",
|
|
"renderOutputAsMarkdown": true
|
|
},
|
|
{
|
|
"id": "read_file_1771607309791_2",
|
|
"name": "read_file",
|
|
"args": {
|
|
"file_path": "spec/integration/tests_local_configuration_spec.rb",
|
|
"offset": 3200,
|
|
"limit": 100
|
|
},
|
|
"result": [
|
|
{
|
|
"functionResponse": {
|
|
"id": "read_file_1771607309791_2",
|
|
"name": "read_file",
|
|
"response": {
|
|
"output": "\nIMPORTANT: The file content has been truncated.\nStatus: Showing lines 3201-3243 of 3243 total lines.\nAction: To read more of the file, you can use the 'offset' and 'limit' parameters in a subsequent 'read_file' call. For example, to read the next section of the file, use offset: 3243.\n\n--- FILE CONTENT (truncated) ---\n it 'passes the opensearch config to \"terraform plan\"' do\n aggregate_failures do\n expect(Helper).to have_received(:run!)\n .with(cluster1_plan_cmd_production_opensearch_cluster)\n expect(Helper).to have_received(:run!)\n .with(cluster1_plan_cmd_staging_opensearch_cluster)\n end\n end\n\n it 'passes the services config to \"terraform plan\"' do\n aggregate_failures do\n expect(Helper).to have_received(:run!).with(cluster1_plan_cmd_production_service)\n expect(Helper).to have_received(:run!).with(cluster1_plan_cmd_staging_service)\n end\n end\n\n it 'passes the loadbalancer config to \"terraform plan\"' do\n aggregate_failures do\n expect(Helper).to have_received(:run!)\n .with(cluster1_plan_cmd_production_shared_loadbalancer)\n expect(Helper).to have_received(:run!)\n .with(cluster1_plan_cmd_staging_shared_loadbalancer)\n end\n end\n\n it 'passes the cluster 2 config to \"terraform plan\"' do\n aggregate_failures do\n expect(Helper).to have_received(:run!).with(cluster2_plan_cmd_production)\n expect(Helper).to have_received(:run!).with(cluster2_plan_cmd_staging)\n end\n end\n\n it 'passes the cluster 3 config to \"terraform plan\"' do\n expect(Helper).to have_received(:run!).with(cluster3_plan_cmd_staging)\n end\n\n it 'passes the cluster 4 config to \"terraform plan\"' do\n expect(Helper).to have_received(:run!).with(cluster4_plan_cmd_production)\n end\n end\n end\nend\n"
|
|
}
|
|
}
|
|
}
|
|
],
|
|
"status": "success",
|
|
"timestamp": "2026-02-20T17:08:29.872Z",
|
|
"resultDisplay": "Read lines 3201-3243 of 3243 from spec/integration/tests_local_configuration_spec.rb",
|
|
"displayName": "ReadFile",
|
|
"description": "Reads and returns the content of a specified file. If the file is large, the content will be truncated. The tool's response will clearly indicate if truncation has occurred and will provide details on how to read more of the file using the 'offset' and 'limit' parameters. Handles text, images (PNG, JPG, GIF, WEBP, SVG, BMP), audio files (MP3, WAV, AIFF, AAC, OGG, FLAC), and PDF files. For text files, it can read specific line ranges.",
|
|
"renderOutputAsMarkdown": true
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"id": "86b01d21-4041-4213-ba4f-af388f5bcd8f",
|
|
"timestamp": "2026-02-20T17:08:54.037Z",
|
|
"type": "gemini",
|
|
"content": "I'll look for the definition of `Dalmatian::RdsDeployment`, which likely includes `Deployable`, to determine what it returns for `env_config`.",
|
|
"thoughts": [
|
|
{
|
|
"subject": "Pinpointing the Definition",
|
|
"description": "I'm currently trying to understand the behavior of `Dalmatian::RdsDeployment`. I'm specifically looking for the implementation of the `env_config` method. My current line of thought is to locate where `RdsDeployment` is defined, as it likely leverages the `Deployable` concern.",
|
|
"timestamp": "2026-02-20T17:08:53.842Z"
|
|
}
|
|
],
|
|
"tokens": {
|
|
"input": 34845,
|
|
"output": 62,
|
|
"cached": 3582,
|
|
"thoughts": 68,
|
|
"tool": 0,
|
|
"total": 34975
|
|
},
|
|
"model": "gemini-3-flash-preview",
|
|
"toolCalls": [
|
|
{
|
|
"id": "run_shell_command_1771607334030_0",
|
|
"name": "run_shell_command",
|
|
"args": {
|
|
"command": "grep -r \"class RdsDeployment\" lib/dalmatian/"
|
|
},
|
|
"result": [
|
|
{
|
|
"functionResponse": {
|
|
"id": "run_shell_command_1771607334030_0",
|
|
"name": "run_shell_command",
|
|
"response": {
|
|
"output": "Output: lib/dalmatian/rds_deployment.rb: class RdsDeployment\nProcess Group PGID: 47122"
|
|
}
|
|
}
|
|
}
|
|
],
|
|
"status": "success",
|
|
"timestamp": "2026-02-20T17:08:58.638Z",
|
|
"resultDisplay": "lib/dalmatian/rds_deployment.rb: class RdsDeployment",
|
|
"displayName": "Shell",
|
|
"description": "This tool executes a given shell command as `bash -c <command>`. To run a command in the background, set the `is_background` parameter to true. Do NOT use `&` to background commands. Command is executed as a subprocess that leads its own process group. Command process group can be terminated as `kill -- -PGID` or signaled as `kill -s SIGNAL -- -PGID`.\n\n Efficiency Guidelines:\n - Quiet Flags: Always prefer silent or quiet flags (e.g., `npm install --silent`, `git --no-pager`) to reduce output volume while still capturing necessary information.\n - Pagination: Always disable terminal pagination to ensure commands terminate (e.g., use `git --no-pager`, `systemctl --no-pager`, or set `PAGER=cat`).\n\n The following information is returned:\n\n Output: Combined stdout/stderr. Can be `(empty)` or partial on error and for any unwaited background processes.\n Exit Code: Only included if non-zero (command failed).\n Error: Only included if a process-level error occurred (e.g., spawn failure).\n Signal: Only included if process was terminated by a signal.\n Background PIDs: Only included if background processes were started.\n Process Group PGID: Only included if available.",
|
|
"renderOutputAsMarkdown": false
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"id": "e5e79ccc-04d0-4516-83c8-72d42b0a4d6e",
|
|
"timestamp": "2026-02-20T17:09:00.558Z",
|
|
"type": "gemini",
|
|
"content": "I'll read `lib/dalmatian/rds_deployment.rb`.",
|
|
"thoughts": [
|
|
{
|
|
"subject": "Reviewing Code Structure",
|
|
"description": "I'm diving into the `lib/dalmatian/rds_deployment.rb` file now. Initial scan suggests a focus on RDS deployment, which is expected. Currently, I am assessing its overall structure to grasp the flow of the code and understand how it handles deployment tasks.",
|
|
"timestamp": "2026-02-20T17:09:00.439Z"
|
|
}
|
|
],
|
|
"tokens": {
|
|
"input": 34939,
|
|
"output": 39,
|
|
"cached": 32174,
|
|
"thoughts": 19,
|
|
"tool": 0,
|
|
"total": 34997
|
|
},
|
|
"model": "gemini-3-flash-preview",
|
|
"toolCalls": [
|
|
{
|
|
"id": "read_file_1771607340556_0",
|
|
"name": "read_file",
|
|
"args": {
|
|
"file_path": "lib/dalmatian/rds_deployment.rb"
|
|
},
|
|
"result": [
|
|
{
|
|
"functionResponse": {
|
|
"id": "read_file_1771607340556_0",
|
|
"name": "read_file",
|
|
"response": {
|
|
"output": "module Dalmatian\n class RdsDeployment\n include Deployable\n\n def initialize(\n rds:,\n env:,\n auto_approve: false,\n plan: false,\n destroy: false,\n verbose: false\n )\n @rds = rds\n @env = env\n @helper = Helper\n @logger = Logger\n @auto_approve = auto_approve\n @plan = plan\n @destroy = destroy\n @verbose = verbose\n end\n\n private\n\n attr_reader :rds, :env, :helper, :logger, :auto_approve, :plan, :destroy, :verbose\n\n def target_directory\n File.join(\n Infrastructure::APP_ROOT,\n Infrastructure::PATH,\n \"rds\"\n )\n end\n\n def env_config\n env_details.merge(\n \"account_id\" => rds.account_id,\n \"infrastructure_name\" => rds.cluster_id,\n \"dalmatian_role\" => dalmatian_role,\n \"rds\" => rds.to_params\n )\n end\n\n def checkout_revision_if_required\n false\n end\n\n def workspace_name\n [rds.cluster_id, rds.identifier, \"rds\", env_name].join(\"-\")\n end\n end\nend\n"
|
|
}
|
|
}
|
|
}
|
|
],
|
|
"status": "success",
|
|
"timestamp": "2026-02-20T17:09:00.570Z",
|
|
"resultDisplay": "",
|
|
"displayName": "ReadFile",
|
|
"description": "Reads and returns the content of a specified file. If the file is large, the content will be truncated. The tool's response will clearly indicate if truncation has occurred and will provide details on how to read more of the file using the 'offset' and 'limit' parameters. Handles text, images (PNG, JPG, GIF, WEBP, SVG, BMP), audio files (MP3, WAV, AIFF, AAC, OGG, FLAC), and PDF files. For text files, it can read specific line ranges.",
|
|
"renderOutputAsMarkdown": true
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"id": "b6160e25-8c08-47c0-ba61-8bae3903536e",
|
|
"timestamp": "2026-02-20T17:09:05.053Z",
|
|
"type": "gemini",
|
|
"content": "I misread the failure; `tests local configuration use of \"terraform plan\" passes the services config to \"terraform plan\"` is failing because it's unexpectedly calling `deploy_rds` with a different `infrastructure_name` and an added `rds` variable. I'll examine `spec/integration/tests_local_configuration_spec.rb` around line 3210 to understand why this is happening.",
|
|
"thoughts": [
|
|
{
|
|
"subject": "Considering the Error",
|
|
"description": "I've re-examined the test failure, and initially, I misinterpreted the root cause. It now appears the issue lies within `deploy_rds`. I need to isolate the exact problem within that context, which should help to clarify the issue with the terraform plan.",
|
|
"timestamp": "2026-02-20T17:09:02.957Z"
|
|
},
|
|
{
|
|
"subject": "Isolating the Context",
|
|
"description": "My attention has now shifted to the failing test's interaction with `deploy_rds`. I was incorrect in thinking the problem was in that context directly; instead, the test's configuration of `TF_VAR_infrastructure_name` doesn't match the expected value. The test itself is what's misconfigured. I am now checking the relevant spec file to see where the divergence arises.",
|
|
"timestamp": "2026-02-20T17:09:04.969Z"
|
|
}
|
|
],
|
|
"tokens": {
|
|
"input": 35292,
|
|
"output": 115,
|
|
"cached": 32176,
|
|
"thoughts": 354,
|
|
"tool": 0,
|
|
"total": 35761
|
|
},
|
|
"model": "gemini-3-flash-preview",
|
|
"toolCalls": [
|
|
{
|
|
"id": "read_file_1771607345049_0",
|
|
"name": "read_file",
|
|
"args": {
|
|
"file_path": "spec/integration/tests_local_configuration_spec.rb",
|
|
"offset": 3150,
|
|
"limit": 100
|
|
},
|
|
"result": [
|
|
{
|
|
"functionResponse": {
|
|
"id": "read_file_1771607345049_0",
|
|
"name": "read_file",
|
|
"response": {
|
|
"output": "\nIMPORTANT: The file content has been truncated.\nStatus: Showing lines 3151-3243 of 3243 total lines.\nAction: To read more of the file, you can use the 'offset' and 'limit' parameters in a subsequent 'read_file' call. For example, to read the next section of the file, use offset: 3243.\n\n--- FILE CONTENT (truncated) ---\n\n describe 'use of \"terraform plan\"' do\n it 'passes the hosted zone config to \"terraform plan\"' do\n aggregate_failures do\n expect(Helper).to have_received(:run!).with(cluster1_plan_cmd_hz)\n end\n end\n\n it 'passes the s3 config to \"terraform plan\"' do\n aggregate_failures do\n expect(Helper).to have_received(:run!).with(cluster1_plan_cmd_s3)\n end\n end\n\n it 'passes the vpn customer gateway config to \"terraform plan\"' do\n aggregate_failures do\n expect(Helper).to have_received(:run!).with(cluster1_plan_cmd_vpn_cg)\n end\n end\n\n it 'passes the base config to \"terraform plan\"' do\n aggregate_failures do\n expect(Helper).to have_received(:run!).with(cluster1_plan_cmd_production).twice\n expect(Helper).to have_received(:run!).with(cluster1_plan_cmd_staging).twice\n end\n end\n\n it 'passes the waf config to \"terraform plan\"' do\n aggregate_failures do\n expect(Helper).to have_received(:run!).with(cluster1_plan_cmd_production_waf)\n expect(Helper).to have_received(:run!).with(cluster1_plan_cmd_staging_waf)\n end\n end\n\n it 'passes the rds config to \"terraform plan\"' do\n aggregate_failures do\n expect(Helper).to have_received(:run!).with(cluster1_plan_cmd_production_rds)\n expect(Helper).to have_received(:run!).with(cluster1_plan_cmd_staging_rds)\n end\n end\n\n it 'passes the elasticache config to \"terraform plan\"' do\n aggregate_failures do\n expect(Helper).to have_received(:run!)\n .with(cluster1_plan_cmd_production_elasticache_cluster)\n expect(Helper).to have_received(:run!)\n .with(cluster1_plan_cmd_staging_elasticache_cluster)\n end\n end\n\n it 'passes the opensearch config to \"terraform plan\"' do\n aggregate_failures do\n expect(Helper).to have_received(:run!)\n .with(cluster1_plan_cmd_production_opensearch_cluster)\n expect(Helper).to have_received(:run!)\n .with(cluster1_plan_cmd_staging_opensearch_cluster)\n end\n end\n\n it 'passes the services config to \"terraform plan\"' do\n aggregate_failures do\n expect(Helper).to have_received(:run!).with(cluster1_plan_cmd_production_service)\n expect(Helper).to have_received(:run!).with(cluster1_plan_cmd_staging_service)\n end\n end\n\n it 'passes the loadbalancer config to \"terraform plan\"' do\n aggregate_failures do\n expect(Helper).to have_received(:run!)\n .with(cluster1_plan_cmd_production_shared_loadbalancer)\n expect(Helper).to have_received(:run!)\n .with(cluster1_plan_cmd_staging_shared_loadbalancer)\n end\n end\n\n it 'passes the cluster 2 config to \"terraform plan\"' do\n aggregate_failures do\n expect(Helper).to have_received(:run!).with(cluster2_plan_cmd_production)\n expect(Helper).to have_received(:run!).with(cluster2_plan_cmd_staging)\n end\n end\n\n it 'passes the cluster 3 config to \"terraform plan\"' do\n expect(Helper).to have_received(:run!).with(cluster3_plan_cmd_staging)\n end\n\n it 'passes the cluster 4 config to \"terraform plan\"' do\n expect(Helper).to have_received(:run!).with(cluster4_plan_cmd_production)\n end\n end\n end\nend\n"
|
|
}
|
|
}
|
|
}
|
|
],
|
|
"status": "success",
|
|
"timestamp": "2026-02-20T17:09:05.071Z",
|
|
"resultDisplay": "Read lines 3151-3243 of 3243 from spec/integration/tests_local_configuration_spec.rb",
|
|
"displayName": "ReadFile",
|
|
"description": "Reads and returns the content of a specified file. If the file is large, the content will be truncated. The tool's response will clearly indicate if truncation has occurred and will provide details on how to read more of the file using the 'offset' and 'limit' parameters. Handles text, images (PNG, JPG, GIF, WEBP, SVG, BMP), audio files (MP3, WAV, AIFF, AAC, OGG, FLAC), and PDF files. For text files, it can read specific line ranges.",
|
|
"renderOutputAsMarkdown": true
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"id": "d6b4066a-b0f1-4ceb-8d66-6b38aab2bb84",
|
|
"timestamp": "2026-02-20T17:09:06.864Z",
|
|
"type": "gemini",
|
|
"content": "I'll check the `before` block for these tests.",
|
|
"thoughts": [
|
|
{
|
|
"subject": "Analyzing Test Prerequisites",
|
|
"description": "I'm currently focused on the setup phase. Understanding the `before` block is critical. That's where all the magic happens. I want to see what needs to be in place. I need that context.",
|
|
"timestamp": "2026-02-20T17:09:06.784Z"
|
|
}
|
|
],
|
|
"tokens": {
|
|
"input": 36429,
|
|
"output": 41,
|
|
"cached": 32002,
|
|
"thoughts": 13,
|
|
"tool": 0,
|
|
"total": 36483
|
|
},
|
|
"model": "gemini-3-flash-preview",
|
|
"toolCalls": [
|
|
{
|
|
"id": "read_file_1771607346861_0",
|
|
"name": "read_file",
|
|
"args": {
|
|
"offset": 3100,
|
|
"file_path": "spec/integration/tests_local_configuration_spec.rb",
|
|
"limit": 100
|
|
},
|
|
"result": [
|
|
{
|
|
"functionResponse": {
|
|
"id": "read_file_1771607346861_0",
|
|
"name": "read_file",
|
|
"response": {
|
|
"output": "\nIMPORTANT: The file content has been truncated.\nStatus: Showing lines 3101-3200 of 3243 total lines.\nAction: To read more of the file, you can use the 'offset' and 'limit' parameters in a subsequent 'read_file' call. For example, to read the next section of the file, use offset: 3200.\n\n--- FILE CONTENT (truncated) ---\n allow(Helper).to receive(:run!).with(cluster3_plan_cmd_staging)\n\n allow(Helper).to receive(:run!).with(cluster4_validate_cmd_production)\n allow(Helper).to receive(:run!).with(cluster4_plan_cmd_production)\n\n Infrastructure.new(\n ConfigurationReader.new(path: \"./dalmatian.yml.example\", parameter_store: fake_parameter_store).infrastructures\n ).test\n end\n\n it 'invokes \"terraform validate\" with the expected cluster options' do\n expect(Helper).to have_received(:run!).with(cluster1_validate_cmd_hz)\n\n expect(Helper).to have_received(:run!).with(cluster1_validate_cmd_s3)\n\n expect(Helper).to have_received(:run!).with(cluster1_validate_cmd_vpn_cg)\n\n expect(Helper).to have_received(:run!).with(cluster1_validate_cmd_production).twice\n expect(Helper).to have_received(:run!).with(cluster1_validate_cmd_staging).twice\n\n expect(Helper).to have_received(:run!).with(cluster1_validate_cmd_production_waf)\n expect(Helper).to have_received(:run!).with(cluster1_validate_cmd_staging_waf)\n\n expect(Helper).to have_received(:run!).with(cluster1_validate_cmd_production_rds)\n expect(Helper).to have_received(:run!).with(cluster1_validate_cmd_staging_rds)\n\n expect(Helper).to have_received(:run!).with(cluster1_validate_cmd_production_elasticache_cluster)\n expect(Helper).to have_received(:run!).with(cluster1_validate_cmd_staging_elasticache_cluster)\n\n expect(Helper).to have_received(:run!).with(cluster1_validate_cmd_production_opensearch_cluster)\n expect(Helper).to have_received(:run!).with(cluster1_validate_cmd_staging_opensearch_cluster)\n\n expect(Helper).to have_received(:run!).with(cluster1_validate_cmd_production_service)\n expect(Helper).to have_received(:run!).with(cluster1_validate_cmd_staging_service)\n\n expect(Helper).to have_received(:run!).with(cluster1_validate_cmd_production_shared_loadbalancer)\n expect(Helper).to have_received(:run!).with(cluster1_validate_cmd_staging_shared_loadbalancer)\n\n expect(Helper).to have_received(:run!).with(cluster2_validate_cmd_production)\n expect(Helper).to have_received(:run!).with(cluster2_validate_cmd_staging)\n\n expect(Helper).to have_received(:run!).with(cluster3_validate_cmd_staging)\n\n expect(Helper).to have_received(:run!).with(cluster4_validate_cmd_production)\n end\n\n it 'invokes \"terraform validate\" with the expected source options' do\n expect(Helper).to have_received(:run!).with(source1_validate_cmd_production).twice\n expect(Helper).to have_received(:run!).with(source1_validate_cmd_staging).twice\n end\n\n describe 'use of \"terraform plan\"' do\n it 'passes the hosted zone config to \"terraform plan\"' do\n aggregate_failures do\n expect(Helper).to have_received(:run!).with(cluster1_plan_cmd_hz)\n end\n end\n\n it 'passes the s3 config to \"terraform plan\"' do\n aggregate_failures do\n expect(Helper).to have_received(:run!).with(cluster1_plan_cmd_s3)\n end\n end\n\n it 'passes the vpn customer gateway config to \"terraform plan\"' do\n aggregate_failures do\n expect(Helper).to have_received(:run!).with(cluster1_plan_cmd_vpn_cg)\n end\n end\n\n it 'passes the base config to \"terraform plan\"' do\n aggregate_failures do\n expect(Helper).to have_received(:run!).with(cluster1_plan_cmd_production).twice\n expect(Helper).to have_received(:run!).with(cluster1_plan_cmd_staging).twice\n end\n end\n\n it 'passes the waf config to \"terraform plan\"' do\n aggregate_failures do\n expect(Helper).to have_received(:run!).with(cluster1_plan_cmd_production_waf)\n expect(Helper).to have_received(:run!).with(cluster1_plan_cmd_staging_waf)\n end\n end\n\n it 'passes the rds config to \"terraform plan\"' do\n aggregate_failures do\n expect(Helper).to have_received(:run!).with(cluster1_plan_cmd_production_rds)\n expect(Helper).to have_received(:run!).with(cluster1_plan_cmd_staging_rds)\n end\n end\n\n it 'passes the elasticache config to \"terraform plan\"' do\n aggregate_failures do\n expect(Helper).to have_received(:run!)\n .with(cluster1_plan_cmd_production_elasticache_cluster)\n expect(Helper).to have_received(:run!)\n .with(cluster1_plan_cmd_staging_elasticache_cluster)\n end\n end\n"
|
|
}
|
|
}
|
|
}
|
|
],
|
|
"status": "success",
|
|
"timestamp": "2026-02-20T17:09:06.879Z",
|
|
"resultDisplay": "Read lines 3101-3200 of 3243 from spec/integration/tests_local_configuration_spec.rb",
|
|
"displayName": "ReadFile",
|
|
"description": "Reads and returns the content of a specified file. If the file is large, the content will be truncated. The tool's response will clearly indicate if truncation has occurred and will provide details on how to read more of the file using the 'offset' and 'limit' parameters. Handles text, images (PNG, JPG, GIF, WEBP, SVG, BMP), audio files (MP3, WAV, AIFF, AAC, OGG, FLAC), and PDF files. For text files, it can read specific line ranges.",
|
|
"renderOutputAsMarkdown": true
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"id": "53254278-0406-4e5e-a52f-1cc5b8ed877b",
|
|
"timestamp": "2026-02-20T17:09:19.727Z",
|
|
"type": "gemini",
|
|
"content": "The `before` block starts before line 3101, so I'll find its actual starting point.",
|
|
"thoughts": [
|
|
{
|
|
"subject": "Beginning the Search",
|
|
"description": "I've located the `before` block's starting point and am currently isolating it within the broader code structure. I'm focusing on its position relative to line 3101 to understand the specific scope of this block.",
|
|
"timestamp": "2026-02-20T17:09:19.557Z"
|
|
}
|
|
],
|
|
"tokens": {
|
|
"input": 37814,
|
|
"output": 61,
|
|
"cached": 32119,
|
|
"thoughts": 19,
|
|
"tool": 0,
|
|
"total": 37894
|
|
},
|
|
"model": "gemini-3-flash-preview",
|
|
"toolCalls": [
|
|
{
|
|
"id": "run_shell_command_1771607359717_0",
|
|
"name": "run_shell_command",
|
|
"args": {
|
|
"command": "grep -n \"before\" spec/integration/tests_local_configuration_spec.rb | head -n 20"
|
|
},
|
|
"result": [
|
|
{
|
|
"functionResponse": {
|
|
"id": "run_shell_command_1771607359717_0",
|
|
"name": "run_shell_command",
|
|
"response": {
|
|
"output": "Output: 3041: before do\nProcess Group PGID: 47394"
|
|
}
|
|
}
|
|
}
|
|
],
|
|
"status": "success",
|
|
"timestamp": "2026-02-20T17:10:35.545Z",
|
|
"resultDisplay": "3041: before do",
|
|
"displayName": "Shell",
|
|
"description": "This tool executes a given shell command as `bash -c <command>`. To run a command in the background, set the `is_background` parameter to true. Do NOT use `&` to background commands. Command is executed as a subprocess that leads its own process group. Command process group can be terminated as `kill -- -PGID` or signaled as `kill -s SIGNAL -- -PGID`.\n\n Efficiency Guidelines:\n - Quiet Flags: Always prefer silent or quiet flags (e.g., `npm install --silent`, `git --no-pager`) to reduce output volume while still capturing necessary information.\n - Pagination: Always disable terminal pagination to ensure commands terminate (e.g., use `git --no-pager`, `systemctl --no-pager`, or set `PAGER=cat`).\n\n The following information is returned:\n\n Output: Combined stdout/stderr. Can be `(empty)` or partial on error and for any unwaited background processes.\n Exit Code: Only included if non-zero (command failed).\n Error: Only included if a process-level error occurred (e.g., spawn failure).\n Signal: Only included if process was terminated by a signal.\n Background PIDs: Only included if background processes were started.\n Process Group PGID: Only included if available.",
|
|
"renderOutputAsMarkdown": false
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"id": "bdd9e423-1c14-4bc1-9bed-9fd3e1314d27",
|
|
"timestamp": "2026-02-20T17:10:37.444Z",
|
|
"type": "gemini",
|
|
"content": "Reading line 3041.",
|
|
"thoughts": [
|
|
{
|
|
"subject": "Starting the Analysis Process",
|
|
"description": "I'm currently at line 3041, commencing the process of careful reading and analysis. My focus now is on understanding the initial context to determine the core arguments presented. I'm taking notes to ensure I grasp the nuances of the concepts and how they are related.",
|
|
"timestamp": "2026-02-20T17:10:37.349Z"
|
|
}
|
|
],
|
|
"tokens": {
|
|
"input": 37900,
|
|
"output": 36,
|
|
"cached": 35658,
|
|
"thoughts": 11,
|
|
"tool": 0,
|
|
"total": 37947
|
|
},
|
|
"model": "gemini-3-flash-preview",
|
|
"toolCalls": [
|
|
{
|
|
"id": "read_file_1771607437441_0",
|
|
"name": "read_file",
|
|
"args": {
|
|
"file_path": "spec/integration/tests_local_configuration_spec.rb",
|
|
"limit": 100,
|
|
"offset": 3041
|
|
},
|
|
"result": [
|
|
{
|
|
"functionResponse": {
|
|
"id": "read_file_1771607437441_0",
|
|
"name": "read_file",
|
|
"response": {
|
|
"output": "\nIMPORTANT: The file content has been truncated.\nStatus: Showing lines 3042-3141 of 3243 total lines.\nAction: To read more of the file, you can use the 'offset' and 'limit' parameters in a subsequent 'read_file' call. For example, to read the next section of the file, use offset: 3141.\n\n--- FILE CONTENT (truncated) ---\n allow(Logger).to receive(:info)\n stub_git_clone_cmds\n stub_git_checkout\n stub_workspace_creation_cmds\n allow(Helper).to receive(:run!).with(\"rake terrafile\")\n allow(Helper).to receive(:run!).with(\"terraform init -upgrade=true\")\n allow(Helper).to receive(:run!).with(\"terraform fmt -check -diff\")\n\n allow(Helper).to receive(:run!).with(cluster1_validate_cmd_hz)\n allow(Helper).to receive(:run!).with(cluster1_validate_cmd_s3)\n allow(Helper).to receive(:run!).with(cluster1_validate_cmd_vpn_cg)\n\n allow(Helper).to receive(:run!).with(cluster1_plan_cmd_hz)\n allow(Helper).to receive(:run!).with(cluster1_plan_cmd_s3)\n allow(Helper).to receive(:run!).with(cluster1_plan_cmd_vpn_cg)\n\n allow(Helper).to receive(:run!).with(cluster1_validate_cmd_production)\n allow(Helper).to receive(:run!).with(cluster1_validate_cmd_staging)\n allow(Helper).to receive(:run!).with(cluster1_plan_cmd_production)\n allow(Helper).to receive(:run!).with(cluster1_plan_cmd_staging)\n allow(Helper).to receive(:run!).with(source1_validate_cmd_production)\n allow(Helper).to receive(:run!).with(source1_validate_cmd_staging)\n\n allow(Helper).to receive(:run!).with(cluster1_validate_cmd_production_waf)\n allow(Helper).to receive(:run!).with(cluster1_validate_cmd_staging_waf)\n allow(Helper).to receive(:run!).with(cluster1_plan_cmd_production_waf)\n allow(Helper).to receive(:run!).with(cluster1_plan_cmd_staging_waf)\n\n allow(Helper).to receive(:run!).with(cluster1_validate_cmd_production_rds)\n allow(Helper).to receive(:run!).with(cluster1_validate_cmd_staging_rds)\n allow(Helper).to receive(:run!).with(cluster1_plan_cmd_production_rds)\n allow(Helper).to receive(:run!).with(cluster1_plan_cmd_staging_rds)\n\n allow(Helper).to receive(:run!).with(cluster1_validate_cmd_production_elasticache_cluster)\n allow(Helper).to receive(:run!).with(cluster1_validate_cmd_staging_elasticache_cluster)\n allow(Helper).to receive(:run!).with(cluster1_plan_cmd_production_elasticache_cluster)\n allow(Helper).to receive(:run!).with(cluster1_plan_cmd_staging_elasticache_cluster)\n\n allow(Helper).to receive(:run!).with(cluster1_validate_cmd_production_opensearch_cluster)\n allow(Helper).to receive(:run!).with(cluster1_validate_cmd_staging_opensearch_cluster)\n allow(Helper).to receive(:run!).with(cluster1_plan_cmd_production_opensearch_cluster)\n allow(Helper).to receive(:run!).with(cluster1_plan_cmd_staging_opensearch_cluster)\n\n allow(Helper).to receive(:run!).with(cluster1_validate_cmd_production_service)\n allow(Helper).to receive(:run!).with(cluster1_validate_cmd_staging_service)\n allow(Helper).to receive(:run!).with(cluster1_plan_cmd_production_service)\n allow(Helper).to receive(:run!).with(cluster1_plan_cmd_staging_service)\n\n allow(Helper).to receive(:run!).with(cluster1_validate_cmd_production_shared_loadbalancer)\n allow(Helper).to receive(:run!).with(cluster1_validate_cmd_staging_shared_loadbalancer)\n allow(Helper).to receive(:run!).with(cluster1_plan_cmd_production_shared_loadbalancer)\n allow(Helper).to receive(:run!).with(cluster1_plan_cmd_staging_shared_loadbalancer)\n\n allow(Helper).to receive(:run!).with(cluster2_validate_cmd_production)\n allow(Helper).to receive(:run!).with(cluster2_validate_cmd_staging)\n allow(Helper).to receive(:run!).with(cluster2_plan_cmd_production)\n allow(Helper).to receive(:run!).with(cluster2_plan_cmd_staging)\n\n allow(Helper).to receive(:run!).with(cluster3_validate_cmd_staging)\n allow(Helper).to receive(:run!).with(cluster3_plan_cmd_staging)\n\n allow(Helper).to receive(:run!).with(cluster4_validate_cmd_production)\n allow(Helper).to receive(:run!).with(cluster4_plan_cmd_production)\n\n Infrastructure.new(\n ConfigurationReader.new(path: \"./dalmatian.yml.example\", parameter_store: fake_parameter_store).infrastructures\n ).test\n end\n\n it 'invokes \"terraform validate\" with the expected cluster options' do\n expect(Helper).to have_received(:run!).with(cluster1_validate_cmd_hz)\n\n expect(Helper).to have_received(:run!).with(cluster1_validate_cmd_s3)\n\n expect(Helper).to have_received(:run!).with(cluster1_validate_cmd_vpn_cg)\n\n expect(Helper).to have_received(:run!).with(cluster1_validate_cmd_production).twice\n expect(Helper).to have_received(:run!).with(cluster1_validate_cmd_staging).twice\n\n expect(Helper).to have_received(:run!).with(cluster1_validate_cmd_production_waf)\n expect(Helper).to have_received(:run!).with(cluster1_validate_cmd_staging_waf)\n\n expect(Helper).to have_received(:run!).with(cluster1_validate_cmd_production_rds)\n expect(Helper).to have_received(:run!).with(cluster1_validate_cmd_staging_rds)\n\n expect(Helper).to have_received(:run!).with(cluster1_validate_cmd_production_elasticache_cluster)\n expect(Helper).to have_received(:run!).with(cluster1_validate_cmd_staging_elasticache_cluster)\n\n expect(Helper).to have_received(:run!).with(cluster1_validate_cmd_production_opensearch_cluster)\n expect(Helper).to have_received(:run!).with(cluster1_validate_cmd_staging_opensearch_cluster)\n\n expect(Helper).to have_received(:run!).with(cluster1_validate_cmd_production_service)\n expect(Helper).to have_received(:run!).with(cluster1_validate_cmd_staging_service)\n\n expect(Helper).to have_received(:run!).with(cluster1_validate_cmd_production_shared_loadbalancer)\n expect(Helper).to have_received(:run!).with(cluster1_validate_cmd_staging_shared_loadbalancer)\n\n expect(Helper).to have_received(:run!).with(cluster2_validate_cmd_production)\n expect(Helper).to have_received(:run!).with(cluster2_validate_cmd_staging)\n"
|
|
}
|
|
}
|
|
}
|
|
],
|
|
"status": "success",
|
|
"timestamp": "2026-02-20T17:10:37.465Z",
|
|
"resultDisplay": "Read lines 3042-3141 of 3243 from spec/integration/tests_local_configuration_spec.rb",
|
|
"displayName": "ReadFile",
|
|
"description": "Reads and returns the content of a specified file. If the file is large, the content will be truncated. The tool's response will clearly indicate if truncation has occurred and will provide details on how to read more of the file using the 'offset' and 'limit' parameters. Handles text, images (PNG, JPG, GIF, WEBP, SVG, BMP), audio files (MP3, WAV, AIFF, AAC, OGG, FLAC), and PDF files. For text files, it can read specific line ranges.",
|
|
"renderOutputAsMarkdown": true
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"id": "afb97ce4-56d5-4e8c-bde5-d189f732f802",
|
|
"timestamp": "2026-02-20T17:10:39.695Z",
|
|
"type": "gemini",
|
|
"content": "I'll find where `cluster1_plan_cmd_production_service` and similar variables are defined, likely in `spec/support/spec_helper.rb` or a shared context.",
|
|
"thoughts": [
|
|
{
|
|
"subject": "Pinpointing Variable Definitions",
|
|
"description": "I'm currently tracing down the definitions of `cluster1_plan_cmd_production_service` and similar variables. My initial hunch is correct; they're probably lurking in `spec/support/spec_helper.rb` or within a shared context. I'll focus my search there.",
|
|
"timestamp": "2026-02-20T17:10:39.609Z"
|
|
}
|
|
],
|
|
"tokens": {
|
|
"input": 39754,
|
|
"output": 69,
|
|
"cached": 35835,
|
|
"thoughts": 44,
|
|
"tool": 0,
|
|
"total": 39867
|
|
},
|
|
"model": "gemini-3-flash-preview",
|
|
"toolCalls": [
|
|
{
|
|
"id": "run_shell_command_1771607439692_0",
|
|
"name": "run_shell_command",
|
|
"args": {
|
|
"command": "grep -r \"cluster1_plan_cmd_production_service\" spec/"
|
|
},
|
|
"result": [
|
|
{
|
|
"functionResponse": {
|
|
"id": "run_shell_command_1771607439692_0",
|
|
"name": "run_shell_command",
|
|
"response": {
|
|
"output": "Output: spec/integration/tests_local_configuration_spec.rb: let(:cluster1_plan_cmd_production_service) do\nspec/integration/tests_local_configuration_spec.rb: allow(Helper).to receive(:run!).with(cluster1_plan_cmd_production_service)\nspec/integration/tests_local_configuration_spec.rb: expect(Helper).to have_received(:run!).with(cluster1_plan_cmd_production_service)\nProcess Group PGID: 47440"
|
|
}
|
|
}
|
|
}
|
|
],
|
|
"status": "success",
|
|
"timestamp": "2026-02-20T17:10:43.000Z",
|
|
"resultDisplay": "spec/integration/tests_local_configuration_spec.rb: let(:cluster1_plan_cmd_production_service) do\nspec/integration/tests_local_configuration_spec.rb: allow(Helper).to receive(:run!).with(cluster1_plan_cmd_production_service)\nspec/integration/tests_local_configuration_spec.rb: expect(Helper).to have_received(:run!).with(cluster1_plan_cmd_production_service)",
|
|
"displayName": "Shell",
|
|
"description": "This tool executes a given shell command as `bash -c <command>`. To run a command in the background, set the `is_background` parameter to true. Do NOT use `&` to background commands. Command is executed as a subprocess that leads its own process group. Command process group can be terminated as `kill -- -PGID` or signaled as `kill -s SIGNAL -- -PGID`.\n\n Efficiency Guidelines:\n - Quiet Flags: Always prefer silent or quiet flags (e.g., `npm install --silent`, `git --no-pager`) to reduce output volume while still capturing necessary information.\n - Pagination: Always disable terminal pagination to ensure commands terminate (e.g., use `git --no-pager`, `systemctl --no-pager`, or set `PAGER=cat`).\n\n The following information is returned:\n\n Output: Combined stdout/stderr. Can be `(empty)` or partial on error and for any unwaited background processes.\n Exit Code: Only included if non-zero (command failed).\n Error: Only included if a process-level error occurred (e.g., spawn failure).\n Signal: Only included if process was terminated by a signal.\n Background PIDs: Only included if background processes were started.\n Process Group PGID: Only included if available.",
|
|
"renderOutputAsMarkdown": false
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"id": "5c53d75b-97da-4152-8a68-e0860dcaa92f",
|
|
"timestamp": "2026-02-20T17:10:45.674Z",
|
|
"type": "gemini",
|
|
"content": "They're `let` variables in the same file; I'll find their definitions.",
|
|
"thoughts": [
|
|
{
|
|
"subject": "Tracing Variable Definitions",
|
|
"description": "I'm currently focused on locating the definitions of `let` variables within the same file. My next step will be to analyze how these variables are used after their definitions.",
|
|
"timestamp": "2026-02-20T17:10:45.525Z"
|
|
}
|
|
],
|
|
"tokens": {
|
|
"input": 39946,
|
|
"output": 60,
|
|
"cached": 3579,
|
|
"thoughts": 19,
|
|
"tool": 0,
|
|
"total": 40025
|
|
},
|
|
"model": "gemini-3-flash-preview",
|
|
"toolCalls": [
|
|
{
|
|
"id": "run_shell_command_1771607445671_0",
|
|
"name": "run_shell_command",
|
|
"args": {
|
|
"command": "grep -n \"let(:cluster1_plan_cmd_production_service)\" spec/integration/tests_local_configuration_spec.rb"
|
|
},
|
|
"result": [
|
|
{
|
|
"functionResponse": {
|
|
"id": "run_shell_command_1771607445671_0",
|
|
"name": "run_shell_command",
|
|
"response": {
|
|
"output": "Output: 2066: let(:cluster1_plan_cmd_production_service) do\nProcess Group PGID: 47447"
|
|
}
|
|
}
|
|
}
|
|
],
|
|
"status": "success",
|
|
"timestamp": "2026-02-20T17:10:47.799Z",
|
|
"resultDisplay": "2066: let(:cluster1_plan_cmd_production_service) do",
|
|
"displayName": "Shell",
|
|
"description": "This tool executes a given shell command as `bash -c <command>`. To run a command in the background, set the `is_background` parameter to true. Do NOT use `&` to background commands. Command is executed as a subprocess that leads its own process group. Command process group can be terminated as `kill -- -PGID` or signaled as `kill -s SIGNAL -- -PGID`.\n\n Efficiency Guidelines:\n - Quiet Flags: Always prefer silent or quiet flags (e.g., `npm install --silent`, `git --no-pager`) to reduce output volume while still capturing necessary information.\n - Pagination: Always disable terminal pagination to ensure commands terminate (e.g., use `git --no-pager`, `systemctl --no-pager`, or set `PAGER=cat`).\n\n The following information is returned:\n\n Output: Combined stdout/stderr. Can be `(empty)` or partial on error and for any unwaited background processes.\n Exit Code: Only included if non-zero (command failed).\n Error: Only included if a process-level error occurred (e.g., spawn failure).\n Signal: Only included if process was terminated by a signal.\n Background PIDs: Only included if background processes were started.\n Process Group PGID: Only included if available.",
|
|
"renderOutputAsMarkdown": false
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"id": "2b3a7c21-2b74-4451-a1dd-82a21fed1294",
|
|
"timestamp": "2026-02-20T17:10:50.072Z",
|
|
"type": "gemini",
|
|
"content": "I'll check the command string definitions.",
|
|
"thoughts": [
|
|
{
|
|
"subject": "Investigating Command Definitions",
|
|
"description": "I'm currently delving into the core definitions of these command strings. Specifically, I'm trying to unpack the meaning of each one to better understand its intended function. This should help me when I start to formulate my theory.",
|
|
"timestamp": "2026-02-20T17:10:49.994Z"
|
|
}
|
|
],
|
|
"tokens": {
|
|
"input": 40043,
|
|
"output": 37,
|
|
"cached": 39348,
|
|
"thoughts": 12,
|
|
"tool": 0,
|
|
"total": 40092
|
|
},
|
|
"model": "gemini-3-flash-preview",
|
|
"toolCalls": [
|
|
{
|
|
"id": "read_file_1771607450069_0",
|
|
"name": "read_file",
|
|
"args": {
|
|
"file_path": "spec/integration/tests_local_configuration_spec.rb",
|
|
"limit": 100,
|
|
"offset": 2066
|
|
},
|
|
"result": [
|
|
{
|
|
"functionResponse": {
|
|
"id": "read_file_1771607450069_0",
|
|
"name": "read_file",
|
|
"response": {
|
|
"output": "\nIMPORTANT: The file content has been truncated.\nStatus: Showing lines 2067-2166 of 3243 total lines.\nAction: To read more of the file, you can use the 'offset' and 'limit' parameters in a subsequent 'read_file' call. For example, to read the next section of the file, use offset: 2166.\n\n--- FILE CONTENT (truncated) ---\n terraform_plan_cmd(\n tfvar_arg_string(\n infrastructure_defaults.merge(\n \"instance_type\" => \"t2.medium\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"environment\" => \"production\",\n \"cluster_name\" => \"new-dedicated-cluster-production\",\n \"account_id\" => \"123456789012\",\n \"infrastructure_name\" => \"new-dedicated-cluster\",\n \"dalmatian_role\" => \"dalmatian-read\",\n \"service\" => {\n \"name\" => \"test-service\",\n \"blue_green\" => {\n \"production\" => {\n \"enabled\" => true,\n \"db_copy\" => {\n \"from_db_host_ps_key\" => \"/test-app/other-test-service/production/DB_HOST\",\n \"from_db_name_ps_key\" => \"/test-app/other-test-service/production/DB_NAME\",\n \"from_db_user_ps_key\" => \"/test-app/other-test-service/production/DB_USER\",\n \"from_db_pass_ps_key\" => \"/test-app/other-test-service/production/DB_PASSWORD\",\n \"blue_green_db_name_ps_key\" => \"/test-app/test-service/production/DB_HOST\",\n \"blue_green_db_user_ps_key\" => \"/test-app/test-service/production/DB_USER\",\n \"blue_green_db_pass_ps_key\" => \"/test-app/test-service/production/DB_PASSWORD\",\n \"sql_backups_s3_bucket\" => \"new-dedicated-cluster-testservice-production-sql-backup\"\n },\n \"db_rewrites\" => [\n {\n \"from\" => \"other-test-service.example.com\",\n \"to\" => \"test-service.example.com\"\n }\n ],\n \"directory_copy\" => [\n {\n \"from\" => \"/mnt/efs/other-test-service-media\",\n \"to\" => \"/mnt/efs/test-service-media\",\n \"chown\" => \"33:33\"\n }\n ],\n \"asset_copy_trigger_ps_key\" => \"/test-app/test-service/production/BLUE_GREEN_ASSET_COPY_TRIGGER\"\n },\n \"staging\" => {\n \"enabled\" => false\n }\n },\n \"launch_on\" => [\"production\", \"staging\"],\n \"launch_on_cluster\" => \"test\",\n \"cluster_min_servers\" => {\n \"production\" => \"2\",\n \"staging\" => \"2\"\n },\n \"parameter_store_path\" => {\n \"production\" => \"\",\n \"staging\" => \"/test-path\"\n },\n \"parameter_store_key\" => {\n \"production\" => \"\",\n \"staging\" => \"arn:aws:kms:eu-west-2:000000000000:key/00000000-0000-0000-0000-000000000000\"\n },\n \"daemon\" => false,\n \"monitoring\" => {\n \"production\" => {\n \"opsgenie_alerts\" => {\n \"enabled\" => true,\n \"cloudfront_5xx\" => {\n \"enabled\" => true,\n \"threshold\" => \"95\",\n \"evaluation_periods\" => \"15\"\n }\n },\n \"ghost_inspector\" => {\n \"enabled\" => true\n }\n },\n \"staging\" => {\n \"opsgenie_alerts\" => {\n \"enabled\" => false,\n \"cloudfront_5xx\" => {\n \"enabled\" => true,\n \"threshold\" => \"95\",\n \"evaluation_periods\" => \"15\"\n }\n },\n \"ghost_inspector\" => {\n \"enabled\" => false\n }\n }\n },\n \"cloudfront\" => {\n \"production\" => {\n \"create\" => true,\n \"managed_cache_policy\" => \"CachingDisabled\",\n \"managed_origin_policy\" => \"AllViewerExceptHostHeader\",\n \"managed_response_headers_policy\" => \"CORS-with-preflight-and-SecurityHeadersPolicy\",\n \"tls_protocol_version\" => \"TLSv1.2_2019\",\n \"origin_keepalive_timeout\" => \"60\",\n \"origin_read_timeout\" => \"60\",\n \"basic_auth\" => false,\n \"basic_auth_users_extra\" => {},\n \"viewer_request_functions\" => ["
|
|
}
|
|
}
|
|
}
|
|
],
|
|
"status": "success",
|
|
"timestamp": "2026-02-20T17:10:50.091Z",
|
|
"resultDisplay": "Read lines 2067-2166 of 3243 from spec/integration/tests_local_configuration_spec.rb",
|
|
"displayName": "ReadFile",
|
|
"description": "Reads and returns the content of a specified file. If the file is large, the content will be truncated. The tool's response will clearly indicate if truncation has occurred and will provide details on how to read more of the file using the 'offset' and 'limit' parameters. Handles text, images (PNG, JPG, GIF, WEBP, SVG, BMP), audio files (MP3, WAV, AIFF, AAC, OGG, FLAC), and PDF files. For text files, it can read specific line ranges.",
|
|
"renderOutputAsMarkdown": true
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"id": "51a21c06-bef7-4be2-82f0-acc94ac7af1f",
|
|
"timestamp": "2026-02-20T17:10:58.186Z",
|
|
"type": "gemini",
|
|
"content": "The error message indicates `TF_VAR_rds` is unexpectedly present and `infrastructure_name` is mismatched. `RdsDeployment#env_config` confirms `infrastructure_name` comes from `rds.cluster_id`. Since `Cluster#deploy` calls `deploy_rds` for each RDS instance, I'll examine `dalmatian.yml.example` to see the defined clusters and RDS configurations.",
|
|
"thoughts": [
|
|
{
|
|
"subject": "Observing Error Details",
|
|
"description": "I'm focusing now on the specifics of the error message. It seems the key issue revolves around `TF_VAR_rds` being present where it shouldn't be, according to \"expected\" versus \"got.\" I'll be re-examining failure 24 to see how this applies.",
|
|
"timestamp": "2026-02-20T17:10:52.580Z"
|
|
},
|
|
{
|
|
"subject": "Investigating the Discrepancy",
|
|
"description": "I'm now zeroing in on the `infrastructure_name` mismatch between \"expected\" and \"got\" in the error. This is a crucial clue. Looking at `spec/integration/tests_local_configuration_spec.rb`, I've identified the use of `new-dedicated-cluster` within the `cluster1_plan_cmd_production_service` definition. I'm going to carefully revisit the definitions, and then check failure one, since I am getting the sense that there are multiple failures with the same underlying root cause.",
|
|
"timestamp": "2026-02-20T17:10:54.923Z"
|
|
},
|
|
{
|
|
"subject": "Examining Variable Context",
|
|
"description": "I'm now revisiting the failure scenarios, focusing on the unexpected presence of `TF_VAR_rds`. The `infrastructure_name` discrepancy, specifically the switch from `existing-shared-cluster-production` to `new-dedicated-cluster`, is key. I'm linking this to the `RdsDeployment#env_config` and the way `rds.cluster_id` is defined. This leads me to believe the cause is likely rooted in how RDS deployments are configured and initialized. The `deploy` method in `lib/dalmatian/cluster.rb` is the next target for scrutiny, particularly the call to `rds.each`.",
|
|
"timestamp": "2026-02-20T17:10:57.949Z"
|
|
},
|
|
{
|
|
"subject": "Tracing Deployment Paths",
|
|
"description": "The root cause appears to be the `infrastructure_name` mismatch; it's being set to `new-dedicated-cluster` instead of the expected `existing-shared-cluster-production`. This is due to `rds.cluster_id` being used to set `infrastructure_name` within the `RdsDeployment#env_config` method. The `deploy` method in `lib/dalmatian/cluster.rb`, specifically the `rds.each` iteration, seems to be the trigger. I will now examine `dalmatian.yml.example` to understand how clusters and RDS are defined and initialized.",
|
|
"timestamp": "2026-02-20T17:10:57.985Z"
|
|
}
|
|
],
|
|
"tokens": {
|
|
"input": 41351,
|
|
"output": 104,
|
|
"cached": 39464,
|
|
"thoughts": 778,
|
|
"tool": 0,
|
|
"total": 42233
|
|
},
|
|
"model": "gemini-3-flash-preview",
|
|
"toolCalls": [
|
|
{
|
|
"id": "read_file_1771607458181_0",
|
|
"name": "read_file",
|
|
"args": {
|
|
"file_path": "dalmatian.yml.example"
|
|
},
|
|
"result": [
|
|
{
|
|
"functionResponse": {
|
|
"id": "read_file_1771607458181_0",
|
|
"name": "read_file",
|
|
"response": {
|
|
"output": "---\nparameter-store-path-prefix: /dalmatian-variables/\n\naccount-bootstrap:\n variables:\n region: eu-west-2\n root_domain_zone: dalmatian.dxw.net\n dalmatian_read_users:\n - Joe\n - Ashley\n dalmatian_admin_users:\n - Harper\n - Pat\n\nci:\n variables:\n region: eu-west-2\n prci_github_owner: dxw\n prci_github_repository: dalmatian\n prci_codebuild_image: thedxw/testing-terraform-docker:latest\n bpsp_source_branch: master\n bpbp_codebuild_compute_type: BUILD_GENERAL1_SMALL\n bpbp_codebuild_image: thedxw/testing-terraform-docker:latest\n\ninfrastructure-defaults:\n variables:\n region: eu-west-2\n cidr: 10.0.0.0/16\n root_domain_zone: dalmatian.dxw.net\n internal_domain_zone: dalmatian.internal\n ecs_private_subnets:\n - availability_zone: \"eu-west-2a\"\n cidr: 10.0.128.0/24\n - availability_zone: \"eu-west-2b\"\n cidr: 10.0.129.0/24\n - availability_zone: \"eu-west-2c\"\n cidr: 10.0.130.0/24\n extra_public_subnets:\n - availability_zone: eu-west-2a\n cidr: 10.0.0.0/24\n - availability_zone: eu-west-2b\n cidr: 10.0.1.0/24\n - availability_zone: eu-west-2c\n cidr: 10.0.2.0/24\n instances_key_name: dalmatian-ecs-instances\n instance_type: t2.medium\n min_servers: 2\n max_servers: 4\n max_instance_lifetime: 86400\n associate_public_ip_address: 0\n docker_storage_size: 40\n dockerhub_email: ''\n dockerhub_token: ''\n enable_efs: \"false\"\n encrypt_efs: true\n efs_dirs: []\n monitoring_docs_path: https://github.com/dxw/dalmatian/docs/monitoring-alarms/\n\ninfrastructures:\n new-dedicated-cluster:\n dalmatian_config_source:\n - git@github.com:dxw/awesome-app-dalmatian-config\n account_id: 123456789012\n vpn_customer_gateway:\n - name: test-vpn\n bgp_asn: 65000\n ip_address: 1.2.3.4\n s3:\n - name: 'test'\n enable_s3_versioning: true\n encrypted: true\n acl: 'private'\n policy:\n staging:\n rw:\n services:\n - test-service\n service_cloudfront_read_access:\n - test-service-staging\n cloudfront:\n create: true\n domain_names:\n - example.com\n - example2.com\n certificate: 'arn:aws:acm:lb-region-0:000000000000:certificate/00000000-0000-0000-0000-000000000000'\n hosted_zones:\n - domain: \"example-domain-name.com\"\n ns_records:\n - name: delegated\n value:\n - ns1.aws.com\n a_records:\n - name: some-service\n value:\n - 1.2.3.4\n - name: mail\n value:\n - 5.6.7.8\n alias_records:\n - name: example-domain-name.com\n value: cf-distribution.aws.net\n - name: www\n value: cf-distribution.aws.net\n cname_records:\n - name: alb\n value:\n - aws-alb.aws.net\n mx_records:\n - name: mail\n value:\n - 0 mail.example-domain-name.com\n txt_records:\n - name: mail\n value:\n - \"v=spf1 a ip4:9.10.11.0/24 mx ~all\"\n srv_records:\n - name: \"@\"\n value:\n - \"_imaps._tcp.gmail.com. 86400 IN SRV 5 0 993 imap.gmail.com\"\n cluster:\n create: true\n rds:\n - identifier: testservice\n in_use_by:\n - test-service\n engine: 'postgres'\n instance_class:\n staging: 'db.t2.micro'\n production: 'db.t2.small'\n engine_version: '11.4'\n allocated_storage: 20\n storage_encrypted: true\n storage_type: 'gp3'\n db_name: 'testapp'\n port: 5432\n maintenance_window: 'mon:19:00-mon:19:30'\n backup_window: '09:00-10:00'\n backup_retention_period: 31\n force_ssl: true\n parameter_store_path_db_url_name: 'DATABASE_URL'\n sql_backup_scheduled_task_environment_variables:\n - name: \"foo\"\n value: \"bar\"\n check_sql_backup_scheduled_task_environment_variables:\n - name: \"foo\"\n value: \"bar\"\n codebuild_access:\n - service-name\n elasticache_cluster:\n - identifier: testredis\n in_use_by:\n - test-service\n engine: 'redis'\n node_type: 'cache.t2.micro'\n node_count: 1\n engine: 'redis'\n engine_version: '5.0.6'\n port: 6379\n maintenance_window: 'mon:19:00-mon:22:00'\n snapshot_window: '09:00-10:00'\n parameter_store_path_elasticache_cluster_url_name: 'REDIS_URL'\n opensearch_cluster:\n - identifier: testos\n in_use_by:\n - test-service\n version: '1.2'\n master_enabled: true\n master_count: '1'\n master_type: 'c6g.large.search'\n instance_count: '3'\n instance_type: 't3.small.search'\n warm_enabled: true\n warm_count: '2'\n warm_type: 'ultrawarm1.medium.search'\n volume_size: '20'\n parameter_store_path_opensearch_cluster_url_name: 'ELASTICSEARCH_URL'\n services:\n - name: test-service\n blue_green:\n production:\n enabled: true\n db_copy:\n from_db_host_ps_key: /test-app/other-test-service/production/DB_HOST\n from_db_name_ps_key: /test-app/other-test-service/production/DB_NAME\n from_db_user_ps_key: /test-app/other-test-service/production/DB_USER\n from_db_pass_ps_key: /test-app/other-test-service/production/DB_PASSWORD\n blue_green_db_name_ps_key: /test-app/test-service/production/DB_HOST\n blue_green_db_user_ps_key: /test-app/test-service/production/DB_USER\n blue_green_db_pass_ps_key: /test-app/test-service/production/DB_PASSWORD\n sql_backups_s3_bucket: new-dedicated-cluster-testservice-production-sql-backup\n db_rewrites:\n - from: other-test-service.example.com\n to: test-service.example.com\n directory_copy:\n - from: /mnt/efs/other-test-service-media\n to: /mnt/efs/test-service-media\n chown: \"33:33\"\n asset_copy_trigger_ps_key: /test-app/test-service/production/BLUE_GREEN_ASSET_COPY_TRIGGER\n staging:\n enabled: false\n launch_on:\n - production\n - staging\n launch_on_cluster: \"test\"\n monitoring:\n production:\n opsgenie_alerts:\n enabled: true\n cloudfront_5xx:\n enabled: true\n threshold: \"95\"\n evaluation_periods: \"15\"\n staging:\n opsgenie_alerts:\n enabled: false\n ghost_inspector:\n enabled: false\n parameter_store_path:\n staging: '/test-path'\n parameter_store_key:\n staging: 'arn:aws:kms:eu-west-2:000000000000:key/00000000-0000-0000-0000-000000000000'\n container_count: \"2\"\n enable_max_one_container_per_instance: true\n cloudfront:\n create: true\n managed_cache_policy: \"CachingDisabled\"\n managed_origin_policy: \"AllViewerExceptHostHeader\"\n managed_response_headers_policy: \"CORS-with-preflight-and-SecurityHeadersPolicy\"\n tls_protocol_version:\n production: 'TLSv1.2_2019'\n staging: 'TLSv1.2_2021'\n bypass_protection:\n production:\n enabled: true\n exclude_domains:\n - example.com\n origin_keepalive_timeout:\n staging: \"10\"\n production: \"60\"\n origin_read_timeout:\n staging: \"40\"\n production: \"60\"\n basic_auth:\n staging: true\n viewer_request_functions:\n - name: 'default'\n true_client_ip_header: true\n ip_subnet_allow_list:\n - '0.0.0.0/0'\n redirects:\n - from_hostname_pattern: example-old-domain-name.*\n from_path_pattern: /*\n to_hostname: example-domain-name.co.uk\n to_path: /${path}\n offline_page_http_status:\n 500: \"/error-pages/500.html\"\n 501: \"/error-pages/501.html\"\n 502: \"/error-pages/502.html\"\n 503: \"/error-pages/503.html\"\n 504: \"/error-pages/504.html\"\n custom_origins:\n staging:\n - origin: test-media-staging.s3.amazonaws.com\n id: test-media-staging-s3\n production:\n - origin: test-media-production.s3.amazonaws.com\n id: test-media-production-s3\n custom_behaviors:\n staging:\n - path_patterns:\n - '/media/*'\n target_origin_id: test-media-staging-s3\n min_ttl: 1200\n default_ttl: 3600\n max_ttl: 86400\n associate_viewer_request_function: \"default\"\n production:\n - path_patterns:\n - '/media/*'\n target_origin_id: test-media-production-s3\n min_ttl: 1200\n default_ttl: 3600\n max_ttl: 86400\n associate_viewer_request_function: \"default\"\n managed_cache_policy: \"CachingDisabled\"\n managed_origin_policy: \"AllViewerExceptHostHeader\"\n managed_response_headers_policy: \"CORS-with-preflight-and-SecurityHeadersPolicy\"\n lb_ip_whitelist:\n - name: public\n cidr: 0.0.0.0/0\n lb_idle_timeout: '60'\n global_accelerator:\n production: true\n health_check_path: '/check'\n health_check_grace_period: '0'\n serve_from_subdirectory: \"/test-subdir\"\n domain_names:\n staging:\n - example-domain-name.co.uk\n lb_ssl_certificate:\n staging: 'arn:aws:acm:lb-region-0:000000000000:certificate/00000000-0000-0000-0000-000000000000'\n cloudfront_ssl_certificate:\n staging: 'arn:aws:acm:us-east-1:000000000000:certificate/00000000-0000-0000-0000-000000000000'\n image_source: build_from_github_repo\n image_location: git@github.com:dxw/dalmatian-test-app\n custom_codestar_connection_arn: \"arn:aws:codestar-connections:eu-west-2:000000000000:connection/00000000-0000-0000-0000-000000000000\"\n buildspec: 'buildspec.yml'\n container_port: 3100\n container_command: [\"/docker-entrypoint.sh\", \"rails\", \"server\"]\n container_volumes:\n - name: test-volume\n host_path: /mnt/test\n container_path: /test\n container_extra_hosts:\n - hostname: \"example.com\"\n ipAddress: \"127.0.0.1\"\n scheduled_tasks:\n - name: old-scheduled-task\n command: [\"rake\", \"do:cron\"]\n schedule_expression: \"cron(0 4 * * ? *)\"\n - name: test-scheduled-task\n command: [\"rake\", \"do:something\"]\n schedule_expression:\n staging: \"cron(0 12 * * ? *)\"\n production: \"cron(1 2 * * ? *)\"\n workers:\n - name: test-worker\n command: [\"bundle\", \"exec\", sidekiq]\n proxy_configuration:\n staging:\n https_proxy: \"dalmatian_tinyproxy\"\n http_proxy: \"http://my.test-proxy.com:8888\"\n no_proxy:\n - \"*.example.com\"\n - \"93.184.216.34/32\"\n home_directory: \"/home/user\"\n shared_loadbalancer:\n - name: test-lb-1\n idle_timeout: '60'\n global_accelerator:\n production: true\n staging: false\n in_use_by:\n - test-service\n waf:\n - name: test-1\n action: \"count\"\n aws_managed_rules:\n - name: 'AWSManagedRulesSQLiRuleSet'\n excluded_path_patterns:\n - \"/wp-admin/async-upload.php\"\n - name: 'AWSManagedRulesCommonRuleSet'\n exclude_rules:\n - 'SizeRestrictions_BODY'\n associations:\n shared_loadbalancers:\n - \"test-lb-1\"\n service_cloudfront:\n - \"test-service\"\n environments:\n production:\n instance_type: t2.medium\n min_servers: 2\n max_servers: 4\n staging:\n instance_type: t2.small\n min_servers: 2\n max_servers: 4\n track_revision: feature/experiment\n extra_ecs_clusters:\n - name: \"test\"\n subnets_name: \"extra_private_subnets\"\n min_servers: \"2\"\n max_servers: \"4\"\n instance_type: \"t3.small\"\n tinyproxy:\n create: true\n\n shared-new-cluster:\n account_id: 123456789012\n cluster:\n create: true\n environments:\n production:\n instance_type: t2.medium\n min_servers: 2\n max_servers: 10\n staging:\n instance_type: t2.small\n min_servers: 2\n max_servers: 10\n\n existing-shared-cluster-staging:\n dalmatian_config_source:\n - git@github.com:dxw/funky-app-dalmatian-config\n account_id: 123456789012\n cluster:\n create: false\n name: shared-cluster\n environments:\n staging:\n example_var: foo\n\n existing-shared-cluster-production:\n dalmatian_config_source:\n - git@github.com:dxw/neat-app-dalmatian-config\n account_id: 123456789012\n cluster:\n create: false\n name: shared-cluster\n environments:\n production:\n example_var: bar\n"
|
|
}
|
|
}
|
|
}
|
|
],
|
|
"status": "success",
|
|
"timestamp": "2026-02-20T17:10:58.209Z",
|
|
"resultDisplay": "",
|
|
"displayName": "ReadFile",
|
|
"description": "Reads and returns the content of a specified file. If the file is large, the content will be truncated. The tool's response will clearly indicate if truncation has occurred and will provide details on how to read more of the file using the 'offset' and 'limit' parameters. Handles text, images (PNG, JPG, GIF, WEBP, SVG, BMP), audio files (MP3, WAV, AIFF, AAC, OGG, FLAC), and PDF files. For text files, it can read specific line ranges.",
|
|
"renderOutputAsMarkdown": true
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"id": "d9dd9444-dff6-4c9b-916e-e5d87adfec27",
|
|
"timestamp": "2026-02-20T17:11:01.931Z",
|
|
"type": "gemini",
|
|
"content": "`new-dedicated-cluster` includes an `rds` section, but `existing-shared-cluster-production` does not. `Cluster#deploy` iterates over `rds` to deploy them, so I'll check how `rds` is initialized in the `Cluster` class.",
|
|
"thoughts": [
|
|
{
|
|
"subject": "Inspecting Configurations",
|
|
"description": "I'm currently focused on the configuration files. I've noted the presence of an `rds` section in `new-dedicated-cluster`, but it's absent in the `existing-shared-cluster-production` example. Now I'm delving into `lib/dalmatian/cluster.rb` to understand how these configurations are handled.",
|
|
"timestamp": "2026-02-20T17:11:00.911Z"
|
|
},
|
|
{
|
|
"subject": "Analyzing the RDS Section",
|
|
"description": "I'm now examining how the `rds` attribute is initialized within the `Cluster` class. It appears to be iterated over during the deploy process, as anticipated. This confirms my initial observations about the different configurations. My next step will be to pinpoint the exact logic determining whether or not the `rds` section is populated.",
|
|
"timestamp": "2026-02-20T17:11:01.790Z"
|
|
}
|
|
],
|
|
"tokens": {
|
|
"input": 45843,
|
|
"output": 83,
|
|
"cached": 39335,
|
|
"thoughts": 174,
|
|
"tool": 0,
|
|
"total": 46100
|
|
},
|
|
"model": "gemini-3-flash-preview",
|
|
"toolCalls": [
|
|
{
|
|
"id": "read_file_1771607461927_0",
|
|
"name": "read_file",
|
|
"args": {
|
|
"file_path": "lib/dalmatian/cluster.rb",
|
|
"limit": 100,
|
|
"offset": 0
|
|
},
|
|
"result": [
|
|
{
|
|
"functionResponse": {
|
|
"id": "read_file_1771607461927_0",
|
|
"name": "read_file",
|
|
"response": {
|
|
"output": "\nIMPORTANT: The file content has been truncated.\nStatus: Showing lines 1-100 of 395 total lines.\nAction: To read more of the file, you can use the 'offset' and 'limit' parameters in a subsequent 'read_file' call. For example, to read the next section of the file, use offset: 100.\n\n--- FILE CONTENT (truncated) ---\nmodule Dalmatian\n class Cluster\n def initialize(description, helper: Helper, logger: Logger)\n properties = description.last\n @id = description.first\n @account_id = properties[\"account_id\"]\n @environments = properties[\"environments\"]\n @properties = properties[\"cluster\"]\n @logger = logger\n @helper = helper\n @hosted_zones = build_hosted_zones(properties[\"hosted_zones\"])\n @s3s = build_s3s(properties[\"s3\"])\n @vpn_customer_gateways = build_vpn_customer_gateways(properties[\"vpn_customer_gateway\"])\n @sources = build_sources(properties[\"dalmatian_config_source\"])\n @services = build_services(properties[\"services\"])\n @wafs = build_wafs(properties[\"waf\"])\n @rdss = build_rdss(properties[\"rds\"])\n @auroras = build_auroras(properties[\"aurora\"])\n @elasticache_clusters = build_elasticache_clusters(properties[\"elasticache_cluster\"])\n @opensearch_clusters = build_opensearch_clusters(properties[\"opensearch_cluster\"])\n @shared_loadbalancers = build_shared_loadbalancers(properties[\"shared_loadbalancer\"])\n end\n\n attr_reader :hosted_zones, :s3s, :vpn_customer_gateways, :sources, :services, :wafs, :rdss, :auroras, :elasticache_clusters,\n :opensearch_clusters, :shared_loadbalancers, :environments, :properties, :account_id, :id\n\n def name\n properties[\"name\"] || id\n end\n\n def fetch(infrastructure_name: \"all\")\n sources.each do |source|\n next unless [\"all\", source.cluster_id].include? infrastructure_name\n\n return verify_source_path(source) unless remotely_held?(source)\n\n destination = \"#{Infrastructure::PATH}/#{source.name}.config\"\n fetch_source(source, destination)\n end\n end\n\n def deploy(environment_name: \"all\", service_name: \"all\", skip_deployments: \"\", test: false, auto_approve: false, plan: false, destroy: false, verbose: false)\n skip_deployments = skip_deployments.split(/\\s*,\\s*/)\n hosted_zones.each do |hosted_zone|\n unless skip_deployments.include?(\"hosted-zone\")\n deploy_hosted_zone(hosted_zone, test, auto_approve, plan, destroy, verbose)\n end\n end\n s3s.each do |s3|\n unless skip_deployments.include?(\"s3\")\n deploy_s3(s3, test, auto_approve, plan, destroy, verbose)\n end\n end\n vpn_customer_gateways.each do |vpn_customer_gateway|\n unless skip_deployments.include?(\"vpn-customer-gateway\")\n deploy_vpn_customer_gateway(vpn_customer_gateway, test, auto_approve, plan, destroy, verbose)\n end\n end\n environments.each do |name, details|\n next unless [\"all\", name].include?(environment_name)\n environment = {name: name, details: details}\n deploy_cluster(environment, test, auto_approve, plan, destroy, verbose) if create? && !skip_deployments.include?(\"ecs\")\n wafs.each do |waf|\n unless skip_deployments.include?(\"waf\")\n deploy_waf(waf, environment, test, auto_approve, plan, destroy, verbose)\n end\n end\n rdss.each do |rds|\n unless skip_deployments.include?(\"rds\")\n deploy_rds(rds, environment, test, auto_approve, plan, destroy, verbose)\n end\n end\n auroras.each do |aurora|\n unless skip_deployments.include?(\"aurora\")\n deploy_aurora(aurora, environment, test, auto_approve, plan, destroy, verbose)\n end\n end\n elasticache_clusters.each do |elasticache_cluster|\n unless skip_deployments.include?(\"elasticache-cluster\")\n deploy_elasticache_cluster(elasticache_cluster, environment, test, auto_approve, plan, destroy, verbose)\n end\n end\n opensearch_clusters.each do |opensearch_cluster|\n unless skip_deployments.include?(\"opensearch-cluster\")\n deploy_opensearch_cluster(opensearch_cluster, environment, test, auto_approve, plan, destroy, verbose)\n end\n end\n services.each do |service|\n next unless service.to_params[\"launch_on\"].include?(name)\n if [service.to_params[\"name\"], \"all\"].include?(service_name) && !skip_deployments.include?(\"ecs-services\")\n deploy_service(service, environment, test, auto_approve, plan, destroy, verbose)\n end\n end\n shared_loadbalancers.each do |shared_loadbalancer|\n unless skip_deployments.include?(\"shared-loadbalancer\")\n deploy_shared_loadbalancer(shared_loadbalancer, environment, test, auto_approve, plan, destroy, verbose)\n end\n end\n sources.each do |source|\n deploy_source(source, environment, test, auto_approve, plan, destroy, verbose)"
|
|
}
|
|
}
|
|
}
|
|
],
|
|
"status": "success",
|
|
"timestamp": "2026-02-20T17:11:01.953Z",
|
|
"resultDisplay": "Read lines 1-100 of 395 from lib/dalmatian/cluster.rb",
|
|
"displayName": "ReadFile",
|
|
"description": "Reads and returns the content of a specified file. If the file is large, the content will be truncated. The tool's response will clearly indicate if truncation has occurred and will provide details on how to read more of the file using the 'offset' and 'limit' parameters. Handles text, images (PNG, JPG, GIF, WEBP, SVG, BMP), audio files (MP3, WAV, AIFF, AAC, OGG, FLAC), and PDF files. For text files, it can read specific line ranges.",
|
|
"renderOutputAsMarkdown": true
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"id": "32ce884a-852e-4b6c-b37a-fb599e55634f",
|
|
"timestamp": "2026-02-20T17:11:09.180Z",
|
|
"type": "gemini",
|
|
"content": "`deploy_rds` is being called for `new-dedicated-cluster`, but the test `passes the services config to \"terraform plan\"` fails because `Helper.run!` receives unstubbed arguments. The `before` block stubs `cluster1_plan_cmd_production_rds`, but the \"got\" command has `infrastructure_name='new-dedicated-cluster'`, so I need to check the definition of `cluster1_plan_cmd_production_rds` to see if it matches.",
|
|
"thoughts": [
|
|
{
|
|
"subject": "Debugging the Deployment Issue",
|
|
"description": "I'm zeroing in on the deployment glitch. It seems `deploy_rds` is unexpectedly kicking in for `new-dedicated-cluster`. To understand the shift, I'm diving into the code changes. I'll use `git log -p` to hunt down the culprit or simply read the code.",
|
|
"timestamp": "2026-02-20T17:11:04.414Z"
|
|
},
|
|
{
|
|
"subject": "Unpacking the Root Cause",
|
|
"description": "I've traced the deployment issue. The error's due to the test suite, specifically `tests_local_configuration_spec.rb`, now passing an RDS config for `new-dedicated-cluster` when calling `terraform plan`. The test expects this for service deployment, but `existing-shared-cluster-production` (which the test likely uses) lacks RDS, thus revealing the unexpected call.",
|
|
"timestamp": "2026-02-20T17:11:06.007Z"
|
|
},
|
|
{
|
|
"subject": "Revisiting Test Expectations",
|
|
"description": "Okay, I've confirmed that the test suite expects an RDS configuration in `terraform plan`, which explains the failure. I'm focusing on the discrepancy between the test's expectations for `new-dedicated-cluster` and the actual arguments passed to `Helper.run!`. I need to figure out why the RDS configuration is being included in the command. I'll carefully examine the interactions with `deploy_rds` and related configurations, to ensure that the test is appropriately configured.",
|
|
"timestamp": "2026-02-20T17:11:09.031Z"
|
|
},
|
|
{
|
|
"subject": "Examining Command Construction",
|
|
"description": "I'm now investigating the construction of the command, specifically `cluster1_plan_cmd_production_rds`. I need to figure out why the RDS-related arguments are included, triggering the unexpected call to `deploy_rds` for `new-dedicated-cluster`. I will compare the arguments in the test against the actual arguments passed to `Helper.run!` to understand the root cause. My focus is on the configurations related to RDS, the test expectations, and the interactions with `deploy_service`.",
|
|
"timestamp": "2026-02-20T17:11:09.052Z"
|
|
}
|
|
],
|
|
"tokens": {
|
|
"input": 47292,
|
|
"output": 146,
|
|
"cached": 39335,
|
|
"thoughts": 707,
|
|
"tool": 0,
|
|
"total": 48145
|
|
},
|
|
"model": "gemini-3-flash-preview",
|
|
"toolCalls": [
|
|
{
|
|
"id": "run_shell_command_1771607469172_0",
|
|
"name": "run_shell_command",
|
|
"args": {
|
|
"command": "grep -n \"let(:cluster1_plan_cmd_production_rds)\" spec/integration/tests_local_configuration_spec.rb"
|
|
},
|
|
"result": [
|
|
{
|
|
"functionResponse": {
|
|
"id": "run_shell_command_1771607469172_0",
|
|
"name": "run_shell_command",
|
|
"response": {
|
|
"output": "Output: 1719: let(:cluster1_plan_cmd_production_rds) do\nProcess Group PGID: 47671"
|
|
}
|
|
}
|
|
}
|
|
],
|
|
"status": "success",
|
|
"timestamp": "2026-02-20T17:12:43.005Z",
|
|
"resultDisplay": "1719: let(:cluster1_plan_cmd_production_rds) do",
|
|
"displayName": "Shell",
|
|
"description": "This tool executes a given shell command as `bash -c <command>`. To run a command in the background, set the `is_background` parameter to true. Do NOT use `&` to background commands. Command is executed as a subprocess that leads its own process group. Command process group can be terminated as `kill -- -PGID` or signaled as `kill -s SIGNAL -- -PGID`.\n\n Efficiency Guidelines:\n - Quiet Flags: Always prefer silent or quiet flags (e.g., `npm install --silent`, `git --no-pager`) to reduce output volume while still capturing necessary information.\n - Pagination: Always disable terminal pagination to ensure commands terminate (e.g., use `git --no-pager`, `systemctl --no-pager`, or set `PAGER=cat`).\n\n The following information is returned:\n\n Output: Combined stdout/stderr. Can be `(empty)` or partial on error and for any unwaited background processes.\n Exit Code: Only included if non-zero (command failed).\n Error: Only included if a process-level error occurred (e.g., spawn failure).\n Signal: Only included if process was terminated by a signal.\n Background PIDs: Only included if background processes were started.\n Process Group PGID: Only included if available.",
|
|
"renderOutputAsMarkdown": false
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"id": "9799e206-aa75-4402-a913-3056b9a39420",
|
|
"timestamp": "2026-02-20T17:12:45.005Z",
|
|
"type": "gemini",
|
|
"content": "Reading.",
|
|
"thoughts": [
|
|
{
|
|
"subject": "Analyzing the Text",
|
|
"description": "I'm currently immersed in the text, carefully dissecting its structure and nuances. The initial read-through has given me a basic grasp of the concepts. Now I'm focused on identifying the key arguments and their supporting evidence.",
|
|
"timestamp": "2026-02-20T17:12:44.888Z"
|
|
}
|
|
],
|
|
"tokens": {
|
|
"input": 47475,
|
|
"output": 30,
|
|
"cached": 45888,
|
|
"thoughts": 3,
|
|
"tool": 0,
|
|
"total": 47508
|
|
},
|
|
"model": "gemini-3-flash-preview",
|
|
"toolCalls": [
|
|
{
|
|
"id": "read_file_1771607564995_0",
|
|
"name": "read_file",
|
|
"args": {
|
|
"limit": 100,
|
|
"offset": 1719,
|
|
"file_path": "spec/integration/tests_local_configuration_spec.rb"
|
|
},
|
|
"result": [
|
|
{
|
|
"functionResponse": {
|
|
"id": "read_file_1771607564995_0",
|
|
"name": "read_file",
|
|
"response": {
|
|
"output": "\nIMPORTANT: The file content has been truncated.\nStatus: Showing lines 1720-1819 of 3243 total lines.\nAction: To read more of the file, you can use the 'offset' and 'limit' parameters in a subsequent 'read_file' call. For example, to read the next section of the file, use offset: 1819.\n\n--- FILE CONTENT (truncated) ---\n terraform_plan_cmd(\n tfvar_arg_string(\n infrastructure_defaults.merge(\n \"instance_type\" => \"t2.medium\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"environment\" => \"production\",\n \"account_id\" => \"123456789012\",\n \"infrastructure_name\" => \"new-dedicated-cluster\",\n \"dalmatian_role\" => \"dalmatian-read\",\n \"rds\" => {\n \"identifier\" => \"testservice\",\n \"in_use_by\" => [\n \"test-service\"\n ],\n \"clusters_in_use\" => {\n \"production\" => [\n \"test\"\n ],\n \"staging\" => [\n \"test\"\n ]\n },\n \"instance_class\" => {\n \"production\" => \"db.t2.small\",\n \"staging\" => \"db.t2.micro\"\n },\n \"engine\" => \"postgres\",\n \"engine_version\" => \"11.4\",\n \"allocated_storage\" => 20,\n \"storage_encrypted\" => true,\n \"storage_type\" => \"gp3\",\n \"db_name\" => \"testapp\",\n \"port\" => 5432,\n \"maintenance_window\" => \"mon:19:00-mon:19:30\",\n \"backup_window\" => \"09:00-10:00\",\n \"backup_retention_period\" => 31,\n \"force_ssl\" => true,\n \"parameter_store_path_db_url_name\" => \"DATABASE_URL\",\n \"sql_backup_scheduled_task_environment_variables\" => [\n {\n \"name\" => \"foo\",\n \"value\" => \"bar\"\n }\n ],\n \"check_sql_backup_scheduled_task_environment_variables\" => [\n {\n \"name\" => \"foo\",\n \"value\" => \"bar\"\n }\n ],\n \"sync_sql_backup_to_azure\" => false,\n \"codebuild_access\" => [\n \"service-name\"\n ]\n }\n )\n )\n )\n end\n\n let(:cluster1_plan_cmd_staging_waf) do\n terraform_plan_cmd(\n tfvar_arg_string(\n infrastructure_defaults.merge(\n \"instance_type\" => \"t2.small\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"track_revision\" => \"feature/experiment\",\n \"extra_ecs_clusters\" => [\n {\n \"name\" => \"test\",\n \"subnets_name\" => \"extra_private_subnets\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"instance_type\" => \"t3.small\"\n }\n ],\n \"tinyproxy\" => {\n \"create\" => true\n },\n \"environment\" => \"staging\",\n \"account_id\" => \"123456789012\",\n \"infrastructure_name\" => \"new-dedicated-cluster\",\n \"dalmatian_role\" => \"dalmatian-read\",\n \"waf\" => {\n \"name\" => \"test-1\",\n \"action\" => \"count\",\n \"ip_deny_list\" => [],\n \"aws_managed_rules\" => [\n {\n \"name\" => \"AWSManagedRulesSQLiRuleSet\",\n \"excluded_path_patterns\" => [\n \"/wp-admin/async-upload.php\"\n ]\n },\n {\n \"name\" => \"AWSManagedRulesCommonRuleSet\",\n \"exclude_rules\" => [\n \"SizeRestrictions_BODY\""
|
|
}
|
|
}
|
|
}
|
|
],
|
|
"status": "success",
|
|
"timestamp": "2026-02-20T17:12:45.029Z",
|
|
"resultDisplay": "Read lines 1720-1819 of 3243 from spec/integration/tests_local_configuration_spec.rb",
|
|
"displayName": "ReadFile",
|
|
"description": "Reads and returns the content of a specified file. If the file is large, the content will be truncated. The tool's response will clearly indicate if truncation has occurred and will provide details on how to read more of the file using the 'offset' and 'limit' parameters. Handles text, images (PNG, JPG, GIF, WEBP, SVG, BMP), audio files (MP3, WAV, AIFF, AAC, OGG, FLAC), and PDF files. For text files, it can read specific line ranges.",
|
|
"renderOutputAsMarkdown": true
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"id": "a938daf5-fbbc-4bc5-9af8-3e00b730d94a",
|
|
"timestamp": "2026-02-20T17:13:28.051Z",
|
|
"type": "gemini",
|
|
"content": "`cluster1_plan_cmd_production_rds` includes `infrastructure_defaults`, but the \"got\" RDS command has extra parameters: `replication_bucket_destination_arn` and `replication_kms_key_id`. I'll check `lib/dalmatian/rds.rb` to see how these parameters are being generated.",
|
|
"thoughts": [
|
|
{
|
|
"subject": "Analyzing Configuration Differences",
|
|
"description": "I'm now focusing on discrepancies between the `cluster1_plan_cmd_production_rds` and the configuration of `infrastructure_defaults`. I see a crucial merge operation happening, which explains how some defaults are applied. I'm also examining the `new-dedicated-cluster` config, specifically the `rds` section and its identifiers.",
|
|
"timestamp": "2026-02-20T17:13:06.189Z"
|
|
},
|
|
{
|
|
"subject": "Pinpointing Configuration Sources",
|
|
"description": "I'm now tracing the configuration values. It appears `infrastructure_defaults` are merged and I see the crucial identifiers in `new-dedicated-cluster`. Examining the final RDS deployment command, I note differences between `cluster1_plan_cmd_production_rds` and the actual values. Specifically, the presence of `replication_bucket_destination_arn` and `replication_kms_key_id` in the command output raises questions about their source, which I will now check in `lib/dalmatian/rds.rb`.",
|
|
"timestamp": "2026-02-20T17:13:17.888Z"
|
|
},
|
|
{
|
|
"subject": "Identifying Parameter Origin",
|
|
"description": "I've noted that `cluster1_plan_cmd_production_rds` doesn't define the `region` or some other `infrastructure_defaults`. It's clear that a merge happens there. The `new-dedicated-cluster` config uses identifiers, specifically for `rds`. More investigation: `replication_bucket_destination_arn` and `replication_kms_key_id` appear in the final command output, though missing in `cluster1_plan_cmd_production_rds`. I am now checking `lib/dalmatian/rds.rb` to find the source of these variables.",
|
|
"timestamp": "2026-02-20T17:13:27.865Z"
|
|
}
|
|
],
|
|
"tokens": {
|
|
"input": 48544,
|
|
"output": 92,
|
|
"cached": 35380,
|
|
"thoughts": 465,
|
|
"tool": 0,
|
|
"total": 49101
|
|
},
|
|
"model": "gemini-3-flash-preview",
|
|
"toolCalls": [
|
|
{
|
|
"id": "read_file_1771607608042_0",
|
|
"name": "read_file",
|
|
"args": {
|
|
"file_path": "lib/dalmatian/rds.rb"
|
|
},
|
|
"result": [
|
|
{
|
|
"functionResponse": {
|
|
"id": "read_file_1771607608042_0",
|
|
"name": "read_file",
|
|
"response": {
|
|
"output": "module Dalmatian\n class Rds\n def initialize(cluster:, reference:)\n @cluster = cluster\n @reference = reference\n end\n\n attr_reader :cluster, :reference\n\n def identifier\n reference[\"identifier\"]\n end\n\n def in_use_by\n reference[\"in_use_by\"] || []\n end\n\n def clusters_in_use\n clusters_in_use = {}\n cluster_environments.each do |env_name, _env_config|\n clusters_in_use[env_name] = []\n services.each do |service|\n in_use_by.each do |service_name|\n next if service.name != service_name\n clusters_in_use[env_name] << if service.launch_on_cluster.empty?\n \"default_dalmatian_ecs_cluster\"\n else\n service.launch_on_cluster\n end\n end\n end\n if in_use_by.empty?\n clusters_in_use[env_name] << \"default_dalmatian_ecs_cluster\" ## fails SimpleCov\n end\n clusters_in_use[env_name] = clusters_in_use[env_name].uniq\n end\n clusters_in_use\n end\n\n def instance_class\n instance_class = {}\n reference[\"instance_class\"] = {} if reference[\"instance_class\"].nil?\n cluster_environments.each do |env_name, _env_config|\n instance_class[env_name] = reference[\"instance_class\"][env_name] || \"\"\n end\n instance_class\n end\n\n def engine\n reference[\"engine\"]\n end\n\n def engine_version\n reference[\"engine_version\"]\n end\n\n def allocated_storage\n reference[\"allocated_storage\"] || \"\"\n end\n\n def storage_encrypted\n reference[\"storage_encrypted\"].nil? || reference[\"storage_encrypted\"]\n end\n\n def storage_type\n reference[\"storage_type\"] || \"gp3\"\n end\n\n def db_name\n reference[\"db_name\"]\n end\n\n def port\n reference[\"port\"] || \"\"\n end\n\n def maintenance_window\n reference[\"maintenance_window\"] || \"\"\n end\n\n def backup_window\n reference[\"backup_window\"] || \"\"\n end\n\n def backup_retention_period\n reference[\"backup_retention_period\"] || \"\"\n end\n\n def force_ssl\n reference[\"force_ssl\"] || \"false\"\n end\n\n def parameter_store_path_db_url_name\n reference[\"parameter_store_path_db_url_name\"] || \"\"\n end\n\n def sql_backup_scheduled_task_environment_variables\n reference[\"sql_backup_scheduled_task_environment_variables\"] || []\n end\n\n def check_sql_backup_scheduled_task_environment_variables\n reference[\"check_sql_backup_scheduled_task_environment_variables\"] || []\n end\n\n def sync_sql_backup_to_azure\n reference[\"sync_sql_backup_to_azure\"] || false\n end\n\n def replication_bucket_destination_arn\n reference[\"replication_bucket_destination_arn\"] || \"\"\n end\n\n def replication_kms_key_id\n reference[\"replication_kms_key_id\"] || \"\"\n end\n\n def codebuild_access\n reference[\"codebuild_access\"] || []\n end\n\n def cluster_id\n cluster.id\n end\n\n def cluster_environments\n cluster.environments\n end\n\n def account_id\n cluster.account_id\n end\n\n def services\n cluster.services\n end\n\n def to_params\n {\n \"identifier\" => identifier,\n \"in_use_by\" => in_use_by,\n \"clusters_in_use\" => clusters_in_use,\n \"instance_class\" => instance_class,\n \"engine\" => engine,\n \"engine_version\" => engine_version,\n \"allocated_storage\" => allocated_storage,\n \"storage_encrypted\" => storage_encrypted,\n \"storage_type\" => storage_type,\n \"db_name\" => db_name,\n \"port\" => port,\n \"maintenance_window\" => maintenance_window,\n \"backup_window\" => backup_window,\n \"backup_retention_period\" => backup_retention_period,\n \"force_ssl\" => force_ssl,\n \"parameter_store_path_db_url_name\" => parameter_store_path_db_url_name,\n \"sql_backup_scheduled_task_environment_variables\" => sql_backup_scheduled_task_environment_variables,\n \"check_sql_backup_scheduled_task_environment_variables\" => check_sql_backup_scheduled_task_environment_variables,\n \"sync_sql_backup_to_azure\" => sync_sql_backup_to_azure,\n \"replication_bucket_destination_arn\" => replication_bucket_destination_arn,\n \"replication_kms_key_id\" => replication_kms_key_id,\n \"codebuild_access\" => codebuild_access\n }\n end\n end\nend\n"
|
|
}
|
|
}
|
|
}
|
|
],
|
|
"status": "success",
|
|
"timestamp": "2026-02-20T17:13:28.073Z",
|
|
"resultDisplay": "",
|
|
"displayName": "ReadFile",
|
|
"description": "Reads and returns the content of a specified file. If the file is large, the content will be truncated. The tool's response will clearly indicate if truncation has occurred and will provide details on how to read more of the file using the 'offset' and 'limit' parameters. Handles text, images (PNG, JPG, GIF, WEBP, SVG, BMP), audio files (MP3, WAV, AIFF, AAC, OGG, FLAC), and PDF files. For text files, it can read specific line ranges.",
|
|
"renderOutputAsMarkdown": true
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"id": "127365e0-8ec7-452a-b0d1-add4135b63e5",
|
|
"timestamp": "2026-02-20T17:13:40.985Z",
|
|
"type": "gemini",
|
|
"content": "`replication_bucket_destination_arn` and `replication_kms_key_id` were added to `to_params` but are missing from test expectations. Failure 24 shows an unexpected `infrastructure_name` and `rds` variable. `Infrastructure.new.test` deploys all infrastructures, so `deploy_rds` is called before `deploy_service`, causing a failure because it's not correctly stubbed. I need to find which `let` variable corresponds to `existing-shared-cluster-production` in `spec/integration/tests_local_configuration_spec.rb`.",
|
|
"thoughts": [
|
|
{
|
|
"subject": "Reviewing Recent Updates",
|
|
"description": "The addition of `replication_bucket_destination_arn` and `replication_kms_key_id` to `to_params` is clear now. Their default values being empty strings explains the test failures. I'll need to update the tests to account for these new parameters.",
|
|
"timestamp": "2026-02-20T17:13:30.348Z"
|
|
},
|
|
{
|
|
"subject": "Tracing Test Failures",
|
|
"description": "I'm now diving into the specifics of failure 24, trying to understand why the \"terraform plan\" command is incorrect. The stack trace points to `deploy_rds`, which is where things are going wrong. It appears the `rds` deployment is incorrectly including the new `replication` parameters, even though the test was expecting a different command structure. My next step is to examine the deploy order in the `Cluster#deploy` method.",
|
|
"timestamp": "2026-02-20T17:13:32.833Z"
|
|
},
|
|
{
|
|
"subject": "Debugging the Root Cause",
|
|
"description": "I'm now zeroing in on the reason for the test failure. Specifically, the mismatch between the expected and actual \"terraform plan\" commands. It's becoming clearer that the `rds` deployment is incorrectly including the new `replication` parameters, even though the test was expecting a different command structure. Further investigation reveals a crucial detail: the test uses an infrastructure from `dalmatian.yml.example`, and this is what is setting the `infrastructure_name` and is the root cause.",
|
|
"timestamp": "2026-02-20T17:13:34.951Z"
|
|
},
|
|
{
|
|
"subject": "Isolating the Root Cause",
|
|
"description": "I'm now zeroing in on why test 24 is failing. It expects a command for `new-dedicated-cluster`, yet the error shows `existing-shared-cluster-production`. This inconsistency is confusing. Examining the `before` block reveals that `Infrastructure.new.test` iterates over all infrastructures in `dalmatian.yml.example`, which is likely causing the issue. I need to understand why the wrong infrastructure name is being used in the actual \"terraform plan\" command.",
|
|
"timestamp": "2026-02-20T17:13:36.995Z"
|
|
},
|
|
{
|
|
"subject": "Tracing the Unexpected Argument",
|
|
"description": "Now, I've returned to the error from test 24. Specifically, I see an incorrect \"terraform plan\" command is being used. The expected command, referencing \"new-dedicated-cluster,\" is not matching the actual command, which incorrectly uses \"existing-shared-cluster-production.\" I've realized the infrastructure name is the problem.",
|
|
"timestamp": "2026-02-20T17:13:39.322Z"
|
|
},
|
|
{
|
|
"subject": "Isolating the Conflict",
|
|
"description": "I've examined the error messages from test 24 more closely. I can now see the full \"terraform plan\" command that failed. The discrepancy stems from the `infrastructure_name` being set to \"existing-shared-cluster-production,\" whereas it *should* be \"new-dedicated-cluster,\" as defined in `cluster1_plan_cmd_production_service`. The root cause is likely the `before` block, which deploys everything, and it is selecting the wrong infrastructure.",
|
|
"timestamp": "2026-02-20T17:13:40.823Z"
|
|
}
|
|
],
|
|
"tokens": {
|
|
"input": 49871,
|
|
"output": 162,
|
|
"cached": 45767,
|
|
"thoughts": 1624,
|
|
"tool": 0,
|
|
"total": 51657
|
|
},
|
|
"model": "gemini-3-flash-preview",
|
|
"toolCalls": [
|
|
{
|
|
"id": "run_shell_command_1771607620984_0",
|
|
"name": "run_shell_command",
|
|
"args": {
|
|
"command": "grep -n \"existing-shared-cluster-production\" spec/integration/tests_local_configuration_spec.rb"
|
|
},
|
|
"result": [
|
|
{
|
|
"functionResponse": {
|
|
"id": "run_shell_command_1771607620984_0",
|
|
"name": "run_shell_command",
|
|
"response": {
|
|
"output": "Output: 49: existing-shared-cluster-production-0-production\n71: name: \"existing-shared-cluster-production-0.config\"\n75: name: \"existing-shared-cluster-production-0.config\"\n3018: \"infrastructure_name\" => \"existing-shared-cluster-production\",\n3034: \"infrastructure_name\" => \"existing-shared-cluster-production\",\nProcess Group PGID: 47774"
|
|
}
|
|
}
|
|
}
|
|
],
|
|
"status": "success",
|
|
"timestamp": "2026-02-20T17:13:41.098Z",
|
|
"resultDisplay": "49: existing-shared-cluster-production-0-production\n71: name: \"existing-shared-cluster-production-0.config\"\n75: name: \"existing-shared-cluster-production-0.config\"\n3018: \"infrastructure_name\" => \"existing-shared-cluster-production\",\n3034: \"infrastructure_name\" => \"existing-shared-cluster-production\",",
|
|
"displayName": "Shell",
|
|
"description": "This tool executes a given shell command as `bash -c <command>`. To run a command in the background, set the `is_background` parameter to true. Do NOT use `&` to background commands. Command is executed as a subprocess that leads its own process group. Command process group can be terminated as `kill -- -PGID` or signaled as `kill -s SIGNAL -- -PGID`.\n\n Efficiency Guidelines:\n - Quiet Flags: Always prefer silent or quiet flags (e.g., `npm install --silent`, `git --no-pager`) to reduce output volume while still capturing necessary information.\n - Pagination: Always disable terminal pagination to ensure commands terminate (e.g., use `git --no-pager`, `systemctl --no-pager`, or set `PAGER=cat`).\n\n The following information is returned:\n\n Output: Combined stdout/stderr. Can be `(empty)` or partial on error and for any unwaited background processes.\n Exit Code: Only included if non-zero (command failed).\n Error: Only included if a process-level error occurred (e.g., spawn failure).\n Signal: Only included if process was terminated by a signal.\n Background PIDs: Only included if background processes were started.\n Process Group PGID: Only included if available.",
|
|
"renderOutputAsMarkdown": false
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"id": "dcc66bac-3f3d-4931-ad06-646e93f9a228",
|
|
"timestamp": "2026-02-20T17:13:43.168Z",
|
|
"type": "gemini",
|
|
"content": "Check lines 3018 and 3034.",
|
|
"thoughts": [
|
|
{
|
|
"subject": "Inspecting Specific Lines",
|
|
"description": "I'm zeroing in on lines 3018 and 3034. My attention is now wholly devoted to understanding the data residing within these specific code segments. I'm cross-referencing to find any pertinent relationships.",
|
|
"timestamp": "2026-02-20T17:13:43.048Z"
|
|
}
|
|
],
|
|
"tokens": {
|
|
"input": 50149,
|
|
"output": 42,
|
|
"cached": 47965,
|
|
"thoughts": 19,
|
|
"tool": 0,
|
|
"total": 50210
|
|
},
|
|
"model": "gemini-3-flash-preview",
|
|
"toolCalls": [
|
|
{
|
|
"id": "read_file_1771607623165_0",
|
|
"name": "read_file",
|
|
"args": {
|
|
"limit": 100,
|
|
"file_path": "spec/integration/tests_local_configuration_spec.rb",
|
|
"offset": 3000
|
|
},
|
|
"result": [
|
|
{
|
|
"functionResponse": {
|
|
"id": "read_file_1771607623165_0",
|
|
"name": "read_file",
|
|
"response": {
|
|
"output": "\nIMPORTANT: The file content has been truncated.\nStatus: Showing lines 3001-3100 of 3243 total lines.\nAction: To read more of the file, you can use the 'offset' and 'limit' parameters in a subsequent 'read_file' call. For example, to read the next section of the file, use offset: 3100.\n\n--- FILE CONTENT (truncated) ---\n \"environment\" => \"staging\",\n \"cluster_name\" => \"shared-cluster-staging\",\n \"account_id\" => \"123456789012\",\n \"infrastructure_name\" => \"existing-shared-cluster-staging\",\n \"dalmatian_role\" => \"dalmatian-read\"\n )\n )\n )\n end\n\n let(:cluster4_validate_cmd_production) do\n terraform_validate_cmd(\n tfvar_arg_string(\n infrastructure_defaults.merge(\n \"example_var\" => \"bar\",\n \"cluster_name\" => \"shared-cluster-production\",\n \"account_id\" => \"123456789012\",\n \"infrastructure_name\" => \"existing-shared-cluster-production\",\n \"dalmatian_role\" => \"dalmatian-read\",\n \"environment\" => \"production\"\n )\n )\n )\n end\n\n let(:cluster4_plan_cmd_production) do\n terraform_plan_cmd(\n tfvar_arg_string(\n infrastructure_defaults.merge(\n \"example_var\" => \"bar\",\n \"environment\" => \"production\",\n \"cluster_name\" => \"shared-cluster-production\",\n \"account_id\" => \"123456789012\",\n \"infrastructure_name\" => \"existing-shared-cluster-production\",\n \"dalmatian_role\" => \"dalmatian-read\"\n )\n )\n )\n end\n\n before do\n allow(Logger).to receive(:info)\n stub_git_clone_cmds\n stub_git_checkout\n stub_workspace_creation_cmds\n allow(Helper).to receive(:run!).with(\"rake terrafile\")\n allow(Helper).to receive(:run!).with(\"terraform init -upgrade=true\")\n allow(Helper).to receive(:run!).with(\"terraform fmt -check -diff\")\n\n allow(Helper).to receive(:run!).with(cluster1_validate_cmd_hz)\n allow(Helper).to receive(:run!).with(cluster1_validate_cmd_s3)\n allow(Helper).to receive(:run!).with(cluster1_validate_cmd_vpn_cg)\n\n allow(Helper).to receive(:run!).with(cluster1_plan_cmd_hz)\n allow(Helper).to receive(:run!).with(cluster1_plan_cmd_s3)\n allow(Helper).to receive(:run!).with(cluster1_plan_cmd_vpn_cg)\n\n allow(Helper).to receive(:run!).with(cluster1_validate_cmd_production)\n allow(Helper).to receive(:run!).with(cluster1_validate_cmd_staging)\n allow(Helper).to receive(:run!).with(cluster1_plan_cmd_production)\n allow(Helper).to receive(:run!).with(cluster1_plan_cmd_staging)\n allow(Helper).to receive(:run!).with(source1_validate_cmd_production)\n allow(Helper).to receive(:run!).with(source1_validate_cmd_staging)\n\n allow(Helper).to receive(:run!).with(cluster1_validate_cmd_production_waf)\n allow(Helper).to receive(:run!).with(cluster1_validate_cmd_staging_waf)\n allow(Helper).to receive(:run!).with(cluster1_plan_cmd_production_waf)\n allow(Helper).to receive(:run!).with(cluster1_plan_cmd_staging_waf)\n\n allow(Helper).to receive(:run!).with(cluster1_validate_cmd_production_rds)\n allow(Helper).to receive(:run!).with(cluster1_validate_cmd_staging_rds)\n allow(Helper).to receive(:run!).with(cluster1_plan_cmd_production_rds)\n allow(Helper).to receive(:run!).with(cluster1_plan_cmd_staging_rds)\n\n allow(Helper).to receive(:run!).with(cluster1_validate_cmd_production_elasticache_cluster)\n allow(Helper).to receive(:run!).with(cluster1_validate_cmd_staging_elasticache_cluster)\n allow(Helper).to receive(:run!).with(cluster1_plan_cmd_production_elasticache_cluster)\n allow(Helper).to receive(:run!).with(cluster1_plan_cmd_staging_elasticache_cluster)\n\n allow(Helper).to receive(:run!).with(cluster1_validate_cmd_production_opensearch_cluster)\n allow(Helper).to receive(:run!).with(cluster1_validate_cmd_staging_opensearch_cluster)\n allow(Helper).to receive(:run!).with(cluster1_plan_cmd_production_opensearch_cluster)\n allow(Helper).to receive(:run!).with(cluster1_plan_cmd_staging_opensearch_cluster)\n\n allow(Helper).to receive(:run!).with(cluster1_validate_cmd_production_service)\n allow(Helper).to receive(:run!).with(cluster1_validate_cmd_staging_service)\n allow(Helper).to receive(:run!).with(cluster1_plan_cmd_production_service)\n allow(Helper).to receive(:run!).with(cluster1_plan_cmd_staging_service)\n\n allow(Helper).to receive(:run!).with(cluster1_validate_cmd_production_shared_loadbalancer)\n allow(Helper).to receive(:run!).with(cluster1_validate_cmd_staging_shared_loadbalancer)\n allow(Helper).to receive(:run!).with(cluster1_plan_cmd_production_shared_loadbalancer)\n allow(Helper).to receive(:run!).with(cluster1_plan_cmd_staging_shared_loadbalancer)\n\n allow(Helper).to receive(:run!).with(cluster2_validate_cmd_production)\n allow(Helper).to receive(:run!).with(cluster2_validate_cmd_staging)\n allow(Helper).to receive(:run!).with(cluster2_plan_cmd_production)\n allow(Helper).to receive(:run!).with(cluster2_plan_cmd_staging)\n\n allow(Helper).to receive(:run!).with(cluster3_validate_cmd_staging)"
|
|
}
|
|
}
|
|
}
|
|
],
|
|
"status": "success",
|
|
"timestamp": "2026-02-20T17:13:43.201Z",
|
|
"resultDisplay": "Read lines 3001-3100 of 3243 from spec/integration/tests_local_configuration_spec.rb",
|
|
"displayName": "ReadFile",
|
|
"description": "Reads and returns the content of a specified file. If the file is large, the content will be truncated. The tool's response will clearly indicate if truncation has occurred and will provide details on how to read more of the file using the 'offset' and 'limit' parameters. Handles text, images (PNG, JPG, GIF, WEBP, SVG, BMP), audio files (MP3, WAV, AIFF, AAC, OGG, FLAC), and PDF files. For text files, it can read specific line ranges.",
|
|
"renderOutputAsMarkdown": true
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"id": "fa401e1d-1569-4b57-bf2f-2bb337bf6b3a",
|
|
"timestamp": "2026-02-20T17:14:00.356Z",
|
|
"type": "gemini",
|
|
"content": "The failure in test 24 is due to `Rds#to_params` having two new fields, `replication_bucket_destination_arn` and `replication_kms_key_id`, which are missing from the test stubs. Since `Infrastructure.new(...).test` in the `before` block calls `deploy_rds`, and the mock for `Helper.run!` receives arguments that don't match the stubbed `cluster1_plan_cmd_production_rds`, it raises a `MockExpectationError`. RSpec then confusingly shows another stubbed call (like `cluster4_plan_cmd_production`) as the \"expected\" one. I need to update all RDS command definitions in `spec/integration/tests_local_configuration_spec.rb` and `spec/integration/deploys_local_configuration_spec.rb` to include these new fields.",
|
|
"thoughts": [
|
|
{
|
|
"subject": "Debugging the Terraform plan",
|
|
"description": "I'm currently wrestling with a frustrating error. The test suite is failing when running \"terraform plan,\" specifically because of an argument mismatch. It seems the service configuration isn't being properly passed. I'm digging into the Dalmatian::Helper class to pinpoint the problem.",
|
|
"timestamp": "2026-02-20T17:13:45.341Z"
|
|
},
|
|
{
|
|
"subject": "Examining the Failing Test",
|
|
"description": "I've been poring over the test failure reports. It seems that the `Helper.run!(cmd)` method is the root of the issue. The tests are expecting a specific argument, `cluster1_plan_cmd_production_service`, but they're receiving something different, something with new fields. I'm starting to suspect that there's an issue with how the service configuration is being constructed or passed to `terraform plan`. Furthermore, this is related to how the tests are set up, as the `before` block might be at fault.",
|
|
"timestamp": "2026-02-20T17:13:47.849Z"
|
|
},
|
|
{
|
|
"subject": "Investigating the RSpec Mock",
|
|
"description": "I'm reviewing the RSpec mock setup. It seems `Helper.run!` is called with arguments that aren't being matched by the mock expectations. I've realized `cluster1_plan_cmd_production_rds` is expected, and the error reports new fields present in the actual call. Now I need to check the mock expectations inside the `before` block and figure out why the arguments don't match, particularly for the RDS deployment. I'm focusing on the `deploy_rds` method and the arguments it passes to `Helper.run!`.",
|
|
"timestamp": "2026-02-20T17:13:50.010Z"
|
|
},
|
|
{
|
|
"subject": "Refining the Mock Expectations",
|
|
"description": "I've been meticulously examining the RSpec setup again. It turns out the root cause is a mismatch between the expected and actual arguments passed to `Helper.run!`, specifically within the RDS deployment. The tests were failing because the `cluster1_plan_cmd_production_rds` command definitions were missing two new fields, which are now present in the actual command. Therefore, I need to update the RDS command definitions within the specs to incorporate these new parameters. I am reviewing the `spec/integration` files for all instances.",
|
|
"timestamp": "2026-02-20T17:13:51.765Z"
|
|
},
|
|
{
|
|
"subject": "Confirming RDS Configuration",
|
|
"description": "I'm now certain the core issue is missing fields in the RDS command definitions. I've pinpointed the discrepancy: The test suite expects arguments without the newly added `replication_bucket_destination_arn` and `replication_kms_key_id`. To resolve this, I must update the command definitions within the failing specs. I've reviewed the `lib/dalmatian/rds.rb` and I'm ready to update the tests.",
|
|
"timestamp": "2026-02-20T17:13:53.606Z"
|
|
},
|
|
{
|
|
"subject": "Confirming the Missing Parameters",
|
|
"description": "I've finally zeroed in on the precise issue. The RDS command definitions within the failing tests are missing the newly introduced `replication_bucket_destination_arn` and `replication_kms_key_id` parameters. This mismatch is causing the mock expectations to fail. My next step is to update the RDS command definitions in the `spec/integration` files to include these missing fields. I have confirmed that those fields are needed by comparing the ruby code and the test definitions.",
|
|
"timestamp": "2026-02-20T17:13:55.401Z"
|
|
},
|
|
{
|
|
"subject": "Diagnosing the RSpec Mock",
|
|
"description": "I'm making a key discovery. The RSpec mock is failing, not in the `it` block as I initially thought, but within the `before` block. The `deploy_rds` method, triggered during the `Infrastructure.new(...).test` call, attempts a `Helper.run!` with the RDS configuration. Because `cluster1_plan_cmd_production_rds` is missing required fields, it causes the mock expectation to fail before the test assertions are even checked. I'm now certain the problem is in the setup.",
|
|
"timestamp": "2026-02-20T17:13:57.722Z"
|
|
},
|
|
{
|
|
"subject": "Isolating the Root Cause",
|
|
"description": "I'm focused on pinpointing the exact reason for the `Helper.run!` failure. I've deduced that the issue arises in the `before` block during the `deploy_rds` call, which is performed by `Infrastructure.new(...).test`. The key lies in outdated RDS command definitions. These tests are expecting arguments without the newly introduced parameters. The fix requires updating the `let` variables defining RDS commands within the failing specs. I have identified the relevant files, and am compiling a complete list of changes.",
|
|
"timestamp": "2026-02-20T17:13:59.886Z"
|
|
}
|
|
],
|
|
"tokens": {
|
|
"input": 51755,
|
|
"output": 227,
|
|
"cached": 48165,
|
|
"thoughts": 2329,
|
|
"tool": 0,
|
|
"total": 54311
|
|
},
|
|
"model": "gemini-3-flash-preview",
|
|
"toolCalls": [
|
|
{
|
|
"id": "run_shell_command_1771607640352_0",
|
|
"name": "run_shell_command",
|
|
"args": {
|
|
"command": "grep -n \"rds\" spec/integration/deploys_local_configuration_spec.rb | grep \"let\""
|
|
},
|
|
"result": [
|
|
{
|
|
"functionResponse": {
|
|
"id": "run_shell_command_1771607640352_0",
|
|
"name": "run_shell_command",
|
|
"response": {
|
|
"output": "Output: 379: let(:cluster1_apply_cmd_production_rds) do\n441: let(:cluster1_apply_cmd_staging_rds) do\nProcess Group PGID: 47798"
|
|
}
|
|
}
|
|
}
|
|
],
|
|
"status": "success",
|
|
"timestamp": "2026-02-20T17:14:00.446Z",
|
|
"resultDisplay": "379: let(:cluster1_apply_cmd_production_rds) do\n441: let(:cluster1_apply_cmd_staging_rds) do",
|
|
"displayName": "Shell",
|
|
"description": "This tool executes a given shell command as `bash -c <command>`. To run a command in the background, set the `is_background` parameter to true. Do NOT use `&` to background commands. Command is executed as a subprocess that leads its own process group. Command process group can be terminated as `kill -- -PGID` or signaled as `kill -s SIGNAL -- -PGID`.\n\n Efficiency Guidelines:\n - Quiet Flags: Always prefer silent or quiet flags (e.g., `npm install --silent`, `git --no-pager`) to reduce output volume while still capturing necessary information.\n - Pagination: Always disable terminal pagination to ensure commands terminate (e.g., use `git --no-pager`, `systemctl --no-pager`, or set `PAGER=cat`).\n\n The following information is returned:\n\n Output: Combined stdout/stderr. Can be `(empty)` or partial on error and for any unwaited background processes.\n Exit Code: Only included if non-zero (command failed).\n Error: Only included if a process-level error occurred (e.g., spawn failure).\n Signal: Only included if process was terminated by a signal.\n Background PIDs: Only included if background processes were started.\n Process Group PGID: Only included if available.",
|
|
"renderOutputAsMarkdown": false
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"id": "61c2d5d4-4fb5-43f8-a563-9f7d3789b651",
|
|
"timestamp": "2026-02-20T17:14:03.210Z",
|
|
"type": "gemini",
|
|
"content": "Check definitions at `spec/integration/deploys_local_configuration_spec.rb:379`.",
|
|
"thoughts": [
|
|
{
|
|
"subject": "Reviewing Configuration Details",
|
|
"description": "I'm currently focused on the `deploys_local_configuration_spec.rb` file, specifically line 379 and its related definitions. I'm taking a close look at the configuration details provided there. The goal is to fully understand how deployments are handled locally.",
|
|
"timestamp": "2026-02-20T17:14:03.121Z"
|
|
}
|
|
],
|
|
"tokens": {
|
|
"input": 52037,
|
|
"output": 54,
|
|
"cached": 39803,
|
|
"thoughts": 31,
|
|
"tool": 0,
|
|
"total": 52122
|
|
},
|
|
"model": "gemini-3-flash-preview",
|
|
"toolCalls": [
|
|
{
|
|
"id": "read_file_1771607643206_0",
|
|
"name": "read_file",
|
|
"args": {
|
|
"limit": 100,
|
|
"file_path": "spec/integration/deploys_local_configuration_spec.rb",
|
|
"offset": 379
|
|
},
|
|
"result": [
|
|
{
|
|
"functionResponse": {
|
|
"id": "read_file_1771607643206_0",
|
|
"name": "read_file",
|
|
"response": {
|
|
"output": "\nIMPORTANT: The file content has been truncated.\nStatus: Showing lines 380-479 of 1663 total lines.\nAction: To read more of the file, you can use the 'offset' and 'limit' parameters in a subsequent 'read_file' call. For example, to read the next section of the file, use offset: 479.\n\n--- FILE CONTENT (truncated) ---\n terraform_apply_cmd(\n tfvar_arg_string(\n infrastructure_defaults.merge(\n \"instance_type\" => \"t2.medium\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"environment\" => \"production\",\n \"account_id\" => \"123456789012\",\n \"infrastructure_name\" => \"new-dedicated-cluster\",\n \"dalmatian_role\" => \"dalmatian-admin\",\n \"rds\" => {\n \"identifier\" => \"testservice\",\n \"in_use_by\" => [\n \"test-service\"\n ],\n \"clusters_in_use\" => {\n \"production\" => [\n \"test\"\n ],\n \"staging\" => [\n \"test\"\n ]\n },\n \"instance_class\" => {\n \"production\" => \"db.t2.small\",\n \"staging\" => \"db.t2.micro\"\n },\n \"engine\" => \"postgres\",\n \"engine_version\" => \"11.4\",\n \"allocated_storage\" => 20,\n \"storage_encrypted\" => true,\n \"storage_type\" => \"gp3\",\n \"db_name\" => \"testapp\",\n \"port\" => 5432,\n \"maintenance_window\" => \"mon:19:00-mon:19:30\",\n \"backup_window\" => \"09:00-10:00\",\n \"backup_retention_period\" => 31,\n \"force_ssl\" => true,\n \"parameter_store_path_db_url_name\" => \"DATABASE_URL\",\n \"sql_backup_scheduled_task_environment_variables\" => [\n {\n \"name\" => \"foo\",\n \"value\" => \"bar\"\n }\n ],\n \"check_sql_backup_scheduled_task_environment_variables\" => [\n {\n \"name\" => \"foo\",\n \"value\" => \"bar\"\n }\n ],\n \"sync_sql_backup_to_azure\" => false,\n \"codebuild_access\" => [\n \"service-name\"\n ]\n }\n )\n )\n )\n end\n\n let(:cluster1_apply_cmd_staging_rds) do\n terraform_apply_cmd(\n tfvar_arg_string(\n infrastructure_defaults.merge(\n \"instance_type\" => \"t2.small\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"track_revision\" => \"feature/experiment\",\n \"extra_ecs_clusters\" => [\n {\n \"name\" => \"test\",\n \"subnets_name\" => \"extra_private_subnets\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"instance_type\" => \"t3.small\"\n }\n ],\n \"tinyproxy\" => {\n \"create\" => true\n },\n \"environment\" => \"staging\",\n \"account_id\" => \"123456789012\",\n \"infrastructure_name\" => \"new-dedicated-cluster\",\n \"dalmatian_role\" => \"dalmatian-admin\",\n \"rds\" => {\n \"identifier\" => \"testservice\",\n \"in_use_by\" => [\n \"test-service\"\n ],\n \"clusters_in_use\" => {\n \"production\" => [\n \"test\"\n ],\n \"staging\" => [\n \"test\"\n ]\n },\n \"instance_class\" => {\n \"production\" => \"db.t2.small\","
|
|
}
|
|
}
|
|
}
|
|
],
|
|
"status": "success",
|
|
"timestamp": "2026-02-20T17:14:03.236Z",
|
|
"resultDisplay": "Read lines 380-479 of 1663 from spec/integration/deploys_local_configuration_spec.rb",
|
|
"displayName": "ReadFile",
|
|
"description": "Reads and returns the content of a specified file. If the file is large, the content will be truncated. The tool's response will clearly indicate if truncation has occurred and will provide details on how to read more of the file using the 'offset' and 'limit' parameters. Handles text, images (PNG, JPG, GIF, WEBP, SVG, BMP), audio files (MP3, WAV, AIFF, AAC, OGG, FLAC), and PDF files. For text files, it can read specific line ranges.",
|
|
"renderOutputAsMarkdown": true
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"id": "16922e66-9539-4758-8559-05b369409a44",
|
|
"timestamp": "2026-02-20T17:14:06.082Z",
|
|
"type": "gemini",
|
|
"content": "I'll fix those RDS definitions and then check `lib/dalmatian/rds.rb` for other `to_params` usage, and see if `spec/unit/rds_spec.rb` exists for further testing.",
|
|
"thoughts": [
|
|
{
|
|
"subject": "Checking RDS Definitions",
|
|
"description": "I'm currently focused on the RDS definitions, starting with those in the two files. I've realized I need to check for any uses of `to_params` and related tests in other files, like `lib/dalmatian/rds.rb`. Next, I'll see if a corresponding spec file, `spec/unit/rds_spec.rb`, exists.",
|
|
"timestamp": "2026-02-20T17:14:05.984Z"
|
|
}
|
|
],
|
|
"tokens": {
|
|
"input": 53101,
|
|
"output": 70,
|
|
"cached": 49891,
|
|
"thoughts": 70,
|
|
"tool": 0,
|
|
"total": 53241
|
|
},
|
|
"model": "gemini-3-flash-preview",
|
|
"toolCalls": [
|
|
{
|
|
"id": "run_shell_command_1771607646079_0",
|
|
"name": "run_shell_command",
|
|
"args": {
|
|
"command": "ls spec/unit/rds_spec.rb"
|
|
},
|
|
"result": [
|
|
{
|
|
"functionResponse": {
|
|
"id": "run_shell_command_1771607646079_0",
|
|
"name": "run_shell_command",
|
|
"response": {
|
|
"output": "Output: spec/unit/rds_spec.rb\nProcess Group PGID: 47859"
|
|
}
|
|
}
|
|
}
|
|
],
|
|
"status": "success",
|
|
"timestamp": "2026-02-20T17:14:06.169Z",
|
|
"resultDisplay": "spec/unit/rds_spec.rb",
|
|
"displayName": "Shell",
|
|
"description": "This tool executes a given shell command as `bash -c <command>`. To run a command in the background, set the `is_background` parameter to true. Do NOT use `&` to background commands. Command is executed as a subprocess that leads its own process group. Command process group can be terminated as `kill -- -PGID` or signaled as `kill -s SIGNAL -- -PGID`.\n\n Efficiency Guidelines:\n - Quiet Flags: Always prefer silent or quiet flags (e.g., `npm install --silent`, `git --no-pager`) to reduce output volume while still capturing necessary information.\n - Pagination: Always disable terminal pagination to ensure commands terminate (e.g., use `git --no-pager`, `systemctl --no-pager`, or set `PAGER=cat`).\n\n The following information is returned:\n\n Output: Combined stdout/stderr. Can be `(empty)` or partial on error and for any unwaited background processes.\n Exit Code: Only included if non-zero (command failed).\n Error: Only included if a process-level error occurred (e.g., spawn failure).\n Signal: Only included if process was terminated by a signal.\n Background PIDs: Only included if background processes were started.\n Process Group PGID: Only included if available.",
|
|
"renderOutputAsMarkdown": false
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"id": "be0a0a8e-f5fd-47e4-b50b-9b44de8b4af6",
|
|
"timestamp": "2026-02-20T17:14:10.515Z",
|
|
"type": "gemini",
|
|
"content": "Check `spec/unit/rds_spec.rb` for updates.",
|
|
"thoughts": [
|
|
{
|
|
"subject": "Checking for Updates",
|
|
"description": "I'm currently focused on the `spec/unit/rds_spec.rb` file. My initial assessment is that it might require some adjustments, so I'm diving in to see what needs updating. I'll need to examine the existing tests to determine the scope of any necessary modifications.",
|
|
"timestamp": "2026-02-20T17:14:10.352Z"
|
|
}
|
|
],
|
|
"tokens": {
|
|
"input": 53196,
|
|
"output": 35,
|
|
"cached": 49832,
|
|
"thoughts": 22,
|
|
"tool": 0,
|
|
"total": 53253
|
|
},
|
|
"model": "gemini-3-flash-preview",
|
|
"toolCalls": [
|
|
{
|
|
"id": "read_file_1771607650511_0",
|
|
"name": "read_file",
|
|
"args": {
|
|
"file_path": "spec/unit/rds_spec.rb"
|
|
},
|
|
"result": [
|
|
{
|
|
"functionResponse": {
|
|
"id": "read_file_1771607650511_0",
|
|
"name": "read_file",
|
|
"response": {
|
|
"output": "require_relative \"../support/spec_helper\"\n\nmodule Dalmatian\n RSpec.describe Rds do\n let(:rds_reference) do\n {\n \"identifier\" => \"testservice\",\n \"in_use_by\" => [\n \"test-service\"\n ],\n \"instance_class\" => {\n \"production\" => \"db.t2.small\",\n \"staging\" => \"db.t2.micro\"\n },\n \"engine\" => \"postgres\",\n \"engine_version\" => \"11.4\",\n \"allocated_storage\" => 20,\n \"storage_encrypted\" => true,\n \"storage_type\" => \"gp3\",\n \"db_name\" => \"testapp\",\n \"port\" => 5432,\n \"maintenance_window\" => \"mon:19:00-mon:19:30\",\n \"backup_window\" => \"09:00-10:00\",\n \"backup_retention_period\" => 31,\n \"force_ssl\" => true,\n \"parameter_store_path_db_url_name\" => \"DATABASE_URL\",\n \"sql_backup_scheduled_task_environment_variables\" => [\n {\n \"name\" => \"foo\",\n \"value\" => \"bar\"\n }\n ],\n \"check_sql_backup_scheduled_task_environment_variables\" => [\n {\n \"name\" => \"foo\",\n \"value\" => \"bar\"\n }\n ],\n \"sync_sql_backup_to_azure\" => false,\n \"replication_bucket_destination_arn\" => \"arn:aws:s3:::dest-bucket\",\n \"replication_kms_key_id\" => \"key-id\",\n \"codebuild_access\" => [\n \"service-name\"\n ]\n }\n end\n\n let(:cluster) do\n instance_double(\n Cluster,\n id: \"new-dedicated-cluster\",\n name: \"new-dedicated-cluster\",\n environments: {\"staging\" => {}, \"production\" => {}},\n services: [double(name: \"test-service\", domain_names: {\"staging\" => [\"example-domain-name.co.uk\"]}, launch_on_cluster: \"test\"),\n double(name: \"test-service\", domain_names: {\"staging\" => [\"example-domain-name.co.uk\"]}, launch_on_cluster: \"\")],\n account_id: 123456789012,\n rdss: [double(reference: {identifier: \"someotherrds\"}),\n double(reference: rds_reference)]\n )\n end\n let(:rds) { Rds.new(cluster: cluster, reference: rds_reference) }\n\n describe \"#identifier\" do\n it \"uses rds identifier\" do\n expect(rds.identifier).to eq(\"testservice\")\n end\n end\n\n describe \"#in_use_by\" do\n it \"uses rds in_use_by list\" do\n expect(rds.in_use_by).to eq([\"test-service\"])\n end\n end\n\n describe \"#clusters_in_use\" do\n it \"uses rds clusters_in_use list\" do\n expect(rds.clusters_in_use).to eq({\"staging\" => [\"test\", \"default_dalmatian_ecs_cluster\"], \"production\" => [\"test\", \"default_dalmatian_ecs_cluster\"]})\n end\n end\n\n describe \"#instance_class\" do\n it \"uses rds instance_class\" do\n expect(rds.instance_class).to eq({\"production\" => \"db.t2.small\", \"staging\" => \"db.t2.micro\"})\n end\n end\n\n describe \"#engine\" do\n it \"uses rds engine\" do\n expect(rds.engine).to eq(\"postgres\")\n end\n end\n\n describe \"#engine_version\" do\n it \"uses the rds engine_version\" do\n expect(rds.engine_version).to eq(\"11.4\")\n end\n end\n\n describe \"#allocated_storage\" do\n it \"uses the rds allocated_storage\" do\n expect(rds.allocated_storage).to eq(20)\n end\n end\n\n describe \"#storage_encrypted\" do\n it \"uses the rds storage_encrypted bool\" do\n expect(rds.storage_encrypted).to eq(true)\n end\n end\n\n describe \"#storage_type\" do\n it \"uses the rds storage_type gp3\" do\n expect(rds.storage_type).to eq(\"gp3\")\n end\n end\n\n describe \"#db_name\" do\n it \"uses the rds db_name\" do\n expect(rds.db_name).to eq(\"testapp\")\n end\n end\n\n describe \"#port\" do\n it \"uses the rds port\" do\n expect(rds.port).to eq(5432)\n end\n end\n\n describe \"#maintenance_window\" do\n it \"uses the rds maintenance_window\" do\n expect(rds.maintenance_window).to eq(\"mon:19:00-mon:19:30\")\n end\n end\n\n describe \"#backup_window\" do\n it \"uses the rds backup_window\" do\n expect(rds.backup_window).to eq(\"09:00-10:00\")\n end\n end\n\n describe \"#backup_retention_period\" do\n it \"uses the rds backup_retention_period\" do\n expect(rds.backup_retention_period).to eq(31)\n end\n end\n\n describe \"#force_ssl\" do\n it \"uses the rds force_ssl bool\" do\n expect(rds.force_ssl).to eq(true)\n end\n end\n\n describe \"#parameter_store_path_db_url_name\" do\n it \"uses the rds parameter_store_path_db_url_name\" do\n expect(rds.parameter_store_path_db_url_name).to eq(\"DATABASE_URL\")\n end\n end\n\n describe \"#sql_backup_scheduled_task_environment_variables\" do\n it \"uses the rds sql_backup_scheduled_task_environment_variables\" do\n expect(rds.sql_backup_scheduled_task_environment_variables).to eq([{\"name\" => \"foo\", \"value\" => \"bar\"}])\n end\n end\n\n describe \"#check_sql_backup_scheduled_task_environment_variables\" do\n it \"uses the rds check_sql_backup_scheduled_task_environment_variables\" do\n expect(rds.check_sql_backup_scheduled_task_environment_variables).to eq([{\"name\" => \"foo\", \"value\" => \"bar\"}])\n end\n end\n\n describe \"#sync_sql_backup_to_azure\" do\n it \"will have offsite backups disabled by default\" do\n expect(rds.sync_sql_backup_to_azure).to eq(false)\n end\n end\n\n describe \"#replication_bucket_destination_arn\" do\n it \"uses the rds replication_bucket_destination_arn\" do\n expect(rds.replication_bucket_destination_arn).to eq(\"arn:aws:s3:::dest-bucket\")\n end\n end\n\n describe \"#replication_kms_key_id\" do\n it \"uses the rds replication_kms_key_id\" do\n expect(rds.replication_kms_key_id).to eq(\"key-id\")\n end\n end\n\n describe \"#codebuild_access\" do\n it \"uses the rds codebuild_access\" do\n expect(rds.codebuild_access).to eq([\"service-name\"])\n end\n end\n\n describe \"#to_params\" do\n it \"provides a hash of attributes for use in deployment\" do\n expected_params = {\n \"identifier\" => \"testservice\",\n \"in_use_by\" => [\n \"test-service\"\n ],\n \"clusters_in_use\" => {\n \"production\" => [\n \"test\",\n \"default_dalmatian_ecs_cluster\"\n ],\n \"staging\" => [\n \"test\",\n \"default_dalmatian_ecs_cluster\"\n ]\n },\n \"instance_class\" => {\n \"production\" => \"db.t2.small\",\n \"staging\" => \"db.t2.micro\"\n },\n \"engine\" => \"postgres\",\n \"engine_version\" => \"11.4\",\n \"allocated_storage\" => 20,\n \"storage_encrypted\" => true,\n \"storage_type\" => \"gp3\",\n \"db_name\" => \"testapp\",\n \"port\" => 5432,\n \"maintenance_window\" => \"mon:19:00-mon:19:30\",\n \"backup_window\" => \"09:00-10:00\",\n \"backup_retention_period\" => 31,\n \"force_ssl\" => true,\n \"parameter_store_path_db_url_name\" => \"DATABASE_URL\",\n \"sql_backup_scheduled_task_environment_variables\" => [\n {\n \"name\" => \"foo\",\n \"value\" => \"bar\"\n }\n ],\n \"check_sql_backup_scheduled_task_environment_variables\" => [\n {\n \"name\" => \"foo\",\n \"value\" => \"bar\"\n }\n ],\n \"sync_sql_backup_to_azure\" => false,\n \"replication_bucket_destination_arn\" => \"arn:aws:s3:::dest-bucket\",\n \"replication_kms_key_id\" => \"key-id\",\n \"codebuild_access\" => [\n \"service-name\"\n ]\n }\n\n expect(rds.to_params).to eq(expected_params)\n end\n end\n end\nend\n"
|
|
}
|
|
}
|
|
}
|
|
],
|
|
"status": "success",
|
|
"timestamp": "2026-02-20T17:14:10.551Z",
|
|
"resultDisplay": "",
|
|
"displayName": "ReadFile",
|
|
"description": "Reads and returns the content of a specified file. If the file is large, the content will be truncated. The tool's response will clearly indicate if truncation has occurred and will provide details on how to read more of the file using the 'offset' and 'limit' parameters. Handles text, images (PNG, JPG, GIF, WEBP, SVG, BMP), audio files (MP3, WAV, AIFF, AAC, OGG, FLAC), and PDF files. For text files, it can read specific line ranges.",
|
|
"renderOutputAsMarkdown": true
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"id": "3db54f7a-c1df-4748-815c-23cd50e40512",
|
|
"timestamp": "2026-02-20T17:14:12.922Z",
|
|
"type": "gemini",
|
|
"content": "`spec/unit/rds_spec.rb` already has those fields and didn't fail, but I'll double-check to be sure.",
|
|
"thoughts": [
|
|
{
|
|
"subject": "Examining the Results",
|
|
"description": "I'm now investigating the results of the `rds_spec.rb` test. Initially, it seemed like the required fields were already present and the test passed. However, I need to confirm that this is truly the case before moving forward.",
|
|
"timestamp": "2026-02-20T17:14:12.843Z"
|
|
}
|
|
],
|
|
"tokens": {
|
|
"input": 55642,
|
|
"output": 56,
|
|
"cached": 50211,
|
|
"thoughts": 43,
|
|
"tool": 0,
|
|
"total": 55741
|
|
},
|
|
"model": "gemini-3-flash-preview",
|
|
"toolCalls": [
|
|
{
|
|
"id": "run_shell_command_1771607652920_0",
|
|
"name": "run_shell_command",
|
|
"args": {
|
|
"command": "bundle exec rspec spec/unit/rds_spec.rb"
|
|
},
|
|
"result": [
|
|
{
|
|
"functionResponse": {
|
|
"id": "run_shell_command_1771607652920_0",
|
|
"name": "run_shell_command",
|
|
"response": {
|
|
"output": "Output: \nDalmatian::Rds\n #identifier\n uses rds identifier\n #in_use_by\n uses rds in_use_by list\n #clusters_in_use\n uses rds clusters_in_use list\n #instance_class\n uses rds instance_class\n #engine\n uses rds engine\n #engine_version\n uses the rds engine_version\n #allocated_storage\n uses the rds allocated_storage\n #storage_encrypted\n uses the rds storage_encrypted bool\n #storage_type\n uses the rds storage_type gp3\n #db_name\n uses the rds db_name\n #port\n uses the rds port\n #maintenance_window\n uses the rds maintenance_window\n #backup_window\n uses the rds backup_window\n #backup_retention_period\n uses the rds backup_retention_period\n #force_ssl\n uses the rds force_ssl bool\n #parameter_store_path_db_url_name\n uses the rds parameter_store_path_db_url_name\n #sql_backup_scheduled_task_environment_variables\n uses the rds sql_backup_scheduled_task_environment_variables\n #check_sql_backup_scheduled_task_environment_variables\n uses the rds check_sql_backup_scheduled_task_environment_variables\n #sync_sql_backup_to_azure\n will have offsite backups disabled by default\n #replication_bucket_destination_arn\n uses the rds replication_bucket_destination_arn\n #replication_kms_key_id\n uses the rds replication_kms_key_id\n #codebuild_access\n uses the rds codebuild_access\n #to_params\n provides a hash of attributes for use in deployment\n\nFinished in 0.06462 seconds (files took 0.60378 seconds to load)\n23 examples, 0 failures\n\nCoverage report generated for RSpec to /Users/bob/git/dxw/dalmatian/coverage. 785 / 1772 LOC (44.3%) covered.\nLine coverage (44.30%) is below the expected minimum coverage (90.00%).\nSimpleCov failed with exit 2 due to a coverage related error\nExit Code: 2\nProcess Group PGID: 47976"
|
|
}
|
|
}
|
|
}
|
|
],
|
|
"status": "success",
|
|
"timestamp": "2026-02-20T17:14:14.300Z",
|
|
"resultDisplay": "\nDalmatian::Rds\n #identifier\n uses rds identifier\n #in_use_by\n uses rds in_use_by list\n #clusters_in_use\n uses rds clusters_in_use list\n #instance_class\n uses rds instance_class\n #engine\n uses rds engine\n #engine_version\n uses the rds engine_version\n #allocated_storage\n uses the rds allocated_storage\n #storage_encrypted\n uses the rds storage_encrypted bool\n #storage_type\n uses the rds storage_type gp3\n #db_name\n uses the rds db_name\n #port\n uses the rds port\n #maintenance_window\n uses the rds maintenance_window\n #backup_window\n uses the rds backup_window\n #backup_retention_period\n uses the rds backup_retention_period\n #force_ssl\n uses the rds force_ssl bool\n #parameter_store_path_db_url_name\n uses the rds parameter_store_path_db_url_name\n #sql_backup_scheduled_task_environment_variables\n uses the rds sql_backup_scheduled_task_environment_variables\n #check_sql_backup_scheduled_task_environment_variables\n uses the rds check_sql_backup_scheduled_task_environment_variables\n #sync_sql_backup_to_azure\n will have offsite backups disabled by default\n #replication_bucket_destination_arn\n uses the rds replication_bucket_destination_arn\n #replication_kms_key_id\n uses the rds replication_kms_key_id\n #codebuild_access\n uses the rds codebuild_access\n #to_params\n provides a hash of attributes for use in deployment\n\nFinished in 0.06462 seconds (files took 0.60378 seconds to load)\n23 examples, 0 failures\n\nCoverage report generated for RSpec to /Users/bob/git/dxw/dalmatian/coverage. 785 / 1772 LOC (44.3%) covered.\nLine coverage (44.30%) is below the expected minimum coverage (90.00%).\nSimpleCov failed with exit 2 due to a coverage related error",
|
|
"displayName": "Shell",
|
|
"description": "This tool executes a given shell command as `bash -c <command>`. To run a command in the background, set the `is_background` parameter to true. Do NOT use `&` to background commands. Command is executed as a subprocess that leads its own process group. Command process group can be terminated as `kill -- -PGID` or signaled as `kill -s SIGNAL -- -PGID`.\n\n Efficiency Guidelines:\n - Quiet Flags: Always prefer silent or quiet flags (e.g., `npm install --silent`, `git --no-pager`) to reduce output volume while still capturing necessary information.\n - Pagination: Always disable terminal pagination to ensure commands terminate (e.g., use `git --no-pager`, `systemctl --no-pager`, or set `PAGER=cat`).\n\n The following information is returned:\n\n Output: Combined stdout/stderr. Can be `(empty)` or partial on error and for any unwaited background processes.\n Exit Code: Only included if non-zero (command failed).\n Error: Only included if a process-level error occurred (e.g., spawn failure).\n Signal: Only included if process was terminated by a signal.\n Background PIDs: Only included if background processes were started.\n Process Group PGID: Only included if available.",
|
|
"renderOutputAsMarkdown": false
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"id": "c86d753a-56da-4144-8659-d1393b7d4b0c",
|
|
"timestamp": "2026-02-20T17:14:29.103Z",
|
|
"type": "gemini",
|
|
"content": "`spec/unit/rds_spec.rb` is fine, but the integration specs need fixing. I'll update `cluster1_plan_cmd_production_rds` and `cluster1_plan_cmd_staging_rds` in `spec/integration/tests_local_configuration_spec.rb`, and then check for any other `rds` commands.",
|
|
"thoughts": [
|
|
{
|
|
"subject": "Refining the integration tests",
|
|
"description": "I've confirmed that the unit tests are passing, which is good. The integration specs are where the issues lie. I'm starting with `tests_local_configuration_spec.rb` and will focus on updating the `cluster1_plan_cmd_production_rds` and `cluster1` sections to resolve the integration problems.",
|
|
"timestamp": "2026-02-20T17:14:28.005Z"
|
|
},
|
|
{
|
|
"subject": "Pinpointing Integration Failures",
|
|
"description": "Right, `spec/unit/rds_spec.rb` passed without issue. The integration tests, though, are the culprit. My focus is on updating `tests_local_configuration_spec.rb`, particularly the `cluster1_plan_cmd_production_rds` and the `cluster1 _plan_cmd_staging_rds` sections. Just ran a `grep` to check for other potentially affected `rds` commands.",
|
|
"timestamp": "2026-02-20T17:14:28.947Z"
|
|
}
|
|
],
|
|
"tokens": {
|
|
"input": 56270,
|
|
"output": 110,
|
|
"cached": 43559,
|
|
"thoughts": 117,
|
|
"tool": 0,
|
|
"total": 56497
|
|
},
|
|
"model": "gemini-3-flash-preview",
|
|
"toolCalls": [
|
|
{
|
|
"id": "run_shell_command_1771607669097_0",
|
|
"name": "run_shell_command",
|
|
"args": {
|
|
"command": "grep \"rds\" spec/integration/tests_local_configuration_spec.rb | grep \"let\""
|
|
},
|
|
"result": [
|
|
{
|
|
"functionResponse": {
|
|
"id": "run_shell_command_1771607669097_0",
|
|
"name": "run_shell_command",
|
|
"response": {
|
|
"output": "Output: let(:cluster1_validate_cmd_production_rds) do\n let(:cluster1_validate_cmd_staging_rds) do\n let(:cluster1_plan_cmd_production_rds) do\n let(:cluster1_plan_cmd_staging_rds) do\nProcess Group PGID: 48423"
|
|
}
|
|
}
|
|
}
|
|
],
|
|
"status": "success",
|
|
"timestamp": "2026-02-20T17:14:29.195Z",
|
|
"resultDisplay": " let(:cluster1_validate_cmd_production_rds) do\n let(:cluster1_validate_cmd_staging_rds) do\n let(:cluster1_plan_cmd_production_rds) do\n let(:cluster1_plan_cmd_staging_rds) do",
|
|
"displayName": "Shell",
|
|
"description": "This tool executes a given shell command as `bash -c <command>`. To run a command in the background, set the `is_background` parameter to true. Do NOT use `&` to background commands. Command is executed as a subprocess that leads its own process group. Command process group can be terminated as `kill -- -PGID` or signaled as `kill -s SIGNAL -- -PGID`.\n\n Efficiency Guidelines:\n - Quiet Flags: Always prefer silent or quiet flags (e.g., `npm install --silent`, `git --no-pager`) to reduce output volume while still capturing necessary information.\n - Pagination: Always disable terminal pagination to ensure commands terminate (e.g., use `git --no-pager`, `systemctl --no-pager`, or set `PAGER=cat`).\n\n The following information is returned:\n\n Output: Combined stdout/stderr. Can be `(empty)` or partial on error and for any unwaited background processes.\n Exit Code: Only included if non-zero (command failed).\n Error: Only included if a process-level error occurred (e.g., spawn failure).\n Signal: Only included if process was terminated by a signal.\n Background PIDs: Only included if background processes were started.\n Process Group PGID: Only included if available.",
|
|
"renderOutputAsMarkdown": false
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"id": "be96dba5-68ee-45e8-9183-d9219c2bffa3",
|
|
"timestamp": "2026-02-20T17:14:33.880Z",
|
|
"type": "gemini",
|
|
"content": "I have four definitions to fix in `spec/integration/tests_local_configuration_spec.rb` and need to check `spec/integration/deploys_local_configuration_spec.rb`. Since `replication_bucket_destination_arn` and `replication_kms_key_id` default to `\"\"` in `lib/dalmatian/rds.rb`, I'll use `replace` to add these fields to the RDS definitions in the spec files.",
|
|
"thoughts": [
|
|
{
|
|
"subject": "Analyzing Configuration Files",
|
|
"description": "I've been examining the `spec/integration/tests_local_configuration_spec.rb` file and have located four key definitions. Now, I need to shift my attention to `spec/integration/deploys_local_configuration_spec.rb` for further analysis. A quick review also revealed `replication_bucket_destination_arn` and `replication_kms_key_id`, which warrant immediate consideration.",
|
|
"timestamp": "2026-02-20T17:14:32.119Z"
|
|
},
|
|
{
|
|
"subject": "Refining Implementation Strategy",
|
|
"description": "I'm now revisiting `lib/dalmatian/rds.rb` to confirm the default string values for `replication_bucket_destination_arn` and `replication_kms_key_id`. This confirms my initial assessment. I will then examine the RDS definitions within `spec/integration/tests_local_configuration_spec.rb` and use a replacement strategy for incorporating the new fields.",
|
|
"timestamp": "2026-02-20T17:14:33.376Z"
|
|
}
|
|
],
|
|
"tokens": {
|
|
"input": 56459,
|
|
"output": 234,
|
|
"cached": 53529,
|
|
"thoughts": 240,
|
|
"tool": 0,
|
|
"total": 56933
|
|
},
|
|
"model": "gemini-3-flash-preview",
|
|
"toolCalls": [
|
|
{
|
|
"id": "run_shell_command_1771607673877_0",
|
|
"name": "run_shell_command",
|
|
"args": {
|
|
"command": "grep -n \"let(:cluster1_validate_cmd_production_rds)\" spec/integration/tests_local_configuration_spec.rb\ngrep -n \"let(:cluster1_validate_cmd_staging_rds)\" spec/integration/tests_local_configuration_spec.rb\ngrep -n \"let(:cluster1_plan_cmd_production_rds)\" spec/integration/tests_local_configuration_spec.rb\ngrep -n \"let(:cluster1_plan_cmd_staging_rds)\" spec/integration/tests_local_configuration_spec.rb"
|
|
},
|
|
"result": [
|
|
{
|
|
"functionResponse": {
|
|
"id": "run_shell_command_1771607673877_0",
|
|
"name": "run_shell_command",
|
|
"response": {
|
|
"output": "Output: 352: let(:cluster1_validate_cmd_production_rds) do\n470: let(:cluster1_validate_cmd_staging_rds) do\n1719: let(:cluster1_plan_cmd_production_rds) do\n1837: let(:cluster1_plan_cmd_staging_rds) do\nProcess Group PGID: 48456"
|
|
}
|
|
}
|
|
}
|
|
],
|
|
"status": "success",
|
|
"timestamp": "2026-02-20T17:14:34.008Z",
|
|
"resultDisplay": "352: let(:cluster1_validate_cmd_production_rds) do\n470: let(:cluster1_validate_cmd_staging_rds) do\n1719: let(:cluster1_plan_cmd_production_rds) do\n1837: let(:cluster1_plan_cmd_staging_rds) do",
|
|
"displayName": "Shell",
|
|
"description": "This tool executes a given shell command as `bash -c <command>`. To run a command in the background, set the `is_background` parameter to true. Do NOT use `&` to background commands. Command is executed as a subprocess that leads its own process group. Command process group can be terminated as `kill -- -PGID` or signaled as `kill -s SIGNAL -- -PGID`.\n\n Efficiency Guidelines:\n - Quiet Flags: Always prefer silent or quiet flags (e.g., `npm install --silent`, `git --no-pager`) to reduce output volume while still capturing necessary information.\n - Pagination: Always disable terminal pagination to ensure commands terminate (e.g., use `git --no-pager`, `systemctl --no-pager`, or set `PAGER=cat`).\n\n The following information is returned:\n\n Output: Combined stdout/stderr. Can be `(empty)` or partial on error and for any unwaited background processes.\n Exit Code: Only included if non-zero (command failed).\n Error: Only included if a process-level error occurred (e.g., spawn failure).\n Signal: Only included if process was terminated by a signal.\n Background PIDs: Only included if background processes were started.\n Process Group PGID: Only included if available.",
|
|
"renderOutputAsMarkdown": false
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"id": "9e680491-11e2-4387-926a-eba212e8863e",
|
|
"timestamp": "2026-02-20T17:14:36.388Z",
|
|
"type": "gemini",
|
|
"content": "Let's check the first one.",
|
|
"thoughts": [
|
|
{
|
|
"subject": "Initiating Conceptualization",
|
|
"description": "I'm starting the process of generating ideas. The goal is to produce some initial concepts. Let's see how this unfolds.",
|
|
"timestamp": "2026-02-20T17:14:36.268Z"
|
|
}
|
|
],
|
|
"tokens": {
|
|
"input": 56791,
|
|
"output": 36,
|
|
"cached": 53379,
|
|
"thoughts": 8,
|
|
"tool": 0,
|
|
"total": 56835
|
|
},
|
|
"model": "gemini-3-flash-preview",
|
|
"toolCalls": [
|
|
{
|
|
"id": "read_file_1771607676386_0",
|
|
"name": "read_file",
|
|
"args": {
|
|
"offset": 352,
|
|
"file_path": "spec/integration/tests_local_configuration_spec.rb",
|
|
"limit": 50
|
|
},
|
|
"result": [
|
|
{
|
|
"functionResponse": {
|
|
"id": "read_file_1771607676386_0",
|
|
"name": "read_file",
|
|
"response": {
|
|
"output": "\nIMPORTANT: The file content has been truncated.\nStatus: Showing lines 353-402 of 3243 total lines.\nAction: To read more of the file, you can use the 'offset' and 'limit' parameters in a subsequent 'read_file' call. For example, to read the next section of the file, use offset: 402.\n\n--- FILE CONTENT (truncated) ---\n terraform_validate_cmd(\n tfvar_arg_string(\n infrastructure_defaults.merge(\n \"instance_type\" => \"t2.medium\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"account_id\" => \"123456789012\",\n \"infrastructure_name\" => \"new-dedicated-cluster\",\n \"dalmatian_role\" => \"dalmatian-read\",\n \"environment\" => \"production\",\n \"rds\" => {\n \"identifier\" => \"testservice\",\n \"in_use_by\" => [\n \"test-service\"\n ],\n \"clusters_in_use\" => {\n \"production\" => [\n \"test\"\n ],\n \"staging\" => [\n \"test\"\n ]\n },\n \"instance_class\" => {\n \"production\" => \"db.t2.small\",\n \"staging\" => \"db.t2.micro\"\n },\n \"engine\" => \"postgres\",\n \"engine_version\" => \"11.4\",\n \"allocated_storage\" => 20,\n \"storage_encrypted\" => true,\n \"storage_type\" => \"gp3\",\n \"db_name\" => \"testapp\",\n \"port\" => 5432,\n \"maintenance_window\" => \"mon:19:00-mon:19:30\",\n \"backup_window\" => \"09:00-10:00\",\n \"backup_retention_period\" => 31,\n \"force_ssl\" => true,\n \"parameter_store_path_db_url_name\" => \"DATABASE_URL\",\n \"sql_backup_scheduled_task_environment_variables\" => [\n {\n \"name\" => \"foo\",\n \"value\" => \"bar\"\n }\n ],\n \"check_sql_backup_scheduled_task_environment_variables\" => [\n {\n \"name\" => \"foo\",\n \"value\" => \"bar\"\n }"
|
|
}
|
|
}
|
|
}
|
|
],
|
|
"status": "success",
|
|
"timestamp": "2026-02-20T17:14:36.414Z",
|
|
"resultDisplay": "Read lines 353-402 of 3243 from spec/integration/tests_local_configuration_spec.rb",
|
|
"displayName": "ReadFile",
|
|
"description": "Reads and returns the content of a specified file. If the file is large, the content will be truncated. The tool's response will clearly indicate if truncation has occurred and will provide details on how to read more of the file using the 'offset' and 'limit' parameters. Handles text, images (PNG, JPG, GIF, WEBP, SVG, BMP), audio files (MP3, WAV, AIFF, AAC, OGG, FLAC), and PDF files. For text files, it can read specific line ranges.",
|
|
"renderOutputAsMarkdown": true
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"id": "bfd79605-95e3-4e88-b484-124fc7e0f583",
|
|
"timestamp": "2026-02-20T17:14:38.657Z",
|
|
"type": "gemini",
|
|
"content": "Is `sync_sql_backup_to_azure` missing? I'll check.",
|
|
"thoughts": [
|
|
{
|
|
"subject": "Reviewing Missing Components",
|
|
"description": "I'm now investigating a missing component, specifically `sync_sql_backup_to_azure`. I was momentarily thrown, but I'm digging deeper now to understand its absence. My focus is on the wider context to ensure I don't miss anything else.",
|
|
"timestamp": "2026-02-20T17:14:38.563Z"
|
|
}
|
|
],
|
|
"tokens": {
|
|
"input": 57425,
|
|
"output": 47,
|
|
"cached": 53455,
|
|
"thoughts": 27,
|
|
"tool": 0,
|
|
"total": 57499
|
|
},
|
|
"model": "gemini-3-flash-preview",
|
|
"toolCalls": [
|
|
{
|
|
"id": "read_file_1771607678654_0",
|
|
"name": "read_file",
|
|
"args": {
|
|
"file_path": "spec/integration/tests_local_configuration_spec.rb",
|
|
"offset": 402,
|
|
"limit": 50
|
|
},
|
|
"result": [
|
|
{
|
|
"functionResponse": {
|
|
"id": "read_file_1771607678654_0",
|
|
"name": "read_file",
|
|
"response": {
|
|
"output": "\nIMPORTANT: The file content has been truncated.\nStatus: Showing lines 403-452 of 3243 total lines.\nAction: To read more of the file, you can use the 'offset' and 'limit' parameters in a subsequent 'read_file' call. For example, to read the next section of the file, use offset: 452.\n\n--- FILE CONTENT (truncated) ---\n ],\n \"sync_sql_backup_to_azure\" => false,\n \"codebuild_access\" => [\n \"service-name\"\n ]\n }\n )\n )\n )\n end\n\n let(:cluster1_validate_cmd_staging_waf) do\n terraform_validate_cmd(\n tfvar_arg_string(\n infrastructure_defaults.merge(\n \"instance_type\" => \"t2.small\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"track_revision\" => \"feature/experiment\",\n \"extra_ecs_clusters\" => [\n {\n \"name\" => \"test\",\n \"subnets_name\" => \"extra_private_subnets\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"instance_type\" => \"t3.small\"\n }\n ],\n \"tinyproxy\" => {\n \"create\" => true\n },\n \"account_id\" => \"123456789012\",\n \"infrastructure_name\" => \"new-dedicated-cluster\",\n \"dalmatian_role\" => \"dalmatian-read\",\n \"environment\" => \"staging\",\n \"waf\" => {\n \"name\" => \"test-1\",\n \"action\" => \"count\",\n \"ip_deny_list\" => [],\n \"aws_managed_rules\" => [\n {\n \"name\" => \"AWSManagedRulesSQLiRuleSet\",\n \"excluded_path_patterns\" => [\n \"/wp-admin/async-upload.php\"\n ]\n },\n {\n \"name\" => \"AWSManagedRulesCommonRuleSet\",\n \"exclude_rules\" => [\n \"SizeRestrictions_BODY\""
|
|
}
|
|
}
|
|
}
|
|
],
|
|
"status": "success",
|
|
"timestamp": "2026-02-20T17:14:38.682Z",
|
|
"resultDisplay": "Read lines 403-452 of 3243 from spec/integration/tests_local_configuration_spec.rb",
|
|
"displayName": "ReadFile",
|
|
"description": "Reads and returns the content of a specified file. If the file is large, the content will be truncated. The tool's response will clearly indicate if truncation has occurred and will provide details on how to read more of the file using the 'offset' and 'limit' parameters. Handles text, images (PNG, JPG, GIF, WEBP, SVG, BMP), audio files (MP3, WAV, AIFF, AAC, OGG, FLAC), and PDF files. For text files, it can read specific line ranges.",
|
|
"renderOutputAsMarkdown": true
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"id": "fcfadadd-0582-4bc5-becb-1570cfe9f5b4",
|
|
"timestamp": "2026-02-20T17:14:44.134Z",
|
|
"type": "gemini",
|
|
"content": "`sync_sql_backup_to_azure` is on line 404. I need to insert `replication_bucket_destination_arn` and `replication_kms_key_id` between `sync_sql_backup_to_azure` and `codebuild_access` in the RDS hashes to match the order in `Rds#to_params`. I'll use the `replace` tool to update `spec/integration/tests_local_configuration_spec.rb` and `spec/integration/deploys_local_configuration_spec.rb`.",
|
|
"thoughts": [
|
|
{
|
|
"subject": "Reviewing the Configuration",
|
|
"description": "I'm currently reviewing the RDS hash configurations, specifically focusing on the replication settings. I've noted the presence of `sync_sql_backup_to_azure` and I'm updating all RDS hashes to include `replication_bucket_destination _arn` and `replication_kms_key_id`. This is where I am now.",
|
|
"timestamp": "2026-02-20T17:14:41.149Z"
|
|
},
|
|
{
|
|
"subject": "Updating the Configuration",
|
|
"description": "I've located `sync_sql_backup_to_azure` and confirmed the need to insert `replication_bucket_destination_arn` and `replication_kms_key_id` into the RDS hash configurations. I've also identified their correct placement within the hash based on the `to_params` method. I'm now planning a script for the automated replacement within the integration tests, but I might just use the `replace` tool, actually.",
|
|
"timestamp": "2026-02-20T17:14:43.133Z"
|
|
}
|
|
],
|
|
"tokens": {
|
|
"input": 58002,
|
|
"output": 307,
|
|
"cached": 56849,
|
|
"thoughts": 376,
|
|
"tool": 0,
|
|
"total": 58685
|
|
},
|
|
"model": "gemini-3-flash-preview",
|
|
"toolCalls": [
|
|
{
|
|
"id": "replace_1771607684132_0",
|
|
"name": "replace",
|
|
"args": {
|
|
"file_path": "/Users/bob/git/dxw/dalmatian/spec/integration/tests_local_configuration_spec.rb",
|
|
"new_string": " \"sync_sql_backup_to_azure\" => false,\n \"replication_bucket_destination_arn\" => \"\",\n \"replication_kms_key_id\" => \"\",\n \"codebuild_access\" => [",
|
|
"expected_replacements": 2,
|
|
"old_string": " \"sync_sql_backup_to_azure\" => false,\n \"codebuild_access\" => [",
|
|
"instruction": "In 'cluster1_validate_cmd_production_rds' and 'cluster1_validate_cmd_staging_rds' (and other RDS command definitions), add the missing 'replication_bucket_destination_arn' and 'replication_kms_key_id' fields to the RDS configuration hash to match the updated 'Rds#to_params' method."
|
|
},
|
|
"result": [
|
|
{
|
|
"functionResponse": {
|
|
"id": "replace_1771607684132_0",
|
|
"name": "replace",
|
|
"response": {
|
|
"error": "Failed to edit, Expected 2 occurrences but found 4 for old_string in file: /Users/bob/git/dxw/dalmatian/spec/integration/tests_local_configuration_spec.rb"
|
|
}
|
|
}
|
|
}
|
|
],
|
|
"status": "error",
|
|
"timestamp": "2026-02-20T17:14:44.175Z",
|
|
"resultDisplay": "Error: Failed to edit, expected 2 occurrences but found 4.",
|
|
"displayName": "Edit",
|
|
"description": "Replaces text within a file. By default, replaces a single occurrence, but can replace multiple occurrences when `expected_replacements` is specified. This tool requires providing significant context around the change to ensure precise targeting. Always use the read_file tool to examine the file's current content before attempting a text replacement.\n \n The user has the ability to modify the `new_string` content. If modified, this will be stated in the response.\n \n Expectation for required parameters:\n 1. `old_string` MUST be the exact literal text to replace (including all whitespace, indentation, newlines, and surrounding code etc.).\n 2. `new_string` MUST be the exact literal text to replace `old_string` with (also including all whitespace, indentation, newlines, and surrounding code etc.). Ensure the resulting code is correct and idiomatic and that `old_string` and `new_string` are different.\n 3. `instruction` is the detailed instruction of what needs to be changed. It is important to Make it specific and detailed so developers or large language models can understand what needs to be changed and perform the changes on their own if necessary. \n 4. NEVER escape `old_string` or `new_string`, that would break the exact literal text requirement.\n **Important:** If ANY of the above are not satisfied, the tool will fail. CRITICAL for `old_string`: Must uniquely identify the single instance to change. Include at least 3 lines of context BEFORE and AFTER the target text, matching whitespace and indentation precisely. If this string matches multiple locations, or does not match exactly, the tool will fail.\n 5. Prefer to break down complex and long changes into multiple smaller atomic calls to this tool. Always check the content of the file after changes or not finding a string to match.\n **Multiple replacements:** Set `expected_replacements` to the number of occurrences you want to replace. The tool will replace ALL occurrences that match `old_string` exactly. Ensure the number of replacements matches your expectation.",
|
|
"renderOutputAsMarkdown": true
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"id": "7296b41c-c8a6-48cc-9b77-1765db888a83",
|
|
"timestamp": "2026-02-20T17:14:46.735Z",
|
|
"type": "gemini",
|
|
"content": "I messed up the `expected_replacements` count; it should be 4. Fixing it now.",
|
|
"thoughts": [
|
|
{
|
|
"subject": "Fixing a Parameter",
|
|
"description": "I've just made a crucial adjustment. The `expected_replacements` parameter was off; it needed to be set to 4. I've corrected it.",
|
|
"timestamp": "2026-02-20T17:14:46.004Z"
|
|
}
|
|
],
|
|
"tokens": {
|
|
"input": 58367,
|
|
"output": 225,
|
|
"cached": 56581,
|
|
"thoughts": 24,
|
|
"tool": 0,
|
|
"total": 58616
|
|
},
|
|
"model": "gemini-3-flash-preview",
|
|
"toolCalls": [
|
|
{
|
|
"id": "replace_1771607686732_0",
|
|
"name": "replace",
|
|
"args": {
|
|
"file_path": "/Users/bob/git/dxw/dalmatian/spec/integration/tests_local_configuration_spec.rb",
|
|
"instruction": "In all RDS command definitions (cluster1_validate_cmd_production_rds, cluster1_validate_cmd_staging_rds, cluster1_plan_cmd_production_rds, cluster1_plan_cmd_staging_rds), add the missing 'replication_bucket_destination_arn' and 'replication_kms_key_id' fields to the RDS configuration hash.",
|
|
"expected_replacements": 4,
|
|
"old_string": " \"sync_sql_backup_to_azure\" => false,\n \"codebuild_access\" => [",
|
|
"new_string": " \"sync_sql_backup_to_azure\" => false,\n \"replication_bucket_destination_arn\" => \"\",\n \"replication_kms_key_id\" => \"\",\n \"codebuild_access\" => ["
|
|
},
|
|
"result": [
|
|
{
|
|
"functionResponse": {
|
|
"id": "replace_1771607686732_0",
|
|
"name": "replace",
|
|
"response": {
|
|
"output": "Successfully modified file: /Users/bob/git/dxw/dalmatian/spec/integration/tests_local_configuration_spec.rb (4 replacements)."
|
|
}
|
|
}
|
|
}
|
|
],
|
|
"status": "success",
|
|
"timestamp": "2026-02-20T17:14:46.775Z",
|
|
"resultDisplay": {
|
|
"fileDiff": "Index: tests_local_configuration_spec.rb\n===================================================================\n--- tests_local_configuration_spec.rb\tCurrent\n+++ tests_local_configuration_spec.rb\tProposed\n@@ -402,6 +402,8 @@\n }\n ],\n \"sync_sql_backup_to_azure\" => false,\n+ \"replication_bucket_destination_arn\" => \"\",\n+ \"replication_kms_key_id\" => \"\",\n \"codebuild_access\" => [\n \"service-name\"\n ]\n@@ -533,6 +535,8 @@\n }\n ],\n \"sync_sql_backup_to_azure\" => false,\n+ \"replication_bucket_destination_arn\" => \"\",\n+ \"replication_kms_key_id\" => \"\",\n \"codebuild_access\" => [\n \"service-name\"\n ]\n@@ -1769,6 +1773,8 @@\n }\n ],\n \"sync_sql_backup_to_azure\" => false,\n+ \"replication_bucket_destination_arn\" => \"\",\n+ \"replication_kms_key_id\" => \"\",\n \"codebuild_access\" => [\n \"service-name\"\n ]\n@@ -1900,6 +1906,8 @@\n }\n ],\n \"sync_sql_backup_to_azure\" => false,\n+ \"replication_bucket_destination_arn\" => \"\",\n+ \"replication_kms_key_id\" => \"\",\n \"codebuild_access\" => [\n \"service-name\"\n ]\n",
|
|
"fileName": "tests_local_configuration_spec.rb",
|
|
"filePath": "/Users/bob/git/dxw/dalmatian/spec/integration/tests_local_configuration_spec.rb",
|
|
"originalContent": "require_relative \"../support/spec_helper\"\n\nmodule Dalmatian\n RSpec.describe \"tests local configuration\" do\n def fake_parameter_store\n double(\n \"parameter_store\",\n get_parameter: \"\",\n get_parameters_by_path: {}\n )\n end\n\n def tfvar_arg_string(tfvars)\n Terraform.tfvar_arg_string(tfvars)\n end\n\n def terraform_validate_cmd(tfvar_string)\n \"#{tfvar_string} terraform validate\"\n end\n\n def terraform_plan_cmd(tfvar_string)\n \"#{tfvar_string} terraform plan\"\n end\n\n def stub_workspace_creation_cmds\n %w[\n new-dedicated-cluster-example-domain-name-com-hz\n new-dedicated-cluster-test-s3\n new-dedicated-cluster-test-vpn-vpn-cg\n new-dedicated-cluster-ecs-production\n new-dedicated-cluster-ecs-staging\n new-dedicated-cluster-0-production\n new-dedicated-cluster-0-staging\n new-dedicated-cluster-test-service-staging\n new-dedicated-cluster-test-service-production\n new-dedicated-cluster-test-1-waf-staging\n new-dedicated-cluster-test-1-waf-production\n new-dedicated-cluster-testservice-rds-staging\n new-dedicated-cluster-testservice-rds-production\n new-dedicated-cluster-testredis-elasticache-cluster-staging\n new-dedicated-cluster-testredis-elasticache-cluster-production\n new-dedicated-cluster-testos-opensearch-cluster-staging\n new-dedicated-cluster-testos-opensearch-cluster-production\n new-dedicated-cluster-test-lb-1-shared-loadbalancer-staging\n new-dedicated-cluster-test-lb-1-shared-loadbalancer-production\n shared-new-cluster-ecs-production\n shared-new-cluster-ecs-staging\n existing-shared-cluster-staging-0-staging\n existing-shared-cluster-production-0-production\n ].each do |workspace_name|\n allow(Helper).to receive(:run!).with(\"terraform workspace new #{workspace_name}\")\n end\n end\n\n def stub_git_checkout\n allow(Helper).to receive(:run!).with(\"git checkout feature/experiment\")\n end\n\n def stub_git_clone_cmds\n [\n {\n source: \"git@github.com:dxw/awesome-app-dalmatian-config\",\n name: \"new-dedicated-cluster-0.config\"\n },\n {\n source: \"git@github.com:dxw/funky-app-dalmatian-config\",\n name: \"existing-shared-cluster-staging-0.config\"\n },\n {\n source: \"git@github.com:dxw/neat-app-dalmatian-config\",\n name: \"existing-shared-cluster-production-0.config\"\n },\n {\n source: \"git@github.com:dxw/neat-app-dalmatian-config\",\n name: \"existing-shared-cluster-production-0.config\"\n }\n\n ].each do |src|\n allow(Helper).to receive(:run!)\n .with(\"git clone #{src.fetch(:source)} terraform/infrastructures/#{src.fetch(:name)}\")\n end\n end\n\n def infrastructure_defaults\n {\n \"region\" => \"eu-west-2\",\n \"cidr\" => \"10.0.0.0/16\",\n \"root_domain_zone\" => \"dalmatian.dxw.net\",\n \"internal_domain_zone\" => \"dalmatian.internal\",\n \"ecs_private_subnets\" => [\n {\n \"availability_zone\" => \"eu-west-2a\",\n \"cidr\" => \"10.0.128.0/24\"\n },\n {\n \"availability_zone\" => \"eu-west-2b\",\n \"cidr\" => \"10.0.129.0/24\"\n },\n {\n \"availability_zone\" => \"eu-west-2c\",\n \"cidr\" => \"10.0.130.0/24\"\n }\n ],\n \"extra_public_subnets\" => [\n {\n \"availability_zone\" => \"eu-west-2a\",\n \"cidr\" => \"10.0.0.0/24\"\n },\n {\n \"availability_zone\" => \"eu-west-2b\",\n \"cidr\" => \"10.0.1.0/24\"\n },\n {\n \"availability_zone\" => \"eu-west-2c\",\n \"cidr\" => \"10.0.2.0/24\"\n }\n ],\n \"instances_key_name\" => \"dalmatian-ecs-instances\",\n \"instance_type\" => \"t2.medium\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"max_instance_lifetime\" => \"86400\",\n \"associate_public_ip_address\" => \"0\",\n \"docker_storage_size\" => \"40\",\n \"dockerhub_email\" => \"\",\n \"dockerhub_token\" => \"\",\n \"enable_efs\" => \"false\",\n \"encrypt_efs\" => \"true\",\n \"efs_dirs\" => [],\n \"monitoring_docs_path\" => \"https://github.com/dxw/dalmatian/docs/monitoring-alarms/\"\n }\n end\n\n let(:cluster1_validate_cmd_hz) do\n terraform_validate_cmd(\n tfvar_arg_string(\n \"account_id\" => \"123456789012\",\n \"cluster_id\" => \"new-dedicated-cluster\",\n \"dalmatian_role\" => \"dalmatian-read\",\n \"hosted_zone\" => {\n \"domain\" => \"example-domain-name.com\",\n \"ns_records\" => [\n {\n \"name\" => \"delegated\",\n \"value\" => [\n \"ns1.aws.com\"\n ]\n }\n ],\n \"a_records\" => [\n {\n \"name\" => \"some-service\",\n \"value\" => [\n \"1.2.3.4\"\n ]\n },\n {\n \"name\" => \"mail\",\n \"value\" => [\n \"5.6.7.8\"\n ]\n }\n ],\n \"alias_records\" => [\n {\n \"name\" => \"example-domain-name.com\",\n \"value\" => \"cf-distribution.aws.net\"\n },\n {\n \"name\" => \"www\",\n \"value\" => \"cf-distribution.aws.net\"\n }\n ],\n \"cname_records\" => [\n {\n \"name\" => \"alb\",\n \"value\" => [\n \"aws-alb.aws.net\"\n ]\n }\n ],\n \"mx_records\" => [\n {\n \"name\" => \"mail\",\n \"value\" => [\n \"0 mail.example-domain-name.com\"\n ]\n }\n ],\n \"txt_records\" => [\n {\n \"name\" => \"mail\",\n \"value\" => [\n \"v=spf1 a ip4:9.10.11.0/24 mx ~all\"\n ]\n }\n ],\n \"srv_records\" => [\n {\n \"name\" => \"@\",\n \"value\" => [\n \"_imaps._tcp.gmail.com. 86400 IN SRV 5 0 993 imap.gmail.com\"\n ]\n }\n ]\n }\n )\n )\n end\n\n let(:cluster1_validate_cmd_s3) do\n terraform_validate_cmd(\n tfvar_arg_string(\n \"account_id\" => \"123456789012\",\n \"cluster_id\" => \"new-dedicated-cluster\",\n \"dalmatian_role\" => \"dalmatian-read\",\n \"s3\" => {\n \"name\" => \"test\",\n \"enable_s3_versioning\" => true,\n \"encrypted\" => true,\n \"acl\" => \"private\",\n \"policy\" => {\n \"staging\" => {\n \"rw\" => {\n \"services\" => [\n \"test-service\"\n ]\n }\n }\n },\n \"service_cloudfront_read_access\" => [\n \"test-service-staging\"\n ],\n \"cloudfront\" => {\n \"create\" => true,\n \"domain_names\" => [\n \"example.com\",\n \"example2.com\"\n ],\n \"certificate\" => \"arn:aws:acm:lb-region-0:000000000000:certificate/00000000-0000-0000-0000-000000000000\"\n }\n }\n )\n )\n end\n\n let(:cluster1_validate_cmd_vpn_cg) do\n terraform_validate_cmd(\n tfvar_arg_string(\n \"account_id\" => \"123456789012\",\n \"cluster_id\" => \"new-dedicated-cluster\",\n \"dalmatian_role\" => \"dalmatian-read\",\n \"vpn_customer_gateway\" => {\n \"name\" => \"test-vpn\",\n \"bgp_asn\" => 65000,\n \"ip_address\" => \"1.2.3.4\"\n }\n )\n )\n end\n\n let(:cluster1_validate_cmd_production) do\n terraform_validate_cmd(\n tfvar_arg_string(\n infrastructure_defaults.merge(\n \"instance_type\" => \"t2.medium\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"cluster_name\" => \"new-dedicated-cluster-production\",\n \"account_id\" => \"123456789012\",\n \"infrastructure_name\" => \"new-dedicated-cluster\",\n \"dalmatian_role\" => \"dalmatian-read\",\n \"environment\" => \"production\"\n )\n )\n )\n end\n\n let(:cluster1_validate_cmd_staging) do\n terraform_validate_cmd(\n tfvar_arg_string(\n infrastructure_defaults.merge(\n \"instance_type\" => \"t2.small\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"track_revision\" => \"feature/experiment\",\n \"extra_ecs_clusters\" => [\n {\n \"name\" => \"test\",\n \"subnets_name\" => \"extra_private_subnets\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"instance_type\" => \"t3.small\"\n }\n ],\n \"tinyproxy\" => {\n \"create\" => true\n },\n \"cluster_name\" => \"new-dedicated-cluster-staging\",\n \"account_id\" => \"123456789012\",\n \"infrastructure_name\" => \"new-dedicated-cluster\",\n \"dalmatian_role\" => \"dalmatian-read\",\n \"environment\" => \"staging\"\n )\n )\n )\n end\n\n let(:cluster1_validate_cmd_production_waf) do\n terraform_validate_cmd(\n tfvar_arg_string(\n infrastructure_defaults.merge(\n \"instance_type\" => \"t2.medium\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"account_id\" => \"123456789012\",\n \"infrastructure_name\" => \"new-dedicated-cluster\",\n \"dalmatian_role\" => \"dalmatian-read\",\n \"environment\" => \"production\",\n \"waf\" => {\n \"name\" => \"test-1\",\n \"action\" => \"count\",\n \"ip_deny_list\" => [],\n \"aws_managed_rules\" => [\n {\n \"name\" => \"AWSManagedRulesSQLiRuleSet\",\n \"excluded_path_patterns\" => [\n \"/wp-admin/async-upload.php\"\n ]\n },\n {\n \"name\" => \"AWSManagedRulesCommonRuleSet\",\n \"exclude_rules\" => [\n \"SizeRestrictions_BODY\"\n ]\n }\n ],\n \"associations\" => {\n shared_loadbalancers: [\n \"test-lb-1\"\n ],\n service_cloudfront: [\n \"test-service\"\n ]\n }\n }\n )\n )\n )\n end\n\n let(:cluster1_validate_cmd_production_rds) do\n terraform_validate_cmd(\n tfvar_arg_string(\n infrastructure_defaults.merge(\n \"instance_type\" => \"t2.medium\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"account_id\" => \"123456789012\",\n \"infrastructure_name\" => \"new-dedicated-cluster\",\n \"dalmatian_role\" => \"dalmatian-read\",\n \"environment\" => \"production\",\n \"rds\" => {\n \"identifier\" => \"testservice\",\n \"in_use_by\" => [\n \"test-service\"\n ],\n \"clusters_in_use\" => {\n \"production\" => [\n \"test\"\n ],\n \"staging\" => [\n \"test\"\n ]\n },\n \"instance_class\" => {\n \"production\" => \"db.t2.small\",\n \"staging\" => \"db.t2.micro\"\n },\n \"engine\" => \"postgres\",\n \"engine_version\" => \"11.4\",\n \"allocated_storage\" => 20,\n \"storage_encrypted\" => true,\n \"storage_type\" => \"gp3\",\n \"db_name\" => \"testapp\",\n \"port\" => 5432,\n \"maintenance_window\" => \"mon:19:00-mon:19:30\",\n \"backup_window\" => \"09:00-10:00\",\n \"backup_retention_period\" => 31,\n \"force_ssl\" => true,\n \"parameter_store_path_db_url_name\" => \"DATABASE_URL\",\n \"sql_backup_scheduled_task_environment_variables\" => [\n {\n \"name\" => \"foo\",\n \"value\" => \"bar\"\n }\n ],\n \"check_sql_backup_scheduled_task_environment_variables\" => [\n {\n \"name\" => \"foo\",\n \"value\" => \"bar\"\n }\n ],\n \"sync_sql_backup_to_azure\" => false,\n \"codebuild_access\" => [\n \"service-name\"\n ]\n }\n )\n )\n )\n end\n\n let(:cluster1_validate_cmd_staging_waf) do\n terraform_validate_cmd(\n tfvar_arg_string(\n infrastructure_defaults.merge(\n \"instance_type\" => \"t2.small\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"track_revision\" => \"feature/experiment\",\n \"extra_ecs_clusters\" => [\n {\n \"name\" => \"test\",\n \"subnets_name\" => \"extra_private_subnets\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"instance_type\" => \"t3.small\"\n }\n ],\n \"tinyproxy\" => {\n \"create\" => true\n },\n \"account_id\" => \"123456789012\",\n \"infrastructure_name\" => \"new-dedicated-cluster\",\n \"dalmatian_role\" => \"dalmatian-read\",\n \"environment\" => \"staging\",\n \"waf\" => {\n \"name\" => \"test-1\",\n \"action\" => \"count\",\n \"ip_deny_list\" => [],\n \"aws_managed_rules\" => [\n {\n \"name\" => \"AWSManagedRulesSQLiRuleSet\",\n \"excluded_path_patterns\" => [\n \"/wp-admin/async-upload.php\"\n ]\n },\n {\n \"name\" => \"AWSManagedRulesCommonRuleSet\",\n \"exclude_rules\" => [\n \"SizeRestrictions_BODY\"\n ]\n }\n ],\n \"associations\" => {\n shared_loadbalancers: [\n \"test-lb-1\"\n ],\n service_cloudfront: [\n \"test-service\"\n ]\n }\n }\n )\n )\n )\n end\n\n let(:cluster1_validate_cmd_staging_rds) do\n terraform_validate_cmd(\n tfvar_arg_string(\n infrastructure_defaults.merge(\n \"instance_type\" => \"t2.small\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"track_revision\" => \"feature/experiment\",\n \"extra_ecs_clusters\" => [\n {\n \"name\" => \"test\",\n \"subnets_name\" => \"extra_private_subnets\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"instance_type\" => \"t3.small\"\n }\n ],\n \"tinyproxy\" => {\n \"create\" => true\n },\n \"account_id\" => \"123456789012\",\n \"infrastructure_name\" => \"new-dedicated-cluster\",\n \"dalmatian_role\" => \"dalmatian-read\",\n \"environment\" => \"staging\",\n \"rds\" => {\n \"identifier\" => \"testservice\",\n \"in_use_by\" => [\n \"test-service\"\n ],\n \"clusters_in_use\" => {\n \"production\" => [\n \"test\"\n ],\n \"staging\" => [\n \"test\"\n ]\n },\n \"instance_class\" => {\n \"production\" => \"db.t2.small\",\n \"staging\" => \"db.t2.micro\"\n },\n \"engine\" => \"postgres\",\n \"engine_version\" => \"11.4\",\n \"allocated_storage\" => 20,\n \"storage_encrypted\" => true,\n \"storage_type\" => \"gp3\",\n \"db_name\" => \"testapp\",\n \"port\" => 5432,\n \"maintenance_window\" => \"mon:19:00-mon:19:30\",\n \"backup_window\" => \"09:00-10:00\",\n \"backup_retention_period\" => 31,\n \"force_ssl\" => true,\n \"parameter_store_path_db_url_name\" => \"DATABASE_URL\",\n \"sql_backup_scheduled_task_environment_variables\" => [\n {\n \"name\" => \"foo\",\n \"value\" => \"bar\"\n }\n ],\n \"check_sql_backup_scheduled_task_environment_variables\" => [\n {\n \"name\" => \"foo\",\n \"value\" => \"bar\"\n }\n ],\n \"sync_sql_backup_to_azure\" => false,\n \"codebuild_access\" => [\n \"service-name\"\n ]\n }\n )\n )\n )\n end\n\n let(:cluster1_validate_cmd_production_elasticache_cluster) do\n terraform_validate_cmd(\n tfvar_arg_string(\n infrastructure_defaults.merge(\n \"instance_type\" => \"t2.medium\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"account_id\" => \"123456789012\",\n \"infrastructure_name\" => \"new-dedicated-cluster\",\n \"dalmatian_role\" => \"dalmatian-read\",\n \"environment\" => \"production\",\n \"elasticache_cluster\" => {\n \"identifier\" => \"testredis\",\n \"in_use_by\" => [\n \"test-service\"\n ],\n \"node_type\" => \"cache.t2.micro\",\n \"node_count\" => 1,\n \"engine\" => \"redis\",\n \"engine_version\" => \"5.0.6\",\n \"parameters\" => [],\n \"port\" => 6379,\n \"maintenance_window\" => \"mon:19:00-mon:22:00\",\n \"snapshot_window\" => \"09:00-10:00\",\n \"parameter_store_path_elasticache_cluster_url_name\" => \"REDIS_URL\"\n }\n )\n )\n )\n end\n\n let(:cluster1_validate_cmd_staging_elasticache_cluster) do\n terraform_validate_cmd(\n tfvar_arg_string(\n infrastructure_defaults.merge(\n \"instance_type\" => \"t2.small\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"track_revision\" => \"feature/experiment\",\n \"extra_ecs_clusters\" => [\n {\n \"name\" => \"test\",\n \"subnets_name\" => \"extra_private_subnets\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"instance_type\" => \"t3.small\"\n }\n ],\n \"tinyproxy\" => {\n \"create\" => true\n },\n \"account_id\" => \"123456789012\",\n \"infrastructure_name\" => \"new-dedicated-cluster\",\n \"dalmatian_role\" => \"dalmatian-read\",\n \"environment\" => \"staging\",\n \"elasticache_cluster\" => {\n \"identifier\" => \"testredis\",\n \"in_use_by\" => [\n \"test-service\"\n ],\n \"node_type\" => \"cache.t2.micro\",\n \"node_count\" => 1,\n \"engine\" => \"redis\",\n \"engine_version\" => \"5.0.6\",\n \"parameters\" => [],\n \"port\" => 6379,\n \"maintenance_window\" => \"mon:19:00-mon:22:00\",\n \"snapshot_window\" => \"09:00-10:00\",\n \"parameter_store_path_elasticache_cluster_url_name\" => \"REDIS_URL\"\n }\n )\n )\n )\n end\n\n let(:cluster1_validate_cmd_production_opensearch_cluster) do\n terraform_validate_cmd(\n tfvar_arg_string(\n infrastructure_defaults.merge(\n \"instance_type\" => \"t2.medium\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"account_id\" => \"123456789012\",\n \"infrastructure_name\" => \"new-dedicated-cluster\",\n \"dalmatian_role\" => \"dalmatian-read\",\n \"environment\" => \"production\",\n \"opensearch_cluster\" => {\n \"identifier\" => \"testos\",\n \"in_use_by\" => [\n \"test-service\"\n ],\n \"version\" => \"1.2\",\n \"master_enabled\" => true,\n \"master_count\" => \"1\",\n \"master_type\" => \"c6g.large.search\",\n \"instance_count\" => \"3\",\n \"instance_type\" => \"t3.small.search\",\n \"warm_enabled\" => true,\n \"warm_count\" => \"2\",\n \"warm_type\" => \"ultrawarm1.medium.search\",\n \"parameter_store_path_opensearch_cluster_url_name\" => \"ELASTICSEARCH_URL\",\n \"volume_size\" => \"20\"\n }\n )\n )\n )\n end\n\n let(:cluster1_validate_cmd_staging_opensearch_cluster) do\n terraform_validate_cmd(\n tfvar_arg_string(\n infrastructure_defaults.merge(\n \"instance_type\" => \"t2.small\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"track_revision\" => \"feature/experiment\",\n \"extra_ecs_clusters\" => [\n {\n \"name\" => \"test\",\n \"subnets_name\" => \"extra_private_subnets\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"instance_type\" => \"t3.small\"\n }\n ],\n \"tinyproxy\" => {\n \"create\" => true\n },\n \"account_id\" => \"123456789012\",\n \"infrastructure_name\" => \"new-dedicated-cluster\",\n \"dalmatian_role\" => \"dalmatian-read\",\n \"environment\" => \"staging\",\n \"opensearch_cluster\" => {\n \"identifier\" => \"testos\",\n \"in_use_by\" => [\n \"test-service\"\n ],\n \"version\" => \"1.2\",\n \"master_enabled\" => true,\n \"master_count\" => \"1\",\n \"master_type\" => \"c6g.large.search\",\n \"instance_count\" => \"3\",\n \"instance_type\" => \"t3.small.search\",\n \"warm_enabled\" => true,\n \"warm_count\" => \"2\",\n \"warm_type\" => \"ultrawarm1.medium.search\",\n \"parameter_store_path_opensearch_cluster_url_name\" => \"ELASTICSEARCH_URL\",\n \"volume_size\" => \"20\"\n }\n )\n )\n )\n end\n\n let(:cluster1_validate_cmd_production_service) do\n terraform_validate_cmd(\n tfvar_arg_string(\n infrastructure_defaults.merge(\n \"instance_type\" => \"t2.medium\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"cluster_name\" => \"new-dedicated-cluster-production\",\n \"account_id\" => \"123456789012\",\n \"infrastructure_name\" => \"new-dedicated-cluster\",\n \"dalmatian_role\" => \"dalmatian-read\",\n \"environment\" => \"production\",\n \"service\" => {\n \"name\" => \"test-service\",\n \"blue_green\" => {\n \"production\" => {\n \"enabled\" => true,\n \"db_copy\" => {\n \"from_db_host_ps_key\" => \"/test-app/other-test-service/production/DB_HOST\",\n \"from_db_name_ps_key\" => \"/test-app/other-test-service/production/DB_NAME\",\n \"from_db_user_ps_key\" => \"/test-app/other-test-service/production/DB_USER\",\n \"from_db_pass_ps_key\" => \"/test-app/other-test-service/production/DB_PASSWORD\",\n \"blue_green_db_name_ps_key\" => \"/test-app/test-service/production/DB_HOST\",\n \"blue_green_db_user_ps_key\" => \"/test-app/test-service/production/DB_USER\",\n \"blue_green_db_pass_ps_key\" => \"/test-app/test-service/production/DB_PASSWORD\",\n \"sql_backups_s3_bucket\" => \"new-dedicated-cluster-testservice-production-sql-backup\"\n },\n \"db_rewrites\" => [\n {\n \"from\" => \"other-test-service.example.com\",\n \"to\" => \"test-service.example.com\"\n }\n ],\n \"directory_copy\" => [\n {\n \"from\" => \"/mnt/efs/other-test-service-media\",\n \"to\" => \"/mnt/efs/test-service-media\",\n \"chown\" => \"33:33\"\n }\n ],\n \"asset_copy_trigger_ps_key\" => \"/test-app/test-service/production/BLUE_GREEN_ASSET_COPY_TRIGGER\"\n },\n \"staging\" => {\n \"enabled\" => false\n }\n },\n \"launch_on\" => [\"production\", \"staging\"],\n \"launch_on_cluster\" => \"test\",\n \"cluster_min_servers\" => {\n \"production\" => \"2\",\n \"staging\" => \"2\"\n },\n \"parameter_store_path\" => {\n \"production\" => \"\",\n \"staging\" => \"/test-path\"\n },\n \"parameter_store_key\" => {\n \"production\" => \"\",\n \"staging\" => \"arn:aws:kms:eu-west-2:000000000000:key/00000000-0000-0000-0000-000000000000\"\n },\n \"daemon\" => false,\n \"monitoring\" => {\n \"production\" => {\n \"opsgenie_alerts\" => {\n \"enabled\" => true,\n \"cloudfront_5xx\" => {\n \"enabled\" => true,\n \"threshold\" => \"95\",\n \"evaluation_periods\" => \"15\"\n }\n },\n \"ghost_inspector\" => {\n \"enabled\" => true\n }\n },\n \"staging\" => {\n \"opsgenie_alerts\" => {\n \"enabled\" => false,\n \"cloudfront_5xx\" => {\n \"enabled\" => true,\n \"threshold\" => \"95\",\n \"evaluation_periods\" => \"15\"\n }\n },\n \"ghost_inspector\" => {\n \"enabled\" => false\n }\n }\n },\n \"cloudfront\" => {\n \"production\" => {\n \"create\" => true,\n \"managed_cache_policy\" => \"CachingDisabled\",\n \"managed_origin_policy\" => \"AllViewerExceptHostHeader\",\n \"managed_response_headers_policy\" => \"CORS-with-preflight-and-SecurityHeadersPolicy\",\n \"tls_protocol_version\" => \"TLSv1.2_2019\",\n \"origin_keepalive_timeout\" => \"60\",\n \"origin_read_timeout\" => \"60\",\n \"basic_auth\" => false,\n \"basic_auth_users_extra\" => {},\n \"viewer_request_functions\" => [\n {\n \"name\" => \"default\",\n \"true_client_ip_header\" => true,\n \"ip_subnet_allow_list\" => [\n \"0.0.0.0/0\"\n ],\n \"redirects\" => [\n {\n \"from_hostname_pattern\" => \"example-old-domain-name.*\",\n \"from_path_pattern\" => \"/*\",\n \"to_hostname\" => \"example-domain-name.co.uk\",\n \"to_path\" => \"/${path}\"\n }\n ]\n }\n ],\n \"offline_page_http_status\" => {\n \"500\" => \"/error-pages/500.html\",\n \"501\" => \"/error-pages/501.html\",\n \"502\" => \"/error-pages/502.html\",\n \"503\" => \"/error-pages/503.html\",\n \"504\" => \"/error-pages/504.html\"\n },\n \"custom_origins\" => [\n {\n \"origin\" => \"test-media-production.s3.amazonaws.com\",\n \"id\" => \"test-media-production-s3\"\n }\n ],\n \"bypass_protection\" => {\n \"enabled\" => true,\n \"exclude_domains\" => [\n \"example.com\"\n ]\n },\n \"custom_behaviors\" => [\n {\n \"target_origin_id\" => \"test-media-production-s3\",\n \"min_ttl\" => 1200,\n \"default_ttl\" => 3600,\n \"max_ttl\" => 86400,\n \"associate_viewer_request_function\" => \"default\",\n \"managed_cache_policy\" => \"CachingDisabled\",\n \"managed_origin_policy\" => \"AllViewerExceptHostHeader\",\n \"managed_response_headers_policy\" => \"CORS-with-preflight-and-SecurityHeadersPolicy\",\n \"path_pattern\" => \"/media/*\"\n }\n ]\n },\n \"staging\" => {\n \"create\" => true,\n \"managed_cache_policy\" => \"CachingDisabled\",\n \"managed_origin_policy\" => \"AllViewerExceptHostHeader\",\n \"managed_response_headers_policy\" => \"CORS-with-preflight-and-SecurityHeadersPolicy\",\n \"tls_protocol_version\" => \"TLSv1.2_2021\",\n \"origin_keepalive_timeout\" => \"10\",\n \"origin_read_timeout\" => \"40\",\n \"basic_auth\" => true,\n \"basic_auth_users_extra\" => {},\n \"viewer_request_functions\" => [\n {\n \"name\" => \"default\",\n \"true_client_ip_header\" => true,\n \"ip_subnet_allow_list\" => [\n \"0.0.0.0/0\"\n ],\n \"redirects\" => [\n {\n \"from_hostname_pattern\" => \"example-old-domain-name.*\",\n \"from_path_pattern\" => \"/*\",\n \"to_hostname\" => \"example-domain-name.co.uk\",\n \"to_path\" => \"/${path}\"\n }\n ]\n }\n ],\n \"offline_page_http_status\" => {\n \"500\" => \"/error-pages/500.html\",\n \"501\" => \"/error-pages/501.html\",\n \"502\" => \"/error-pages/502.html\",\n \"503\" => \"/error-pages/503.html\",\n \"504\" => \"/error-pages/504.html\"\n },\n \"custom_origins\" => [\n {\n \"origin\" => \"test-media-staging.s3.amazonaws.com\",\n \"id\" => \"test-media-staging-s3\"\n }\n ],\n \"bypass_protection\" => {\n \"enabled\" => false,\n \"exclude_domains\" => []\n },\n \"custom_behaviors\" => [\n {\n \"target_origin_id\" => \"test-media-staging-s3\",\n \"min_ttl\" => 1200,\n \"default_ttl\" => 3600,\n \"max_ttl\" => 86400,\n \"associate_viewer_request_function\" => \"default\",\n \"managed_cache_policy\" => \"\",\n \"managed_origin_policy\" => \"\",\n \"managed_response_headers_policy\" => \"\",\n \"path_pattern\" => \"/media/*\"\n }\n ]\n }\n },\n \"s3_policy\" => {\n \"production\" => {},\n \"staging\" => {\n \"rw\" => [\n \"test\"\n ]\n }\n },\n \"shared_loadbalancer_name\" => \"test-lb-1\",\n \"lb_ip_whitelist\" => [\n {\n \"name\" => \"public\",\n \"cidr\" => \"0.0.0.0/0\"\n }\n ],\n \"lb_idle_timeout\" => \"60\",\n \"global_accelerator\" => {\n \"production\" => true,\n \"staging\" => false\n },\n \"health_check_path\" => \"/check\",\n \"health_check_grace_period\" => \"0\",\n \"deregistration_delay\" => \"60\",\n \"serve_from_subdirectory\" => \"/test-subdir\",\n \"domain_names\" => {\n \"production\" => [],\n \"staging\" => [\n \"example-domain-name.co.uk\"\n ]\n },\n \"proxy_configuration\" => {\n \"production\" => {},\n \"staging\" => {\n \"https_proxy\" => \"dalmatian_tinyproxy\",\n \"http_proxy\" => \"http://my.test-proxy.com:8888\",\n \"no_proxy\" => [\n \"*.example.com\",\n \"93.184.216.34/32\"\n ]\n }\n },\n \"home_directory\" => \"/home/user\",\n \"lb_ssl_certificate\" => {\n \"production\" => \"\",\n \"staging\" => \"arn:aws:acm:lb-region-0:000000000000:certificate/00000000-0000-0000-0000-000000000000\"\n },\n \"lb_ssl_policy\" => {\n \"production\" => \"ELBSecurityPolicy-TLS-1-2-2017-01\",\n \"staging\" => \"ELBSecurityPolicy-TLS-1-2-2017-01\"\n },\n \"cloudfront_ssl_certificate\" => {\n \"production\" => \"\",\n \"staging\" => \"arn:aws:acm:us-east-1:000000000000:certificate/00000000-0000-0000-0000-000000000000\"\n },\n \"image_source\" => \"build_from_github_repo\",\n \"image_location\" => \"git@github.com:dxw/dalmatian-test-app\",\n \"track_revision\" => {\n \"production\" => \"\",\n \"staging\" => \"\"\n },\n \"custom_codestar_connection_arn\" => \"arn:aws:codestar-connections:eu-west-2:000000000000:connection/00000000-0000-0000-0000-000000000000\",\n \"codepipeline_use_github_v1\" => false,\n \"codepipeline_codebuild_run_in_vpc\" => false,\n \"codepipeline_codebuild_use_service_env\" => false,\n \"buildspec\" => \"buildspec.yml\",\n \"container_port\" => \"3100\",\n \"container_command\" => [\n \"/docker-entrypoint.sh\",\n \"rails\",\n \"server\"\n ],\n \"container_volumes\" => [\n {\n \"name\" => \"test-volume\",\n \"host_path\" => \"/mnt/test\",\n \"container_path\" => \"/test\"\n }\n ],\n \"container_extra_hosts\" => [\n {\n \"hostname\" => \"example.com\",\n \"ipAddress\" => \"127.0.0.1\"\n }\n ],\n \"container_count\" => \"2\",\n \"enable_max_one_container_per_instance\" => true,\n \"scheduled_tasks\" => [\n {\n \"name\" => \"old-scheduled-task\",\n \"command\" => [\n \"rake\",\n \"do:cron\"\n ],\n \"schedule_expression\" =>\n {\n \"production\" => \"cron(0 4 * * ? *)\",\n \"staging\" => \"cron(0 4 * * ? *)\"\n }\n },\n {\n \"name\" => \"test-scheduled-task\",\n \"command\" => [\n \"rake\",\n \"do:something\"\n ],\n \"schedule_expression\" => {\n \"staging\" => \"cron(0 12 * * ? *)\",\n \"production\" => \"cron(1 2 * * ? *)\"\n }\n }\n ],\n \"workers\" => [\n {\n \"name\" => \"test-worker\",\n \"command\" => [\n \"bundle\",\n \"exec\",\n \"sidekiq\"\n ]\n }\n ]\n }\n )\n )\n )\n end\n\n let(:cluster1_validate_cmd_staging_service) do\n terraform_validate_cmd(\n tfvar_arg_string(\n infrastructure_defaults.merge(\n \"instance_type\" => \"t2.small\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"track_revision\" => \"feature/experiment\",\n \"extra_ecs_clusters\" => [\n {\n \"name\" => \"test\",\n \"subnets_name\" => \"extra_private_subnets\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"instance_type\" => \"t3.small\"\n }\n ],\n \"tinyproxy\" => {\n \"create\" => true\n },\n \"cluster_name\" => \"new-dedicated-cluster-staging\",\n \"account_id\" => \"123456789012\",\n \"infrastructure_name\" => \"new-dedicated-cluster\",\n \"dalmatian_role\" => \"dalmatian-read\",\n \"environment\" => \"staging\",\n \"service\" => {\n \"name\" => \"test-service\",\n \"blue_green\" => {\n \"production\" => {\n \"enabled\" => true,\n \"db_copy\" => {\n \"from_db_host_ps_key\" => \"/test-app/other-test-service/production/DB_HOST\",\n \"from_db_name_ps_key\" => \"/test-app/other-test-service/production/DB_NAME\",\n \"from_db_user_ps_key\" => \"/test-app/other-test-service/production/DB_USER\",\n \"from_db_pass_ps_key\" => \"/test-app/other-test-service/production/DB_PASSWORD\",\n \"blue_green_db_name_ps_key\" => \"/test-app/test-service/production/DB_HOST\",\n \"blue_green_db_user_ps_key\" => \"/test-app/test-service/production/DB_USER\",\n \"blue_green_db_pass_ps_key\" => \"/test-app/test-service/production/DB_PASSWORD\",\n \"sql_backups_s3_bucket\" => \"new-dedicated-cluster-testservice-production-sql-backup\"\n },\n \"db_rewrites\" => [\n {\n \"from\" => \"other-test-service.example.com\",\n \"to\" => \"test-service.example.com\"\n }\n ],\n \"directory_copy\" => [\n {\n \"from\" => \"/mnt/efs/other-test-service-media\",\n \"to\" => \"/mnt/efs/test-service-media\",\n \"chown\" => \"33:33\"\n }\n ],\n \"asset_copy_trigger_ps_key\" => \"/test-app/test-service/production/BLUE_GREEN_ASSET_COPY_TRIGGER\"\n },\n \"staging\" => {\n \"enabled\" => false\n }\n },\n \"launch_on\" => [\"production\", \"staging\"],\n \"launch_on_cluster\" => \"test\",\n \"cluster_min_servers\" => {\n \"production\" => \"2\",\n \"staging\" => \"2\"\n },\n \"parameter_store_path\" => {\n \"production\" => \"\",\n \"staging\" => \"/test-path\"\n },\n \"parameter_store_key\" => {\n \"production\" => \"\",\n \"staging\" => \"arn:aws:kms:eu-west-2:000000000000:key/00000000-0000-0000-0000-000000000000\"\n },\n \"daemon\" => false,\n \"monitoring\" => {\n \"production\" => {\n \"opsgenie_alerts\" => {\n \"enabled\" => true,\n \"cloudfront_5xx\" => {\n \"enabled\" => true,\n \"threshold\" => \"95\",\n \"evaluation_periods\" => \"15\"\n }\n },\n \"ghost_inspector\" => {\n \"enabled\" => true\n }\n },\n \"staging\" => {\n \"opsgenie_alerts\" => {\n \"enabled\" => false,\n \"cloudfront_5xx\" => {\n \"enabled\" => true,\n \"threshold\" => \"95\",\n \"evaluation_periods\" => \"15\"\n }\n },\n \"ghost_inspector\" => {\n \"enabled\" => false\n }\n }\n },\n \"cloudfront\" => {\n \"production\" => {\n \"create\" => true,\n \"managed_cache_policy\" => \"CachingDisabled\",\n \"managed_origin_policy\" => \"AllViewerExceptHostHeader\",\n \"managed_response_headers_policy\" => \"CORS-with-preflight-and-SecurityHeadersPolicy\",\n \"tls_protocol_version\" => \"TLSv1.2_2019\",\n \"origin_keepalive_timeout\" => \"60\",\n \"origin_read_timeout\" => \"60\",\n \"basic_auth\" => false,\n \"basic_auth_users_extra\" => {},\n \"viewer_request_functions\" => [\n {\n \"name\" => \"default\",\n \"true_client_ip_header\" => true,\n \"ip_subnet_allow_list\" => [\n \"0.0.0.0/0\"\n ],\n \"redirects\" => [\n {\n \"from_hostname_pattern\" => \"example-old-domain-name.*\",\n \"from_path_pattern\" => \"/*\",\n \"to_hostname\" => \"example-domain-name.co.uk\",\n \"to_path\" => \"/${path}\"\n }\n ]\n }\n ],\n \"offline_page_http_status\" => {\n \"500\" => \"/error-pages/500.html\",\n \"501\" => \"/error-pages/501.html\",\n \"502\" => \"/error-pages/502.html\",\n \"503\" => \"/error-pages/503.html\",\n \"504\" => \"/error-pages/504.html\"\n },\n \"custom_origins\" => [\n {\n \"origin\" => \"test-media-production.s3.amazonaws.com\",\n \"id\" => \"test-media-production-s3\"\n }\n ],\n \"bypass_protection\" => {\n \"enabled\" => true,\n \"exclude_domains\" => [\n \"example.com\"\n ]\n },\n \"custom_behaviors\" => [\n {\n \"target_origin_id\" => \"test-media-production-s3\",\n \"min_ttl\" => 1200,\n \"default_ttl\" => 3600,\n \"max_ttl\" => 86400,\n \"associate_viewer_request_function\" => \"default\",\n \"managed_cache_policy\" => \"CachingDisabled\",\n \"managed_origin_policy\" => \"AllViewerExceptHostHeader\",\n \"managed_response_headers_policy\" => \"CORS-with-preflight-and-SecurityHeadersPolicy\",\n \"path_pattern\" => \"/media/*\"\n }\n ]\n },\n \"staging\" => {\n \"create\" => true,\n \"managed_cache_policy\" => \"CachingDisabled\",\n \"managed_origin_policy\" => \"AllViewerExceptHostHeader\",\n \"managed_response_headers_policy\" => \"CORS-with-preflight-and-SecurityHeadersPolicy\",\n \"tls_protocol_version\" => \"TLSv1.2_2021\",\n \"origin_keepalive_timeout\" => \"10\",\n \"origin_read_timeout\" => \"40\",\n \"basic_auth\" => true,\n \"basic_auth_users_extra\" => {},\n \"viewer_request_functions\" => [\n {\n \"name\" => \"default\",\n \"true_client_ip_header\" => true,\n \"ip_subnet_allow_list\" => [\n \"0.0.0.0/0\"\n ],\n \"redirects\" => [\n {\n \"from_hostname_pattern\" => \"example-old-domain-name.*\",\n \"from_path_pattern\" => \"/*\",\n \"to_hostname\" => \"example-domain-name.co.uk\",\n \"to_path\" => \"/${path}\"\n }\n ]\n }\n ],\n \"offline_page_http_status\" => {\n \"500\" => \"/error-pages/500.html\",\n \"501\" => \"/error-pages/501.html\",\n \"502\" => \"/error-pages/502.html\",\n \"503\" => \"/error-pages/503.html\",\n \"504\" => \"/error-pages/504.html\"\n },\n \"custom_origins\" => [\n {\n \"origin\" => \"test-media-staging.s3.amazonaws.com\",\n \"id\" => \"test-media-staging-s3\"\n }\n ],\n \"bypass_protection\" => {\n \"enabled\" => false,\n \"exclude_domains\" => []\n },\n \"custom_behaviors\" => [\n {\n \"target_origin_id\" => \"test-media-staging-s3\",\n \"min_ttl\" => 1200,\n \"default_ttl\" => 3600,\n \"max_ttl\" => 86400,\n \"associate_viewer_request_function\" => \"default\",\n \"managed_cache_policy\" => \"\",\n \"managed_origin_policy\" => \"\",\n \"managed_response_headers_policy\" => \"\",\n \"path_pattern\" => \"/media/*\"\n }\n ]\n }\n },\n \"s3_policy\" => {\n \"production\" => {},\n \"staging\" => {\n \"rw\" => [\n \"test\"\n ]\n }\n },\n \"shared_loadbalancer_name\" => \"test-lb-1\",\n \"lb_ip_whitelist\" => [\n {\n \"name\" => \"public\",\n \"cidr\" => \"0.0.0.0/0\"\n }\n ],\n \"lb_idle_timeout\" => \"60\",\n \"global_accelerator\" => {\n \"production\" => true,\n \"staging\" => false\n },\n \"health_check_path\" => \"/check\",\n \"health_check_grace_period\" => \"0\",\n \"deregistration_delay\" => \"60\",\n \"serve_from_subdirectory\" => \"/test-subdir\",\n \"domain_names\" => {\n \"production\" => [],\n \"staging\" => [\n \"example-domain-name.co.uk\"\n ]\n },\n \"proxy_configuration\" => {\n \"production\" => {},\n \"staging\" => {\n \"https_proxy\" => \"dalmatian_tinyproxy\",\n \"http_proxy\" => \"http://my.test-proxy.com:8888\",\n \"no_proxy\" => [\n \"*.example.com\",\n \"93.184.216.34/32\"\n ]\n }\n },\n \"home_directory\" => \"/home/user\",\n \"lb_ssl_certificate\" => {\n \"production\" => \"\",\n \"staging\" => \"arn:aws:acm:lb-region-0:000000000000:certificate/00000000-0000-0000-0000-000000000000\"\n },\n \"lb_ssl_policy\" => {\n \"production\" => \"ELBSecurityPolicy-TLS-1-2-2017-01\",\n \"staging\" => \"ELBSecurityPolicy-TLS-1-2-2017-01\"\n },\n \"cloudfront_ssl_certificate\" => {\n \"production\" => \"\",\n \"staging\" => \"arn:aws:acm:us-east-1:000000000000:certificate/00000000-0000-0000-0000-000000000000\"\n },\n \"image_source\" => \"build_from_github_repo\",\n \"image_location\" => \"git@github.com:dxw/dalmatian-test-app\",\n \"track_revision\" => {\n \"production\" => \"\",\n \"staging\" => \"\"\n },\n \"custom_codestar_connection_arn\" => \"arn:aws:codestar-connections:eu-west-2:000000000000:connection/00000000-0000-0000-0000-000000000000\",\n \"codepipeline_use_github_v1\" => false,\n \"codepipeline_codebuild_run_in_vpc\" => false,\n \"codepipeline_codebuild_use_service_env\" => false,\n \"buildspec\" => \"buildspec.yml\",\n \"container_port\" => \"3100\",\n \"container_command\" => [\n \"/docker-entrypoint.sh\",\n \"rails\",\n \"server\"\n ],\n \"container_volumes\" => [\n {\n \"name\" => \"test-volume\",\n \"host_path\" => \"/mnt/test\",\n \"container_path\" => \"/test\"\n }\n ],\n \"container_extra_hosts\" => [\n {\n \"hostname\" => \"example.com\",\n \"ipAddress\" => \"127.0.0.1\"\n }\n ],\n \"container_count\" => \"2\",\n \"enable_max_one_container_per_instance\" => true,\n \"scheduled_tasks\" => [\n {\n \"name\" => \"old-scheduled-task\",\n \"command\" => [\n \"rake\",\n \"do:cron\"\n ],\n \"schedule_expression\" =>\n {\n \"production\" => \"cron(0 4 * * ? *)\",\n \"staging\" => \"cron(0 4 * * ? *)\"\n }\n },\n {\n \"name\" => \"test-scheduled-task\",\n \"command\" => [\n \"rake\",\n \"do:something\"\n ],\n \"schedule_expression\" => {\n \"staging\" => \"cron(0 12 * * ? *)\",\n \"production\" => \"cron(1 2 * * ? *)\"\n }\n }\n ],\n \"workers\" => [\n {\n \"name\" => \"test-worker\",\n \"command\" => [\n \"bundle\",\n \"exec\",\n \"sidekiq\"\n ]\n }\n ]\n }\n )\n )\n )\n end\n\n let(:cluster1_validate_cmd_production_shared_loadbalancer) do\n terraform_validate_cmd(\n tfvar_arg_string(\n infrastructure_defaults.merge(\n \"instance_type\" => \"t2.medium\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"account_id\" => \"123456789012\",\n \"infrastructure_name\" => \"new-dedicated-cluster\",\n \"dalmatian_role\" => \"dalmatian-read\",\n \"environment\" => \"production\",\n \"shared_loadbalancer\" => {\n \"name\" => \"test-lb-1\",\n \"in_use_by\" => [\n \"test-service\"\n ],\n \"clusters_in_use\" => {\n \"production\" => [\n \"test\"\n ],\n \"staging\" => [\n \"test\"\n ]\n },\n \"subnets_name\" => \"\",\n \"domain_names\" => {\n \"test-service\" => {\n \"production\" => [],\n \"staging\" => [\n \"example-domain-name.co.uk\"\n ]\n }\n },\n \"internal\" => false,\n \"ip_whitelist\" => [\n {\n \"name\" => \"public\",\n \"cidr\" => \"0.0.0.0/0\"\n }\n ],\n \"idle_timeout\" => \"60\",\n \"global_accelerator\" => {\n \"production\" => true,\n \"staging\" => false\n },\n \"ssl_policy\" => \"ELBSecurityPolicy-TLS-1-2-2017-01\"\n }\n )\n )\n )\n end\n\n let(:cluster1_validate_cmd_staging_shared_loadbalancer) do\n terraform_validate_cmd(\n tfvar_arg_string(\n infrastructure_defaults.merge(\n \"instance_type\" => \"t2.small\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"track_revision\" => \"feature/experiment\",\n \"extra_ecs_clusters\" => [\n {\n \"name\" => \"test\",\n \"subnets_name\" => \"extra_private_subnets\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"instance_type\" => \"t3.small\"\n }\n ],\n \"tinyproxy\" => {\n \"create\" => true\n },\n \"account_id\" => \"123456789012\",\n \"infrastructure_name\" => \"new-dedicated-cluster\",\n \"dalmatian_role\" => \"dalmatian-read\",\n \"environment\" => \"staging\",\n \"shared_loadbalancer\" => {\n \"name\" => \"test-lb-1\",\n \"in_use_by\" => [\n \"test-service\"\n ],\n \"clusters_in_use\" => {\n \"production\" => [\n \"test\"\n ],\n \"staging\" => [\n \"test\"\n ]\n },\n \"subnets_name\" => \"\",\n \"domain_names\" => {\n \"test-service\" => {\n \"production\" => [],\n \"staging\" => [\n \"example-domain-name.co.uk\"\n ]\n }\n },\n \"internal\" => false,\n \"ip_whitelist\" => [\n {\n \"name\" => \"public\",\n \"cidr\" => \"0.0.0.0/0\"\n }\n ],\n \"idle_timeout\" => \"60\",\n \"global_accelerator\" => {\n \"production\" => true,\n \"staging\" => false\n },\n \"ssl_policy\" => \"ELBSecurityPolicy-TLS-1-2-2017-01\"\n }\n )\n )\n )\n end\n\n let(:cluster1_plan_cmd_hz) do\n terraform_plan_cmd(\n tfvar_arg_string(\n \"account_id\" => \"123456789012\",\n \"cluster_id\" => \"new-dedicated-cluster\",\n \"dalmatian_role\" => \"dalmatian-read\",\n \"hosted_zone\" => {\n \"domain\" => \"example-domain-name.com\",\n \"ns_records\" => [\n {\n \"name\" => \"delegated\",\n \"value\" => [\n \"ns1.aws.com\"\n ]\n }\n ],\n \"a_records\" => [\n {\n \"name\" => \"some-service\",\n \"value\" => [\n \"1.2.3.4\"\n ]\n },\n {\n \"name\" => \"mail\",\n \"value\" => [\n \"5.6.7.8\"\n ]\n }\n ],\n \"alias_records\" => [\n {\n \"name\" => \"example-domain-name.com\",\n \"value\" => \"cf-distribution.aws.net\"\n },\n {\n \"name\" => \"www\",\n \"value\" => \"cf-distribution.aws.net\"\n }\n ],\n \"cname_records\" => [\n {\n \"name\" => \"alb\",\n \"value\" => [\n \"aws-alb.aws.net\"\n ]\n }\n ],\n \"mx_records\" => [\n {\n \"name\" => \"mail\",\n \"value\" => [\n \"0 mail.example-domain-name.com\"\n ]\n }\n ],\n \"txt_records\" => [\n {\n \"name\" => \"mail\",\n \"value\" => [\n \"v=spf1 a ip4:9.10.11.0/24 mx ~all\"\n ]\n }\n ],\n \"srv_records\" => [\n {\n \"name\" => \"@\",\n \"value\" => [\n \"_imaps._tcp.gmail.com. 86400 IN SRV 5 0 993 imap.gmail.com\"\n ]\n }\n ]\n }\n )\n )\n end\n\n let(:cluster1_plan_cmd_s3) do\n terraform_plan_cmd(\n tfvar_arg_string(\n \"account_id\" => \"123456789012\",\n \"cluster_id\" => \"new-dedicated-cluster\",\n \"dalmatian_role\" => \"dalmatian-read\",\n \"s3\" => {\n \"name\" => \"test\",\n \"enable_s3_versioning\" => true,\n \"encrypted\" => true,\n \"acl\" => \"private\",\n \"policy\" => {\n \"staging\" => {\n \"rw\" => {\n \"services\" => [\n \"test-service\"\n ]\n }\n }\n },\n \"service_cloudfront_read_access\" => [\n \"test-service-staging\"\n ],\n \"cloudfront\" => {\n \"create\" => true,\n \"domain_names\" => [\n \"example.com\",\n \"example2.com\"\n ],\n \"certificate\" => \"arn:aws:acm:lb-region-0:000000000000:certificate/00000000-0000-0000-0000-000000000000\"\n }\n }\n )\n )\n end\n\n let(:cluster1_plan_cmd_vpn_cg) do\n terraform_plan_cmd(\n tfvar_arg_string(\n \"account_id\" => \"123456789012\",\n \"cluster_id\" => \"new-dedicated-cluster\",\n \"dalmatian_role\" => \"dalmatian-read\",\n \"vpn_customer_gateway\" => {\n \"name\" => \"test-vpn\",\n \"bgp_asn\" => 65000,\n \"ip_address\" => \"1.2.3.4\"\n }\n )\n )\n end\n\n let(:cluster1_plan_cmd_production) do\n terraform_plan_cmd(\n tfvar_arg_string(\n infrastructure_defaults.merge(\n \"instance_type\" => \"t2.medium\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"environment\" => \"production\",\n \"cluster_name\" => \"new-dedicated-cluster-production\",\n \"account_id\" => \"123456789012\",\n \"infrastructure_name\" => \"new-dedicated-cluster\",\n \"dalmatian_role\" => \"dalmatian-read\"\n )\n )\n )\n end\n\n let(:cluster1_plan_cmd_staging) do\n terraform_plan_cmd(\n tfvar_arg_string(\n infrastructure_defaults.merge(\n \"instance_type\" => \"t2.small\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"track_revision\" => \"feature/experiment\",\n \"extra_ecs_clusters\" => [\n {\n \"name\" => \"test\",\n \"subnets_name\" => \"extra_private_subnets\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"instance_type\" => \"t3.small\"\n }\n ],\n \"tinyproxy\" => {\n \"create\" => true\n },\n \"environment\" => \"staging\",\n \"cluster_name\" => \"new-dedicated-cluster-staging\",\n \"account_id\" => \"123456789012\",\n \"infrastructure_name\" => \"new-dedicated-cluster\",\n \"dalmatian_role\" => \"dalmatian-read\"\n )\n )\n )\n end\n\n let(:cluster1_plan_cmd_production_waf) do\n terraform_plan_cmd(\n tfvar_arg_string(\n infrastructure_defaults.merge(\n \"instance_type\" => \"t2.medium\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"environment\" => \"production\",\n \"account_id\" => \"123456789012\",\n \"infrastructure_name\" => \"new-dedicated-cluster\",\n \"dalmatian_role\" => \"dalmatian-read\",\n \"waf\" => {\n \"name\" => \"test-1\",\n \"action\" => \"count\",\n \"ip_deny_list\" => [],\n \"aws_managed_rules\" => [\n {\n \"name\" => \"AWSManagedRulesSQLiRuleSet\",\n \"excluded_path_patterns\" => [\n \"/wp-admin/async-upload.php\"\n ]\n },\n {\n \"name\" => \"AWSManagedRulesCommonRuleSet\",\n \"exclude_rules\" => [\n \"SizeRestrictions_BODY\"\n ]\n }\n ],\n \"associations\" => {\n shared_loadbalancers: [\n \"test-lb-1\"\n ],\n service_cloudfront: [\n \"test-service\"\n ]\n }\n }\n )\n )\n )\n end\n\n let(:cluster1_plan_cmd_production_rds) do\n terraform_plan_cmd(\n tfvar_arg_string(\n infrastructure_defaults.merge(\n \"instance_type\" => \"t2.medium\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"environment\" => \"production\",\n \"account_id\" => \"123456789012\",\n \"infrastructure_name\" => \"new-dedicated-cluster\",\n \"dalmatian_role\" => \"dalmatian-read\",\n \"rds\" => {\n \"identifier\" => \"testservice\",\n \"in_use_by\" => [\n \"test-service\"\n ],\n \"clusters_in_use\" => {\n \"production\" => [\n \"test\"\n ],\n \"staging\" => [\n \"test\"\n ]\n },\n \"instance_class\" => {\n \"production\" => \"db.t2.small\",\n \"staging\" => \"db.t2.micro\"\n },\n \"engine\" => \"postgres\",\n \"engine_version\" => \"11.4\",\n \"allocated_storage\" => 20,\n \"storage_encrypted\" => true,\n \"storage_type\" => \"gp3\",\n \"db_name\" => \"testapp\",\n \"port\" => 5432,\n \"maintenance_window\" => \"mon:19:00-mon:19:30\",\n \"backup_window\" => \"09:00-10:00\",\n \"backup_retention_period\" => 31,\n \"force_ssl\" => true,\n \"parameter_store_path_db_url_name\" => \"DATABASE_URL\",\n \"sql_backup_scheduled_task_environment_variables\" => [\n {\n \"name\" => \"foo\",\n \"value\" => \"bar\"\n }\n ],\n \"check_sql_backup_scheduled_task_environment_variables\" => [\n {\n \"name\" => \"foo\",\n \"value\" => \"bar\"\n }\n ],\n \"sync_sql_backup_to_azure\" => false,\n \"codebuild_access\" => [\n \"service-name\"\n ]\n }\n )\n )\n )\n end\n\n let(:cluster1_plan_cmd_staging_waf) do\n terraform_plan_cmd(\n tfvar_arg_string(\n infrastructure_defaults.merge(\n \"instance_type\" => \"t2.small\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"track_revision\" => \"feature/experiment\",\n \"extra_ecs_clusters\" => [\n {\n \"name\" => \"test\",\n \"subnets_name\" => \"extra_private_subnets\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"instance_type\" => \"t3.small\"\n }\n ],\n \"tinyproxy\" => {\n \"create\" => true\n },\n \"environment\" => \"staging\",\n \"account_id\" => \"123456789012\",\n \"infrastructure_name\" => \"new-dedicated-cluster\",\n \"dalmatian_role\" => \"dalmatian-read\",\n \"waf\" => {\n \"name\" => \"test-1\",\n \"action\" => \"count\",\n \"ip_deny_list\" => [],\n \"aws_managed_rules\" => [\n {\n \"name\" => \"AWSManagedRulesSQLiRuleSet\",\n \"excluded_path_patterns\" => [\n \"/wp-admin/async-upload.php\"\n ]\n },\n {\n \"name\" => \"AWSManagedRulesCommonRuleSet\",\n \"exclude_rules\" => [\n \"SizeRestrictions_BODY\"\n ]\n }\n ],\n \"associations\" => {\n shared_loadbalancers: [\n \"test-lb-1\"\n ],\n service_cloudfront: [\n \"test-service\"\n ]\n }\n }\n )\n )\n )\n end\n\n let(:cluster1_plan_cmd_staging_rds) do\n terraform_plan_cmd(\n tfvar_arg_string(\n infrastructure_defaults.merge(\n \"instance_type\" => \"t2.small\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"track_revision\" => \"feature/experiment\",\n \"extra_ecs_clusters\" => [\n {\n \"name\" => \"test\",\n \"subnets_name\" => \"extra_private_subnets\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"instance_type\" => \"t3.small\"\n }\n ],\n \"tinyproxy\" => {\n \"create\" => true\n },\n \"environment\" => \"staging\",\n \"account_id\" => \"123456789012\",\n \"infrastructure_name\" => \"new-dedicated-cluster\",\n \"dalmatian_role\" => \"dalmatian-read\",\n \"rds\" => {\n \"identifier\" => \"testservice\",\n \"in_use_by\" => [\n \"test-service\"\n ],\n \"clusters_in_use\" => {\n \"production\" => [\n \"test\"\n ],\n \"staging\" => [\n \"test\"\n ]\n },\n \"instance_class\" => {\n \"production\" => \"db.t2.small\",\n \"staging\" => \"db.t2.micro\"\n },\n \"engine\" => \"postgres\",\n \"engine_version\" => \"11.4\",\n \"allocated_storage\" => 20,\n \"storage_encrypted\" => true,\n \"storage_type\" => \"gp3\",\n \"db_name\" => \"testapp\",\n \"port\" => 5432,\n \"maintenance_window\" => \"mon:19:00-mon:19:30\",\n \"backup_window\" => \"09:00-10:00\",\n \"backup_retention_period\" => 31,\n \"force_ssl\" => true,\n \"parameter_store_path_db_url_name\" => \"DATABASE_URL\",\n \"sql_backup_scheduled_task_environment_variables\" => [\n {\n \"name\" => \"foo\",\n \"value\" => \"bar\"\n }\n ],\n \"check_sql_backup_scheduled_task_environment_variables\" => [\n {\n \"name\" => \"foo\",\n \"value\" => \"bar\"\n }\n ],\n \"sync_sql_backup_to_azure\" => false,\n \"codebuild_access\" => [\n \"service-name\"\n ]\n }\n )\n )\n )\n end\n\n let(:cluster1_plan_cmd_production_elasticache_cluster) do\n terraform_plan_cmd(\n tfvar_arg_string(\n infrastructure_defaults.merge(\n \"instance_type\" => \"t2.medium\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"environment\" => \"production\",\n \"account_id\" => \"123456789012\",\n \"infrastructure_name\" => \"new-dedicated-cluster\",\n \"dalmatian_role\" => \"dalmatian-read\",\n \"elasticache_cluster\" => {\n \"identifier\" => \"testredis\",\n \"in_use_by\" => [\n \"test-service\"\n ],\n \"node_type\" => \"cache.t2.micro\",\n \"node_count\" => 1,\n \"engine\" => \"redis\",\n \"engine_version\" => \"5.0.6\",\n \"parameters\" => [],\n \"port\" => 6379,\n \"maintenance_window\" => \"mon:19:00-mon:22:00\",\n \"snapshot_window\" => \"09:00-10:00\",\n \"parameter_store_path_elasticache_cluster_url_name\" => \"REDIS_URL\"\n }\n )\n )\n )\n end\n\n let(:cluster1_plan_cmd_staging_elasticache_cluster) do\n terraform_plan_cmd(\n tfvar_arg_string(\n infrastructure_defaults.merge(\n \"instance_type\" => \"t2.small\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"track_revision\" => \"feature/experiment\",\n \"extra_ecs_clusters\" => [\n {\n \"name\" => \"test\",\n \"subnets_name\" => \"extra_private_subnets\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"instance_type\" => \"t3.small\"\n }\n ],\n \"tinyproxy\" => {\n \"create\" => true\n },\n \"environment\" => \"staging\",\n \"account_id\" => \"123456789012\",\n \"infrastructure_name\" => \"new-dedicated-cluster\",\n \"dalmatian_role\" => \"dalmatian-read\",\n \"elasticache_cluster\" => {\n \"identifier\" => \"testredis\",\n \"in_use_by\" => [\n \"test-service\"\n ],\n \"node_type\" => \"cache.t2.micro\",\n \"node_count\" => 1,\n \"engine\" => \"redis\",\n \"engine_version\" => \"5.0.6\",\n \"parameters\" => [],\n \"port\" => 6379,\n \"maintenance_window\" => \"mon:19:00-mon:22:00\",\n \"snapshot_window\" => \"09:00-10:00\",\n \"parameter_store_path_elasticache_cluster_url_name\" => \"REDIS_URL\"\n }\n )\n )\n )\n end\n\n let(:cluster1_plan_cmd_production_opensearch_cluster) do\n terraform_plan_cmd(\n tfvar_arg_string(\n infrastructure_defaults.merge(\n \"instance_type\" => \"t2.medium\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"environment\" => \"production\",\n \"account_id\" => \"123456789012\",\n \"infrastructure_name\" => \"new-dedicated-cluster\",\n \"dalmatian_role\" => \"dalmatian-read\",\n \"opensearch_cluster\" => {\n \"identifier\" => \"testos\",\n \"in_use_by\" => [\n \"test-service\"\n ],\n \"version\" => \"1.2\",\n \"master_enabled\" => true,\n \"master_count\" => \"1\",\n \"master_type\" => \"c6g.large.search\",\n \"instance_count\" => \"3\",\n \"instance_type\" => \"t3.small.search\",\n \"warm_enabled\" => true,\n \"warm_count\" => \"2\",\n \"warm_type\" => \"ultrawarm1.medium.search\",\n \"parameter_store_path_opensearch_cluster_url_name\" => \"ELASTICSEARCH_URL\",\n \"volume_size\" => \"20\"\n }\n )\n )\n )\n end\n\n let(:cluster1_plan_cmd_staging_opensearch_cluster) do\n terraform_plan_cmd(\n tfvar_arg_string(\n infrastructure_defaults.merge(\n \"instance_type\" => \"t2.small\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"track_revision\" => \"feature/experiment\",\n \"extra_ecs_clusters\" => [\n {\n \"name\" => \"test\",\n \"subnets_name\" => \"extra_private_subnets\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"instance_type\" => \"t3.small\"\n }\n ],\n \"tinyproxy\" => {\n \"create\" => true\n },\n \"environment\" => \"staging\",\n \"account_id\" => \"123456789012\",\n \"infrastructure_name\" => \"new-dedicated-cluster\",\n \"dalmatian_role\" => \"dalmatian-read\",\n \"opensearch_cluster\" => {\n \"identifier\" => \"testos\",\n \"in_use_by\" => [\n \"test-service\"\n ],\n \"version\" => \"1.2\",\n \"master_enabled\" => true,\n \"master_count\" => \"1\",\n \"master_type\" => \"c6g.large.search\",\n \"instance_count\" => \"3\",\n \"instance_type\" => \"t3.small.search\",\n \"warm_enabled\" => true,\n \"warm_count\" => \"2\",\n \"warm_type\" => \"ultrawarm1.medium.search\",\n \"parameter_store_path_opensearch_cluster_url_name\" => \"ELASTICSEARCH_URL\",\n \"volume_size\" => \"20\"\n }\n )\n )\n )\n end\n\n let(:cluster1_plan_cmd_production_service) do\n terraform_plan_cmd(\n tfvar_arg_string(\n infrastructure_defaults.merge(\n \"instance_type\" => \"t2.medium\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"environment\" => \"production\",\n \"cluster_name\" => \"new-dedicated-cluster-production\",\n \"account_id\" => \"123456789012\",\n \"infrastructure_name\" => \"new-dedicated-cluster\",\n \"dalmatian_role\" => \"dalmatian-read\",\n \"service\" => {\n \"name\" => \"test-service\",\n \"blue_green\" => {\n \"production\" => {\n \"enabled\" => true,\n \"db_copy\" => {\n \"from_db_host_ps_key\" => \"/test-app/other-test-service/production/DB_HOST\",\n \"from_db_name_ps_key\" => \"/test-app/other-test-service/production/DB_NAME\",\n \"from_db_user_ps_key\" => \"/test-app/other-test-service/production/DB_USER\",\n \"from_db_pass_ps_key\" => \"/test-app/other-test-service/production/DB_PASSWORD\",\n \"blue_green_db_name_ps_key\" => \"/test-app/test-service/production/DB_HOST\",\n \"blue_green_db_user_ps_key\" => \"/test-app/test-service/production/DB_USER\",\n \"blue_green_db_pass_ps_key\" => \"/test-app/test-service/production/DB_PASSWORD\",\n \"sql_backups_s3_bucket\" => \"new-dedicated-cluster-testservice-production-sql-backup\"\n },\n \"db_rewrites\" => [\n {\n \"from\" => \"other-test-service.example.com\",\n \"to\" => \"test-service.example.com\"\n }\n ],\n \"directory_copy\" => [\n {\n \"from\" => \"/mnt/efs/other-test-service-media\",\n \"to\" => \"/mnt/efs/test-service-media\",\n \"chown\" => \"33:33\"\n }\n ],\n \"asset_copy_trigger_ps_key\" => \"/test-app/test-service/production/BLUE_GREEN_ASSET_COPY_TRIGGER\"\n },\n \"staging\" => {\n \"enabled\" => false\n }\n },\n \"launch_on\" => [\"production\", \"staging\"],\n \"launch_on_cluster\" => \"test\",\n \"cluster_min_servers\" => {\n \"production\" => \"2\",\n \"staging\" => \"2\"\n },\n \"parameter_store_path\" => {\n \"production\" => \"\",\n \"staging\" => \"/test-path\"\n },\n \"parameter_store_key\" => {\n \"production\" => \"\",\n \"staging\" => \"arn:aws:kms:eu-west-2:000000000000:key/00000000-0000-0000-0000-000000000000\"\n },\n \"daemon\" => false,\n \"monitoring\" => {\n \"production\" => {\n \"opsgenie_alerts\" => {\n \"enabled\" => true,\n \"cloudfront_5xx\" => {\n \"enabled\" => true,\n \"threshold\" => \"95\",\n \"evaluation_periods\" => \"15\"\n }\n },\n \"ghost_inspector\" => {\n \"enabled\" => true\n }\n },\n \"staging\" => {\n \"opsgenie_alerts\" => {\n \"enabled\" => false,\n \"cloudfront_5xx\" => {\n \"enabled\" => true,\n \"threshold\" => \"95\",\n \"evaluation_periods\" => \"15\"\n }\n },\n \"ghost_inspector\" => {\n \"enabled\" => false\n }\n }\n },\n \"cloudfront\" => {\n \"production\" => {\n \"create\" => true,\n \"managed_cache_policy\" => \"CachingDisabled\",\n \"managed_origin_policy\" => \"AllViewerExceptHostHeader\",\n \"managed_response_headers_policy\" => \"CORS-with-preflight-and-SecurityHeadersPolicy\",\n \"tls_protocol_version\" => \"TLSv1.2_2019\",\n \"origin_keepalive_timeout\" => \"60\",\n \"origin_read_timeout\" => \"60\",\n \"basic_auth\" => false,\n \"basic_auth_users_extra\" => {},\n \"viewer_request_functions\" => [\n {\n \"name\" => \"default\",\n \"true_client_ip_header\" => true,\n \"ip_subnet_allow_list\" => [\n \"0.0.0.0/0\"\n ],\n \"redirects\" => [\n {\n \"from_hostname_pattern\" => \"example-old-domain-name.*\",\n \"from_path_pattern\" => \"/*\",\n \"to_hostname\" => \"example-domain-name.co.uk\",\n \"to_path\" => \"/${path}\"\n }\n ]\n }\n ],\n \"offline_page_http_status\" => {\n \"500\" => \"/error-pages/500.html\",\n \"501\" => \"/error-pages/501.html\",\n \"502\" => \"/error-pages/502.html\",\n \"503\" => \"/error-pages/503.html\",\n \"504\" => \"/error-pages/504.html\"\n },\n \"custom_origins\" => [\n {\n \"origin\" => \"test-media-production.s3.amazonaws.com\",\n \"id\" => \"test-media-production-s3\"\n }\n ],\n \"bypass_protection\" => {\n \"enabled\" => true,\n \"exclude_domains\" => [\n \"example.com\"\n ]\n },\n \"custom_behaviors\" => [\n {\n \"target_origin_id\" => \"test-media-production-s3\",\n \"min_ttl\" => 1200,\n \"default_ttl\" => 3600,\n \"max_ttl\" => 86400,\n \"associate_viewer_request_function\" => \"default\",\n \"managed_cache_policy\" => \"CachingDisabled\",\n \"managed_origin_policy\" => \"AllViewerExceptHostHeader\",\n \"managed_response_headers_policy\" => \"CORS-with-preflight-and-SecurityHeadersPolicy\",\n \"path_pattern\" => \"/media/*\"\n }\n ]\n },\n \"staging\" => {\n \"create\" => true,\n \"managed_cache_policy\" => \"CachingDisabled\",\n \"managed_origin_policy\" => \"AllViewerExceptHostHeader\",\n \"managed_response_headers_policy\" => \"CORS-with-preflight-and-SecurityHeadersPolicy\",\n \"tls_protocol_version\" => \"TLSv1.2_2021\",\n \"origin_keepalive_timeout\" => \"10\",\n \"origin_read_timeout\" => \"40\",\n \"basic_auth\" => true,\n \"basic_auth_users_extra\" => {},\n \"viewer_request_functions\" => [\n {\n \"name\" => \"default\",\n \"true_client_ip_header\" => true,\n \"ip_subnet_allow_list\" => [\n \"0.0.0.0/0\"\n ],\n \"redirects\" => [\n {\n \"from_hostname_pattern\" => \"example-old-domain-name.*\",\n \"from_path_pattern\" => \"/*\",\n \"to_hostname\" => \"example-domain-name.co.uk\",\n \"to_path\" => \"/${path}\"\n }\n ]\n }\n ],\n \"offline_page_http_status\" => {\n \"500\" => \"/error-pages/500.html\",\n \"501\" => \"/error-pages/501.html\",\n \"502\" => \"/error-pages/502.html\",\n \"503\" => \"/error-pages/503.html\",\n \"504\" => \"/error-pages/504.html\"\n },\n \"custom_origins\" => [\n {\n \"origin\" => \"test-media-staging.s3.amazonaws.com\",\n \"id\" => \"test-media-staging-s3\"\n }\n ],\n \"bypass_protection\" => {\n \"enabled\" => false,\n \"exclude_domains\" => []\n },\n \"custom_behaviors\" => [\n {\n \"target_origin_id\" => \"test-media-staging-s3\",\n \"min_ttl\" => 1200,\n \"default_ttl\" => 3600,\n \"max_ttl\" => 86400,\n \"associate_viewer_request_function\" => \"default\",\n \"managed_cache_policy\" => \"\",\n \"managed_origin_policy\" => \"\",\n \"managed_response_headers_policy\" => \"\",\n \"path_pattern\" => \"/media/*\"\n }\n ]\n }\n },\n \"s3_policy\" => {\n \"production\" => {},\n \"staging\" => {\n \"rw\" => [\n \"test\"\n ]\n }\n },\n \"shared_loadbalancer_name\" => \"test-lb-1\",\n \"lb_ip_whitelist\" => [\n \"name\" => \"public\",\n \"cidr\" => \"0.0.0.0/0\"\n ],\n \"lb_idle_timeout\" => \"60\",\n \"global_accelerator\" => {\n \"production\" => true,\n \"staging\" => false\n },\n \"health_check_path\" => \"/check\",\n \"health_check_grace_period\" => \"0\",\n \"deregistration_delay\" => \"60\",\n \"serve_from_subdirectory\" => \"/test-subdir\",\n \"domain_names\" => {\n \"production\" => [],\n \"staging\" => [\n \"example-domain-name.co.uk\"\n ]\n },\n \"proxy_configuration\" => {\n \"production\" => {},\n \"staging\" => {\n \"https_proxy\" => \"dalmatian_tinyproxy\",\n \"http_proxy\" => \"http://my.test-proxy.com:8888\",\n \"no_proxy\" => [\n \"*.example.com\",\n \"93.184.216.34/32\"\n ]\n }\n },\n \"home_directory\" => \"/home/user\",\n \"lb_ssl_certificate\" => {\n \"production\" => \"\",\n \"staging\" => \"arn:aws:acm:lb-region-0:000000000000:certificate/00000000-0000-0000-0000-000000000000\"\n },\n \"lb_ssl_policy\" => {\n \"production\" => \"ELBSecurityPolicy-TLS-1-2-2017-01\",\n \"staging\" => \"ELBSecurityPolicy-TLS-1-2-2017-01\"\n },\n \"cloudfront_ssl_certificate\" => {\n \"production\" => \"\",\n \"staging\" => \"arn:aws:acm:us-east-1:000000000000:certificate/00000000-0000-0000-0000-000000000000\"\n },\n \"image_source\" => \"build_from_github_repo\",\n \"image_location\" => \"git@github.com:dxw/dalmatian-test-app\",\n \"track_revision\" => {\n \"production\" => \"\",\n \"staging\" => \"\"\n },\n \"custom_codestar_connection_arn\" => \"arn:aws:codestar-connections:eu-west-2:000000000000:connection/00000000-0000-0000-0000-000000000000\",\n \"codepipeline_use_github_v1\" => false,\n \"codepipeline_codebuild_run_in_vpc\" => false,\n \"codepipeline_codebuild_use_service_env\" => false,\n \"buildspec\" => \"buildspec.yml\",\n \"container_port\" => \"3100\",\n \"container_command\" => [\n \"/docker-entrypoint.sh\",\n \"rails\",\n \"server\"\n ],\n \"container_volumes\" => [\n {\n \"name\" => \"test-volume\",\n \"host_path\" => \"/mnt/test\",\n \"container_path\" => \"/test\"\n }\n ],\n \"container_extra_hosts\" => [\n {\n \"hostname\" => \"example.com\",\n \"ipAddress\" => \"127.0.0.1\"\n }\n ],\n \"container_count\" => \"2\",\n \"enable_max_one_container_per_instance\" => true,\n \"scheduled_tasks\" => [\n {\n \"name\" => \"old-scheduled-task\",\n \"command\" => [\n \"rake\",\n \"do:cron\"\n ],\n \"schedule_expression\" =>\n {\n \"production\" => \"cron(0 4 * * ? *)\",\n \"staging\" => \"cron(0 4 * * ? *)\"\n }\n },\n {\n \"name\" => \"test-scheduled-task\",\n \"command\" => [\n \"rake\",\n \"do:something\"\n ],\n \"schedule_expression\" => {\n \"staging\" => \"cron(0 12 * * ? *)\",\n \"production\" => \"cron(1 2 * * ? *)\"\n }\n }\n ],\n \"workers\" => [\n {\n \"name\" => \"test-worker\",\n \"command\" => [\n \"bundle\",\n \"exec\",\n \"sidekiq\"\n ]\n }\n ]\n }\n )\n )\n )\n end\n\n let(:cluster1_plan_cmd_staging_service) do\n terraform_plan_cmd(\n tfvar_arg_string(\n infrastructure_defaults.merge(\n \"instance_type\" => \"t2.small\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"track_revision\" => \"feature/experiment\",\n \"extra_ecs_clusters\" => [\n {\n \"name\" => \"test\",\n \"subnets_name\" => \"extra_private_subnets\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"instance_type\" => \"t3.small\"\n }\n ],\n \"tinyproxy\" => {\n \"create\" => true\n },\n \"environment\" => \"staging\",\n \"cluster_name\" => \"new-dedicated-cluster-staging\",\n \"account_id\" => \"123456789012\",\n \"infrastructure_name\" => \"new-dedicated-cluster\",\n \"dalmatian_role\" => \"dalmatian-read\",\n \"service\" => {\n \"name\" => \"test-service\",\n \"blue_green\" => {\n \"production\" => {\n \"enabled\" => true,\n \"db_copy\" => {\n \"from_db_host_ps_key\" => \"/test-app/other-test-service/production/DB_HOST\",\n \"from_db_name_ps_key\" => \"/test-app/other-test-service/production/DB_NAME\",\n \"from_db_user_ps_key\" => \"/test-app/other-test-service/production/DB_USER\",\n \"from_db_pass_ps_key\" => \"/test-app/other-test-service/production/DB_PASSWORD\",\n \"blue_green_db_name_ps_key\" => \"/test-app/test-service/production/DB_HOST\",\n \"blue_green_db_user_ps_key\" => \"/test-app/test-service/production/DB_USER\",\n \"blue_green_db_pass_ps_key\" => \"/test-app/test-service/production/DB_PASSWORD\",\n \"sql_backups_s3_bucket\" => \"new-dedicated-cluster-testservice-production-sql-backup\"\n },\n \"db_rewrites\" => [\n {\n \"from\" => \"other-test-service.example.com\",\n \"to\" => \"test-service.example.com\"\n }\n ],\n \"directory_copy\" => [\n {\n \"from\" => \"/mnt/efs/other-test-service-media\",\n \"to\" => \"/mnt/efs/test-service-media\",\n \"chown\" => \"33:33\"\n }\n ],\n \"asset_copy_trigger_ps_key\" => \"/test-app/test-service/production/BLUE_GREEN_ASSET_COPY_TRIGGER\"\n },\n \"staging\" => {\n \"enabled\" => false\n }\n },\n \"launch_on\" => [\"production\", \"staging\"],\n \"launch_on_cluster\" => \"test\",\n \"cluster_min_servers\" => {\n \"production\" => \"2\",\n \"staging\" => \"2\"\n },\n \"parameter_store_path\" => {\n \"production\" => \"\",\n \"staging\" => \"/test-path\"\n },\n \"parameter_store_key\" => {\n \"production\" => \"\",\n \"staging\" => \"arn:aws:kms:eu-west-2:000000000000:key/00000000-0000-0000-0000-000000000000\"\n },\n \"daemon\" => false,\n \"monitoring\" => {\n \"production\" => {\n \"opsgenie_alerts\" => {\n \"enabled\" => true,\n \"cloudfront_5xx\" => {\n \"enabled\" => true,\n \"threshold\" => \"95\",\n \"evaluation_periods\" => \"15\"\n }\n },\n \"ghost_inspector\" => {\n \"enabled\" => true\n }\n },\n \"staging\" => {\n \"opsgenie_alerts\" => {\n \"enabled\" => false,\n \"cloudfront_5xx\" => {\n \"enabled\" => true,\n \"threshold\" => \"95\",\n \"evaluation_periods\" => \"15\"\n }\n },\n \"ghost_inspector\" => {\n \"enabled\" => false\n }\n }\n },\n \"cloudfront\" => {\n \"production\" => {\n \"create\" => true,\n \"managed_cache_policy\" => \"CachingDisabled\",\n \"managed_origin_policy\" => \"AllViewerExceptHostHeader\",\n \"managed_response_headers_policy\" => \"CORS-with-preflight-and-SecurityHeadersPolicy\",\n \"tls_protocol_version\" => \"TLSv1.2_2019\",\n \"origin_keepalive_timeout\" => \"60\",\n \"origin_read_timeout\" => \"60\",\n \"basic_auth\" => false,\n \"basic_auth_users_extra\" => {},\n \"viewer_request_functions\" => [\n {\n \"name\" => \"default\",\n \"true_client_ip_header\" => true,\n \"ip_subnet_allow_list\" => [\n \"0.0.0.0/0\"\n ],\n \"redirects\" => [\n {\n \"from_hostname_pattern\" => \"example-old-domain-name.*\",\n \"from_path_pattern\" => \"/*\",\n \"to_hostname\" => \"example-domain-name.co.uk\",\n \"to_path\" => \"/${path}\"\n }\n ]\n }\n ],\n \"offline_page_http_status\" => {\n \"500\" => \"/error-pages/500.html\",\n \"501\" => \"/error-pages/501.html\",\n \"502\" => \"/error-pages/502.html\",\n \"503\" => \"/error-pages/503.html\",\n \"504\" => \"/error-pages/504.html\"\n },\n \"custom_origins\" => [\n {\n \"origin\" => \"test-media-production.s3.amazonaws.com\",\n \"id\" => \"test-media-production-s3\"\n }\n ],\n \"bypass_protection\" => {\n \"enabled\" => true,\n \"exclude_domains\" => [\n \"example.com\"\n ]\n },\n \"custom_behaviors\" => [\n {\n \"target_origin_id\" => \"test-media-production-s3\",\n \"min_ttl\" => 1200,\n \"default_ttl\" => 3600,\n \"max_ttl\" => 86400,\n \"associate_viewer_request_function\" => \"default\",\n \"managed_cache_policy\" => \"CachingDisabled\",\n \"managed_origin_policy\" => \"AllViewerExceptHostHeader\",\n \"managed_response_headers_policy\" => \"CORS-with-preflight-and-SecurityHeadersPolicy\",\n \"path_pattern\" => \"/media/*\"\n }\n ]\n },\n \"staging\" => {\n \"create\" => true,\n \"managed_cache_policy\" => \"CachingDisabled\",\n \"managed_origin_policy\" => \"AllViewerExceptHostHeader\",\n \"managed_response_headers_policy\" => \"CORS-with-preflight-and-SecurityHeadersPolicy\",\n \"tls_protocol_version\" => \"TLSv1.2_2021\",\n \"origin_keepalive_timeout\" => \"10\",\n \"origin_read_timeout\" => \"40\",\n \"basic_auth\" => true,\n \"basic_auth_users_extra\" => {},\n \"viewer_request_functions\" => [\n {\n \"name\" => \"default\",\n \"true_client_ip_header\" => true,\n \"ip_subnet_allow_list\" => [\n \"0.0.0.0/0\"\n ],\n \"redirects\" => [\n {\n \"from_hostname_pattern\" => \"example-old-domain-name.*\",\n \"from_path_pattern\" => \"/*\",\n \"to_hostname\" => \"example-domain-name.co.uk\",\n \"to_path\" => \"/${path}\"\n }\n ]\n }\n ],\n \"offline_page_http_status\" => {\n \"500\" => \"/error-pages/500.html\",\n \"501\" => \"/error-pages/501.html\",\n \"502\" => \"/error-pages/502.html\",\n \"503\" => \"/error-pages/503.html\",\n \"504\" => \"/error-pages/504.html\"\n },\n \"custom_origins\" => [\n {\n \"origin\" => \"test-media-staging.s3.amazonaws.com\",\n \"id\" => \"test-media-staging-s3\"\n }\n ],\n \"bypass_protection\" => {\n \"enabled\" => false,\n \"exclude_domains\" => []\n },\n \"custom_behaviors\" => [\n {\n \"target_origin_id\" => \"test-media-staging-s3\",\n \"min_ttl\" => 1200,\n \"default_ttl\" => 3600,\n \"max_ttl\" => 86400,\n \"associate_viewer_request_function\" => \"default\",\n \"managed_cache_policy\" => \"\",\n \"managed_origin_policy\" => \"\",\n \"managed_response_headers_policy\" => \"\",\n \"path_pattern\" => \"/media/*\"\n }\n ]\n }\n },\n \"s3_policy\" => {\n \"production\" => {},\n \"staging\" => {\n \"rw\" => [\n \"test\"\n ]\n }\n },\n \"shared_loadbalancer_name\" => \"test-lb-1\",\n \"lb_ip_whitelist\" => [\n {\n \"name\" => \"public\",\n \"cidr\" => \"0.0.0.0/0\"\n }\n ],\n \"lb_idle_timeout\" => \"60\",\n \"global_accelerator\" => {\n \"production\" => true,\n \"staging\" => false\n },\n \"health_check_path\" => \"/check\",\n \"health_check_grace_period\" => \"0\",\n \"deregistration_delay\" => \"60\",\n \"serve_from_subdirectory\" => \"/test-subdir\",\n \"domain_names\" => {\n \"production\" => [],\n \"staging\" => [\n \"example-domain-name.co.uk\"\n ]\n },\n \"proxy_configuration\" => {\n \"production\" => {},\n \"staging\" => {\n \"https_proxy\" => \"dalmatian_tinyproxy\",\n \"http_proxy\" => \"http://my.test-proxy.com:8888\",\n \"no_proxy\" => [\n \"*.example.com\",\n \"93.184.216.34/32\"\n ]\n }\n },\n \"home_directory\" => \"/home/user\",\n \"lb_ssl_certificate\" => {\n \"production\" => \"\",\n \"staging\" => \"arn:aws:acm:lb-region-0:000000000000:certificate/00000000-0000-0000-0000-000000000000\"\n },\n \"lb_ssl_policy\" => {\n \"production\" => \"ELBSecurityPolicy-TLS-1-2-2017-01\",\n \"staging\" => \"ELBSecurityPolicy-TLS-1-2-2017-01\"\n },\n \"cloudfront_ssl_certificate\" => {\n \"production\" => \"\",\n \"staging\" => \"arn:aws:acm:us-east-1:000000000000:certificate/00000000-0000-0000-0000-000000000000\"\n },\n \"image_source\" => \"build_from_github_repo\",\n \"image_location\" => \"git@github.com:dxw/dalmatian-test-app\",\n \"track_revision\" => {\n \"production\" => \"\",\n \"staging\" => \"\"\n },\n \"custom_codestar_connection_arn\" => \"arn:aws:codestar-connections:eu-west-2:000000000000:connection/00000000-0000-0000-0000-000000000000\",\n \"codepipeline_use_github_v1\" => false,\n \"codepipeline_codebuild_run_in_vpc\" => false,\n \"codepipeline_codebuild_use_service_env\" => false,\n \"buildspec\" => \"buildspec.yml\",\n \"container_port\" => \"3100\",\n \"container_command\" => [\n \"/docker-entrypoint.sh\",\n \"rails\",\n \"server\"\n ],\n \"container_volumes\" => [\n {\n \"name\" => \"test-volume\",\n \"host_path\" => \"/mnt/test\",\n \"container_path\" => \"/test\"\n }\n ],\n \"container_extra_hosts\" => [\n {\n \"hostname\" => \"example.com\",\n \"ipAddress\" => \"127.0.0.1\"\n }\n ],\n \"container_count\" => \"2\",\n \"enable_max_one_container_per_instance\" => true,\n \"scheduled_tasks\" => [\n {\n \"name\" => \"old-scheduled-task\",\n \"command\" => [\n \"rake\",\n \"do:cron\"\n ],\n \"schedule_expression\" =>\n {\n \"production\" => \"cron(0 4 * * ? *)\",\n \"staging\" => \"cron(0 4 * * ? *)\"\n }\n },\n {\n \"name\" => \"test-scheduled-task\",\n \"command\" => [\n \"rake\",\n \"do:something\"\n ],\n \"schedule_expression\" => {\n \"staging\" => \"cron(0 12 * * ? *)\",\n \"production\" => \"cron(1 2 * * ? *)\"\n }\n }\n ],\n \"workers\" => [\n {\n \"name\" => \"test-worker\",\n \"command\" => [\n \"bundle\",\n \"exec\",\n \"sidekiq\"\n ]\n }\n ]\n }\n )\n )\n )\n end\n\n let(:cluster1_plan_cmd_production_shared_loadbalancer) do\n terraform_plan_cmd(\n tfvar_arg_string(\n infrastructure_defaults.merge(\n \"instance_type\" => \"t2.medium\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"environment\" => \"production\",\n \"account_id\" => \"123456789012\",\n \"infrastructure_name\" => \"new-dedicated-cluster\",\n \"dalmatian_role\" => \"dalmatian-read\",\n \"shared_loadbalancer\" => {\n \"name\" => \"test-lb-1\",\n \"in_use_by\" => [\n \"test-service\"\n ],\n \"clusters_in_use\" => {\n \"production\" => [\n \"test\"\n ],\n \"staging\" => [\n \"test\"\n ]\n },\n \"subnets_name\" => \"\",\n \"domain_names\" => {\n \"test-service\" => {\n \"production\" => [],\n \"staging\" => [\n \"example-domain-name.co.uk\"\n ]\n }\n },\n \"internal\" => false,\n \"ip_whitelist\" => [\n {\n \"name\" => \"public\",\n \"cidr\" => \"0.0.0.0/0\"\n }\n ],\n \"idle_timeout\" => \"60\",\n \"global_accelerator\" => {\n \"production\" => true,\n \"staging\" => false\n },\n \"ssl_policy\" => \"ELBSecurityPolicy-TLS-1-2-2017-01\"\n }\n )\n )\n )\n end\n\n let(:cluster1_plan_cmd_staging_shared_loadbalancer) do\n terraform_plan_cmd(\n tfvar_arg_string(\n infrastructure_defaults.merge(\n \"instance_type\" => \"t2.small\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"track_revision\" => \"feature/experiment\",\n \"extra_ecs_clusters\" => [\n {\n \"name\" => \"test\",\n \"subnets_name\" => \"extra_private_subnets\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"instance_type\" => \"t3.small\"\n }\n ],\n \"tinyproxy\" => {\n \"create\" => true\n },\n \"environment\" => \"staging\",\n \"account_id\" => \"123456789012\",\n \"infrastructure_name\" => \"new-dedicated-cluster\",\n \"dalmatian_role\" => \"dalmatian-read\",\n \"shared_loadbalancer\" => {\n \"name\" => \"test-lb-1\",\n \"in_use_by\" => [\n \"test-service\"\n ],\n \"clusters_in_use\" => {\n \"production\" => [\n \"test\"\n ],\n \"staging\" => [\n \"test\"\n ]\n },\n \"subnets_name\" => \"\",\n \"domain_names\" => {\n \"test-service\" => {\n \"production\" => [],\n \"staging\" => [\n \"example-domain-name.co.uk\"\n ]\n }\n },\n \"internal\" => false,\n \"ip_whitelist\" => [\n {\n \"name\" => \"public\",\n \"cidr\" => \"0.0.0.0/0\"\n }\n ],\n \"idle_timeout\" => \"60\",\n \"global_accelerator\" => {\n \"production\" => true,\n \"staging\" => false\n },\n \"ssl_policy\" => \"ELBSecurityPolicy-TLS-1-2-2017-01\"\n }\n )\n )\n )\n end\n\n let(:source1_validate_cmd_production) do\n terraform_validate_cmd(\n tfvar_arg_string(\n infrastructure_defaults.merge(\n \"instance_type\" => \"t2.medium\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"cluster_name\" => \"new-dedicated-cluster-production\",\n \"account_id\" => \"123456789012\",\n \"infrastructure_name\" => \"new-dedicated-cluster\",\n \"dalmatian_role\" => \"dalmatian-read\",\n \"environment\" => \"production\"\n )\n )\n )\n end\n\n let(:source1_validate_cmd_staging) do\n terraform_validate_cmd(\n tfvar_arg_string(\n infrastructure_defaults.merge(\n \"instance_type\" => \"t2.small\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"track_revision\" => \"feature/experiment\",\n \"extra_ecs_clusters\" => [\n {\n \"name\" => \"test\",\n \"subnets_name\" => \"extra_private_subnets\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"instance_type\" => \"t3.small\"\n }\n ],\n \"tinyproxy\" => {\n \"create\" => true\n },\n \"cluster_name\" => \"new-dedicated-cluster-staging\",\n \"account_id\" => \"123456789012\",\n \"infrastructure_name\" => \"new-dedicated-cluster\",\n \"dalmatian_role\" => \"dalmatian-read\",\n \"environment\" => \"staging\"\n )\n )\n )\n end\n\n let(:cluster2_validate_cmd_production) do\n terraform_validate_cmd(\n tfvar_arg_string(\n infrastructure_defaults.merge(\n \"instance_type\" => \"t2.medium\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"10\",\n \"cluster_name\" => \"shared-new-cluster-production\",\n \"account_id\" => \"123456789012\",\n \"infrastructure_name\" => \"shared-new-cluster\",\n \"dalmatian_role\" => \"dalmatian-read\",\n \"environment\" => \"production\"\n )\n )\n )\n end\n\n let(:cluster2_validate_cmd_staging) do\n terraform_validate_cmd(\n tfvar_arg_string(\n infrastructure_defaults.merge(\n \"instance_type\" => \"t2.small\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"10\",\n \"cluster_name\" => \"shared-new-cluster-staging\",\n \"account_id\" => \"123456789012\",\n \"infrastructure_name\" => \"shared-new-cluster\",\n \"dalmatian_role\" => \"dalmatian-read\",\n \"environment\" => \"staging\"\n )\n )\n )\n end\n\n let(:cluster2_plan_cmd_production) do\n terraform_plan_cmd(\n tfvar_arg_string(\n infrastructure_defaults.merge(\n \"instance_type\" => \"t2.medium\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"10\",\n \"environment\" => \"production\",\n \"cluster_name\" => \"shared-new-cluster-production\",\n \"account_id\" => \"123456789012\",\n \"infrastructure_name\" => \"shared-new-cluster\",\n \"dalmatian_role\" => \"dalmatian-read\"\n )\n )\n )\n end\n\n let(:cluster2_plan_cmd_staging) do\n terraform_plan_cmd(\n tfvar_arg_string(\n infrastructure_defaults.merge(\n \"instance_type\" => \"t2.small\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"10\",\n \"environment\" => \"staging\",\n \"cluster_name\" => \"shared-new-cluster-staging\",\n \"account_id\" => \"123456789012\",\n \"infrastructure_name\" => \"shared-new-cluster\",\n \"dalmatian_role\" => \"dalmatian-read\"\n )\n )\n )\n end\n\n let(:cluster3_validate_cmd_staging) do\n terraform_validate_cmd(\n tfvar_arg_string(\n infrastructure_defaults.merge(\n \"example_var\" => \"foo\",\n \"cluster_name\" => \"shared-cluster-staging\",\n \"account_id\" => \"123456789012\",\n \"infrastructure_name\" => \"existing-shared-cluster-staging\",\n \"dalmatian_role\" => \"dalmatian-read\",\n \"environment\" => \"staging\"\n )\n )\n )\n end\n\n let(:cluster3_plan_cmd_staging) do\n terraform_plan_cmd(\n tfvar_arg_string(\n infrastructure_defaults.merge(\n \"example_var\" => \"foo\",\n \"environment\" => \"staging\",\n \"cluster_name\" => \"shared-cluster-staging\",\n \"account_id\" => \"123456789012\",\n \"infrastructure_name\" => \"existing-shared-cluster-staging\",\n \"dalmatian_role\" => \"dalmatian-read\"\n )\n )\n )\n end\n\n let(:cluster4_validate_cmd_production) do\n terraform_validate_cmd(\n tfvar_arg_string(\n infrastructure_defaults.merge(\n \"example_var\" => \"bar\",\n \"cluster_name\" => \"shared-cluster-production\",\n \"account_id\" => \"123456789012\",\n \"infrastructure_name\" => \"existing-shared-cluster-production\",\n \"dalmatian_role\" => \"dalmatian-read\",\n \"environment\" => \"production\"\n )\n )\n )\n end\n\n let(:cluster4_plan_cmd_production) do\n terraform_plan_cmd(\n tfvar_arg_string(\n infrastructure_defaults.merge(\n \"example_var\" => \"bar\",\n \"environment\" => \"production\",\n \"cluster_name\" => \"shared-cluster-production\",\n \"account_id\" => \"123456789012\",\n \"infrastructure_name\" => \"existing-shared-cluster-production\",\n \"dalmatian_role\" => \"dalmatian-read\"\n )\n )\n )\n end\n\n before do\n allow(Logger).to receive(:info)\n stub_git_clone_cmds\n stub_git_checkout\n stub_workspace_creation_cmds\n allow(Helper).to receive(:run!).with(\"rake terrafile\")\n allow(Helper).to receive(:run!).with(\"terraform init -upgrade=true\")\n allow(Helper).to receive(:run!).with(\"terraform fmt -check -diff\")\n\n allow(Helper).to receive(:run!).with(cluster1_validate_cmd_hz)\n allow(Helper).to receive(:run!).with(cluster1_validate_cmd_s3)\n allow(Helper).to receive(:run!).with(cluster1_validate_cmd_vpn_cg)\n\n allow(Helper).to receive(:run!).with(cluster1_plan_cmd_hz)\n allow(Helper).to receive(:run!).with(cluster1_plan_cmd_s3)\n allow(Helper).to receive(:run!).with(cluster1_plan_cmd_vpn_cg)\n\n allow(Helper).to receive(:run!).with(cluster1_validate_cmd_production)\n allow(Helper).to receive(:run!).with(cluster1_validate_cmd_staging)\n allow(Helper).to receive(:run!).with(cluster1_plan_cmd_production)\n allow(Helper).to receive(:run!).with(cluster1_plan_cmd_staging)\n allow(Helper).to receive(:run!).with(source1_validate_cmd_production)\n allow(Helper).to receive(:run!).with(source1_validate_cmd_staging)\n\n allow(Helper).to receive(:run!).with(cluster1_validate_cmd_production_waf)\n allow(Helper).to receive(:run!).with(cluster1_validate_cmd_staging_waf)\n allow(Helper).to receive(:run!).with(cluster1_plan_cmd_production_waf)\n allow(Helper).to receive(:run!).with(cluster1_plan_cmd_staging_waf)\n\n allow(Helper).to receive(:run!).with(cluster1_validate_cmd_production_rds)\n allow(Helper).to receive(:run!).with(cluster1_validate_cmd_staging_rds)\n allow(Helper).to receive(:run!).with(cluster1_plan_cmd_production_rds)\n allow(Helper).to receive(:run!).with(cluster1_plan_cmd_staging_rds)\n\n allow(Helper).to receive(:run!).with(cluster1_validate_cmd_production_elasticache_cluster)\n allow(Helper).to receive(:run!).with(cluster1_validate_cmd_staging_elasticache_cluster)\n allow(Helper).to receive(:run!).with(cluster1_plan_cmd_production_elasticache_cluster)\n allow(Helper).to receive(:run!).with(cluster1_plan_cmd_staging_elasticache_cluster)\n\n allow(Helper).to receive(:run!).with(cluster1_validate_cmd_production_opensearch_cluster)\n allow(Helper).to receive(:run!).with(cluster1_validate_cmd_staging_opensearch_cluster)\n allow(Helper).to receive(:run!).with(cluster1_plan_cmd_production_opensearch_cluster)\n allow(Helper).to receive(:run!).with(cluster1_plan_cmd_staging_opensearch_cluster)\n\n allow(Helper).to receive(:run!).with(cluster1_validate_cmd_production_service)\n allow(Helper).to receive(:run!).with(cluster1_validate_cmd_staging_service)\n allow(Helper).to receive(:run!).with(cluster1_plan_cmd_production_service)\n allow(Helper).to receive(:run!).with(cluster1_plan_cmd_staging_service)\n\n allow(Helper).to receive(:run!).with(cluster1_validate_cmd_production_shared_loadbalancer)\n allow(Helper).to receive(:run!).with(cluster1_validate_cmd_staging_shared_loadbalancer)\n allow(Helper).to receive(:run!).with(cluster1_plan_cmd_production_shared_loadbalancer)\n allow(Helper).to receive(:run!).with(cluster1_plan_cmd_staging_shared_loadbalancer)\n\n allow(Helper).to receive(:run!).with(cluster2_validate_cmd_production)\n allow(Helper).to receive(:run!).with(cluster2_validate_cmd_staging)\n allow(Helper).to receive(:run!).with(cluster2_plan_cmd_production)\n allow(Helper).to receive(:run!).with(cluster2_plan_cmd_staging)\n\n allow(Helper).to receive(:run!).with(cluster3_validate_cmd_staging)\n allow(Helper).to receive(:run!).with(cluster3_plan_cmd_staging)\n\n allow(Helper).to receive(:run!).with(cluster4_validate_cmd_production)\n allow(Helper).to receive(:run!).with(cluster4_plan_cmd_production)\n\n Infrastructure.new(\n ConfigurationReader.new(path: \"./dalmatian.yml.example\", parameter_store: fake_parameter_store).infrastructures\n ).test\n end\n\n it 'invokes \"terraform validate\" with the expected cluster options' do\n expect(Helper).to have_received(:run!).with(cluster1_validate_cmd_hz)\n\n expect(Helper).to have_received(:run!).with(cluster1_validate_cmd_s3)\n\n expect(Helper).to have_received(:run!).with(cluster1_validate_cmd_vpn_cg)\n\n expect(Helper).to have_received(:run!).with(cluster1_validate_cmd_production).twice\n expect(Helper).to have_received(:run!).with(cluster1_validate_cmd_staging).twice\n\n expect(Helper).to have_received(:run!).with(cluster1_validate_cmd_production_waf)\n expect(Helper).to have_received(:run!).with(cluster1_validate_cmd_staging_waf)\n\n expect(Helper).to have_received(:run!).with(cluster1_validate_cmd_production_rds)\n expect(Helper).to have_received(:run!).with(cluster1_validate_cmd_staging_rds)\n\n expect(Helper).to have_received(:run!).with(cluster1_validate_cmd_production_elasticache_cluster)\n expect(Helper).to have_received(:run!).with(cluster1_validate_cmd_staging_elasticache_cluster)\n\n expect(Helper).to have_received(:run!).with(cluster1_validate_cmd_production_opensearch_cluster)\n expect(Helper).to have_received(:run!).with(cluster1_validate_cmd_staging_opensearch_cluster)\n\n expect(Helper).to have_received(:run!).with(cluster1_validate_cmd_production_service)\n expect(Helper).to have_received(:run!).with(cluster1_validate_cmd_staging_service)\n\n expect(Helper).to have_received(:run!).with(cluster1_validate_cmd_production_shared_loadbalancer)\n expect(Helper).to have_received(:run!).with(cluster1_validate_cmd_staging_shared_loadbalancer)\n\n expect(Helper).to have_received(:run!).with(cluster2_validate_cmd_production)\n expect(Helper).to have_received(:run!).with(cluster2_validate_cmd_staging)\n\n expect(Helper).to have_received(:run!).with(cluster3_validate_cmd_staging)\n\n expect(Helper).to have_received(:run!).with(cluster4_validate_cmd_production)\n end\n\n it 'invokes \"terraform validate\" with the expected source options' do\n expect(Helper).to have_received(:run!).with(source1_validate_cmd_production).twice\n expect(Helper).to have_received(:run!).with(source1_validate_cmd_staging).twice\n end\n\n describe 'use of \"terraform plan\"' do\n it 'passes the hosted zone config to \"terraform plan\"' do\n aggregate_failures do\n expect(Helper).to have_received(:run!).with(cluster1_plan_cmd_hz)\n end\n end\n\n it 'passes the s3 config to \"terraform plan\"' do\n aggregate_failures do\n expect(Helper).to have_received(:run!).with(cluster1_plan_cmd_s3)\n end\n end\n\n it 'passes the vpn customer gateway config to \"terraform plan\"' do\n aggregate_failures do\n expect(Helper).to have_received(:run!).with(cluster1_plan_cmd_vpn_cg)\n end\n end\n\n it 'passes the base config to \"terraform plan\"' do\n aggregate_failures do\n expect(Helper).to have_received(:run!).with(cluster1_plan_cmd_production).twice\n expect(Helper).to have_received(:run!).with(cluster1_plan_cmd_staging).twice\n end\n end\n\n it 'passes the waf config to \"terraform plan\"' do\n aggregate_failures do\n expect(Helper).to have_received(:run!).with(cluster1_plan_cmd_production_waf)\n expect(Helper).to have_received(:run!).with(cluster1_plan_cmd_staging_waf)\n end\n end\n\n it 'passes the rds config to \"terraform plan\"' do\n aggregate_failures do\n expect(Helper).to have_received(:run!).with(cluster1_plan_cmd_production_rds)\n expect(Helper).to have_received(:run!).with(cluster1_plan_cmd_staging_rds)\n end\n end\n\n it 'passes the elasticache config to \"terraform plan\"' do\n aggregate_failures do\n expect(Helper).to have_received(:run!)\n .with(cluster1_plan_cmd_production_elasticache_cluster)\n expect(Helper).to have_received(:run!)\n .with(cluster1_plan_cmd_staging_elasticache_cluster)\n end\n end\n\n it 'passes the opensearch config to \"terraform plan\"' do\n aggregate_failures do\n expect(Helper).to have_received(:run!)\n .with(cluster1_plan_cmd_production_opensearch_cluster)\n expect(Helper).to have_received(:run!)\n .with(cluster1_plan_cmd_staging_opensearch_cluster)\n end\n end\n\n it 'passes the services config to \"terraform plan\"' do\n aggregate_failures do\n expect(Helper).to have_received(:run!).with(cluster1_plan_cmd_production_service)\n expect(Helper).to have_received(:run!).with(cluster1_plan_cmd_staging_service)\n end\n end\n\n it 'passes the loadbalancer config to \"terraform plan\"' do\n aggregate_failures do\n expect(Helper).to have_received(:run!)\n .with(cluster1_plan_cmd_production_shared_loadbalancer)\n expect(Helper).to have_received(:run!)\n .with(cluster1_plan_cmd_staging_shared_loadbalancer)\n end\n end\n\n it 'passes the cluster 2 config to \"terraform plan\"' do\n aggregate_failures do\n expect(Helper).to have_received(:run!).with(cluster2_plan_cmd_production)\n expect(Helper).to have_received(:run!).with(cluster2_plan_cmd_staging)\n end\n end\n\n it 'passes the cluster 3 config to \"terraform plan\"' do\n expect(Helper).to have_received(:run!).with(cluster3_plan_cmd_staging)\n end\n\n it 'passes the cluster 4 config to \"terraform plan\"' do\n expect(Helper).to have_received(:run!).with(cluster4_plan_cmd_production)\n end\n end\n end\nend\n",
|
|
"newContent": "require_relative \"../support/spec_helper\"\n\nmodule Dalmatian\n RSpec.describe \"tests local configuration\" do\n def fake_parameter_store\n double(\n \"parameter_store\",\n get_parameter: \"\",\n get_parameters_by_path: {}\n )\n end\n\n def tfvar_arg_string(tfvars)\n Terraform.tfvar_arg_string(tfvars)\n end\n\n def terraform_validate_cmd(tfvar_string)\n \"#{tfvar_string} terraform validate\"\n end\n\n def terraform_plan_cmd(tfvar_string)\n \"#{tfvar_string} terraform plan\"\n end\n\n def stub_workspace_creation_cmds\n %w[\n new-dedicated-cluster-example-domain-name-com-hz\n new-dedicated-cluster-test-s3\n new-dedicated-cluster-test-vpn-vpn-cg\n new-dedicated-cluster-ecs-production\n new-dedicated-cluster-ecs-staging\n new-dedicated-cluster-0-production\n new-dedicated-cluster-0-staging\n new-dedicated-cluster-test-service-staging\n new-dedicated-cluster-test-service-production\n new-dedicated-cluster-test-1-waf-staging\n new-dedicated-cluster-test-1-waf-production\n new-dedicated-cluster-testservice-rds-staging\n new-dedicated-cluster-testservice-rds-production\n new-dedicated-cluster-testredis-elasticache-cluster-staging\n new-dedicated-cluster-testredis-elasticache-cluster-production\n new-dedicated-cluster-testos-opensearch-cluster-staging\n new-dedicated-cluster-testos-opensearch-cluster-production\n new-dedicated-cluster-test-lb-1-shared-loadbalancer-staging\n new-dedicated-cluster-test-lb-1-shared-loadbalancer-production\n shared-new-cluster-ecs-production\n shared-new-cluster-ecs-staging\n existing-shared-cluster-staging-0-staging\n existing-shared-cluster-production-0-production\n ].each do |workspace_name|\n allow(Helper).to receive(:run!).with(\"terraform workspace new #{workspace_name}\")\n end\n end\n\n def stub_git_checkout\n allow(Helper).to receive(:run!).with(\"git checkout feature/experiment\")\n end\n\n def stub_git_clone_cmds\n [\n {\n source: \"git@github.com:dxw/awesome-app-dalmatian-config\",\n name: \"new-dedicated-cluster-0.config\"\n },\n {\n source: \"git@github.com:dxw/funky-app-dalmatian-config\",\n name: \"existing-shared-cluster-staging-0.config\"\n },\n {\n source: \"git@github.com:dxw/neat-app-dalmatian-config\",\n name: \"existing-shared-cluster-production-0.config\"\n },\n {\n source: \"git@github.com:dxw/neat-app-dalmatian-config\",\n name: \"existing-shared-cluster-production-0.config\"\n }\n\n ].each do |src|\n allow(Helper).to receive(:run!)\n .with(\"git clone #{src.fetch(:source)} terraform/infrastructures/#{src.fetch(:name)}\")\n end\n end\n\n def infrastructure_defaults\n {\n \"region\" => \"eu-west-2\",\n \"cidr\" => \"10.0.0.0/16\",\n \"root_domain_zone\" => \"dalmatian.dxw.net\",\n \"internal_domain_zone\" => \"dalmatian.internal\",\n \"ecs_private_subnets\" => [\n {\n \"availability_zone\" => \"eu-west-2a\",\n \"cidr\" => \"10.0.128.0/24\"\n },\n {\n \"availability_zone\" => \"eu-west-2b\",\n \"cidr\" => \"10.0.129.0/24\"\n },\n {\n \"availability_zone\" => \"eu-west-2c\",\n \"cidr\" => \"10.0.130.0/24\"\n }\n ],\n \"extra_public_subnets\" => [\n {\n \"availability_zone\" => \"eu-west-2a\",\n \"cidr\" => \"10.0.0.0/24\"\n },\n {\n \"availability_zone\" => \"eu-west-2b\",\n \"cidr\" => \"10.0.1.0/24\"\n },\n {\n \"availability_zone\" => \"eu-west-2c\",\n \"cidr\" => \"10.0.2.0/24\"\n }\n ],\n \"instances_key_name\" => \"dalmatian-ecs-instances\",\n \"instance_type\" => \"t2.medium\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"max_instance_lifetime\" => \"86400\",\n \"associate_public_ip_address\" => \"0\",\n \"docker_storage_size\" => \"40\",\n \"dockerhub_email\" => \"\",\n \"dockerhub_token\" => \"\",\n \"enable_efs\" => \"false\",\n \"encrypt_efs\" => \"true\",\n \"efs_dirs\" => [],\n \"monitoring_docs_path\" => \"https://github.com/dxw/dalmatian/docs/monitoring-alarms/\"\n }\n end\n\n let(:cluster1_validate_cmd_hz) do\n terraform_validate_cmd(\n tfvar_arg_string(\n \"account_id\" => \"123456789012\",\n \"cluster_id\" => \"new-dedicated-cluster\",\n \"dalmatian_role\" => \"dalmatian-read\",\n \"hosted_zone\" => {\n \"domain\" => \"example-domain-name.com\",\n \"ns_records\" => [\n {\n \"name\" => \"delegated\",\n \"value\" => [\n \"ns1.aws.com\"\n ]\n }\n ],\n \"a_records\" => [\n {\n \"name\" => \"some-service\",\n \"value\" => [\n \"1.2.3.4\"\n ]\n },\n {\n \"name\" => \"mail\",\n \"value\" => [\n \"5.6.7.8\"\n ]\n }\n ],\n \"alias_records\" => [\n {\n \"name\" => \"example-domain-name.com\",\n \"value\" => \"cf-distribution.aws.net\"\n },\n {\n \"name\" => \"www\",\n \"value\" => \"cf-distribution.aws.net\"\n }\n ],\n \"cname_records\" => [\n {\n \"name\" => \"alb\",\n \"value\" => [\n \"aws-alb.aws.net\"\n ]\n }\n ],\n \"mx_records\" => [\n {\n \"name\" => \"mail\",\n \"value\" => [\n \"0 mail.example-domain-name.com\"\n ]\n }\n ],\n \"txt_records\" => [\n {\n \"name\" => \"mail\",\n \"value\" => [\n \"v=spf1 a ip4:9.10.11.0/24 mx ~all\"\n ]\n }\n ],\n \"srv_records\" => [\n {\n \"name\" => \"@\",\n \"value\" => [\n \"_imaps._tcp.gmail.com. 86400 IN SRV 5 0 993 imap.gmail.com\"\n ]\n }\n ]\n }\n )\n )\n end\n\n let(:cluster1_validate_cmd_s3) do\n terraform_validate_cmd(\n tfvar_arg_string(\n \"account_id\" => \"123456789012\",\n \"cluster_id\" => \"new-dedicated-cluster\",\n \"dalmatian_role\" => \"dalmatian-read\",\n \"s3\" => {\n \"name\" => \"test\",\n \"enable_s3_versioning\" => true,\n \"encrypted\" => true,\n \"acl\" => \"private\",\n \"policy\" => {\n \"staging\" => {\n \"rw\" => {\n \"services\" => [\n \"test-service\"\n ]\n }\n }\n },\n \"service_cloudfront_read_access\" => [\n \"test-service-staging\"\n ],\n \"cloudfront\" => {\n \"create\" => true,\n \"domain_names\" => [\n \"example.com\",\n \"example2.com\"\n ],\n \"certificate\" => \"arn:aws:acm:lb-region-0:000000000000:certificate/00000000-0000-0000-0000-000000000000\"\n }\n }\n )\n )\n end\n\n let(:cluster1_validate_cmd_vpn_cg) do\n terraform_validate_cmd(\n tfvar_arg_string(\n \"account_id\" => \"123456789012\",\n \"cluster_id\" => \"new-dedicated-cluster\",\n \"dalmatian_role\" => \"dalmatian-read\",\n \"vpn_customer_gateway\" => {\n \"name\" => \"test-vpn\",\n \"bgp_asn\" => 65000,\n \"ip_address\" => \"1.2.3.4\"\n }\n )\n )\n end\n\n let(:cluster1_validate_cmd_production) do\n terraform_validate_cmd(\n tfvar_arg_string(\n infrastructure_defaults.merge(\n \"instance_type\" => \"t2.medium\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"cluster_name\" => \"new-dedicated-cluster-production\",\n \"account_id\" => \"123456789012\",\n \"infrastructure_name\" => \"new-dedicated-cluster\",\n \"dalmatian_role\" => \"dalmatian-read\",\n \"environment\" => \"production\"\n )\n )\n )\n end\n\n let(:cluster1_validate_cmd_staging) do\n terraform_validate_cmd(\n tfvar_arg_string(\n infrastructure_defaults.merge(\n \"instance_type\" => \"t2.small\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"track_revision\" => \"feature/experiment\",\n \"extra_ecs_clusters\" => [\n {\n \"name\" => \"test\",\n \"subnets_name\" => \"extra_private_subnets\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"instance_type\" => \"t3.small\"\n }\n ],\n \"tinyproxy\" => {\n \"create\" => true\n },\n \"cluster_name\" => \"new-dedicated-cluster-staging\",\n \"account_id\" => \"123456789012\",\n \"infrastructure_name\" => \"new-dedicated-cluster\",\n \"dalmatian_role\" => \"dalmatian-read\",\n \"environment\" => \"staging\"\n )\n )\n )\n end\n\n let(:cluster1_validate_cmd_production_waf) do\n terraform_validate_cmd(\n tfvar_arg_string(\n infrastructure_defaults.merge(\n \"instance_type\" => \"t2.medium\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"account_id\" => \"123456789012\",\n \"infrastructure_name\" => \"new-dedicated-cluster\",\n \"dalmatian_role\" => \"dalmatian-read\",\n \"environment\" => \"production\",\n \"waf\" => {\n \"name\" => \"test-1\",\n \"action\" => \"count\",\n \"ip_deny_list\" => [],\n \"aws_managed_rules\" => [\n {\n \"name\" => \"AWSManagedRulesSQLiRuleSet\",\n \"excluded_path_patterns\" => [\n \"/wp-admin/async-upload.php\"\n ]\n },\n {\n \"name\" => \"AWSManagedRulesCommonRuleSet\",\n \"exclude_rules\" => [\n \"SizeRestrictions_BODY\"\n ]\n }\n ],\n \"associations\" => {\n shared_loadbalancers: [\n \"test-lb-1\"\n ],\n service_cloudfront: [\n \"test-service\"\n ]\n }\n }\n )\n )\n )\n end\n\n let(:cluster1_validate_cmd_production_rds) do\n terraform_validate_cmd(\n tfvar_arg_string(\n infrastructure_defaults.merge(\n \"instance_type\" => \"t2.medium\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"account_id\" => \"123456789012\",\n \"infrastructure_name\" => \"new-dedicated-cluster\",\n \"dalmatian_role\" => \"dalmatian-read\",\n \"environment\" => \"production\",\n \"rds\" => {\n \"identifier\" => \"testservice\",\n \"in_use_by\" => [\n \"test-service\"\n ],\n \"clusters_in_use\" => {\n \"production\" => [\n \"test\"\n ],\n \"staging\" => [\n \"test\"\n ]\n },\n \"instance_class\" => {\n \"production\" => \"db.t2.small\",\n \"staging\" => \"db.t2.micro\"\n },\n \"engine\" => \"postgres\",\n \"engine_version\" => \"11.4\",\n \"allocated_storage\" => 20,\n \"storage_encrypted\" => true,\n \"storage_type\" => \"gp3\",\n \"db_name\" => \"testapp\",\n \"port\" => 5432,\n \"maintenance_window\" => \"mon:19:00-mon:19:30\",\n \"backup_window\" => \"09:00-10:00\",\n \"backup_retention_period\" => 31,\n \"force_ssl\" => true,\n \"parameter_store_path_db_url_name\" => \"DATABASE_URL\",\n \"sql_backup_scheduled_task_environment_variables\" => [\n {\n \"name\" => \"foo\",\n \"value\" => \"bar\"\n }\n ],\n \"check_sql_backup_scheduled_task_environment_variables\" => [\n {\n \"name\" => \"foo\",\n \"value\" => \"bar\"\n }\n ],\n \"sync_sql_backup_to_azure\" => false,\n \"replication_bucket_destination_arn\" => \"\",\n \"replication_kms_key_id\" => \"\",\n \"codebuild_access\" => [\n \"service-name\"\n ]\n }\n )\n )\n )\n end\n\n let(:cluster1_validate_cmd_staging_waf) do\n terraform_validate_cmd(\n tfvar_arg_string(\n infrastructure_defaults.merge(\n \"instance_type\" => \"t2.small\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"track_revision\" => \"feature/experiment\",\n \"extra_ecs_clusters\" => [\n {\n \"name\" => \"test\",\n \"subnets_name\" => \"extra_private_subnets\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"instance_type\" => \"t3.small\"\n }\n ],\n \"tinyproxy\" => {\n \"create\" => true\n },\n \"account_id\" => \"123456789012\",\n \"infrastructure_name\" => \"new-dedicated-cluster\",\n \"dalmatian_role\" => \"dalmatian-read\",\n \"environment\" => \"staging\",\n \"waf\" => {\n \"name\" => \"test-1\",\n \"action\" => \"count\",\n \"ip_deny_list\" => [],\n \"aws_managed_rules\" => [\n {\n \"name\" => \"AWSManagedRulesSQLiRuleSet\",\n \"excluded_path_patterns\" => [\n \"/wp-admin/async-upload.php\"\n ]\n },\n {\n \"name\" => \"AWSManagedRulesCommonRuleSet\",\n \"exclude_rules\" => [\n \"SizeRestrictions_BODY\"\n ]\n }\n ],\n \"associations\" => {\n shared_loadbalancers: [\n \"test-lb-1\"\n ],\n service_cloudfront: [\n \"test-service\"\n ]\n }\n }\n )\n )\n )\n end\n\n let(:cluster1_validate_cmd_staging_rds) do\n terraform_validate_cmd(\n tfvar_arg_string(\n infrastructure_defaults.merge(\n \"instance_type\" => \"t2.small\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"track_revision\" => \"feature/experiment\",\n \"extra_ecs_clusters\" => [\n {\n \"name\" => \"test\",\n \"subnets_name\" => \"extra_private_subnets\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"instance_type\" => \"t3.small\"\n }\n ],\n \"tinyproxy\" => {\n \"create\" => true\n },\n \"account_id\" => \"123456789012\",\n \"infrastructure_name\" => \"new-dedicated-cluster\",\n \"dalmatian_role\" => \"dalmatian-read\",\n \"environment\" => \"staging\",\n \"rds\" => {\n \"identifier\" => \"testservice\",\n \"in_use_by\" => [\n \"test-service\"\n ],\n \"clusters_in_use\" => {\n \"production\" => [\n \"test\"\n ],\n \"staging\" => [\n \"test\"\n ]\n },\n \"instance_class\" => {\n \"production\" => \"db.t2.small\",\n \"staging\" => \"db.t2.micro\"\n },\n \"engine\" => \"postgres\",\n \"engine_version\" => \"11.4\",\n \"allocated_storage\" => 20,\n \"storage_encrypted\" => true,\n \"storage_type\" => \"gp3\",\n \"db_name\" => \"testapp\",\n \"port\" => 5432,\n \"maintenance_window\" => \"mon:19:00-mon:19:30\",\n \"backup_window\" => \"09:00-10:00\",\n \"backup_retention_period\" => 31,\n \"force_ssl\" => true,\n \"parameter_store_path_db_url_name\" => \"DATABASE_URL\",\n \"sql_backup_scheduled_task_environment_variables\" => [\n {\n \"name\" => \"foo\",\n \"value\" => \"bar\"\n }\n ],\n \"check_sql_backup_scheduled_task_environment_variables\" => [\n {\n \"name\" => \"foo\",\n \"value\" => \"bar\"\n }\n ],\n \"sync_sql_backup_to_azure\" => false,\n \"replication_bucket_destination_arn\" => \"\",\n \"replication_kms_key_id\" => \"\",\n \"codebuild_access\" => [\n \"service-name\"\n ]\n }\n )\n )\n )\n end\n\n let(:cluster1_validate_cmd_production_elasticache_cluster) do\n terraform_validate_cmd(\n tfvar_arg_string(\n infrastructure_defaults.merge(\n \"instance_type\" => \"t2.medium\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"account_id\" => \"123456789012\",\n \"infrastructure_name\" => \"new-dedicated-cluster\",\n \"dalmatian_role\" => \"dalmatian-read\",\n \"environment\" => \"production\",\n \"elasticache_cluster\" => {\n \"identifier\" => \"testredis\",\n \"in_use_by\" => [\n \"test-service\"\n ],\n \"node_type\" => \"cache.t2.micro\",\n \"node_count\" => 1,\n \"engine\" => \"redis\",\n \"engine_version\" => \"5.0.6\",\n \"parameters\" => [],\n \"port\" => 6379,\n \"maintenance_window\" => \"mon:19:00-mon:22:00\",\n \"snapshot_window\" => \"09:00-10:00\",\n \"parameter_store_path_elasticache_cluster_url_name\" => \"REDIS_URL\"\n }\n )\n )\n )\n end\n\n let(:cluster1_validate_cmd_staging_elasticache_cluster) do\n terraform_validate_cmd(\n tfvar_arg_string(\n infrastructure_defaults.merge(\n \"instance_type\" => \"t2.small\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"track_revision\" => \"feature/experiment\",\n \"extra_ecs_clusters\" => [\n {\n \"name\" => \"test\",\n \"subnets_name\" => \"extra_private_subnets\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"instance_type\" => \"t3.small\"\n }\n ],\n \"tinyproxy\" => {\n \"create\" => true\n },\n \"account_id\" => \"123456789012\",\n \"infrastructure_name\" => \"new-dedicated-cluster\",\n \"dalmatian_role\" => \"dalmatian-read\",\n \"environment\" => \"staging\",\n \"elasticache_cluster\" => {\n \"identifier\" => \"testredis\",\n \"in_use_by\" => [\n \"test-service\"\n ],\n \"node_type\" => \"cache.t2.micro\",\n \"node_count\" => 1,\n \"engine\" => \"redis\",\n \"engine_version\" => \"5.0.6\",\n \"parameters\" => [],\n \"port\" => 6379,\n \"maintenance_window\" => \"mon:19:00-mon:22:00\",\n \"snapshot_window\" => \"09:00-10:00\",\n \"parameter_store_path_elasticache_cluster_url_name\" => \"REDIS_URL\"\n }\n )\n )\n )\n end\n\n let(:cluster1_validate_cmd_production_opensearch_cluster) do\n terraform_validate_cmd(\n tfvar_arg_string(\n infrastructure_defaults.merge(\n \"instance_type\" => \"t2.medium\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"account_id\" => \"123456789012\",\n \"infrastructure_name\" => \"new-dedicated-cluster\",\n \"dalmatian_role\" => \"dalmatian-read\",\n \"environment\" => \"production\",\n \"opensearch_cluster\" => {\n \"identifier\" => \"testos\",\n \"in_use_by\" => [\n \"test-service\"\n ],\n \"version\" => \"1.2\",\n \"master_enabled\" => true,\n \"master_count\" => \"1\",\n \"master_type\" => \"c6g.large.search\",\n \"instance_count\" => \"3\",\n \"instance_type\" => \"t3.small.search\",\n \"warm_enabled\" => true,\n \"warm_count\" => \"2\",\n \"warm_type\" => \"ultrawarm1.medium.search\",\n \"parameter_store_path_opensearch_cluster_url_name\" => \"ELASTICSEARCH_URL\",\n \"volume_size\" => \"20\"\n }\n )\n )\n )\n end\n\n let(:cluster1_validate_cmd_staging_opensearch_cluster) do\n terraform_validate_cmd(\n tfvar_arg_string(\n infrastructure_defaults.merge(\n \"instance_type\" => \"t2.small\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"track_revision\" => \"feature/experiment\",\n \"extra_ecs_clusters\" => [\n {\n \"name\" => \"test\",\n \"subnets_name\" => \"extra_private_subnets\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"instance_type\" => \"t3.small\"\n }\n ],\n \"tinyproxy\" => {\n \"create\" => true\n },\n \"account_id\" => \"123456789012\",\n \"infrastructure_name\" => \"new-dedicated-cluster\",\n \"dalmatian_role\" => \"dalmatian-read\",\n \"environment\" => \"staging\",\n \"opensearch_cluster\" => {\n \"identifier\" => \"testos\",\n \"in_use_by\" => [\n \"test-service\"\n ],\n \"version\" => \"1.2\",\n \"master_enabled\" => true,\n \"master_count\" => \"1\",\n \"master_type\" => \"c6g.large.search\",\n \"instance_count\" => \"3\",\n \"instance_type\" => \"t3.small.search\",\n \"warm_enabled\" => true,\n \"warm_count\" => \"2\",\n \"warm_type\" => \"ultrawarm1.medium.search\",\n \"parameter_store_path_opensearch_cluster_url_name\" => \"ELASTICSEARCH_URL\",\n \"volume_size\" => \"20\"\n }\n )\n )\n )\n end\n\n let(:cluster1_validate_cmd_production_service) do\n terraform_validate_cmd(\n tfvar_arg_string(\n infrastructure_defaults.merge(\n \"instance_type\" => \"t2.medium\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"cluster_name\" => \"new-dedicated-cluster-production\",\n \"account_id\" => \"123456789012\",\n \"infrastructure_name\" => \"new-dedicated-cluster\",\n \"dalmatian_role\" => \"dalmatian-read\",\n \"environment\" => \"production\",\n \"service\" => {\n \"name\" => \"test-service\",\n \"blue_green\" => {\n \"production\" => {\n \"enabled\" => true,\n \"db_copy\" => {\n \"from_db_host_ps_key\" => \"/test-app/other-test-service/production/DB_HOST\",\n \"from_db_name_ps_key\" => \"/test-app/other-test-service/production/DB_NAME\",\n \"from_db_user_ps_key\" => \"/test-app/other-test-service/production/DB_USER\",\n \"from_db_pass_ps_key\" => \"/test-app/other-test-service/production/DB_PASSWORD\",\n \"blue_green_db_name_ps_key\" => \"/test-app/test-service/production/DB_HOST\",\n \"blue_green_db_user_ps_key\" => \"/test-app/test-service/production/DB_USER\",\n \"blue_green_db_pass_ps_key\" => \"/test-app/test-service/production/DB_PASSWORD\",\n \"sql_backups_s3_bucket\" => \"new-dedicated-cluster-testservice-production-sql-backup\"\n },\n \"db_rewrites\" => [\n {\n \"from\" => \"other-test-service.example.com\",\n \"to\" => \"test-service.example.com\"\n }\n ],\n \"directory_copy\" => [\n {\n \"from\" => \"/mnt/efs/other-test-service-media\",\n \"to\" => \"/mnt/efs/test-service-media\",\n \"chown\" => \"33:33\"\n }\n ],\n \"asset_copy_trigger_ps_key\" => \"/test-app/test-service/production/BLUE_GREEN_ASSET_COPY_TRIGGER\"\n },\n \"staging\" => {\n \"enabled\" => false\n }\n },\n \"launch_on\" => [\"production\", \"staging\"],\n \"launch_on_cluster\" => \"test\",\n \"cluster_min_servers\" => {\n \"production\" => \"2\",\n \"staging\" => \"2\"\n },\n \"parameter_store_path\" => {\n \"production\" => \"\",\n \"staging\" => \"/test-path\"\n },\n \"parameter_store_key\" => {\n \"production\" => \"\",\n \"staging\" => \"arn:aws:kms:eu-west-2:000000000000:key/00000000-0000-0000-0000-000000000000\"\n },\n \"daemon\" => false,\n \"monitoring\" => {\n \"production\" => {\n \"opsgenie_alerts\" => {\n \"enabled\" => true,\n \"cloudfront_5xx\" => {\n \"enabled\" => true,\n \"threshold\" => \"95\",\n \"evaluation_periods\" => \"15\"\n }\n },\n \"ghost_inspector\" => {\n \"enabled\" => true\n }\n },\n \"staging\" => {\n \"opsgenie_alerts\" => {\n \"enabled\" => false,\n \"cloudfront_5xx\" => {\n \"enabled\" => true,\n \"threshold\" => \"95\",\n \"evaluation_periods\" => \"15\"\n }\n },\n \"ghost_inspector\" => {\n \"enabled\" => false\n }\n }\n },\n \"cloudfront\" => {\n \"production\" => {\n \"create\" => true,\n \"managed_cache_policy\" => \"CachingDisabled\",\n \"managed_origin_policy\" => \"AllViewerExceptHostHeader\",\n \"managed_response_headers_policy\" => \"CORS-with-preflight-and-SecurityHeadersPolicy\",\n \"tls_protocol_version\" => \"TLSv1.2_2019\",\n \"origin_keepalive_timeout\" => \"60\",\n \"origin_read_timeout\" => \"60\",\n \"basic_auth\" => false,\n \"basic_auth_users_extra\" => {},\n \"viewer_request_functions\" => [\n {\n \"name\" => \"default\",\n \"true_client_ip_header\" => true,\n \"ip_subnet_allow_list\" => [\n \"0.0.0.0/0\"\n ],\n \"redirects\" => [\n {\n \"from_hostname_pattern\" => \"example-old-domain-name.*\",\n \"from_path_pattern\" => \"/*\",\n \"to_hostname\" => \"example-domain-name.co.uk\",\n \"to_path\" => \"/${path}\"\n }\n ]\n }\n ],\n \"offline_page_http_status\" => {\n \"500\" => \"/error-pages/500.html\",\n \"501\" => \"/error-pages/501.html\",\n \"502\" => \"/error-pages/502.html\",\n \"503\" => \"/error-pages/503.html\",\n \"504\" => \"/error-pages/504.html\"\n },\n \"custom_origins\" => [\n {\n \"origin\" => \"test-media-production.s3.amazonaws.com\",\n \"id\" => \"test-media-production-s3\"\n }\n ],\n \"bypass_protection\" => {\n \"enabled\" => true,\n \"exclude_domains\" => [\n \"example.com\"\n ]\n },\n \"custom_behaviors\" => [\n {\n \"target_origin_id\" => \"test-media-production-s3\",\n \"min_ttl\" => 1200,\n \"default_ttl\" => 3600,\n \"max_ttl\" => 86400,\n \"associate_viewer_request_function\" => \"default\",\n \"managed_cache_policy\" => \"CachingDisabled\",\n \"managed_origin_policy\" => \"AllViewerExceptHostHeader\",\n \"managed_response_headers_policy\" => \"CORS-with-preflight-and-SecurityHeadersPolicy\",\n \"path_pattern\" => \"/media/*\"\n }\n ]\n },\n \"staging\" => {\n \"create\" => true,\n \"managed_cache_policy\" => \"CachingDisabled\",\n \"managed_origin_policy\" => \"AllViewerExceptHostHeader\",\n \"managed_response_headers_policy\" => \"CORS-with-preflight-and-SecurityHeadersPolicy\",\n \"tls_protocol_version\" => \"TLSv1.2_2021\",\n \"origin_keepalive_timeout\" => \"10\",\n \"origin_read_timeout\" => \"40\",\n \"basic_auth\" => true,\n \"basic_auth_users_extra\" => {},\n \"viewer_request_functions\" => [\n {\n \"name\" => \"default\",\n \"true_client_ip_header\" => true,\n \"ip_subnet_allow_list\" => [\n \"0.0.0.0/0\"\n ],\n \"redirects\" => [\n {\n \"from_hostname_pattern\" => \"example-old-domain-name.*\",\n \"from_path_pattern\" => \"/*\",\n \"to_hostname\" => \"example-domain-name.co.uk\",\n \"to_path\" => \"/${path}\"\n }\n ]\n }\n ],\n \"offline_page_http_status\" => {\n \"500\" => \"/error-pages/500.html\",\n \"501\" => \"/error-pages/501.html\",\n \"502\" => \"/error-pages/502.html\",\n \"503\" => \"/error-pages/503.html\",\n \"504\" => \"/error-pages/504.html\"\n },\n \"custom_origins\" => [\n {\n \"origin\" => \"test-media-staging.s3.amazonaws.com\",\n \"id\" => \"test-media-staging-s3\"\n }\n ],\n \"bypass_protection\" => {\n \"enabled\" => false,\n \"exclude_domains\" => []\n },\n \"custom_behaviors\" => [\n {\n \"target_origin_id\" => \"test-media-staging-s3\",\n \"min_ttl\" => 1200,\n \"default_ttl\" => 3600,\n \"max_ttl\" => 86400,\n \"associate_viewer_request_function\" => \"default\",\n \"managed_cache_policy\" => \"\",\n \"managed_origin_policy\" => \"\",\n \"managed_response_headers_policy\" => \"\",\n \"path_pattern\" => \"/media/*\"\n }\n ]\n }\n },\n \"s3_policy\" => {\n \"production\" => {},\n \"staging\" => {\n \"rw\" => [\n \"test\"\n ]\n }\n },\n \"shared_loadbalancer_name\" => \"test-lb-1\",\n \"lb_ip_whitelist\" => [\n {\n \"name\" => \"public\",\n \"cidr\" => \"0.0.0.0/0\"\n }\n ],\n \"lb_idle_timeout\" => \"60\",\n \"global_accelerator\" => {\n \"production\" => true,\n \"staging\" => false\n },\n \"health_check_path\" => \"/check\",\n \"health_check_grace_period\" => \"0\",\n \"deregistration_delay\" => \"60\",\n \"serve_from_subdirectory\" => \"/test-subdir\",\n \"domain_names\" => {\n \"production\" => [],\n \"staging\" => [\n \"example-domain-name.co.uk\"\n ]\n },\n \"proxy_configuration\" => {\n \"production\" => {},\n \"staging\" => {\n \"https_proxy\" => \"dalmatian_tinyproxy\",\n \"http_proxy\" => \"http://my.test-proxy.com:8888\",\n \"no_proxy\" => [\n \"*.example.com\",\n \"93.184.216.34/32\"\n ]\n }\n },\n \"home_directory\" => \"/home/user\",\n \"lb_ssl_certificate\" => {\n \"production\" => \"\",\n \"staging\" => \"arn:aws:acm:lb-region-0:000000000000:certificate/00000000-0000-0000-0000-000000000000\"\n },\n \"lb_ssl_policy\" => {\n \"production\" => \"ELBSecurityPolicy-TLS-1-2-2017-01\",\n \"staging\" => \"ELBSecurityPolicy-TLS-1-2-2017-01\"\n },\n \"cloudfront_ssl_certificate\" => {\n \"production\" => \"\",\n \"staging\" => \"arn:aws:acm:us-east-1:000000000000:certificate/00000000-0000-0000-0000-000000000000\"\n },\n \"image_source\" => \"build_from_github_repo\",\n \"image_location\" => \"git@github.com:dxw/dalmatian-test-app\",\n \"track_revision\" => {\n \"production\" => \"\",\n \"staging\" => \"\"\n },\n \"custom_codestar_connection_arn\" => \"arn:aws:codestar-connections:eu-west-2:000000000000:connection/00000000-0000-0000-0000-000000000000\",\n \"codepipeline_use_github_v1\" => false,\n \"codepipeline_codebuild_run_in_vpc\" => false,\n \"codepipeline_codebuild_use_service_env\" => false,\n \"buildspec\" => \"buildspec.yml\",\n \"container_port\" => \"3100\",\n \"container_command\" => [\n \"/docker-entrypoint.sh\",\n \"rails\",\n \"server\"\n ],\n \"container_volumes\" => [\n {\n \"name\" => \"test-volume\",\n \"host_path\" => \"/mnt/test\",\n \"container_path\" => \"/test\"\n }\n ],\n \"container_extra_hosts\" => [\n {\n \"hostname\" => \"example.com\",\n \"ipAddress\" => \"127.0.0.1\"\n }\n ],\n \"container_count\" => \"2\",\n \"enable_max_one_container_per_instance\" => true,\n \"scheduled_tasks\" => [\n {\n \"name\" => \"old-scheduled-task\",\n \"command\" => [\n \"rake\",\n \"do:cron\"\n ],\n \"schedule_expression\" =>\n {\n \"production\" => \"cron(0 4 * * ? *)\",\n \"staging\" => \"cron(0 4 * * ? *)\"\n }\n },\n {\n \"name\" => \"test-scheduled-task\",\n \"command\" => [\n \"rake\",\n \"do:something\"\n ],\n \"schedule_expression\" => {\n \"staging\" => \"cron(0 12 * * ? *)\",\n \"production\" => \"cron(1 2 * * ? *)\"\n }\n }\n ],\n \"workers\" => [\n {\n \"name\" => \"test-worker\",\n \"command\" => [\n \"bundle\",\n \"exec\",\n \"sidekiq\"\n ]\n }\n ]\n }\n )\n )\n )\n end\n\n let(:cluster1_validate_cmd_staging_service) do\n terraform_validate_cmd(\n tfvar_arg_string(\n infrastructure_defaults.merge(\n \"instance_type\" => \"t2.small\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"track_revision\" => \"feature/experiment\",\n \"extra_ecs_clusters\" => [\n {\n \"name\" => \"test\",\n \"subnets_name\" => \"extra_private_subnets\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"instance_type\" => \"t3.small\"\n }\n ],\n \"tinyproxy\" => {\n \"create\" => true\n },\n \"cluster_name\" => \"new-dedicated-cluster-staging\",\n \"account_id\" => \"123456789012\",\n \"infrastructure_name\" => \"new-dedicated-cluster\",\n \"dalmatian_role\" => \"dalmatian-read\",\n \"environment\" => \"staging\",\n \"service\" => {\n \"name\" => \"test-service\",\n \"blue_green\" => {\n \"production\" => {\n \"enabled\" => true,\n \"db_copy\" => {\n \"from_db_host_ps_key\" => \"/test-app/other-test-service/production/DB_HOST\",\n \"from_db_name_ps_key\" => \"/test-app/other-test-service/production/DB_NAME\",\n \"from_db_user_ps_key\" => \"/test-app/other-test-service/production/DB_USER\",\n \"from_db_pass_ps_key\" => \"/test-app/other-test-service/production/DB_PASSWORD\",\n \"blue_green_db_name_ps_key\" => \"/test-app/test-service/production/DB_HOST\",\n \"blue_green_db_user_ps_key\" => \"/test-app/test-service/production/DB_USER\",\n \"blue_green_db_pass_ps_key\" => \"/test-app/test-service/production/DB_PASSWORD\",\n \"sql_backups_s3_bucket\" => \"new-dedicated-cluster-testservice-production-sql-backup\"\n },\n \"db_rewrites\" => [\n {\n \"from\" => \"other-test-service.example.com\",\n \"to\" => \"test-service.example.com\"\n }\n ],\n \"directory_copy\" => [\n {\n \"from\" => \"/mnt/efs/other-test-service-media\",\n \"to\" => \"/mnt/efs/test-service-media\",\n \"chown\" => \"33:33\"\n }\n ],\n \"asset_copy_trigger_ps_key\" => \"/test-app/test-service/production/BLUE_GREEN_ASSET_COPY_TRIGGER\"\n },\n \"staging\" => {\n \"enabled\" => false\n }\n },\n \"launch_on\" => [\"production\", \"staging\"],\n \"launch_on_cluster\" => \"test\",\n \"cluster_min_servers\" => {\n \"production\" => \"2\",\n \"staging\" => \"2\"\n },\n \"parameter_store_path\" => {\n \"production\" => \"\",\n \"staging\" => \"/test-path\"\n },\n \"parameter_store_key\" => {\n \"production\" => \"\",\n \"staging\" => \"arn:aws:kms:eu-west-2:000000000000:key/00000000-0000-0000-0000-000000000000\"\n },\n \"daemon\" => false,\n \"monitoring\" => {\n \"production\" => {\n \"opsgenie_alerts\" => {\n \"enabled\" => true,\n \"cloudfront_5xx\" => {\n \"enabled\" => true,\n \"threshold\" => \"95\",\n \"evaluation_periods\" => \"15\"\n }\n },\n \"ghost_inspector\" => {\n \"enabled\" => true\n }\n },\n \"staging\" => {\n \"opsgenie_alerts\" => {\n \"enabled\" => false,\n \"cloudfront_5xx\" => {\n \"enabled\" => true,\n \"threshold\" => \"95\",\n \"evaluation_periods\" => \"15\"\n }\n },\n \"ghost_inspector\" => {\n \"enabled\" => false\n }\n }\n },\n \"cloudfront\" => {\n \"production\" => {\n \"create\" => true,\n \"managed_cache_policy\" => \"CachingDisabled\",\n \"managed_origin_policy\" => \"AllViewerExceptHostHeader\",\n \"managed_response_headers_policy\" => \"CORS-with-preflight-and-SecurityHeadersPolicy\",\n \"tls_protocol_version\" => \"TLSv1.2_2019\",\n \"origin_keepalive_timeout\" => \"60\",\n \"origin_read_timeout\" => \"60\",\n \"basic_auth\" => false,\n \"basic_auth_users_extra\" => {},\n \"viewer_request_functions\" => [\n {\n \"name\" => \"default\",\n \"true_client_ip_header\" => true,\n \"ip_subnet_allow_list\" => [\n \"0.0.0.0/0\"\n ],\n \"redirects\" => [\n {\n \"from_hostname_pattern\" => \"example-old-domain-name.*\",\n \"from_path_pattern\" => \"/*\",\n \"to_hostname\" => \"example-domain-name.co.uk\",\n \"to_path\" => \"/${path}\"\n }\n ]\n }\n ],\n \"offline_page_http_status\" => {\n \"500\" => \"/error-pages/500.html\",\n \"501\" => \"/error-pages/501.html\",\n \"502\" => \"/error-pages/502.html\",\n \"503\" => \"/error-pages/503.html\",\n \"504\" => \"/error-pages/504.html\"\n },\n \"custom_origins\" => [\n {\n \"origin\" => \"test-media-production.s3.amazonaws.com\",\n \"id\" => \"test-media-production-s3\"\n }\n ],\n \"bypass_protection\" => {\n \"enabled\" => true,\n \"exclude_domains\" => [\n \"example.com\"\n ]\n },\n \"custom_behaviors\" => [\n {\n \"target_origin_id\" => \"test-media-production-s3\",\n \"min_ttl\" => 1200,\n \"default_ttl\" => 3600,\n \"max_ttl\" => 86400,\n \"associate_viewer_request_function\" => \"default\",\n \"managed_cache_policy\" => \"CachingDisabled\",\n \"managed_origin_policy\" => \"AllViewerExceptHostHeader\",\n \"managed_response_headers_policy\" => \"CORS-with-preflight-and-SecurityHeadersPolicy\",\n \"path_pattern\" => \"/media/*\"\n }\n ]\n },\n \"staging\" => {\n \"create\" => true,\n \"managed_cache_policy\" => \"CachingDisabled\",\n \"managed_origin_policy\" => \"AllViewerExceptHostHeader\",\n \"managed_response_headers_policy\" => \"CORS-with-preflight-and-SecurityHeadersPolicy\",\n \"tls_protocol_version\" => \"TLSv1.2_2021\",\n \"origin_keepalive_timeout\" => \"10\",\n \"origin_read_timeout\" => \"40\",\n \"basic_auth\" => true,\n \"basic_auth_users_extra\" => {},\n \"viewer_request_functions\" => [\n {\n \"name\" => \"default\",\n \"true_client_ip_header\" => true,\n \"ip_subnet_allow_list\" => [\n \"0.0.0.0/0\"\n ],\n \"redirects\" => [\n {\n \"from_hostname_pattern\" => \"example-old-domain-name.*\",\n \"from_path_pattern\" => \"/*\",\n \"to_hostname\" => \"example-domain-name.co.uk\",\n \"to_path\" => \"/${path}\"\n }\n ]\n }\n ],\n \"offline_page_http_status\" => {\n \"500\" => \"/error-pages/500.html\",\n \"501\" => \"/error-pages/501.html\",\n \"502\" => \"/error-pages/502.html\",\n \"503\" => \"/error-pages/503.html\",\n \"504\" => \"/error-pages/504.html\"\n },\n \"custom_origins\" => [\n {\n \"origin\" => \"test-media-staging.s3.amazonaws.com\",\n \"id\" => \"test-media-staging-s3\"\n }\n ],\n \"bypass_protection\" => {\n \"enabled\" => false,\n \"exclude_domains\" => []\n },\n \"custom_behaviors\" => [\n {\n \"target_origin_id\" => \"test-media-staging-s3\",\n \"min_ttl\" => 1200,\n \"default_ttl\" => 3600,\n \"max_ttl\" => 86400,\n \"associate_viewer_request_function\" => \"default\",\n \"managed_cache_policy\" => \"\",\n \"managed_origin_policy\" => \"\",\n \"managed_response_headers_policy\" => \"\",\n \"path_pattern\" => \"/media/*\"\n }\n ]\n }\n },\n \"s3_policy\" => {\n \"production\" => {},\n \"staging\" => {\n \"rw\" => [\n \"test\"\n ]\n }\n },\n \"shared_loadbalancer_name\" => \"test-lb-1\",\n \"lb_ip_whitelist\" => [\n {\n \"name\" => \"public\",\n \"cidr\" => \"0.0.0.0/0\"\n }\n ],\n \"lb_idle_timeout\" => \"60\",\n \"global_accelerator\" => {\n \"production\" => true,\n \"staging\" => false\n },\n \"health_check_path\" => \"/check\",\n \"health_check_grace_period\" => \"0\",\n \"deregistration_delay\" => \"60\",\n \"serve_from_subdirectory\" => \"/test-subdir\",\n \"domain_names\" => {\n \"production\" => [],\n \"staging\" => [\n \"example-domain-name.co.uk\"\n ]\n },\n \"proxy_configuration\" => {\n \"production\" => {},\n \"staging\" => {\n \"https_proxy\" => \"dalmatian_tinyproxy\",\n \"http_proxy\" => \"http://my.test-proxy.com:8888\",\n \"no_proxy\" => [\n \"*.example.com\",\n \"93.184.216.34/32\"\n ]\n }\n },\n \"home_directory\" => \"/home/user\",\n \"lb_ssl_certificate\" => {\n \"production\" => \"\",\n \"staging\" => \"arn:aws:acm:lb-region-0:000000000000:certificate/00000000-0000-0000-0000-000000000000\"\n },\n \"lb_ssl_policy\" => {\n \"production\" => \"ELBSecurityPolicy-TLS-1-2-2017-01\",\n \"staging\" => \"ELBSecurityPolicy-TLS-1-2-2017-01\"\n },\n \"cloudfront_ssl_certificate\" => {\n \"production\" => \"\",\n \"staging\" => \"arn:aws:acm:us-east-1:000000000000:certificate/00000000-0000-0000-0000-000000000000\"\n },\n \"image_source\" => \"build_from_github_repo\",\n \"image_location\" => \"git@github.com:dxw/dalmatian-test-app\",\n \"track_revision\" => {\n \"production\" => \"\",\n \"staging\" => \"\"\n },\n \"custom_codestar_connection_arn\" => \"arn:aws:codestar-connections:eu-west-2:000000000000:connection/00000000-0000-0000-0000-000000000000\",\n \"codepipeline_use_github_v1\" => false,\n \"codepipeline_codebuild_run_in_vpc\" => false,\n \"codepipeline_codebuild_use_service_env\" => false,\n \"buildspec\" => \"buildspec.yml\",\n \"container_port\" => \"3100\",\n \"container_command\" => [\n \"/docker-entrypoint.sh\",\n \"rails\",\n \"server\"\n ],\n \"container_volumes\" => [\n {\n \"name\" => \"test-volume\",\n \"host_path\" => \"/mnt/test\",\n \"container_path\" => \"/test\"\n }\n ],\n \"container_extra_hosts\" => [\n {\n \"hostname\" => \"example.com\",\n \"ipAddress\" => \"127.0.0.1\"\n }\n ],\n \"container_count\" => \"2\",\n \"enable_max_one_container_per_instance\" => true,\n \"scheduled_tasks\" => [\n {\n \"name\" => \"old-scheduled-task\",\n \"command\" => [\n \"rake\",\n \"do:cron\"\n ],\n \"schedule_expression\" =>\n {\n \"production\" => \"cron(0 4 * * ? *)\",\n \"staging\" => \"cron(0 4 * * ? *)\"\n }\n },\n {\n \"name\" => \"test-scheduled-task\",\n \"command\" => [\n \"rake\",\n \"do:something\"\n ],\n \"schedule_expression\" => {\n \"staging\" => \"cron(0 12 * * ? *)\",\n \"production\" => \"cron(1 2 * * ? *)\"\n }\n }\n ],\n \"workers\" => [\n {\n \"name\" => \"test-worker\",\n \"command\" => [\n \"bundle\",\n \"exec\",\n \"sidekiq\"\n ]\n }\n ]\n }\n )\n )\n )\n end\n\n let(:cluster1_validate_cmd_production_shared_loadbalancer) do\n terraform_validate_cmd(\n tfvar_arg_string(\n infrastructure_defaults.merge(\n \"instance_type\" => \"t2.medium\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"account_id\" => \"123456789012\",\n \"infrastructure_name\" => \"new-dedicated-cluster\",\n \"dalmatian_role\" => \"dalmatian-read\",\n \"environment\" => \"production\",\n \"shared_loadbalancer\" => {\n \"name\" => \"test-lb-1\",\n \"in_use_by\" => [\n \"test-service\"\n ],\n \"clusters_in_use\" => {\n \"production\" => [\n \"test\"\n ],\n \"staging\" => [\n \"test\"\n ]\n },\n \"subnets_name\" => \"\",\n \"domain_names\" => {\n \"test-service\" => {\n \"production\" => [],\n \"staging\" => [\n \"example-domain-name.co.uk\"\n ]\n }\n },\n \"internal\" => false,\n \"ip_whitelist\" => [\n {\n \"name\" => \"public\",\n \"cidr\" => \"0.0.0.0/0\"\n }\n ],\n \"idle_timeout\" => \"60\",\n \"global_accelerator\" => {\n \"production\" => true,\n \"staging\" => false\n },\n \"ssl_policy\" => \"ELBSecurityPolicy-TLS-1-2-2017-01\"\n }\n )\n )\n )\n end\n\n let(:cluster1_validate_cmd_staging_shared_loadbalancer) do\n terraform_validate_cmd(\n tfvar_arg_string(\n infrastructure_defaults.merge(\n \"instance_type\" => \"t2.small\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"track_revision\" => \"feature/experiment\",\n \"extra_ecs_clusters\" => [\n {\n \"name\" => \"test\",\n \"subnets_name\" => \"extra_private_subnets\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"instance_type\" => \"t3.small\"\n }\n ],\n \"tinyproxy\" => {\n \"create\" => true\n },\n \"account_id\" => \"123456789012\",\n \"infrastructure_name\" => \"new-dedicated-cluster\",\n \"dalmatian_role\" => \"dalmatian-read\",\n \"environment\" => \"staging\",\n \"shared_loadbalancer\" => {\n \"name\" => \"test-lb-1\",\n \"in_use_by\" => [\n \"test-service\"\n ],\n \"clusters_in_use\" => {\n \"production\" => [\n \"test\"\n ],\n \"staging\" => [\n \"test\"\n ]\n },\n \"subnets_name\" => \"\",\n \"domain_names\" => {\n \"test-service\" => {\n \"production\" => [],\n \"staging\" => [\n \"example-domain-name.co.uk\"\n ]\n }\n },\n \"internal\" => false,\n \"ip_whitelist\" => [\n {\n \"name\" => \"public\",\n \"cidr\" => \"0.0.0.0/0\"\n }\n ],\n \"idle_timeout\" => \"60\",\n \"global_accelerator\" => {\n \"production\" => true,\n \"staging\" => false\n },\n \"ssl_policy\" => \"ELBSecurityPolicy-TLS-1-2-2017-01\"\n }\n )\n )\n )\n end\n\n let(:cluster1_plan_cmd_hz) do\n terraform_plan_cmd(\n tfvar_arg_string(\n \"account_id\" => \"123456789012\",\n \"cluster_id\" => \"new-dedicated-cluster\",\n \"dalmatian_role\" => \"dalmatian-read\",\n \"hosted_zone\" => {\n \"domain\" => \"example-domain-name.com\",\n \"ns_records\" => [\n {\n \"name\" => \"delegated\",\n \"value\" => [\n \"ns1.aws.com\"\n ]\n }\n ],\n \"a_records\" => [\n {\n \"name\" => \"some-service\",\n \"value\" => [\n \"1.2.3.4\"\n ]\n },\n {\n \"name\" => \"mail\",\n \"value\" => [\n \"5.6.7.8\"\n ]\n }\n ],\n \"alias_records\" => [\n {\n \"name\" => \"example-domain-name.com\",\n \"value\" => \"cf-distribution.aws.net\"\n },\n {\n \"name\" => \"www\",\n \"value\" => \"cf-distribution.aws.net\"\n }\n ],\n \"cname_records\" => [\n {\n \"name\" => \"alb\",\n \"value\" => [\n \"aws-alb.aws.net\"\n ]\n }\n ],\n \"mx_records\" => [\n {\n \"name\" => \"mail\",\n \"value\" => [\n \"0 mail.example-domain-name.com\"\n ]\n }\n ],\n \"txt_records\" => [\n {\n \"name\" => \"mail\",\n \"value\" => [\n \"v=spf1 a ip4:9.10.11.0/24 mx ~all\"\n ]\n }\n ],\n \"srv_records\" => [\n {\n \"name\" => \"@\",\n \"value\" => [\n \"_imaps._tcp.gmail.com. 86400 IN SRV 5 0 993 imap.gmail.com\"\n ]\n }\n ]\n }\n )\n )\n end\n\n let(:cluster1_plan_cmd_s3) do\n terraform_plan_cmd(\n tfvar_arg_string(\n \"account_id\" => \"123456789012\",\n \"cluster_id\" => \"new-dedicated-cluster\",\n \"dalmatian_role\" => \"dalmatian-read\",\n \"s3\" => {\n \"name\" => \"test\",\n \"enable_s3_versioning\" => true,\n \"encrypted\" => true,\n \"acl\" => \"private\",\n \"policy\" => {\n \"staging\" => {\n \"rw\" => {\n \"services\" => [\n \"test-service\"\n ]\n }\n }\n },\n \"service_cloudfront_read_access\" => [\n \"test-service-staging\"\n ],\n \"cloudfront\" => {\n \"create\" => true,\n \"domain_names\" => [\n \"example.com\",\n \"example2.com\"\n ],\n \"certificate\" => \"arn:aws:acm:lb-region-0:000000000000:certificate/00000000-0000-0000-0000-000000000000\"\n }\n }\n )\n )\n end\n\n let(:cluster1_plan_cmd_vpn_cg) do\n terraform_plan_cmd(\n tfvar_arg_string(\n \"account_id\" => \"123456789012\",\n \"cluster_id\" => \"new-dedicated-cluster\",\n \"dalmatian_role\" => \"dalmatian-read\",\n \"vpn_customer_gateway\" => {\n \"name\" => \"test-vpn\",\n \"bgp_asn\" => 65000,\n \"ip_address\" => \"1.2.3.4\"\n }\n )\n )\n end\n\n let(:cluster1_plan_cmd_production) do\n terraform_plan_cmd(\n tfvar_arg_string(\n infrastructure_defaults.merge(\n \"instance_type\" => \"t2.medium\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"environment\" => \"production\",\n \"cluster_name\" => \"new-dedicated-cluster-production\",\n \"account_id\" => \"123456789012\",\n \"infrastructure_name\" => \"new-dedicated-cluster\",\n \"dalmatian_role\" => \"dalmatian-read\"\n )\n )\n )\n end\n\n let(:cluster1_plan_cmd_staging) do\n terraform_plan_cmd(\n tfvar_arg_string(\n infrastructure_defaults.merge(\n \"instance_type\" => \"t2.small\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"track_revision\" => \"feature/experiment\",\n \"extra_ecs_clusters\" => [\n {\n \"name\" => \"test\",\n \"subnets_name\" => \"extra_private_subnets\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"instance_type\" => \"t3.small\"\n }\n ],\n \"tinyproxy\" => {\n \"create\" => true\n },\n \"environment\" => \"staging\",\n \"cluster_name\" => \"new-dedicated-cluster-staging\",\n \"account_id\" => \"123456789012\",\n \"infrastructure_name\" => \"new-dedicated-cluster\",\n \"dalmatian_role\" => \"dalmatian-read\"\n )\n )\n )\n end\n\n let(:cluster1_plan_cmd_production_waf) do\n terraform_plan_cmd(\n tfvar_arg_string(\n infrastructure_defaults.merge(\n \"instance_type\" => \"t2.medium\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"environment\" => \"production\",\n \"account_id\" => \"123456789012\",\n \"infrastructure_name\" => \"new-dedicated-cluster\",\n \"dalmatian_role\" => \"dalmatian-read\",\n \"waf\" => {\n \"name\" => \"test-1\",\n \"action\" => \"count\",\n \"ip_deny_list\" => [],\n \"aws_managed_rules\" => [\n {\n \"name\" => \"AWSManagedRulesSQLiRuleSet\",\n \"excluded_path_patterns\" => [\n \"/wp-admin/async-upload.php\"\n ]\n },\n {\n \"name\" => \"AWSManagedRulesCommonRuleSet\",\n \"exclude_rules\" => [\n \"SizeRestrictions_BODY\"\n ]\n }\n ],\n \"associations\" => {\n shared_loadbalancers: [\n \"test-lb-1\"\n ],\n service_cloudfront: [\n \"test-service\"\n ]\n }\n }\n )\n )\n )\n end\n\n let(:cluster1_plan_cmd_production_rds) do\n terraform_plan_cmd(\n tfvar_arg_string(\n infrastructure_defaults.merge(\n \"instance_type\" => \"t2.medium\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"environment\" => \"production\",\n \"account_id\" => \"123456789012\",\n \"infrastructure_name\" => \"new-dedicated-cluster\",\n \"dalmatian_role\" => \"dalmatian-read\",\n \"rds\" => {\n \"identifier\" => \"testservice\",\n \"in_use_by\" => [\n \"test-service\"\n ],\n \"clusters_in_use\" => {\n \"production\" => [\n \"test\"\n ],\n \"staging\" => [\n \"test\"\n ]\n },\n \"instance_class\" => {\n \"production\" => \"db.t2.small\",\n \"staging\" => \"db.t2.micro\"\n },\n \"engine\" => \"postgres\",\n \"engine_version\" => \"11.4\",\n \"allocated_storage\" => 20,\n \"storage_encrypted\" => true,\n \"storage_type\" => \"gp3\",\n \"db_name\" => \"testapp\",\n \"port\" => 5432,\n \"maintenance_window\" => \"mon:19:00-mon:19:30\",\n \"backup_window\" => \"09:00-10:00\",\n \"backup_retention_period\" => 31,\n \"force_ssl\" => true,\n \"parameter_store_path_db_url_name\" => \"DATABASE_URL\",\n \"sql_backup_scheduled_task_environment_variables\" => [\n {\n \"name\" => \"foo\",\n \"value\" => \"bar\"\n }\n ],\n \"check_sql_backup_scheduled_task_environment_variables\" => [\n {\n \"name\" => \"foo\",\n \"value\" => \"bar\"\n }\n ],\n \"sync_sql_backup_to_azure\" => false,\n \"replication_bucket_destination_arn\" => \"\",\n \"replication_kms_key_id\" => \"\",\n \"codebuild_access\" => [\n \"service-name\"\n ]\n }\n )\n )\n )\n end\n\n let(:cluster1_plan_cmd_staging_waf) do\n terraform_plan_cmd(\n tfvar_arg_string(\n infrastructure_defaults.merge(\n \"instance_type\" => \"t2.small\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"track_revision\" => \"feature/experiment\",\n \"extra_ecs_clusters\" => [\n {\n \"name\" => \"test\",\n \"subnets_name\" => \"extra_private_subnets\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"instance_type\" => \"t3.small\"\n }\n ],\n \"tinyproxy\" => {\n \"create\" => true\n },\n \"environment\" => \"staging\",\n \"account_id\" => \"123456789012\",\n \"infrastructure_name\" => \"new-dedicated-cluster\",\n \"dalmatian_role\" => \"dalmatian-read\",\n \"waf\" => {\n \"name\" => \"test-1\",\n \"action\" => \"count\",\n \"ip_deny_list\" => [],\n \"aws_managed_rules\" => [\n {\n \"name\" => \"AWSManagedRulesSQLiRuleSet\",\n \"excluded_path_patterns\" => [\n \"/wp-admin/async-upload.php\"\n ]\n },\n {\n \"name\" => \"AWSManagedRulesCommonRuleSet\",\n \"exclude_rules\" => [\n \"SizeRestrictions_BODY\"\n ]\n }\n ],\n \"associations\" => {\n shared_loadbalancers: [\n \"test-lb-1\"\n ],\n service_cloudfront: [\n \"test-service\"\n ]\n }\n }\n )\n )\n )\n end\n\n let(:cluster1_plan_cmd_staging_rds) do\n terraform_plan_cmd(\n tfvar_arg_string(\n infrastructure_defaults.merge(\n \"instance_type\" => \"t2.small\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"track_revision\" => \"feature/experiment\",\n \"extra_ecs_clusters\" => [\n {\n \"name\" => \"test\",\n \"subnets_name\" => \"extra_private_subnets\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"instance_type\" => \"t3.small\"\n }\n ],\n \"tinyproxy\" => {\n \"create\" => true\n },\n \"environment\" => \"staging\",\n \"account_id\" => \"123456789012\",\n \"infrastructure_name\" => \"new-dedicated-cluster\",\n \"dalmatian_role\" => \"dalmatian-read\",\n \"rds\" => {\n \"identifier\" => \"testservice\",\n \"in_use_by\" => [\n \"test-service\"\n ],\n \"clusters_in_use\" => {\n \"production\" => [\n \"test\"\n ],\n \"staging\" => [\n \"test\"\n ]\n },\n \"instance_class\" => {\n \"production\" => \"db.t2.small\",\n \"staging\" => \"db.t2.micro\"\n },\n \"engine\" => \"postgres\",\n \"engine_version\" => \"11.4\",\n \"allocated_storage\" => 20,\n \"storage_encrypted\" => true,\n \"storage_type\" => \"gp3\",\n \"db_name\" => \"testapp\",\n \"port\" => 5432,\n \"maintenance_window\" => \"mon:19:00-mon:19:30\",\n \"backup_window\" => \"09:00-10:00\",\n \"backup_retention_period\" => 31,\n \"force_ssl\" => true,\n \"parameter_store_path_db_url_name\" => \"DATABASE_URL\",\n \"sql_backup_scheduled_task_environment_variables\" => [\n {\n \"name\" => \"foo\",\n \"value\" => \"bar\"\n }\n ],\n \"check_sql_backup_scheduled_task_environment_variables\" => [\n {\n \"name\" => \"foo\",\n \"value\" => \"bar\"\n }\n ],\n \"sync_sql_backup_to_azure\" => false,\n \"replication_bucket_destination_arn\" => \"\",\n \"replication_kms_key_id\" => \"\",\n \"codebuild_access\" => [\n \"service-name\"\n ]\n }\n )\n )\n )\n end\n\n let(:cluster1_plan_cmd_production_elasticache_cluster) do\n terraform_plan_cmd(\n tfvar_arg_string(\n infrastructure_defaults.merge(\n \"instance_type\" => \"t2.medium\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"environment\" => \"production\",\n \"account_id\" => \"123456789012\",\n \"infrastructure_name\" => \"new-dedicated-cluster\",\n \"dalmatian_role\" => \"dalmatian-read\",\n \"elasticache_cluster\" => {\n \"identifier\" => \"testredis\",\n \"in_use_by\" => [\n \"test-service\"\n ],\n \"node_type\" => \"cache.t2.micro\",\n \"node_count\" => 1,\n \"engine\" => \"redis\",\n \"engine_version\" => \"5.0.6\",\n \"parameters\" => [],\n \"port\" => 6379,\n \"maintenance_window\" => \"mon:19:00-mon:22:00\",\n \"snapshot_window\" => \"09:00-10:00\",\n \"parameter_store_path_elasticache_cluster_url_name\" => \"REDIS_URL\"\n }\n )\n )\n )\n end\n\n let(:cluster1_plan_cmd_staging_elasticache_cluster) do\n terraform_plan_cmd(\n tfvar_arg_string(\n infrastructure_defaults.merge(\n \"instance_type\" => \"t2.small\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"track_revision\" => \"feature/experiment\",\n \"extra_ecs_clusters\" => [\n {\n \"name\" => \"test\",\n \"subnets_name\" => \"extra_private_subnets\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"instance_type\" => \"t3.small\"\n }\n ],\n \"tinyproxy\" => {\n \"create\" => true\n },\n \"environment\" => \"staging\",\n \"account_id\" => \"123456789012\",\n \"infrastructure_name\" => \"new-dedicated-cluster\",\n \"dalmatian_role\" => \"dalmatian-read\",\n \"elasticache_cluster\" => {\n \"identifier\" => \"testredis\",\n \"in_use_by\" => [\n \"test-service\"\n ],\n \"node_type\" => \"cache.t2.micro\",\n \"node_count\" => 1,\n \"engine\" => \"redis\",\n \"engine_version\" => \"5.0.6\",\n \"parameters\" => [],\n \"port\" => 6379,\n \"maintenance_window\" => \"mon:19:00-mon:22:00\",\n \"snapshot_window\" => \"09:00-10:00\",\n \"parameter_store_path_elasticache_cluster_url_name\" => \"REDIS_URL\"\n }\n )\n )\n )\n end\n\n let(:cluster1_plan_cmd_production_opensearch_cluster) do\n terraform_plan_cmd(\n tfvar_arg_string(\n infrastructure_defaults.merge(\n \"instance_type\" => \"t2.medium\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"environment\" => \"production\",\n \"account_id\" => \"123456789012\",\n \"infrastructure_name\" => \"new-dedicated-cluster\",\n \"dalmatian_role\" => \"dalmatian-read\",\n \"opensearch_cluster\" => {\n \"identifier\" => \"testos\",\n \"in_use_by\" => [\n \"test-service\"\n ],\n \"version\" => \"1.2\",\n \"master_enabled\" => true,\n \"master_count\" => \"1\",\n \"master_type\" => \"c6g.large.search\",\n \"instance_count\" => \"3\",\n \"instance_type\" => \"t3.small.search\",\n \"warm_enabled\" => true,\n \"warm_count\" => \"2\",\n \"warm_type\" => \"ultrawarm1.medium.search\",\n \"parameter_store_path_opensearch_cluster_url_name\" => \"ELASTICSEARCH_URL\",\n \"volume_size\" => \"20\"\n }\n )\n )\n )\n end\n\n let(:cluster1_plan_cmd_staging_opensearch_cluster) do\n terraform_plan_cmd(\n tfvar_arg_string(\n infrastructure_defaults.merge(\n \"instance_type\" => \"t2.small\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"track_revision\" => \"feature/experiment\",\n \"extra_ecs_clusters\" => [\n {\n \"name\" => \"test\",\n \"subnets_name\" => \"extra_private_subnets\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"instance_type\" => \"t3.small\"\n }\n ],\n \"tinyproxy\" => {\n \"create\" => true\n },\n \"environment\" => \"staging\",\n \"account_id\" => \"123456789012\",\n \"infrastructure_name\" => \"new-dedicated-cluster\",\n \"dalmatian_role\" => \"dalmatian-read\",\n \"opensearch_cluster\" => {\n \"identifier\" => \"testos\",\n \"in_use_by\" => [\n \"test-service\"\n ],\n \"version\" => \"1.2\",\n \"master_enabled\" => true,\n \"master_count\" => \"1\",\n \"master_type\" => \"c6g.large.search\",\n \"instance_count\" => \"3\",\n \"instance_type\" => \"t3.small.search\",\n \"warm_enabled\" => true,\n \"warm_count\" => \"2\",\n \"warm_type\" => \"ultrawarm1.medium.search\",\n \"parameter_store_path_opensearch_cluster_url_name\" => \"ELASTICSEARCH_URL\",\n \"volume_size\" => \"20\"\n }\n )\n )\n )\n end\n\n let(:cluster1_plan_cmd_production_service) do\n terraform_plan_cmd(\n tfvar_arg_string(\n infrastructure_defaults.merge(\n \"instance_type\" => \"t2.medium\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"environment\" => \"production\",\n \"cluster_name\" => \"new-dedicated-cluster-production\",\n \"account_id\" => \"123456789012\",\n \"infrastructure_name\" => \"new-dedicated-cluster\",\n \"dalmatian_role\" => \"dalmatian-read\",\n \"service\" => {\n \"name\" => \"test-service\",\n \"blue_green\" => {\n \"production\" => {\n \"enabled\" => true,\n \"db_copy\" => {\n \"from_db_host_ps_key\" => \"/test-app/other-test-service/production/DB_HOST\",\n \"from_db_name_ps_key\" => \"/test-app/other-test-service/production/DB_NAME\",\n \"from_db_user_ps_key\" => \"/test-app/other-test-service/production/DB_USER\",\n \"from_db_pass_ps_key\" => \"/test-app/other-test-service/production/DB_PASSWORD\",\n \"blue_green_db_name_ps_key\" => \"/test-app/test-service/production/DB_HOST\",\n \"blue_green_db_user_ps_key\" => \"/test-app/test-service/production/DB_USER\",\n \"blue_green_db_pass_ps_key\" => \"/test-app/test-service/production/DB_PASSWORD\",\n \"sql_backups_s3_bucket\" => \"new-dedicated-cluster-testservice-production-sql-backup\"\n },\n \"db_rewrites\" => [\n {\n \"from\" => \"other-test-service.example.com\",\n \"to\" => \"test-service.example.com\"\n }\n ],\n \"directory_copy\" => [\n {\n \"from\" => \"/mnt/efs/other-test-service-media\",\n \"to\" => \"/mnt/efs/test-service-media\",\n \"chown\" => \"33:33\"\n }\n ],\n \"asset_copy_trigger_ps_key\" => \"/test-app/test-service/production/BLUE_GREEN_ASSET_COPY_TRIGGER\"\n },\n \"staging\" => {\n \"enabled\" => false\n }\n },\n \"launch_on\" => [\"production\", \"staging\"],\n \"launch_on_cluster\" => \"test\",\n \"cluster_min_servers\" => {\n \"production\" => \"2\",\n \"staging\" => \"2\"\n },\n \"parameter_store_path\" => {\n \"production\" => \"\",\n \"staging\" => \"/test-path\"\n },\n \"parameter_store_key\" => {\n \"production\" => \"\",\n \"staging\" => \"arn:aws:kms:eu-west-2:000000000000:key/00000000-0000-0000-0000-000000000000\"\n },\n \"daemon\" => false,\n \"monitoring\" => {\n \"production\" => {\n \"opsgenie_alerts\" => {\n \"enabled\" => true,\n \"cloudfront_5xx\" => {\n \"enabled\" => true,\n \"threshold\" => \"95\",\n \"evaluation_periods\" => \"15\"\n }\n },\n \"ghost_inspector\" => {\n \"enabled\" => true\n }\n },\n \"staging\" => {\n \"opsgenie_alerts\" => {\n \"enabled\" => false,\n \"cloudfront_5xx\" => {\n \"enabled\" => true,\n \"threshold\" => \"95\",\n \"evaluation_periods\" => \"15\"\n }\n },\n \"ghost_inspector\" => {\n \"enabled\" => false\n }\n }\n },\n \"cloudfront\" => {\n \"production\" => {\n \"create\" => true,\n \"managed_cache_policy\" => \"CachingDisabled\",\n \"managed_origin_policy\" => \"AllViewerExceptHostHeader\",\n \"managed_response_headers_policy\" => \"CORS-with-preflight-and-SecurityHeadersPolicy\",\n \"tls_protocol_version\" => \"TLSv1.2_2019\",\n \"origin_keepalive_timeout\" => \"60\",\n \"origin_read_timeout\" => \"60\",\n \"basic_auth\" => false,\n \"basic_auth_users_extra\" => {},\n \"viewer_request_functions\" => [\n {\n \"name\" => \"default\",\n \"true_client_ip_header\" => true,\n \"ip_subnet_allow_list\" => [\n \"0.0.0.0/0\"\n ],\n \"redirects\" => [\n {\n \"from_hostname_pattern\" => \"example-old-domain-name.*\",\n \"from_path_pattern\" => \"/*\",\n \"to_hostname\" => \"example-domain-name.co.uk\",\n \"to_path\" => \"/${path}\"\n }\n ]\n }\n ],\n \"offline_page_http_status\" => {\n \"500\" => \"/error-pages/500.html\",\n \"501\" => \"/error-pages/501.html\",\n \"502\" => \"/error-pages/502.html\",\n \"503\" => \"/error-pages/503.html\",\n \"504\" => \"/error-pages/504.html\"\n },\n \"custom_origins\" => [\n {\n \"origin\" => \"test-media-production.s3.amazonaws.com\",\n \"id\" => \"test-media-production-s3\"\n }\n ],\n \"bypass_protection\" => {\n \"enabled\" => true,\n \"exclude_domains\" => [\n \"example.com\"\n ]\n },\n \"custom_behaviors\" => [\n {\n \"target_origin_id\" => \"test-media-production-s3\",\n \"min_ttl\" => 1200,\n \"default_ttl\" => 3600,\n \"max_ttl\" => 86400,\n \"associate_viewer_request_function\" => \"default\",\n \"managed_cache_policy\" => \"CachingDisabled\",\n \"managed_origin_policy\" => \"AllViewerExceptHostHeader\",\n \"managed_response_headers_policy\" => \"CORS-with-preflight-and-SecurityHeadersPolicy\",\n \"path_pattern\" => \"/media/*\"\n }\n ]\n },\n \"staging\" => {\n \"create\" => true,\n \"managed_cache_policy\" => \"CachingDisabled\",\n \"managed_origin_policy\" => \"AllViewerExceptHostHeader\",\n \"managed_response_headers_policy\" => \"CORS-with-preflight-and-SecurityHeadersPolicy\",\n \"tls_protocol_version\" => \"TLSv1.2_2021\",\n \"origin_keepalive_timeout\" => \"10\",\n \"origin_read_timeout\" => \"40\",\n \"basic_auth\" => true,\n \"basic_auth_users_extra\" => {},\n \"viewer_request_functions\" => [\n {\n \"name\" => \"default\",\n \"true_client_ip_header\" => true,\n \"ip_subnet_allow_list\" => [\n \"0.0.0.0/0\"\n ],\n \"redirects\" => [\n {\n \"from_hostname_pattern\" => \"example-old-domain-name.*\",\n \"from_path_pattern\" => \"/*\",\n \"to_hostname\" => \"example-domain-name.co.uk\",\n \"to_path\" => \"/${path}\"\n }\n ]\n }\n ],\n \"offline_page_http_status\" => {\n \"500\" => \"/error-pages/500.html\",\n \"501\" => \"/error-pages/501.html\",\n \"502\" => \"/error-pages/502.html\",\n \"503\" => \"/error-pages/503.html\",\n \"504\" => \"/error-pages/504.html\"\n },\n \"custom_origins\" => [\n {\n \"origin\" => \"test-media-staging.s3.amazonaws.com\",\n \"id\" => \"test-media-staging-s3\"\n }\n ],\n \"bypass_protection\" => {\n \"enabled\" => false,\n \"exclude_domains\" => []\n },\n \"custom_behaviors\" => [\n {\n \"target_origin_id\" => \"test-media-staging-s3\",\n \"min_ttl\" => 1200,\n \"default_ttl\" => 3600,\n \"max_ttl\" => 86400,\n \"associate_viewer_request_function\" => \"default\",\n \"managed_cache_policy\" => \"\",\n \"managed_origin_policy\" => \"\",\n \"managed_response_headers_policy\" => \"\",\n \"path_pattern\" => \"/media/*\"\n }\n ]\n }\n },\n \"s3_policy\" => {\n \"production\" => {},\n \"staging\" => {\n \"rw\" => [\n \"test\"\n ]\n }\n },\n \"shared_loadbalancer_name\" => \"test-lb-1\",\n \"lb_ip_whitelist\" => [\n \"name\" => \"public\",\n \"cidr\" => \"0.0.0.0/0\"\n ],\n \"lb_idle_timeout\" => \"60\",\n \"global_accelerator\" => {\n \"production\" => true,\n \"staging\" => false\n },\n \"health_check_path\" => \"/check\",\n \"health_check_grace_period\" => \"0\",\n \"deregistration_delay\" => \"60\",\n \"serve_from_subdirectory\" => \"/test-subdir\",\n \"domain_names\" => {\n \"production\" => [],\n \"staging\" => [\n \"example-domain-name.co.uk\"\n ]\n },\n \"proxy_configuration\" => {\n \"production\" => {},\n \"staging\" => {\n \"https_proxy\" => \"dalmatian_tinyproxy\",\n \"http_proxy\" => \"http://my.test-proxy.com:8888\",\n \"no_proxy\" => [\n \"*.example.com\",\n \"93.184.216.34/32\"\n ]\n }\n },\n \"home_directory\" => \"/home/user\",\n \"lb_ssl_certificate\" => {\n \"production\" => \"\",\n \"staging\" => \"arn:aws:acm:lb-region-0:000000000000:certificate/00000000-0000-0000-0000-000000000000\"\n },\n \"lb_ssl_policy\" => {\n \"production\" => \"ELBSecurityPolicy-TLS-1-2-2017-01\",\n \"staging\" => \"ELBSecurityPolicy-TLS-1-2-2017-01\"\n },\n \"cloudfront_ssl_certificate\" => {\n \"production\" => \"\",\n \"staging\" => \"arn:aws:acm:us-east-1:000000000000:certificate/00000000-0000-0000-0000-000000000000\"\n },\n \"image_source\" => \"build_from_github_repo\",\n \"image_location\" => \"git@github.com:dxw/dalmatian-test-app\",\n \"track_revision\" => {\n \"production\" => \"\",\n \"staging\" => \"\"\n },\n \"custom_codestar_connection_arn\" => \"arn:aws:codestar-connections:eu-west-2:000000000000:connection/00000000-0000-0000-0000-000000000000\",\n \"codepipeline_use_github_v1\" => false,\n \"codepipeline_codebuild_run_in_vpc\" => false,\n \"codepipeline_codebuild_use_service_env\" => false,\n \"buildspec\" => \"buildspec.yml\",\n \"container_port\" => \"3100\",\n \"container_command\" => [\n \"/docker-entrypoint.sh\",\n \"rails\",\n \"server\"\n ],\n \"container_volumes\" => [\n {\n \"name\" => \"test-volume\",\n \"host_path\" => \"/mnt/test\",\n \"container_path\" => \"/test\"\n }\n ],\n \"container_extra_hosts\" => [\n {\n \"hostname\" => \"example.com\",\n \"ipAddress\" => \"127.0.0.1\"\n }\n ],\n \"container_count\" => \"2\",\n \"enable_max_one_container_per_instance\" => true,\n \"scheduled_tasks\" => [\n {\n \"name\" => \"old-scheduled-task\",\n \"command\" => [\n \"rake\",\n \"do:cron\"\n ],\n \"schedule_expression\" =>\n {\n \"production\" => \"cron(0 4 * * ? *)\",\n \"staging\" => \"cron(0 4 * * ? *)\"\n }\n },\n {\n \"name\" => \"test-scheduled-task\",\n \"command\" => [\n \"rake\",\n \"do:something\"\n ],\n \"schedule_expression\" => {\n \"staging\" => \"cron(0 12 * * ? *)\",\n \"production\" => \"cron(1 2 * * ? *)\"\n }\n }\n ],\n \"workers\" => [\n {\n \"name\" => \"test-worker\",\n \"command\" => [\n \"bundle\",\n \"exec\",\n \"sidekiq\"\n ]\n }\n ]\n }\n )\n )\n )\n end\n\n let(:cluster1_plan_cmd_staging_service) do\n terraform_plan_cmd(\n tfvar_arg_string(\n infrastructure_defaults.merge(\n \"instance_type\" => \"t2.small\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"track_revision\" => \"feature/experiment\",\n \"extra_ecs_clusters\" => [\n {\n \"name\" => \"test\",\n \"subnets_name\" => \"extra_private_subnets\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"instance_type\" => \"t3.small\"\n }\n ],\n \"tinyproxy\" => {\n \"create\" => true\n },\n \"environment\" => \"staging\",\n \"cluster_name\" => \"new-dedicated-cluster-staging\",\n \"account_id\" => \"123456789012\",\n \"infrastructure_name\" => \"new-dedicated-cluster\",\n \"dalmatian_role\" => \"dalmatian-read\",\n \"service\" => {\n \"name\" => \"test-service\",\n \"blue_green\" => {\n \"production\" => {\n \"enabled\" => true,\n \"db_copy\" => {\n \"from_db_host_ps_key\" => \"/test-app/other-test-service/production/DB_HOST\",\n \"from_db_name_ps_key\" => \"/test-app/other-test-service/production/DB_NAME\",\n \"from_db_user_ps_key\" => \"/test-app/other-test-service/production/DB_USER\",\n \"from_db_pass_ps_key\" => \"/test-app/other-test-service/production/DB_PASSWORD\",\n \"blue_green_db_name_ps_key\" => \"/test-app/test-service/production/DB_HOST\",\n \"blue_green_db_user_ps_key\" => \"/test-app/test-service/production/DB_USER\",\n \"blue_green_db_pass_ps_key\" => \"/test-app/test-service/production/DB_PASSWORD\",\n \"sql_backups_s3_bucket\" => \"new-dedicated-cluster-testservice-production-sql-backup\"\n },\n \"db_rewrites\" => [\n {\n \"from\" => \"other-test-service.example.com\",\n \"to\" => \"test-service.example.com\"\n }\n ],\n \"directory_copy\" => [\n {\n \"from\" => \"/mnt/efs/other-test-service-media\",\n \"to\" => \"/mnt/efs/test-service-media\",\n \"chown\" => \"33:33\"\n }\n ],\n \"asset_copy_trigger_ps_key\" => \"/test-app/test-service/production/BLUE_GREEN_ASSET_COPY_TRIGGER\"\n },\n \"staging\" => {\n \"enabled\" => false\n }\n },\n \"launch_on\" => [\"production\", \"staging\"],\n \"launch_on_cluster\" => \"test\",\n \"cluster_min_servers\" => {\n \"production\" => \"2\",\n \"staging\" => \"2\"\n },\n \"parameter_store_path\" => {\n \"production\" => \"\",\n \"staging\" => \"/test-path\"\n },\n \"parameter_store_key\" => {\n \"production\" => \"\",\n \"staging\" => \"arn:aws:kms:eu-west-2:000000000000:key/00000000-0000-0000-0000-000000000000\"\n },\n \"daemon\" => false,\n \"monitoring\" => {\n \"production\" => {\n \"opsgenie_alerts\" => {\n \"enabled\" => true,\n \"cloudfront_5xx\" => {\n \"enabled\" => true,\n \"threshold\" => \"95\",\n \"evaluation_periods\" => \"15\"\n }\n },\n \"ghost_inspector\" => {\n \"enabled\" => true\n }\n },\n \"staging\" => {\n \"opsgenie_alerts\" => {\n \"enabled\" => false,\n \"cloudfront_5xx\" => {\n \"enabled\" => true,\n \"threshold\" => \"95\",\n \"evaluation_periods\" => \"15\"\n }\n },\n \"ghost_inspector\" => {\n \"enabled\" => false\n }\n }\n },\n \"cloudfront\" => {\n \"production\" => {\n \"create\" => true,\n \"managed_cache_policy\" => \"CachingDisabled\",\n \"managed_origin_policy\" => \"AllViewerExceptHostHeader\",\n \"managed_response_headers_policy\" => \"CORS-with-preflight-and-SecurityHeadersPolicy\",\n \"tls_protocol_version\" => \"TLSv1.2_2019\",\n \"origin_keepalive_timeout\" => \"60\",\n \"origin_read_timeout\" => \"60\",\n \"basic_auth\" => false,\n \"basic_auth_users_extra\" => {},\n \"viewer_request_functions\" => [\n {\n \"name\" => \"default\",\n \"true_client_ip_header\" => true,\n \"ip_subnet_allow_list\" => [\n \"0.0.0.0/0\"\n ],\n \"redirects\" => [\n {\n \"from_hostname_pattern\" => \"example-old-domain-name.*\",\n \"from_path_pattern\" => \"/*\",\n \"to_hostname\" => \"example-domain-name.co.uk\",\n \"to_path\" => \"/${path}\"\n }\n ]\n }\n ],\n \"offline_page_http_status\" => {\n \"500\" => \"/error-pages/500.html\",\n \"501\" => \"/error-pages/501.html\",\n \"502\" => \"/error-pages/502.html\",\n \"503\" => \"/error-pages/503.html\",\n \"504\" => \"/error-pages/504.html\"\n },\n \"custom_origins\" => [\n {\n \"origin\" => \"test-media-production.s3.amazonaws.com\",\n \"id\" => \"test-media-production-s3\"\n }\n ],\n \"bypass_protection\" => {\n \"enabled\" => true,\n \"exclude_domains\" => [\n \"example.com\"\n ]\n },\n \"custom_behaviors\" => [\n {\n \"target_origin_id\" => \"test-media-production-s3\",\n \"min_ttl\" => 1200,\n \"default_ttl\" => 3600,\n \"max_ttl\" => 86400,\n \"associate_viewer_request_function\" => \"default\",\n \"managed_cache_policy\" => \"CachingDisabled\",\n \"managed_origin_policy\" => \"AllViewerExceptHostHeader\",\n \"managed_response_headers_policy\" => \"CORS-with-preflight-and-SecurityHeadersPolicy\",\n \"path_pattern\" => \"/media/*\"\n }\n ]\n },\n \"staging\" => {\n \"create\" => true,\n \"managed_cache_policy\" => \"CachingDisabled\",\n \"managed_origin_policy\" => \"AllViewerExceptHostHeader\",\n \"managed_response_headers_policy\" => \"CORS-with-preflight-and-SecurityHeadersPolicy\",\n \"tls_protocol_version\" => \"TLSv1.2_2021\",\n \"origin_keepalive_timeout\" => \"10\",\n \"origin_read_timeout\" => \"40\",\n \"basic_auth\" => true,\n \"basic_auth_users_extra\" => {},\n \"viewer_request_functions\" => [\n {\n \"name\" => \"default\",\n \"true_client_ip_header\" => true,\n \"ip_subnet_allow_list\" => [\n \"0.0.0.0/0\"\n ],\n \"redirects\" => [\n {\n \"from_hostname_pattern\" => \"example-old-domain-name.*\",\n \"from_path_pattern\" => \"/*\",\n \"to_hostname\" => \"example-domain-name.co.uk\",\n \"to_path\" => \"/${path}\"\n }\n ]\n }\n ],\n \"offline_page_http_status\" => {\n \"500\" => \"/error-pages/500.html\",\n \"501\" => \"/error-pages/501.html\",\n \"502\" => \"/error-pages/502.html\",\n \"503\" => \"/error-pages/503.html\",\n \"504\" => \"/error-pages/504.html\"\n },\n \"custom_origins\" => [\n {\n \"origin\" => \"test-media-staging.s3.amazonaws.com\",\n \"id\" => \"test-media-staging-s3\"\n }\n ],\n \"bypass_protection\" => {\n \"enabled\" => false,\n \"exclude_domains\" => []\n },\n \"custom_behaviors\" => [\n {\n \"target_origin_id\" => \"test-media-staging-s3\",\n \"min_ttl\" => 1200,\n \"default_ttl\" => 3600,\n \"max_ttl\" => 86400,\n \"associate_viewer_request_function\" => \"default\",\n \"managed_cache_policy\" => \"\",\n \"managed_origin_policy\" => \"\",\n \"managed_response_headers_policy\" => \"\",\n \"path_pattern\" => \"/media/*\"\n }\n ]\n }\n },\n \"s3_policy\" => {\n \"production\" => {},\n \"staging\" => {\n \"rw\" => [\n \"test\"\n ]\n }\n },\n \"shared_loadbalancer_name\" => \"test-lb-1\",\n \"lb_ip_whitelist\" => [\n {\n \"name\" => \"public\",\n \"cidr\" => \"0.0.0.0/0\"\n }\n ],\n \"lb_idle_timeout\" => \"60\",\n \"global_accelerator\" => {\n \"production\" => true,\n \"staging\" => false\n },\n \"health_check_path\" => \"/check\",\n \"health_check_grace_period\" => \"0\",\n \"deregistration_delay\" => \"60\",\n \"serve_from_subdirectory\" => \"/test-subdir\",\n \"domain_names\" => {\n \"production\" => [],\n \"staging\" => [\n \"example-domain-name.co.uk\"\n ]\n },\n \"proxy_configuration\" => {\n \"production\" => {},\n \"staging\" => {\n \"https_proxy\" => \"dalmatian_tinyproxy\",\n \"http_proxy\" => \"http://my.test-proxy.com:8888\",\n \"no_proxy\" => [\n \"*.example.com\",\n \"93.184.216.34/32\"\n ]\n }\n },\n \"home_directory\" => \"/home/user\",\n \"lb_ssl_certificate\" => {\n \"production\" => \"\",\n \"staging\" => \"arn:aws:acm:lb-region-0:000000000000:certificate/00000000-0000-0000-0000-000000000000\"\n },\n \"lb_ssl_policy\" => {\n \"production\" => \"ELBSecurityPolicy-TLS-1-2-2017-01\",\n \"staging\" => \"ELBSecurityPolicy-TLS-1-2-2017-01\"\n },\n \"cloudfront_ssl_certificate\" => {\n \"production\" => \"\",\n \"staging\" => \"arn:aws:acm:us-east-1:000000000000:certificate/00000000-0000-0000-0000-000000000000\"\n },\n \"image_source\" => \"build_from_github_repo\",\n \"image_location\" => \"git@github.com:dxw/dalmatian-test-app\",\n \"track_revision\" => {\n \"production\" => \"\",\n \"staging\" => \"\"\n },\n \"custom_codestar_connection_arn\" => \"arn:aws:codestar-connections:eu-west-2:000000000000:connection/00000000-0000-0000-0000-000000000000\",\n \"codepipeline_use_github_v1\" => false,\n \"codepipeline_codebuild_run_in_vpc\" => false,\n \"codepipeline_codebuild_use_service_env\" => false,\n \"buildspec\" => \"buildspec.yml\",\n \"container_port\" => \"3100\",\n \"container_command\" => [\n \"/docker-entrypoint.sh\",\n \"rails\",\n \"server\"\n ],\n \"container_volumes\" => [\n {\n \"name\" => \"test-volume\",\n \"host_path\" => \"/mnt/test\",\n \"container_path\" => \"/test\"\n }\n ],\n \"container_extra_hosts\" => [\n {\n \"hostname\" => \"example.com\",\n \"ipAddress\" => \"127.0.0.1\"\n }\n ],\n \"container_count\" => \"2\",\n \"enable_max_one_container_per_instance\" => true,\n \"scheduled_tasks\" => [\n {\n \"name\" => \"old-scheduled-task\",\n \"command\" => [\n \"rake\",\n \"do:cron\"\n ],\n \"schedule_expression\" =>\n {\n \"production\" => \"cron(0 4 * * ? *)\",\n \"staging\" => \"cron(0 4 * * ? *)\"\n }\n },\n {\n \"name\" => \"test-scheduled-task\",\n \"command\" => [\n \"rake\",\n \"do:something\"\n ],\n \"schedule_expression\" => {\n \"staging\" => \"cron(0 12 * * ? *)\",\n \"production\" => \"cron(1 2 * * ? *)\"\n }\n }\n ],\n \"workers\" => [\n {\n \"name\" => \"test-worker\",\n \"command\" => [\n \"bundle\",\n \"exec\",\n \"sidekiq\"\n ]\n }\n ]\n }\n )\n )\n )\n end\n\n let(:cluster1_plan_cmd_production_shared_loadbalancer) do\n terraform_plan_cmd(\n tfvar_arg_string(\n infrastructure_defaults.merge(\n \"instance_type\" => \"t2.medium\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"environment\" => \"production\",\n \"account_id\" => \"123456789012\",\n \"infrastructure_name\" => \"new-dedicated-cluster\",\n \"dalmatian_role\" => \"dalmatian-read\",\n \"shared_loadbalancer\" => {\n \"name\" => \"test-lb-1\",\n \"in_use_by\" => [\n \"test-service\"\n ],\n \"clusters_in_use\" => {\n \"production\" => [\n \"test\"\n ],\n \"staging\" => [\n \"test\"\n ]\n },\n \"subnets_name\" => \"\",\n \"domain_names\" => {\n \"test-service\" => {\n \"production\" => [],\n \"staging\" => [\n \"example-domain-name.co.uk\"\n ]\n }\n },\n \"internal\" => false,\n \"ip_whitelist\" => [\n {\n \"name\" => \"public\",\n \"cidr\" => \"0.0.0.0/0\"\n }\n ],\n \"idle_timeout\" => \"60\",\n \"global_accelerator\" => {\n \"production\" => true,\n \"staging\" => false\n },\n \"ssl_policy\" => \"ELBSecurityPolicy-TLS-1-2-2017-01\"\n }\n )\n )\n )\n end\n\n let(:cluster1_plan_cmd_staging_shared_loadbalancer) do\n terraform_plan_cmd(\n tfvar_arg_string(\n infrastructure_defaults.merge(\n \"instance_type\" => \"t2.small\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"track_revision\" => \"feature/experiment\",\n \"extra_ecs_clusters\" => [\n {\n \"name\" => \"test\",\n \"subnets_name\" => \"extra_private_subnets\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"instance_type\" => \"t3.small\"\n }\n ],\n \"tinyproxy\" => {\n \"create\" => true\n },\n \"environment\" => \"staging\",\n \"account_id\" => \"123456789012\",\n \"infrastructure_name\" => \"new-dedicated-cluster\",\n \"dalmatian_role\" => \"dalmatian-read\",\n \"shared_loadbalancer\" => {\n \"name\" => \"test-lb-1\",\n \"in_use_by\" => [\n \"test-service\"\n ],\n \"clusters_in_use\" => {\n \"production\" => [\n \"test\"\n ],\n \"staging\" => [\n \"test\"\n ]\n },\n \"subnets_name\" => \"\",\n \"domain_names\" => {\n \"test-service\" => {\n \"production\" => [],\n \"staging\" => [\n \"example-domain-name.co.uk\"\n ]\n }\n },\n \"internal\" => false,\n \"ip_whitelist\" => [\n {\n \"name\" => \"public\",\n \"cidr\" => \"0.0.0.0/0\"\n }\n ],\n \"idle_timeout\" => \"60\",\n \"global_accelerator\" => {\n \"production\" => true,\n \"staging\" => false\n },\n \"ssl_policy\" => \"ELBSecurityPolicy-TLS-1-2-2017-01\"\n }\n )\n )\n )\n end\n\n let(:source1_validate_cmd_production) do\n terraform_validate_cmd(\n tfvar_arg_string(\n infrastructure_defaults.merge(\n \"instance_type\" => \"t2.medium\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"cluster_name\" => \"new-dedicated-cluster-production\",\n \"account_id\" => \"123456789012\",\n \"infrastructure_name\" => \"new-dedicated-cluster\",\n \"dalmatian_role\" => \"dalmatian-read\",\n \"environment\" => \"production\"\n )\n )\n )\n end\n\n let(:source1_validate_cmd_staging) do\n terraform_validate_cmd(\n tfvar_arg_string(\n infrastructure_defaults.merge(\n \"instance_type\" => \"t2.small\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"track_revision\" => \"feature/experiment\",\n \"extra_ecs_clusters\" => [\n {\n \"name\" => \"test\",\n \"subnets_name\" => \"extra_private_subnets\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"instance_type\" => \"t3.small\"\n }\n ],\n \"tinyproxy\" => {\n \"create\" => true\n },\n \"cluster_name\" => \"new-dedicated-cluster-staging\",\n \"account_id\" => \"123456789012\",\n \"infrastructure_name\" => \"new-dedicated-cluster\",\n \"dalmatian_role\" => \"dalmatian-read\",\n \"environment\" => \"staging\"\n )\n )\n )\n end\n\n let(:cluster2_validate_cmd_production) do\n terraform_validate_cmd(\n tfvar_arg_string(\n infrastructure_defaults.merge(\n \"instance_type\" => \"t2.medium\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"10\",\n \"cluster_name\" => \"shared-new-cluster-production\",\n \"account_id\" => \"123456789012\",\n \"infrastructure_name\" => \"shared-new-cluster\",\n \"dalmatian_role\" => \"dalmatian-read\",\n \"environment\" => \"production\"\n )\n )\n )\n end\n\n let(:cluster2_validate_cmd_staging) do\n terraform_validate_cmd(\n tfvar_arg_string(\n infrastructure_defaults.merge(\n \"instance_type\" => \"t2.small\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"10\",\n \"cluster_name\" => \"shared-new-cluster-staging\",\n \"account_id\" => \"123456789012\",\n \"infrastructure_name\" => \"shared-new-cluster\",\n \"dalmatian_role\" => \"dalmatian-read\",\n \"environment\" => \"staging\"\n )\n )\n )\n end\n\n let(:cluster2_plan_cmd_production) do\n terraform_plan_cmd(\n tfvar_arg_string(\n infrastructure_defaults.merge(\n \"instance_type\" => \"t2.medium\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"10\",\n \"environment\" => \"production\",\n \"cluster_name\" => \"shared-new-cluster-production\",\n \"account_id\" => \"123456789012\",\n \"infrastructure_name\" => \"shared-new-cluster\",\n \"dalmatian_role\" => \"dalmatian-read\"\n )\n )\n )\n end\n\n let(:cluster2_plan_cmd_staging) do\n terraform_plan_cmd(\n tfvar_arg_string(\n infrastructure_defaults.merge(\n \"instance_type\" => \"t2.small\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"10\",\n \"environment\" => \"staging\",\n \"cluster_name\" => \"shared-new-cluster-staging\",\n \"account_id\" => \"123456789012\",\n \"infrastructure_name\" => \"shared-new-cluster\",\n \"dalmatian_role\" => \"dalmatian-read\"\n )\n )\n )\n end\n\n let(:cluster3_validate_cmd_staging) do\n terraform_validate_cmd(\n tfvar_arg_string(\n infrastructure_defaults.merge(\n \"example_var\" => \"foo\",\n \"cluster_name\" => \"shared-cluster-staging\",\n \"account_id\" => \"123456789012\",\n \"infrastructure_name\" => \"existing-shared-cluster-staging\",\n \"dalmatian_role\" => \"dalmatian-read\",\n \"environment\" => \"staging\"\n )\n )\n )\n end\n\n let(:cluster3_plan_cmd_staging) do\n terraform_plan_cmd(\n tfvar_arg_string(\n infrastructure_defaults.merge(\n \"example_var\" => \"foo\",\n \"environment\" => \"staging\",\n \"cluster_name\" => \"shared-cluster-staging\",\n \"account_id\" => \"123456789012\",\n \"infrastructure_name\" => \"existing-shared-cluster-staging\",\n \"dalmatian_role\" => \"dalmatian-read\"\n )\n )\n )\n end\n\n let(:cluster4_validate_cmd_production) do\n terraform_validate_cmd(\n tfvar_arg_string(\n infrastructure_defaults.merge(\n \"example_var\" => \"bar\",\n \"cluster_name\" => \"shared-cluster-production\",\n \"account_id\" => \"123456789012\",\n \"infrastructure_name\" => \"existing-shared-cluster-production\",\n \"dalmatian_role\" => \"dalmatian-read\",\n \"environment\" => \"production\"\n )\n )\n )\n end\n\n let(:cluster4_plan_cmd_production) do\n terraform_plan_cmd(\n tfvar_arg_string(\n infrastructure_defaults.merge(\n \"example_var\" => \"bar\",\n \"environment\" => \"production\",\n \"cluster_name\" => \"shared-cluster-production\",\n \"account_id\" => \"123456789012\",\n \"infrastructure_name\" => \"existing-shared-cluster-production\",\n \"dalmatian_role\" => \"dalmatian-read\"\n )\n )\n )\n end\n\n before do\n allow(Logger).to receive(:info)\n stub_git_clone_cmds\n stub_git_checkout\n stub_workspace_creation_cmds\n allow(Helper).to receive(:run!).with(\"rake terrafile\")\n allow(Helper).to receive(:run!).with(\"terraform init -upgrade=true\")\n allow(Helper).to receive(:run!).with(\"terraform fmt -check -diff\")\n\n allow(Helper).to receive(:run!).with(cluster1_validate_cmd_hz)\n allow(Helper).to receive(:run!).with(cluster1_validate_cmd_s3)\n allow(Helper).to receive(:run!).with(cluster1_validate_cmd_vpn_cg)\n\n allow(Helper).to receive(:run!).with(cluster1_plan_cmd_hz)\n allow(Helper).to receive(:run!).with(cluster1_plan_cmd_s3)\n allow(Helper).to receive(:run!).with(cluster1_plan_cmd_vpn_cg)\n\n allow(Helper).to receive(:run!).with(cluster1_validate_cmd_production)\n allow(Helper).to receive(:run!).with(cluster1_validate_cmd_staging)\n allow(Helper).to receive(:run!).with(cluster1_plan_cmd_production)\n allow(Helper).to receive(:run!).with(cluster1_plan_cmd_staging)\n allow(Helper).to receive(:run!).with(source1_validate_cmd_production)\n allow(Helper).to receive(:run!).with(source1_validate_cmd_staging)\n\n allow(Helper).to receive(:run!).with(cluster1_validate_cmd_production_waf)\n allow(Helper).to receive(:run!).with(cluster1_validate_cmd_staging_waf)\n allow(Helper).to receive(:run!).with(cluster1_plan_cmd_production_waf)\n allow(Helper).to receive(:run!).with(cluster1_plan_cmd_staging_waf)\n\n allow(Helper).to receive(:run!).with(cluster1_validate_cmd_production_rds)\n allow(Helper).to receive(:run!).with(cluster1_validate_cmd_staging_rds)\n allow(Helper).to receive(:run!).with(cluster1_plan_cmd_production_rds)\n allow(Helper).to receive(:run!).with(cluster1_plan_cmd_staging_rds)\n\n allow(Helper).to receive(:run!).with(cluster1_validate_cmd_production_elasticache_cluster)\n allow(Helper).to receive(:run!).with(cluster1_validate_cmd_staging_elasticache_cluster)\n allow(Helper).to receive(:run!).with(cluster1_plan_cmd_production_elasticache_cluster)\n allow(Helper).to receive(:run!).with(cluster1_plan_cmd_staging_elasticache_cluster)\n\n allow(Helper).to receive(:run!).with(cluster1_validate_cmd_production_opensearch_cluster)\n allow(Helper).to receive(:run!).with(cluster1_validate_cmd_staging_opensearch_cluster)\n allow(Helper).to receive(:run!).with(cluster1_plan_cmd_production_opensearch_cluster)\n allow(Helper).to receive(:run!).with(cluster1_plan_cmd_staging_opensearch_cluster)\n\n allow(Helper).to receive(:run!).with(cluster1_validate_cmd_production_service)\n allow(Helper).to receive(:run!).with(cluster1_validate_cmd_staging_service)\n allow(Helper).to receive(:run!).with(cluster1_plan_cmd_production_service)\n allow(Helper).to receive(:run!).with(cluster1_plan_cmd_staging_service)\n\n allow(Helper).to receive(:run!).with(cluster1_validate_cmd_production_shared_loadbalancer)\n allow(Helper).to receive(:run!).with(cluster1_validate_cmd_staging_shared_loadbalancer)\n allow(Helper).to receive(:run!).with(cluster1_plan_cmd_production_shared_loadbalancer)\n allow(Helper).to receive(:run!).with(cluster1_plan_cmd_staging_shared_loadbalancer)\n\n allow(Helper).to receive(:run!).with(cluster2_validate_cmd_production)\n allow(Helper).to receive(:run!).with(cluster2_validate_cmd_staging)\n allow(Helper).to receive(:run!).with(cluster2_plan_cmd_production)\n allow(Helper).to receive(:run!).with(cluster2_plan_cmd_staging)\n\n allow(Helper).to receive(:run!).with(cluster3_validate_cmd_staging)\n allow(Helper).to receive(:run!).with(cluster3_plan_cmd_staging)\n\n allow(Helper).to receive(:run!).with(cluster4_validate_cmd_production)\n allow(Helper).to receive(:run!).with(cluster4_plan_cmd_production)\n\n Infrastructure.new(\n ConfigurationReader.new(path: \"./dalmatian.yml.example\", parameter_store: fake_parameter_store).infrastructures\n ).test\n end\n\n it 'invokes \"terraform validate\" with the expected cluster options' do\n expect(Helper).to have_received(:run!).with(cluster1_validate_cmd_hz)\n\n expect(Helper).to have_received(:run!).with(cluster1_validate_cmd_s3)\n\n expect(Helper).to have_received(:run!).with(cluster1_validate_cmd_vpn_cg)\n\n expect(Helper).to have_received(:run!).with(cluster1_validate_cmd_production).twice\n expect(Helper).to have_received(:run!).with(cluster1_validate_cmd_staging).twice\n\n expect(Helper).to have_received(:run!).with(cluster1_validate_cmd_production_waf)\n expect(Helper).to have_received(:run!).with(cluster1_validate_cmd_staging_waf)\n\n expect(Helper).to have_received(:run!).with(cluster1_validate_cmd_production_rds)\n expect(Helper).to have_received(:run!).with(cluster1_validate_cmd_staging_rds)\n\n expect(Helper).to have_received(:run!).with(cluster1_validate_cmd_production_elasticache_cluster)\n expect(Helper).to have_received(:run!).with(cluster1_validate_cmd_staging_elasticache_cluster)\n\n expect(Helper).to have_received(:run!).with(cluster1_validate_cmd_production_opensearch_cluster)\n expect(Helper).to have_received(:run!).with(cluster1_validate_cmd_staging_opensearch_cluster)\n\n expect(Helper).to have_received(:run!).with(cluster1_validate_cmd_production_service)\n expect(Helper).to have_received(:run!).with(cluster1_validate_cmd_staging_service)\n\n expect(Helper).to have_received(:run!).with(cluster1_validate_cmd_production_shared_loadbalancer)\n expect(Helper).to have_received(:run!).with(cluster1_validate_cmd_staging_shared_loadbalancer)\n\n expect(Helper).to have_received(:run!).with(cluster2_validate_cmd_production)\n expect(Helper).to have_received(:run!).with(cluster2_validate_cmd_staging)\n\n expect(Helper).to have_received(:run!).with(cluster3_validate_cmd_staging)\n\n expect(Helper).to have_received(:run!).with(cluster4_validate_cmd_production)\n end\n\n it 'invokes \"terraform validate\" with the expected source options' do\n expect(Helper).to have_received(:run!).with(source1_validate_cmd_production).twice\n expect(Helper).to have_received(:run!).with(source1_validate_cmd_staging).twice\n end\n\n describe 'use of \"terraform plan\"' do\n it 'passes the hosted zone config to \"terraform plan\"' do\n aggregate_failures do\n expect(Helper).to have_received(:run!).with(cluster1_plan_cmd_hz)\n end\n end\n\n it 'passes the s3 config to \"terraform plan\"' do\n aggregate_failures do\n expect(Helper).to have_received(:run!).with(cluster1_plan_cmd_s3)\n end\n end\n\n it 'passes the vpn customer gateway config to \"terraform plan\"' do\n aggregate_failures do\n expect(Helper).to have_received(:run!).with(cluster1_plan_cmd_vpn_cg)\n end\n end\n\n it 'passes the base config to \"terraform plan\"' do\n aggregate_failures do\n expect(Helper).to have_received(:run!).with(cluster1_plan_cmd_production).twice\n expect(Helper).to have_received(:run!).with(cluster1_plan_cmd_staging).twice\n end\n end\n\n it 'passes the waf config to \"terraform plan\"' do\n aggregate_failures do\n expect(Helper).to have_received(:run!).with(cluster1_plan_cmd_production_waf)\n expect(Helper).to have_received(:run!).with(cluster1_plan_cmd_staging_waf)\n end\n end\n\n it 'passes the rds config to \"terraform plan\"' do\n aggregate_failures do\n expect(Helper).to have_received(:run!).with(cluster1_plan_cmd_production_rds)\n expect(Helper).to have_received(:run!).with(cluster1_plan_cmd_staging_rds)\n end\n end\n\n it 'passes the elasticache config to \"terraform plan\"' do\n aggregate_failures do\n expect(Helper).to have_received(:run!)\n .with(cluster1_plan_cmd_production_elasticache_cluster)\n expect(Helper).to have_received(:run!)\n .with(cluster1_plan_cmd_staging_elasticache_cluster)\n end\n end\n\n it 'passes the opensearch config to \"terraform plan\"' do\n aggregate_failures do\n expect(Helper).to have_received(:run!)\n .with(cluster1_plan_cmd_production_opensearch_cluster)\n expect(Helper).to have_received(:run!)\n .with(cluster1_plan_cmd_staging_opensearch_cluster)\n end\n end\n\n it 'passes the services config to \"terraform plan\"' do\n aggregate_failures do\n expect(Helper).to have_received(:run!).with(cluster1_plan_cmd_production_service)\n expect(Helper).to have_received(:run!).with(cluster1_plan_cmd_staging_service)\n end\n end\n\n it 'passes the loadbalancer config to \"terraform plan\"' do\n aggregate_failures do\n expect(Helper).to have_received(:run!)\n .with(cluster1_plan_cmd_production_shared_loadbalancer)\n expect(Helper).to have_received(:run!)\n .with(cluster1_plan_cmd_staging_shared_loadbalancer)\n end\n end\n\n it 'passes the cluster 2 config to \"terraform plan\"' do\n aggregate_failures do\n expect(Helper).to have_received(:run!).with(cluster2_plan_cmd_production)\n expect(Helper).to have_received(:run!).with(cluster2_plan_cmd_staging)\n end\n end\n\n it 'passes the cluster 3 config to \"terraform plan\"' do\n expect(Helper).to have_received(:run!).with(cluster3_plan_cmd_staging)\n end\n\n it 'passes the cluster 4 config to \"terraform plan\"' do\n expect(Helper).to have_received(:run!).with(cluster4_plan_cmd_production)\n end\n end\n end\nend\n",
|
|
"diffStat": {
|
|
"model_added_lines": 8,
|
|
"model_removed_lines": 0,
|
|
"model_added_chars": 408,
|
|
"model_removed_chars": 0,
|
|
"user_added_lines": 1,
|
|
"user_removed_lines": 3247,
|
|
"user_added_chars": 37,
|
|
"user_removed_chars": 115853
|
|
},
|
|
"isNewFile": false
|
|
},
|
|
"displayName": "Edit",
|
|
"description": "Replaces text within a file. By default, replaces a single occurrence, but can replace multiple occurrences when `expected_replacements` is specified. This tool requires providing significant context around the change to ensure precise targeting. Always use the read_file tool to examine the file's current content before attempting a text replacement.\n \n The user has the ability to modify the `new_string` content. If modified, this will be stated in the response.\n \n Expectation for required parameters:\n 1. `old_string` MUST be the exact literal text to replace (including all whitespace, indentation, newlines, and surrounding code etc.).\n 2. `new_string` MUST be the exact literal text to replace `old_string` with (also including all whitespace, indentation, newlines, and surrounding code etc.). Ensure the resulting code is correct and idiomatic and that `old_string` and `new_string` are different.\n 3. `instruction` is the detailed instruction of what needs to be changed. It is important to Make it specific and detailed so developers or large language models can understand what needs to be changed and perform the changes on their own if necessary. \n 4. NEVER escape `old_string` or `new_string`, that would break the exact literal text requirement.\n **Important:** If ANY of the above are not satisfied, the tool will fail. CRITICAL for `old_string`: Must uniquely identify the single instance to change. Include at least 3 lines of context BEFORE and AFTER the target text, matching whitespace and indentation precisely. If this string matches multiple locations, or does not match exactly, the tool will fail.\n 5. Prefer to break down complex and long changes into multiple smaller atomic calls to this tool. Always check the content of the file after changes or not finding a string to match.\n **Multiple replacements:** Set `expected_replacements` to the number of occurrences you want to replace. The tool will replace ALL occurrences that match `old_string` exactly. Ensure the number of replacements matches your expectation.",
|
|
"renderOutputAsMarkdown": true
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"id": "8c799d05-5509-4acb-8bb9-8586d743882f",
|
|
"timestamp": "2026-02-20T17:14:59.494Z",
|
|
"type": "gemini",
|
|
"content": "Now, I'll repeat that for `spec/integration/deploys_local_configuration_spec.rb`, but first, I need to check the number of occurrences.",
|
|
"thoughts": [
|
|
{
|
|
"subject": "Investigating Deployments' Scope",
|
|
"description": "Okay, I'm digging into `spec/integration/deploys_local_configuration_spec.rb` now. My current focus is to pinpoint the exact number of instances where it's referenced. This should give me a better grasp of its overall significance and usage context.",
|
|
"timestamp": "2026-02-20T17:14:59.280Z"
|
|
}
|
|
],
|
|
"tokens": {
|
|
"input": 58625,
|
|
"output": 77,
|
|
"cached": 56575,
|
|
"thoughts": 36,
|
|
"tool": 0,
|
|
"total": 58738
|
|
},
|
|
"model": "gemini-3-flash-preview",
|
|
"toolCalls": [
|
|
{
|
|
"id": "run_shell_command_1771607699490_0",
|
|
"name": "run_shell_command",
|
|
"args": {
|
|
"command": "grep -c \"sync_sql_backup_to_azure\" spec/integration/deploys_local_configuration_spec.rb"
|
|
},
|
|
"result": [
|
|
{
|
|
"functionResponse": {
|
|
"id": "run_shell_command_1771607699490_0",
|
|
"name": "run_shell_command",
|
|
"response": {
|
|
"output": "Output: 2\nProcess Group PGID: 48525"
|
|
}
|
|
}
|
|
}
|
|
],
|
|
"status": "success",
|
|
"timestamp": "2026-02-20T17:14:59.559Z",
|
|
"resultDisplay": "2",
|
|
"displayName": "Shell",
|
|
"description": "This tool executes a given shell command as `bash -c <command>`. To run a command in the background, set the `is_background` parameter to true. Do NOT use `&` to background commands. Command is executed as a subprocess that leads its own process group. Command process group can be terminated as `kill -- -PGID` or signaled as `kill -s SIGNAL -- -PGID`.\n\n Efficiency Guidelines:\n - Quiet Flags: Always prefer silent or quiet flags (e.g., `npm install --silent`, `git --no-pager`) to reduce output volume while still capturing necessary information.\n - Pagination: Always disable terminal pagination to ensure commands terminate (e.g., use `git --no-pager`, `systemctl --no-pager`, or set `PAGER=cat`).\n\n The following information is returned:\n\n Output: Combined stdout/stderr. Can be `(empty)` or partial on error and for any unwaited background processes.\n Exit Code: Only included if non-zero (command failed).\n Error: Only included if a process-level error occurred (e.g., spawn failure).\n Signal: Only included if process was terminated by a signal.\n Background PIDs: Only included if background processes were started.\n Process Group PGID: Only included if available.",
|
|
"renderOutputAsMarkdown": false
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"id": "6b7f90e1-e891-4eb8-a0e7-67450f47f24b",
|
|
"timestamp": "2026-02-20T17:15:02.045Z",
|
|
"type": "gemini",
|
|
"content": "Two? Let me check again.",
|
|
"thoughts": [
|
|
{
|
|
"subject": "Checking the Constraints",
|
|
"description": "I'm currently verifying the maximum word count and constraint specifics. It seems like the word limit is 50 words, and the instructions are quite clear about the formatting. No references to my initial instructions allowed!",
|
|
"timestamp": "2026-02-20T17:15:01.892Z"
|
|
}
|
|
],
|
|
"tokens": {
|
|
"input": 58720,
|
|
"output": 47,
|
|
"cached": 56540,
|
|
"thoughts": 10,
|
|
"tool": 0,
|
|
"total": 58777
|
|
},
|
|
"model": "gemini-3-flash-preview",
|
|
"toolCalls": [
|
|
{
|
|
"id": "run_shell_command_1771607702041_0",
|
|
"name": "run_shell_command",
|
|
"args": {
|
|
"command": "grep -n \"sync_sql_backup_to_azure\" spec/integration/deploys_local_configuration_spec.rb"
|
|
},
|
|
"result": [
|
|
{
|
|
"functionResponse": {
|
|
"id": "run_shell_command_1771607702041_0",
|
|
"name": "run_shell_command",
|
|
"response": {
|
|
"output": "Output: 431: \"sync_sql_backup_to_azure\" => false,\n506: \"sync_sql_backup_to_azure\" => false,\nProcess Group PGID: 48553"
|
|
}
|
|
}
|
|
}
|
|
],
|
|
"status": "success",
|
|
"timestamp": "2026-02-20T17:15:02.136Z",
|
|
"resultDisplay": "431: \"sync_sql_backup_to_azure\" => false,\n506: \"sync_sql_backup_to_azure\" => false,",
|
|
"displayName": "Shell",
|
|
"description": "This tool executes a given shell command as `bash -c <command>`. To run a command in the background, set the `is_background` parameter to true. Do NOT use `&` to background commands. Command is executed as a subprocess that leads its own process group. Command process group can be terminated as `kill -- -PGID` or signaled as `kill -s SIGNAL -- -PGID`.\n\n Efficiency Guidelines:\n - Quiet Flags: Always prefer silent or quiet flags (e.g., `npm install --silent`, `git --no-pager`) to reduce output volume while still capturing necessary information.\n - Pagination: Always disable terminal pagination to ensure commands terminate (e.g., use `git --no-pager`, `systemctl --no-pager`, or set `PAGER=cat`).\n\n The following information is returned:\n\n Output: Combined stdout/stderr. Can be `(empty)` or partial on error and for any unwaited background processes.\n Exit Code: Only included if non-zero (command failed).\n Error: Only included if a process-level error occurred (e.g., spawn failure).\n Signal: Only included if process was terminated by a signal.\n Background PIDs: Only included if background processes were started.\n Process Group PGID: Only included if available.",
|
|
"renderOutputAsMarkdown": false
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"id": "e82c1af4-8fc2-4535-bc82-fac6f4697f0f",
|
|
"timestamp": "2026-02-20T17:15:05.105Z",
|
|
"type": "gemini",
|
|
"content": "Only two: `cluster1_apply_cmd_production_rds` and `cluster1_apply_cmd_staging_rds`. I'll check `spec/integration/deploys_local_configuration_spec.rb` for any other RDS-related commands.",
|
|
"thoughts": [
|
|
{
|
|
"subject": "Considering RDS commands",
|
|
"description": "I've homed in on two commands related to RDS for production and staging: `cluster1_apply_cmd_production_rds` and `cluster1_apply_cmd_staging_rds`. Now, I'm digging into the integration specs to see if any other RDS commands exist, specifically by searching the `deploys_local_configuration_spec` file for occurrences of \"rds.\"",
|
|
"timestamp": "2026-02-20T17:15:04.993Z"
|
|
},
|
|
{
|
|
"subject": "Examining RDS command count",
|
|
"description": "Okay, so I've confirmed that the only RDS-related commands are `cluster1_apply_cmd_production_rds` and `cluster1_apply_cmd_staging_rds`. I've looked through the integration specs as I intended, and the search yielded no other RDS commands. Seems I'm good on that front.",
|
|
"timestamp": "2026-02-20T17:15:05.017Z"
|
|
}
|
|
],
|
|
"tokens": {
|
|
"input": 58823,
|
|
"output": 92,
|
|
"cached": 56528,
|
|
"thoughts": 70,
|
|
"tool": 0,
|
|
"total": 58985
|
|
},
|
|
"model": "gemini-3-flash-preview",
|
|
"toolCalls": [
|
|
{
|
|
"id": "run_shell_command_1771607705101_0",
|
|
"name": "run_shell_command",
|
|
"args": {
|
|
"command": "grep \"rds\" spec/integration/deploys_local_configuration_spec.rb | grep \"let\""
|
|
},
|
|
"result": [
|
|
{
|
|
"functionResponse": {
|
|
"id": "run_shell_command_1771607705101_0",
|
|
"name": "run_shell_command",
|
|
"response": {
|
|
"output": "Output: let(:cluster1_apply_cmd_production_rds) do\n let(:cluster1_apply_cmd_staging_rds) do\nProcess Group PGID: 48558"
|
|
}
|
|
}
|
|
}
|
|
],
|
|
"status": "success",
|
|
"timestamp": "2026-02-20T17:15:05.178Z",
|
|
"resultDisplay": " let(:cluster1_apply_cmd_production_rds) do\n let(:cluster1_apply_cmd_staging_rds) do",
|
|
"displayName": "Shell",
|
|
"description": "This tool executes a given shell command as `bash -c <command>`. To run a command in the background, set the `is_background` parameter to true. Do NOT use `&` to background commands. Command is executed as a subprocess that leads its own process group. Command process group can be terminated as `kill -- -PGID` or signaled as `kill -s SIGNAL -- -PGID`.\n\n Efficiency Guidelines:\n - Quiet Flags: Always prefer silent or quiet flags (e.g., `npm install --silent`, `git --no-pager`) to reduce output volume while still capturing necessary information.\n - Pagination: Always disable terminal pagination to ensure commands terminate (e.g., use `git --no-pager`, `systemctl --no-pager`, or set `PAGER=cat`).\n\n The following information is returned:\n\n Output: Combined stdout/stderr. Can be `(empty)` or partial on error and for any unwaited background processes.\n Exit Code: Only included if non-zero (command failed).\n Error: Only included if a process-level error occurred (e.g., spawn failure).\n Signal: Only included if process was terminated by a signal.\n Background PIDs: Only included if background processes were started.\n Process Group PGID: Only included if available.",
|
|
"renderOutputAsMarkdown": false
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"id": "ca805c8a-c87d-4127-8ca4-1140391ffa27",
|
|
"timestamp": "2026-02-20T17:15:07.467Z",
|
|
"type": "gemini",
|
|
"content": "Two. Running `replace` on `spec/integration/deploys_local_configuration_spec.rb`.",
|
|
"thoughts": [
|
|
{
|
|
"subject": "Continuing the Process",
|
|
"description": "I've successfully performed the necessary `replace` operation for the specified file. Now I will move on to the next file and repeat the process there. My goal is to maintain accuracy while efficiently working through this list.",
|
|
"timestamp": "2026-02-20T17:15:07.142Z"
|
|
}
|
|
],
|
|
"tokens": {
|
|
"input": 58962,
|
|
"output": 184,
|
|
"cached": 56475,
|
|
"thoughts": 35,
|
|
"tool": 0,
|
|
"total": 59181
|
|
},
|
|
"model": "gemini-3-flash-preview",
|
|
"toolCalls": [
|
|
{
|
|
"id": "replace_1771607707463_0",
|
|
"name": "replace",
|
|
"args": {
|
|
"expected_replacements": 2,
|
|
"old_string": " \"sync_sql_backup_to_azure\" => false,\n \"codebuild_access\" => [",
|
|
"file_path": "/Users/bob/git/dxw/dalmatian/spec/integration/deploys_local_configuration_spec.rb",
|
|
"new_string": " \"sync_sql_backup_to_azure\" => false,\n \"replication_bucket_destination_arn\" => \"\",\n \"replication_kms_key_id\" => \"\",\n \"codebuild_access\" => [",
|
|
"instruction": "In RDS command definitions, add the missing 'replication_bucket_destination_arn' and 'replication_kms_key_id' fields to the RDS configuration hash."
|
|
},
|
|
"result": [
|
|
{
|
|
"functionResponse": {
|
|
"id": "replace_1771607707463_0",
|
|
"name": "replace",
|
|
"response": {
|
|
"output": "Successfully modified file: /Users/bob/git/dxw/dalmatian/spec/integration/deploys_local_configuration_spec.rb (2 replacements)."
|
|
}
|
|
}
|
|
}
|
|
],
|
|
"status": "success",
|
|
"timestamp": "2026-02-20T17:15:07.500Z",
|
|
"resultDisplay": {
|
|
"fileDiff": "Index: deploys_local_configuration_spec.rb\n===================================================================\n--- deploys_local_configuration_spec.rb\tCurrent\n+++ deploys_local_configuration_spec.rb\tProposed\n@@ -429,6 +429,8 @@\n }\n ],\n \"sync_sql_backup_to_azure\" => false,\n+ \"replication_bucket_destination_arn\" => \"\",\n+ \"replication_kms_key_id\" => \"\",\n \"codebuild_access\" => [\n \"service-name\"\n ]\n@@ -504,6 +506,8 @@\n }\n ],\n \"sync_sql_backup_to_azure\" => false,\n+ \"replication_bucket_destination_arn\" => \"\",\n+ \"replication_kms_key_id\" => \"\",\n \"codebuild_access\" => [\n \"service-name\"\n ]\n",
|
|
"fileName": "deploys_local_configuration_spec.rb",
|
|
"filePath": "/Users/bob/git/dxw/dalmatian/spec/integration/deploys_local_configuration_spec.rb",
|
|
"originalContent": "require_relative \"../support/spec_helper\"\n\nmodule Dalmatian\n RSpec.describe \"tests local configuration\" do\n def fake_parameter_store\n double(\n \"parameter_store\",\n get_parameter: \"\",\n get_parameters_by_path: {}\n )\n end\n\n def tfvar_arg_string(tfvars)\n Terraform.tfvar_arg_string(tfvars)\n end\n\n def terraform_apply_cmd(tfvar_string)\n \"#{tfvar_string} terraform apply\"\n end\n\n def stub_git_checkout\n allow(Helper).to receive(:run!).with(\"git checkout feature/experiment\")\n end\n\n def stub_workspace_creation_cmds\n %w[\n new-dedicated-cluster-example-domain-name-com-hz\n new-dedicated-cluster-test-s3\n new-dedicated-cluster-test-vpn-vpn-cg\n new-dedicated-cluster-ecs-production\n new-dedicated-cluster-ecs-staging\n new-dedicated-cluster-0-production\n new-dedicated-cluster-0-staging\n new-dedicated-cluster-test-service-production\n new-dedicated-cluster-test-service-staging\n new-dedicated-cluster-test-1-waf-staging\n new-dedicated-cluster-test-1-waf-production\n new-dedicated-cluster-testservice-rds-staging\n new-dedicated-cluster-testservice-rds-production\n new-dedicated-cluster-testredis-elasticache-cluster-staging\n new-dedicated-cluster-testredis-elasticache-cluster-production\n new-dedicated-cluster-testos-opensearch-cluster-staging\n new-dedicated-cluster-testos-opensearch-cluster-production\n new-dedicated-cluster-test-lb-1-shared-loadbalancer-staging\n new-dedicated-cluster-test-lb-1-shared-loadbalancer-production\n shared-new-cluster-ecs-production\n shared-new-cluster-ecs-staging\n existing-shared-cluster-staging-0-staging\n existing-shared-cluster-production-0-production\n ].each do |workspace_name|\n allow(Helper).to receive(:run!).with(\"terraform workspace new #{workspace_name}\")\n end\n end\n\n def infrastructure_defaults\n {\n \"region\" => \"eu-west-2\",\n \"cidr\" => \"10.0.0.0/16\",\n \"root_domain_zone\" => \"dalmatian.dxw.net\",\n \"internal_domain_zone\" => \"dalmatian.internal\",\n \"ecs_private_subnets\" => [\n {\n \"availability_zone\" => \"eu-west-2a\",\n \"cidr\" => \"10.0.128.0/24\"\n },\n {\n \"availability_zone\" => \"eu-west-2b\",\n \"cidr\" => \"10.0.129.0/24\"\n },\n {\n \"availability_zone\" => \"eu-west-2c\",\n \"cidr\" => \"10.0.130.0/24\"\n }\n ],\n \"extra_public_subnets\" => [\n {\n \"availability_zone\" => \"eu-west-2a\",\n \"cidr\" => \"10.0.0.0/24\"\n },\n {\n \"availability_zone\" => \"eu-west-2b\",\n \"cidr\" => \"10.0.1.0/24\"\n },\n {\n \"availability_zone\" => \"eu-west-2c\",\n \"cidr\" => \"10.0.2.0/24\"\n }\n ],\n \"instances_key_name\" => \"dalmatian-ecs-instances\",\n \"instance_type\" => \"t2.medium\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"max_instance_lifetime\" => \"86400\",\n \"associate_public_ip_address\" => \"0\",\n \"docker_storage_size\" => \"40\",\n \"dockerhub_email\" => \"\",\n \"dockerhub_token\" => \"\",\n \"enable_efs\" => \"false\",\n \"encrypt_efs\" => \"true\",\n \"efs_dirs\" => [],\n \"monitoring_docs_path\" => \"https://github.com/dxw/dalmatian/docs/monitoring-alarms/\"\n }\n end\n\n let(:cluster1_apply_cmd_hz) do\n terraform_apply_cmd(\n tfvar_arg_string(\n \"account_id\" => \"123456789012\",\n \"cluster_id\" => \"new-dedicated-cluster\",\n \"dalmatian_role\" => \"dalmatian-admin\",\n \"hosted_zone\" => {\n \"domain\" => \"example-domain-name.com\",\n \"ns_records\" => [\n {\n \"name\" => \"delegated\",\n \"value\" => [\n \"ns1.aws.com\"\n ]\n }\n ],\n \"a_records\" => [\n {\n \"name\" => \"some-service\",\n \"value\" => [\n \"1.2.3.4\"\n ]\n },\n {\n \"name\" => \"mail\",\n \"value\" => [\n \"5.6.7.8\"\n ]\n }\n ],\n \"alias_records\" => [\n {\n \"name\" => \"example-domain-name.com\",\n \"value\" => \"cf-distribution.aws.net\"\n },\n {\n \"name\" => \"www\",\n \"value\" => \"cf-distribution.aws.net\"\n }\n ],\n \"cname_records\" => [\n {\n \"name\" => \"alb\",\n \"value\" => [\n \"aws-alb.aws.net\"\n ]\n }\n ],\n \"mx_records\" => [\n {\n \"name\" => \"mail\",\n \"value\" => [\n \"0 mail.example-domain-name.com\"\n ]\n }\n ],\n \"txt_records\" => [\n {\n \"name\" => \"mail\",\n \"value\" => [\n \"v=spf1 a ip4:9.10.11.0/24 mx ~all\"\n ]\n }\n ],\n \"srv_records\" => [\n {\n \"name\" => \"@\",\n \"value\" => [\n \"_imaps._tcp.gmail.com. 86400 IN SRV 5 0 993 imap.gmail.com\"\n ]\n }\n ]\n }\n )\n )\n end\n\n let(:cluster1_apply_cmd_s3) do\n terraform_apply_cmd(\n tfvar_arg_string(\n \"account_id\" => \"123456789012\",\n \"cluster_id\" => \"new-dedicated-cluster\",\n \"dalmatian_role\" => \"dalmatian-admin\",\n \"s3\" => {\n \"name\" => \"test\",\n \"enable_s3_versioning\" => true,\n \"encrypted\" => true,\n \"acl\" => \"private\",\n \"policy\" => {\n \"staging\" => {\n \"rw\" => {\n \"services\" => [\n \"test-service\"\n ]\n }\n }\n },\n \"service_cloudfront_read_access\" => [\n \"test-service-staging\"\n ],\n \"cloudfront\" => {\n \"create\" => true,\n \"domain_names\" => [\n \"example.com\",\n \"example2.com\"\n ],\n \"certificate\" => \"arn:aws:acm:lb-region-0:000000000000:certificate/00000000-0000-0000-0000-000000000000\"\n }\n }\n )\n )\n end\n\n let(:cluster1_apply_cmd_vpn_cg) do\n terraform_apply_cmd(\n tfvar_arg_string(\n \"account_id\" => \"123456789012\",\n \"cluster_id\" => \"new-dedicated-cluster\",\n \"dalmatian_role\" => \"dalmatian-admin\",\n \"vpn_customer_gateway\" => {\n \"name\" => \"test-vpn\",\n \"bgp_asn\" => 65000,\n \"ip_address\" => \"1.2.3.4\"\n }\n )\n )\n end\n\n let(:cluster1_apply_cmd_production) do\n terraform_apply_cmd(\n tfvar_arg_string(\n infrastructure_defaults.merge(\n \"instance_type\" => \"t2.medium\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"environment\" => \"production\",\n \"cluster_name\" => \"new-dedicated-cluster-production\",\n \"account_id\" => \"123456789012\",\n \"infrastructure_name\" => \"new-dedicated-cluster\",\n \"dalmatian_role\" => \"dalmatian-admin\"\n )\n )\n )\n end\n\n let(:cluster1_apply_cmd_staging) do\n terraform_apply_cmd(\n tfvar_arg_string(\n infrastructure_defaults.merge(\n \"instance_type\" => \"t2.small\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"track_revision\" => \"feature/experiment\",\n \"extra_ecs_clusters\" => [\n {\n \"name\" => \"test\",\n \"subnets_name\" => \"extra_private_subnets\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"instance_type\" => \"t3.small\"\n }\n ],\n \"tinyproxy\" => {\n \"create\" => true\n },\n \"environment\" => \"staging\",\n \"cluster_name\" => \"new-dedicated-cluster-staging\",\n \"account_id\" => \"123456789012\",\n \"infrastructure_name\" => \"new-dedicated-cluster\",\n \"dalmatian_role\" => \"dalmatian-admin\"\n )\n )\n )\n end\n\n let(:cluster1_apply_cmd_production_waf) do\n terraform_apply_cmd(\n tfvar_arg_string(\n infrastructure_defaults.merge(\n \"instance_type\" => \"t2.medium\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"environment\" => \"production\",\n \"account_id\" => \"123456789012\",\n \"infrastructure_name\" => \"new-dedicated-cluster\",\n \"dalmatian_role\" => \"dalmatian-admin\",\n \"waf\" => {\n \"name\" => \"test-1\",\n \"action\" => \"count\",\n \"ip_deny_list\" => [],\n \"aws_managed_rules\" => [\n {\n \"name\" => \"AWSManagedRulesSQLiRuleSet\",\n \"excluded_path_patterns\" => [\n \"/wp-admin/async-upload.php\"\n ]\n },\n {\n \"name\" => \"AWSManagedRulesCommonRuleSet\",\n \"exclude_rules\" => [\n \"SizeRestrictions_BODY\"\n ]\n }\n ],\n \"associations\" => {\n shared_loadbalancers: [\n \"test-lb-1\"\n ],\n service_cloudfront: [\n \"test-service\"\n ]\n }\n }\n )\n )\n )\n end\n\n let(:cluster1_apply_cmd_staging_waf) do\n terraform_apply_cmd(\n tfvar_arg_string(\n infrastructure_defaults.merge(\n \"instance_type\" => \"t2.small\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"track_revision\" => \"feature/experiment\",\n \"extra_ecs_clusters\" => [\n {\n \"name\" => \"test\",\n \"subnets_name\" => \"extra_private_subnets\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"instance_type\" => \"t3.small\"\n }\n ],\n \"tinyproxy\" => {\n \"create\" => true\n },\n \"environment\" => \"staging\",\n \"account_id\" => \"123456789012\",\n \"infrastructure_name\" => \"new-dedicated-cluster\",\n \"dalmatian_role\" => \"dalmatian-admin\",\n \"waf\" => {\n \"name\" => \"test-1\",\n \"action\" => \"count\",\n \"ip_deny_list\" => [],\n \"aws_managed_rules\" => [\n {\n \"name\" => \"AWSManagedRulesSQLiRuleSet\",\n \"excluded_path_patterns\" => [\n \"/wp-admin/async-upload.php\"\n ]\n },\n {\n \"name\" => \"AWSManagedRulesCommonRuleSet\",\n \"exclude_rules\" => [\n \"SizeRestrictions_BODY\"\n ]\n }\n ],\n \"associations\" => {\n shared_loadbalancers: [\n \"test-lb-1\"\n ],\n service_cloudfront: [\n \"test-service\"\n ]\n }\n }\n )\n )\n )\n end\n\n let(:cluster1_apply_cmd_production_rds) do\n terraform_apply_cmd(\n tfvar_arg_string(\n infrastructure_defaults.merge(\n \"instance_type\" => \"t2.medium\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"environment\" => \"production\",\n \"account_id\" => \"123456789012\",\n \"infrastructure_name\" => \"new-dedicated-cluster\",\n \"dalmatian_role\" => \"dalmatian-admin\",\n \"rds\" => {\n \"identifier\" => \"testservice\",\n \"in_use_by\" => [\n \"test-service\"\n ],\n \"clusters_in_use\" => {\n \"production\" => [\n \"test\"\n ],\n \"staging\" => [\n \"test\"\n ]\n },\n \"instance_class\" => {\n \"production\" => \"db.t2.small\",\n \"staging\" => \"db.t2.micro\"\n },\n \"engine\" => \"postgres\",\n \"engine_version\" => \"11.4\",\n \"allocated_storage\" => 20,\n \"storage_encrypted\" => true,\n \"storage_type\" => \"gp3\",\n \"db_name\" => \"testapp\",\n \"port\" => 5432,\n \"maintenance_window\" => \"mon:19:00-mon:19:30\",\n \"backup_window\" => \"09:00-10:00\",\n \"backup_retention_period\" => 31,\n \"force_ssl\" => true,\n \"parameter_store_path_db_url_name\" => \"DATABASE_URL\",\n \"sql_backup_scheduled_task_environment_variables\" => [\n {\n \"name\" => \"foo\",\n \"value\" => \"bar\"\n }\n ],\n \"check_sql_backup_scheduled_task_environment_variables\" => [\n {\n \"name\" => \"foo\",\n \"value\" => \"bar\"\n }\n ],\n \"sync_sql_backup_to_azure\" => false,\n \"codebuild_access\" => [\n \"service-name\"\n ]\n }\n )\n )\n )\n end\n\n let(:cluster1_apply_cmd_staging_rds) do\n terraform_apply_cmd(\n tfvar_arg_string(\n infrastructure_defaults.merge(\n \"instance_type\" => \"t2.small\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"track_revision\" => \"feature/experiment\",\n \"extra_ecs_clusters\" => [\n {\n \"name\" => \"test\",\n \"subnets_name\" => \"extra_private_subnets\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"instance_type\" => \"t3.small\"\n }\n ],\n \"tinyproxy\" => {\n \"create\" => true\n },\n \"environment\" => \"staging\",\n \"account_id\" => \"123456789012\",\n \"infrastructure_name\" => \"new-dedicated-cluster\",\n \"dalmatian_role\" => \"dalmatian-admin\",\n \"rds\" => {\n \"identifier\" => \"testservice\",\n \"in_use_by\" => [\n \"test-service\"\n ],\n \"clusters_in_use\" => {\n \"production\" => [\n \"test\"\n ],\n \"staging\" => [\n \"test\"\n ]\n },\n \"instance_class\" => {\n \"production\" => \"db.t2.small\",\n \"staging\" => \"db.t2.micro\"\n },\n \"engine\" => \"postgres\",\n \"engine_version\" => \"11.4\",\n \"allocated_storage\" => 20,\n \"storage_encrypted\" => true,\n \"storage_type\" => \"gp3\",\n \"db_name\" => \"testapp\",\n \"port\" => 5432,\n \"maintenance_window\" => \"mon:19:00-mon:19:30\",\n \"backup_window\" => \"09:00-10:00\",\n \"backup_retention_period\" => 31,\n \"force_ssl\" => true,\n \"parameter_store_path_db_url_name\" => \"DATABASE_URL\",\n \"sql_backup_scheduled_task_environment_variables\" => [\n {\n \"name\" => \"foo\",\n \"value\" => \"bar\"\n }\n ],\n \"check_sql_backup_scheduled_task_environment_variables\" => [\n {\n \"name\" => \"foo\",\n \"value\" => \"bar\"\n }\n ],\n \"sync_sql_backup_to_azure\" => false,\n \"codebuild_access\" => [\n \"service-name\"\n ]\n }\n )\n )\n )\n end\n\n let(:cluster1_apply_cmd_production_elasticache_cluster) do\n terraform_apply_cmd(\n tfvar_arg_string(\n infrastructure_defaults.merge(\n \"instance_type\" => \"t2.medium\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"environment\" => \"production\",\n \"account_id\" => \"123456789012\",\n \"infrastructure_name\" => \"new-dedicated-cluster\",\n \"dalmatian_role\" => \"dalmatian-admin\",\n \"elasticache_cluster\" => {\n \"identifier\" => \"testredis\",\n \"in_use_by\" => [\n \"test-service\"\n ],\n \"node_type\" => \"cache.t2.micro\",\n \"node_count\" => 1,\n \"engine\" => \"redis\",\n \"engine_version\" => \"5.0.6\",\n \"parameters\" => [],\n \"port\" => 6379,\n \"maintenance_window\" => \"mon:19:00-mon:22:00\",\n \"snapshot_window\" => \"09:00-10:00\",\n \"parameter_store_path_elasticache_cluster_url_name\" => \"REDIS_URL\"\n }\n )\n )\n )\n end\n\n let(:cluster1_apply_cmd_staging_elasticache_cluster) do\n terraform_apply_cmd(\n tfvar_arg_string(\n infrastructure_defaults.merge(\n \"instance_type\" => \"t2.small\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"track_revision\" => \"feature/experiment\",\n \"extra_ecs_clusters\" => [\n {\n \"name\" => \"test\",\n \"subnets_name\" => \"extra_private_subnets\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"instance_type\" => \"t3.small\"\n }\n ],\n \"tinyproxy\" => {\n \"create\" => true\n },\n \"environment\" => \"staging\",\n \"account_id\" => \"123456789012\",\n \"infrastructure_name\" => \"new-dedicated-cluster\",\n \"dalmatian_role\" => \"dalmatian-admin\",\n \"elasticache_cluster\" => {\n \"identifier\" => \"testredis\",\n \"in_use_by\" => [\n \"test-service\"\n ],\n \"node_type\" => \"cache.t2.micro\",\n \"node_count\" => 1,\n \"engine\" => \"redis\",\n \"engine_version\" => \"5.0.6\",\n \"parameters\" => [],\n \"port\" => 6379,\n \"maintenance_window\" => \"mon:19:00-mon:22:00\",\n \"snapshot_window\" => \"09:00-10:00\",\n \"parameter_store_path_elasticache_cluster_url_name\" => \"REDIS_URL\"\n }\n )\n )\n )\n end\n\n let(:cluster1_apply_cmd_production_opensearch_cluster) do\n terraform_apply_cmd(\n tfvar_arg_string(\n infrastructure_defaults.merge(\n \"instance_type\" => \"t2.medium\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"environment\" => \"production\",\n \"account_id\" => \"123456789012\",\n \"infrastructure_name\" => \"new-dedicated-cluster\",\n \"dalmatian_role\" => \"dalmatian-admin\",\n \"opensearch_cluster\" => {\n \"identifier\" => \"testos\",\n \"in_use_by\" => [\n \"test-service\"\n ],\n \"version\" => \"1.2\",\n \"master_enabled\" => true,\n \"master_count\" => \"1\",\n \"master_type\" => \"c6g.large.search\",\n \"instance_count\" => \"3\",\n \"instance_type\" => \"t3.small.search\",\n \"warm_enabled\" => true,\n \"warm_count\" => \"2\",\n \"warm_type\" => \"ultrawarm1.medium.search\",\n \"parameter_store_path_opensearch_cluster_url_name\" => \"ELASTICSEARCH_URL\",\n \"volume_size\" => \"20\"\n }\n )\n )\n )\n end\n\n let(:cluster1_apply_cmd_staging_opensearch_cluster) do\n terraform_apply_cmd(\n tfvar_arg_string(\n infrastructure_defaults.merge(\n \"instance_type\" => \"t2.small\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"track_revision\" => \"feature/experiment\",\n \"extra_ecs_clusters\" => [\n {\n \"name\" => \"test\",\n \"subnets_name\" => \"extra_private_subnets\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"instance_type\" => \"t3.small\"\n }\n ],\n \"tinyproxy\" => {\n \"create\" => true\n },\n \"environment\" => \"staging\",\n \"account_id\" => \"123456789012\",\n \"infrastructure_name\" => \"new-dedicated-cluster\",\n \"dalmatian_role\" => \"dalmatian-admin\",\n \"opensearch_cluster\" => {\n \"identifier\" => \"testos\",\n \"in_use_by\" => [\n \"test-service\"\n ],\n \"version\" => \"1.2\",\n \"master_enabled\" => true,\n \"master_count\" => \"1\",\n \"master_type\" => \"c6g.large.search\",\n \"instance_count\" => \"3\",\n \"instance_type\" => \"t3.small.search\",\n \"warm_enabled\" => true,\n \"warm_count\" => \"2\",\n \"warm_type\" => \"ultrawarm1.medium.search\",\n \"parameter_store_path_opensearch_cluster_url_name\" => \"ELASTICSEARCH_URL\",\n \"volume_size\" => \"20\"\n }\n )\n )\n )\n end\n\n let(:cluster1_apply_cmd_production_service) do\n terraform_apply_cmd(\n tfvar_arg_string(\n infrastructure_defaults.merge(\n \"instance_type\" => \"t2.medium\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"environment\" => \"production\",\n \"cluster_name\" => \"new-dedicated-cluster-production\",\n \"account_id\" => \"123456789012\",\n \"infrastructure_name\" => \"new-dedicated-cluster\",\n \"dalmatian_role\" => \"dalmatian-admin\",\n \"service\" => {\n \"name\" => \"test-service\",\n \"blue_green\" => {\n \"production\" => {\n \"enabled\" => true,\n \"db_copy\" => {\n \"from_db_host_ps_key\" => \"/test-app/other-test-service/production/DB_HOST\",\n \"from_db_name_ps_key\" => \"/test-app/other-test-service/production/DB_NAME\",\n \"from_db_user_ps_key\" => \"/test-app/other-test-service/production/DB_USER\",\n \"from_db_pass_ps_key\" => \"/test-app/other-test-service/production/DB_PASSWORD\",\n \"blue_green_db_name_ps_key\" => \"/test-app/test-service/production/DB_HOST\",\n \"blue_green_db_user_ps_key\" => \"/test-app/test-service/production/DB_USER\",\n \"blue_green_db_pass_ps_key\" => \"/test-app/test-service/production/DB_PASSWORD\",\n \"sql_backups_s3_bucket\" => \"new-dedicated-cluster-testservice-production-sql-backup\"\n },\n \"db_rewrites\" => [\n {\n \"from\" => \"other-test-service.example.com\",\n \"to\" => \"test-service.example.com\"\n }\n ],\n \"directory_copy\" => [\n {\n \"from\" => \"/mnt/efs/other-test-service-media\",\n \"to\" => \"/mnt/efs/test-service-media\",\n \"chown\" => \"33:33\"\n }\n ],\n \"asset_copy_trigger_ps_key\" => \"/test-app/test-service/production/BLUE_GREEN_ASSET_COPY_TRIGGER\"\n },\n \"staging\" => {\n \"enabled\" => false\n }\n },\n \"launch_on\" => [\"production\", \"staging\"],\n \"launch_on_cluster\" => \"test\",\n \"cluster_min_servers\" => {\n \"production\" => \"2\",\n \"staging\" => \"2\"\n },\n \"parameter_store_path\" => {\n \"production\" => \"\",\n \"staging\" => \"/test-path\"\n },\n \"parameter_store_key\" => {\n \"production\" => \"\",\n \"staging\" => \"arn:aws:kms:eu-west-2:000000000000:key/00000000-0000-0000-0000-000000000000\"\n },\n \"daemon\" => false,\n \"monitoring\" => {\n \"production\" => {\n \"opsgenie_alerts\" => {\n \"enabled\" => true,\n \"cloudfront_5xx\" => {\n \"enabled\" => true,\n \"threshold\" => \"95\",\n \"evaluation_periods\" => \"15\"\n }\n },\n \"ghost_inspector\" => {\n \"enabled\" => true\n }\n },\n \"staging\" => {\n \"opsgenie_alerts\" => {\n \"enabled\" => false,\n \"cloudfront_5xx\" => {\n \"enabled\" => true,\n \"threshold\" => \"95\",\n \"evaluation_periods\" => \"15\"\n }\n },\n \"ghost_inspector\" => {\n \"enabled\" => false\n }\n }\n },\n \"cloudfront\" => {\n \"production\" => {\n \"create\" => true,\n \"managed_cache_policy\" => \"CachingDisabled\",\n \"managed_origin_policy\" => \"AllViewerExceptHostHeader\",\n \"managed_response_headers_policy\" => \"CORS-with-preflight-and-SecurityHeadersPolicy\",\n \"tls_protocol_version\" => \"TLSv1.2_2019\",\n \"origin_keepalive_timeout\" => \"60\",\n \"origin_read_timeout\" => \"60\",\n \"basic_auth\" => false,\n \"basic_auth_users_extra\" => {},\n \"viewer_request_functions\" => [\n {\n \"name\" => \"default\",\n \"true_client_ip_header\" => true,\n \"ip_subnet_allow_list\" => [\n \"0.0.0.0/0\"\n ],\n \"redirects\" => [\n {\n \"from_hostname_pattern\" => \"example-old-domain-name.*\",\n \"from_path_pattern\" => \"/*\",\n \"to_hostname\" => \"example-domain-name.co.uk\",\n \"to_path\" => \"/${path}\"\n }\n ]\n }\n ],\n \"offline_page_http_status\" => {\n \"500\" => \"/error-pages/500.html\",\n \"501\" => \"/error-pages/501.html\",\n \"502\" => \"/error-pages/502.html\",\n \"503\" => \"/error-pages/503.html\",\n \"504\" => \"/error-pages/504.html\"\n },\n \"custom_origins\" => [\n {\n \"origin\" => \"test-media-production.s3.amazonaws.com\",\n \"id\" => \"test-media-production-s3\"\n }\n ],\n \"bypass_protection\" => {\n \"enabled\" => true,\n \"exclude_domains\" => [\n \"example.com\"\n ]\n },\n \"custom_behaviors\" => [\n {\n \"target_origin_id\" => \"test-media-production-s3\",\n \"min_ttl\" => 1200,\n \"default_ttl\" => 3600,\n \"max_ttl\" => 86400,\n \"associate_viewer_request_function\" => \"default\",\n \"managed_cache_policy\" => \"CachingDisabled\",\n \"managed_origin_policy\" => \"AllViewerExceptHostHeader\",\n \"managed_response_headers_policy\" => \"CORS-with-preflight-and-SecurityHeadersPolicy\",\n \"path_pattern\" => \"/media/*\"\n }\n ]\n },\n \"staging\" => {\n \"create\" => true,\n \"managed_cache_policy\" => \"CachingDisabled\",\n \"managed_origin_policy\" => \"AllViewerExceptHostHeader\",\n \"managed_response_headers_policy\" => \"CORS-with-preflight-and-SecurityHeadersPolicy\",\n \"tls_protocol_version\" => \"TLSv1.2_2021\",\n \"origin_keepalive_timeout\" => \"10\",\n \"origin_read_timeout\" => \"40\",\n \"basic_auth\" => true,\n \"basic_auth_users_extra\" => {},\n \"viewer_request_functions\" => [\n {\n \"name\" => \"default\",\n \"true_client_ip_header\" => true,\n \"ip_subnet_allow_list\" => [\n \"0.0.0.0/0\"\n ],\n \"redirects\" => [\n {\n \"from_hostname_pattern\" => \"example-old-domain-name.*\",\n \"from_path_pattern\" => \"/*\",\n \"to_hostname\" => \"example-domain-name.co.uk\",\n \"to_path\" => \"/${path}\"\n }\n ]\n }\n ],\n \"offline_page_http_status\" => {\n \"500\" => \"/error-pages/500.html\",\n \"501\" => \"/error-pages/501.html\",\n \"502\" => \"/error-pages/502.html\",\n \"503\" => \"/error-pages/503.html\",\n \"504\" => \"/error-pages/504.html\"\n },\n \"custom_origins\" => [\n {\n \"origin\" => \"test-media-staging.s3.amazonaws.com\",\n \"id\" => \"test-media-staging-s3\"\n }\n ],\n \"bypass_protection\" => {\n \"enabled\" => false,\n \"exclude_domains\" => []\n },\n \"custom_behaviors\" => [\n {\n \"target_origin_id\" => \"test-media-staging-s3\",\n \"min_ttl\" => 1200,\n \"default_ttl\" => 3600,\n \"max_ttl\" => 86400,\n \"associate_viewer_request_function\" => \"default\",\n \"managed_cache_policy\" => \"\",\n \"managed_origin_policy\" => \"\",\n \"managed_response_headers_policy\" => \"\",\n \"path_pattern\" => \"/media/*\"\n }\n ]\n }\n },\n \"s3_policy\" => {\n \"production\" => {},\n \"staging\" => {\n \"rw\" => [\n \"test\"\n ]\n }\n },\n \"shared_loadbalancer_name\" => \"test-lb-1\",\n \"lb_ip_whitelist\" => [\n {\n \"name\" => \"public\",\n \"cidr\" => \"0.0.0.0/0\"\n }\n ],\n \"lb_idle_timeout\" => \"60\",\n \"global_accelerator\" => {\n \"production\" => true,\n \"staging\" => false\n },\n \"health_check_path\" => \"/check\",\n \"health_check_grace_period\" => \"0\",\n \"deregistration_delay\" => \"60\",\n \"serve_from_subdirectory\" => \"/test-subdir\",\n \"domain_names\" => {\n \"production\" => [],\n \"staging\" => [\n \"example-domain-name.co.uk\"\n ]\n },\n \"proxy_configuration\" => {\n \"production\" => {},\n \"staging\" => {\n \"https_proxy\" => \"dalmatian_tinyproxy\",\n \"http_proxy\" => \"http://my.test-proxy.com:8888\",\n \"no_proxy\" => [\n \"*.example.com\",\n \"93.184.216.34/32\"\n ]\n }\n },\n \"home_directory\" => \"/home/user\",\n \"lb_ssl_certificate\" => {\n \"production\" => \"\",\n \"staging\" => \"arn:aws:acm:lb-region-0:000000000000:certificate/00000000-0000-0000-0000-000000000000\"\n },\n \"lb_ssl_policy\" => {\n \"production\" => \"ELBSecurityPolicy-TLS-1-2-2017-01\",\n \"staging\" => \"ELBSecurityPolicy-TLS-1-2-2017-01\"\n },\n \"cloudfront_ssl_certificate\" => {\n \"production\" => \"\",\n \"staging\" => \"arn:aws:acm:us-east-1:000000000000:certificate/00000000-0000-0000-0000-000000000000\"\n },\n \"image_source\" => \"build_from_github_repo\",\n \"image_location\" => \"git@github.com:dxw/dalmatian-test-app\",\n \"track_revision\" => {\n \"production\" => \"\",\n \"staging\" => \"\"\n },\n \"custom_codestar_connection_arn\" => \"arn:aws:codestar-connections:eu-west-2:000000000000:connection/00000000-0000-0000-0000-000000000000\",\n \"codepipeline_use_github_v1\" => false,\n \"codepipeline_codebuild_run_in_vpc\" => false,\n \"codepipeline_codebuild_use_service_env\" => false,\n \"buildspec\" => \"buildspec.yml\",\n \"container_port\" => \"3100\",\n \"container_command\" => [\n \"/docker-entrypoint.sh\",\n \"rails\",\n \"server\"\n ],\n \"container_volumes\" => [\n {\n \"name\" => \"test-volume\",\n \"host_path\" => \"/mnt/test\",\n \"container_path\" => \"/test\"\n }\n ],\n \"container_extra_hosts\" => [\n {\n \"hostname\" => \"example.com\",\n \"ipAddress\" => \"127.0.0.1\"\n }\n ],\n \"container_count\" => \"2\",\n \"enable_max_one_container_per_instance\" => true,\n \"scheduled_tasks\" => [\n {\n \"name\" => \"old-scheduled-task\",\n \"command\" => [\n \"rake\",\n \"do:cron\"\n ],\n \"schedule_expression\" =>\n {\n \"production\" => \"cron(0 4 * * ? *)\",\n \"staging\" => \"cron(0 4 * * ? *)\"\n }\n },\n {\n \"name\" => \"test-scheduled-task\",\n \"command\" => [\n \"rake\",\n \"do:something\"\n ],\n \"schedule_expression\" => {\n \"staging\" => \"cron(0 12 * * ? *)\",\n \"production\" => \"cron(1 2 * * ? *)\"\n }\n }\n ],\n \"workers\" => [\n {\n \"name\" => \"test-worker\",\n \"command\" => [\n \"bundle\",\n \"exec\",\n \"sidekiq\"\n ]\n }\n ]\n }\n )\n )\n )\n end\n\n let(:cluster1_apply_cmd_staging_service) do\n terraform_apply_cmd(\n tfvar_arg_string(\n infrastructure_defaults.merge(\n \"instance_type\" => \"t2.small\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"track_revision\" => \"feature/experiment\",\n \"extra_ecs_clusters\" => [\n {\n \"name\" => \"test\",\n \"subnets_name\" => \"extra_private_subnets\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"instance_type\" => \"t3.small\"\n }\n ],\n \"tinyproxy\" => {\n \"create\" => true\n },\n \"environment\" => \"staging\",\n \"cluster_name\" => \"new-dedicated-cluster-staging\",\n \"account_id\" => \"123456789012\",\n \"infrastructure_name\" => \"new-dedicated-cluster\",\n \"dalmatian_role\" => \"dalmatian-admin\",\n \"service\" => {\n \"name\" => \"test-service\",\n \"blue_green\" => {\n \"production\" => {\n \"enabled\" => true,\n \"db_copy\" => {\n \"from_db_host_ps_key\" => \"/test-app/other-test-service/production/DB_HOST\",\n \"from_db_name_ps_key\" => \"/test-app/other-test-service/production/DB_NAME\",\n \"from_db_user_ps_key\" => \"/test-app/other-test-service/production/DB_USER\",\n \"from_db_pass_ps_key\" => \"/test-app/other-test-service/production/DB_PASSWORD\",\n \"blue_green_db_name_ps_key\" => \"/test-app/test-service/production/DB_HOST\",\n \"blue_green_db_user_ps_key\" => \"/test-app/test-service/production/DB_USER\",\n \"blue_green_db_pass_ps_key\" => \"/test-app/test-service/production/DB_PASSWORD\",\n \"sql_backups_s3_bucket\" => \"new-dedicated-cluster-testservice-production-sql-backup\"\n },\n \"db_rewrites\" => [\n {\n \"from\" => \"other-test-service.example.com\",\n \"to\" => \"test-service.example.com\"\n }\n ],\n \"directory_copy\" => [\n {\n \"from\" => \"/mnt/efs/other-test-service-media\",\n \"to\" => \"/mnt/efs/test-service-media\",\n \"chown\" => \"33:33\"\n }\n ],\n \"asset_copy_trigger_ps_key\" => \"/test-app/test-service/production/BLUE_GREEN_ASSET_COPY_TRIGGER\"\n },\n \"staging\" => {\n \"enabled\" => false\n }\n },\n \"launch_on\" => [\"production\", \"staging\"],\n \"launch_on_cluster\" => \"test\",\n \"cluster_min_servers\" => {\n \"production\" => \"2\",\n \"staging\" => \"2\"\n },\n \"parameter_store_path\" => {\n \"production\" => \"\",\n \"staging\" => \"/test-path\"\n },\n \"parameter_store_key\" => {\n \"production\" => \"\",\n \"staging\" => \"arn:aws:kms:eu-west-2:000000000000:key/00000000-0000-0000-0000-000000000000\"\n },\n \"daemon\" => false,\n \"monitoring\" => {\n \"production\" => {\n \"opsgenie_alerts\" => {\n \"enabled\" => true,\n \"cloudfront_5xx\" => {\n \"enabled\" => true,\n \"threshold\" => \"95\",\n \"evaluation_periods\" => \"15\"\n }\n },\n \"ghost_inspector\" => {\n \"enabled\" => true\n }\n },\n \"staging\" => {\n \"opsgenie_alerts\" => {\n \"enabled\" => false,\n \"cloudfront_5xx\" => {\n \"enabled\" => true,\n \"threshold\" => \"95\",\n \"evaluation_periods\" => \"15\"\n }\n },\n \"ghost_inspector\" => {\n \"enabled\" => false\n }\n }\n },\n \"cloudfront\" => {\n \"production\" => {\n \"create\" => true,\n \"managed_cache_policy\" => \"CachingDisabled\",\n \"managed_origin_policy\" => \"AllViewerExceptHostHeader\",\n \"managed_response_headers_policy\" => \"CORS-with-preflight-and-SecurityHeadersPolicy\",\n \"tls_protocol_version\" => \"TLSv1.2_2019\",\n \"origin_keepalive_timeout\" => \"60\",\n \"origin_read_timeout\" => \"60\",\n \"basic_auth\" => false,\n \"basic_auth_users_extra\" => {},\n \"viewer_request_functions\" => [\n {\n \"name\" => \"default\",\n \"true_client_ip_header\" => true,\n \"ip_subnet_allow_list\" => [\n \"0.0.0.0/0\"\n ],\n \"redirects\" => [\n {\n \"from_hostname_pattern\" => \"example-old-domain-name.*\",\n \"from_path_pattern\" => \"/*\",\n \"to_hostname\" => \"example-domain-name.co.uk\",\n \"to_path\" => \"/${path}\"\n }\n ]\n }\n ],\n \"offline_page_http_status\" => {\n \"500\" => \"/error-pages/500.html\",\n \"501\" => \"/error-pages/501.html\",\n \"502\" => \"/error-pages/502.html\",\n \"503\" => \"/error-pages/503.html\",\n \"504\" => \"/error-pages/504.html\"\n },\n \"custom_origins\" => [\n {\n \"origin\" => \"test-media-production.s3.amazonaws.com\",\n \"id\" => \"test-media-production-s3\"\n }\n ],\n \"bypass_protection\" => {\n \"enabled\" => true,\n \"exclude_domains\" => [\n \"example.com\"\n ]\n },\n \"custom_behaviors\" => [\n {\n \"target_origin_id\" => \"test-media-production-s3\",\n \"min_ttl\" => 1200,\n \"default_ttl\" => 3600,\n \"max_ttl\" => 86400,\n \"associate_viewer_request_function\" => \"default\",\n \"managed_cache_policy\" => \"CachingDisabled\",\n \"managed_origin_policy\" => \"AllViewerExceptHostHeader\",\n \"managed_response_headers_policy\" => \"CORS-with-preflight-and-SecurityHeadersPolicy\",\n \"path_pattern\" => \"/media/*\"\n }\n ]\n },\n \"staging\" => {\n \"create\" => true,\n \"managed_cache_policy\" => \"CachingDisabled\",\n \"managed_origin_policy\" => \"AllViewerExceptHostHeader\",\n \"managed_response_headers_policy\" => \"CORS-with-preflight-and-SecurityHeadersPolicy\",\n \"tls_protocol_version\" => \"TLSv1.2_2021\",\n \"origin_keepalive_timeout\" => \"10\",\n \"origin_read_timeout\" => \"40\",\n \"basic_auth\" => true,\n \"basic_auth_users_extra\" => {},\n \"viewer_request_functions\" => [\n {\n \"name\" => \"default\",\n \"true_client_ip_header\" => true,\n \"ip_subnet_allow_list\" => [\n \"0.0.0.0/0\"\n ],\n \"redirects\" => [\n {\n \"from_hostname_pattern\" => \"example-old-domain-name.*\",\n \"from_path_pattern\" => \"/*\",\n \"to_hostname\" => \"example-domain-name.co.uk\",\n \"to_path\" => \"/${path}\"\n }\n ]\n }\n ],\n \"offline_page_http_status\" => {\n \"500\" => \"/error-pages/500.html\",\n \"501\" => \"/error-pages/501.html\",\n \"502\" => \"/error-pages/502.html\",\n \"503\" => \"/error-pages/503.html\",\n \"504\" => \"/error-pages/504.html\"\n },\n \"custom_origins\" => [\n {\n \"origin\" => \"test-media-staging.s3.amazonaws.com\",\n \"id\" => \"test-media-staging-s3\"\n }\n ],\n \"bypass_protection\" => {\n \"enabled\" => false,\n \"exclude_domains\" => []\n },\n \"custom_behaviors\" => [\n {\n \"target_origin_id\" => \"test-media-staging-s3\",\n \"min_ttl\" => 1200,\n \"default_ttl\" => 3600,\n \"max_ttl\" => 86400,\n \"associate_viewer_request_function\" => \"default\",\n \"managed_cache_policy\" => \"\",\n \"managed_origin_policy\" => \"\",\n \"managed_response_headers_policy\" => \"\",\n \"path_pattern\" => \"/media/*\"\n }\n ]\n }\n },\n \"s3_policy\" => {\n \"production\" => {},\n \"staging\" => {\n \"rw\" => [\n \"test\"\n ]\n }\n },\n \"shared_loadbalancer_name\" => \"test-lb-1\",\n \"lb_ip_whitelist\" => [\n {\n \"name\" => \"public\",\n \"cidr\" => \"0.0.0.0/0\"\n }\n ],\n \"lb_idle_timeout\" => \"60\",\n \"global_accelerator\" => {\n \"production\" => true,\n \"staging\" => false\n },\n \"health_check_path\" => \"/check\",\n \"health_check_grace_period\" => \"0\",\n \"deregistration_delay\" => \"60\",\n \"serve_from_subdirectory\" => \"/test-subdir\",\n \"domain_names\" => {\n \"production\" => [],\n \"staging\" => [\n \"example-domain-name.co.uk\"\n ]\n },\n \"proxy_configuration\" => {\n \"production\" => {},\n \"staging\" => {\n \"https_proxy\" => \"dalmatian_tinyproxy\",\n \"http_proxy\" => \"http://my.test-proxy.com:8888\",\n \"no_proxy\" => [\n \"*.example.com\",\n \"93.184.216.34/32\"\n ]\n }\n },\n \"home_directory\" => \"/home/user\",\n \"lb_ssl_certificate\" => {\n \"production\" => \"\",\n \"staging\" => \"arn:aws:acm:lb-region-0:000000000000:certificate/00000000-0000-0000-0000-000000000000\"\n },\n \"lb_ssl_policy\" => {\n \"production\" => \"ELBSecurityPolicy-TLS-1-2-2017-01\",\n \"staging\" => \"ELBSecurityPolicy-TLS-1-2-2017-01\"\n },\n \"cloudfront_ssl_certificate\" => {\n \"production\" => \"\",\n \"staging\" => \"arn:aws:acm:us-east-1:000000000000:certificate/00000000-0000-0000-0000-000000000000\"\n },\n \"image_source\" => \"build_from_github_repo\",\n \"image_location\" => \"git@github.com:dxw/dalmatian-test-app\",\n \"track_revision\" => {\n \"production\" => \"\",\n \"staging\" => \"\"\n },\n \"custom_codestar_connection_arn\" => \"arn:aws:codestar-connections:eu-west-2:000000000000:connection/00000000-0000-0000-0000-000000000000\",\n \"codepipeline_use_github_v1\" => false,\n \"codepipeline_codebuild_run_in_vpc\" => false,\n \"codepipeline_codebuild_use_service_env\" => false,\n \"buildspec\" => \"buildspec.yml\",\n \"container_port\" => \"3100\",\n \"container_command\" => [\n \"/docker-entrypoint.sh\",\n \"rails\",\n \"server\"\n ],\n \"container_volumes\" => [\n {\n \"name\" => \"test-volume\",\n \"host_path\" => \"/mnt/test\",\n \"container_path\" => \"/test\"\n }\n ],\n \"container_extra_hosts\" => [\n {\n \"hostname\" => \"example.com\",\n \"ipAddress\" => \"127.0.0.1\"\n }\n ],\n \"container_count\" => \"2\",\n \"enable_max_one_container_per_instance\" => true,\n \"scheduled_tasks\" => [\n {\n \"name\" => \"old-scheduled-task\",\n \"command\" => [\n \"rake\",\n \"do:cron\"\n ],\n \"schedule_expression\" =>\n {\n \"production\" => \"cron(0 4 * * ? *)\",\n \"staging\" => \"cron(0 4 * * ? *)\"\n }\n },\n {\n \"name\" => \"test-scheduled-task\",\n \"command\" => [\n \"rake\",\n \"do:something\"\n ],\n \"schedule_expression\" => {\n \"staging\" => \"cron(0 12 * * ? *)\",\n \"production\" => \"cron(1 2 * * ? *)\"\n }\n }\n ],\n \"workers\" => [\n {\n \"name\" => \"test-worker\",\n \"command\" => [\n \"bundle\",\n \"exec\",\n \"sidekiq\"\n ]\n }\n ]\n }\n )\n )\n )\n end\n\n let(:cluster1_apply_cmd_production_shared_loadbalancer) do\n terraform_apply_cmd(\n tfvar_arg_string(\n infrastructure_defaults.merge(\n \"instance_type\" => \"t2.medium\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"environment\" => \"production\",\n \"account_id\" => \"123456789012\",\n \"infrastructure_name\" => \"new-dedicated-cluster\",\n \"dalmatian_role\" => \"dalmatian-admin\",\n \"shared_loadbalancer\" => {\n \"name\" => \"test-lb-1\",\n \"in_use_by\" => [\n \"test-service\"\n ],\n \"clusters_in_use\" => {\n \"production\" => [\n \"test\"\n ],\n \"staging\" => [\n \"test\"\n ]\n },\n \"subnets_name\" => \"\",\n \"domain_names\" => {\n \"test-service\" => {\n \"production\" => [],\n \"staging\" => [\n \"example-domain-name.co.uk\"\n ]\n }\n },\n \"internal\" => false,\n \"ip_whitelist\" => [\n {\n \"name\" => \"public\",\n \"cidr\" => \"0.0.0.0/0\"\n }\n ],\n \"idle_timeout\" => \"60\",\n \"global_accelerator\" => {\n \"production\" => true,\n \"staging\" => false\n },\n \"ssl_policy\" => \"ELBSecurityPolicy-TLS-1-2-2017-01\"\n }\n )\n )\n )\n end\n\n let(:cluster1_apply_cmd_staging_shared_loadbalancer) do\n terraform_apply_cmd(\n tfvar_arg_string(\n infrastructure_defaults.merge(\n \"instance_type\" => \"t2.small\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"track_revision\" => \"feature/experiment\",\n \"extra_ecs_clusters\" => [\n {\n \"name\" => \"test\",\n \"subnets_name\" => \"extra_private_subnets\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"instance_type\" => \"t3.small\"\n }\n ],\n \"tinyproxy\" => {\n \"create\" => true\n },\n \"environment\" => \"staging\",\n \"account_id\" => \"123456789012\",\n \"infrastructure_name\" => \"new-dedicated-cluster\",\n \"dalmatian_role\" => \"dalmatian-admin\",\n \"shared_loadbalancer\" => {\n \"name\" => \"test-lb-1\",\n \"in_use_by\" => [\n \"test-service\"\n ],\n \"clusters_in_use\" => {\n \"production\" => [\n \"test\"\n ],\n \"staging\" => [\n \"test\"\n ]\n },\n \"subnets_name\" => \"\",\n \"domain_names\" => {\n \"test-service\" => {\n \"production\" => [],\n \"staging\" => [\n \"example-domain-name.co.uk\"\n ]\n }\n },\n \"internal\" => false,\n \"ip_whitelist\" => [\n {\n \"name\" => \"public\",\n \"cidr\" => \"0.0.0.0/0\"\n }\n ],\n \"idle_timeout\" => \"60\",\n \"global_accelerator\" => {\n \"production\" => true,\n \"staging\" => false\n },\n \"ssl_policy\" => \"ELBSecurityPolicy-TLS-1-2-2017-01\"\n }\n )\n )\n )\n end\n\n let(:cluster2_apply_cmd_production) do\n terraform_apply_cmd(\n tfvar_arg_string(\n infrastructure_defaults.merge(\n \"instance_type\" => \"t2.medium\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"10\",\n \"environment\" => \"production\",\n \"cluster_name\" => \"shared-new-cluster-production\",\n \"account_id\" => \"123456789012\",\n \"infrastructure_name\" => \"shared-new-cluster\",\n \"dalmatian_role\" => \"dalmatian-admin\"\n )\n )\n )\n end\n\n let(:cluster2_apply_cmd_staging) do\n terraform_apply_cmd(\n tfvar_arg_string(\n infrastructure_defaults.merge(\n \"instance_type\" => \"t2.small\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"10\",\n \"environment\" => \"staging\",\n \"cluster_name\" => \"shared-new-cluster-staging\",\n \"account_id\" => \"123456789012\",\n \"infrastructure_name\" => \"shared-new-cluster\",\n \"dalmatian_role\" => \"dalmatian-admin\"\n )\n )\n )\n end\n\n let(:cluster3_apply_cmd_staging) do\n terraform_apply_cmd(\n tfvar_arg_string(\n infrastructure_defaults.merge(\n \"example_var\" => \"foo\",\n \"environment\" => \"staging\",\n \"cluster_name\" => \"shared-cluster-staging\",\n \"account_id\" => \"123456789012\",\n \"infrastructure_name\" => \"existing-shared-cluster-staging\",\n \"dalmatian_role\" => \"dalmatian-admin\"\n )\n )\n )\n end\n\n let(:cluster4_apply_cmd_production) do\n terraform_apply_cmd(\n tfvar_arg_string(\n infrastructure_defaults.merge(\n \"example_var\" => \"bar\",\n \"environment\" => \"production\",\n \"cluster_name\" => \"shared-cluster-production\",\n \"account_id\" => \"123456789012\",\n \"infrastructure_name\" => \"existing-shared-cluster-production\",\n \"dalmatian_role\" => \"dalmatian-admin\"\n )\n )\n )\n end\n\n before do\n allow(Logger).to receive(:info)\n stub_git_checkout\n stub_workspace_creation_cmds\n\n allow(Helper).to receive(:run!).with(cluster1_apply_cmd_hz)\n\n allow(Helper).to receive(:run!).with(cluster1_apply_cmd_s3)\n\n allow(Helper).to receive(:run!).with(cluster1_apply_cmd_vpn_cg)\n\n allow(Helper).to receive(:run!).with(cluster1_apply_cmd_production)\n allow(Helper).to receive(:run!).with(cluster1_apply_cmd_staging)\n\n allow(Helper).to receive(:run!).with(cluster1_apply_cmd_production_waf)\n allow(Helper).to receive(:run!).with(cluster1_apply_cmd_staging_waf)\n\n allow(Helper).to receive(:run!).with(cluster1_apply_cmd_production_rds)\n allow(Helper).to receive(:run!).with(cluster1_apply_cmd_staging_rds)\n\n allow(Helper).to receive(:run!).with(cluster1_apply_cmd_production_elasticache_cluster)\n allow(Helper).to receive(:run!).with(cluster1_apply_cmd_staging_elasticache_cluster)\n\n allow(Helper).to receive(:run!).with(cluster1_apply_cmd_production_opensearch_cluster)\n allow(Helper).to receive(:run!).with(cluster1_apply_cmd_staging_opensearch_cluster)\n\n allow(Helper).to receive(:run!).with(cluster1_apply_cmd_production_service)\n allow(Helper).to receive(:run!).with(cluster1_apply_cmd_staging_service)\n\n allow(Helper).to receive(:run!).with(cluster1_apply_cmd_production_shared_loadbalancer)\n allow(Helper).to receive(:run!).with(cluster1_apply_cmd_staging_shared_loadbalancer)\n\n allow(Helper).to receive(:run!).with(cluster2_apply_cmd_production)\n allow(Helper).to receive(:run!).with(cluster2_apply_cmd_staging)\n\n allow(Helper).to receive(:run!).with(cluster3_apply_cmd_staging)\n\n allow(Helper).to receive(:run!).with(cluster4_apply_cmd_production)\n\n Infrastructure.new(\n ConfigurationReader.new(path: \"./dalmatian.yml.example\", parameter_store: fake_parameter_store).infrastructures\n ).deploy(auto_approve: false, plan: false)\n end\n\n describe 'use of \"terraform apply\"' do\n it 'passes the hosted zone config to \"terraform apply\"' do\n expect(Helper).to have_received(:run!).with(cluster1_apply_cmd_hz)\n end\n\n it 'passes the s3 config to \"terraform apply\"' do\n expect(Helper).to have_received(:run!).with(cluster1_apply_cmd_s3)\n end\n\n it 'passes the vpn customer gateway config to \"terraform apply\"' do\n expect(Helper).to have_received(:run!).with(cluster1_apply_cmd_vpn_cg)\n end\n\n it 'passes the base config to \"terraform apply\"' do\n expect(Helper).to have_received(:run!).with(cluster1_apply_cmd_production).twice\n expect(Helper).to have_received(:run!).with(cluster1_apply_cmd_staging).twice\n end\n\n it 'passes the waf config to \"terraform apply\"' do\n aggregate_failures do\n expect(Helper).to have_received(:run!).with(cluster1_apply_cmd_production_waf)\n expect(Helper).to have_received(:run!).with(cluster1_apply_cmd_staging_waf)\n end\n end\n\n it 'passes the rds config to \"terraform apply\"' do\n aggregate_failures do\n expect(Helper).to have_received(:run!).with(cluster1_apply_cmd_production_rds)\n expect(Helper).to have_received(:run!).with(cluster1_apply_cmd_staging_rds)\n end\n end\n\n it 'passes the elasticache config to \"terraform apply\"' do\n aggregate_failures do\n expect(Helper).to have_received(:run!)\n .with(cluster1_apply_cmd_production_elasticache_cluster)\n expect(Helper).to have_received(:run!)\n .with(cluster1_apply_cmd_staging_elasticache_cluster)\n end\n end\n\n it 'passes the opensearch config to \"terraform apply\"' do\n aggregate_failures do\n expect(Helper).to have_received(:run!)\n .with(cluster1_apply_cmd_production_opensearch_cluster)\n expect(Helper).to have_received(:run!)\n .with(cluster1_apply_cmd_staging_opensearch_cluster)\n end\n end\n\n it 'passes the service config to \"terraform apply\"' do\n aggregate_failures do\n expect(Helper).to have_received(:run!).with(cluster1_apply_cmd_production_service)\n expect(Helper).to have_received(:run!).with(cluster1_apply_cmd_staging_service)\n end\n end\n\n it 'passes the loadbalancer config to \"terraform apply\"' do\n aggregate_failures do\n expect(Helper).to have_received(:run!)\n .with(cluster1_apply_cmd_production_shared_loadbalancer)\n expect(Helper).to have_received(:run!)\n .with(cluster1_apply_cmd_staging_shared_loadbalancer)\n end\n end\n\n it 'passes the cluster 2 config to \"terraform apply\"' do\n aggregate_failures do\n expect(Helper).to have_received(:run!).with(cluster2_apply_cmd_production)\n expect(Helper).to have_received(:run!).with(cluster2_apply_cmd_staging)\n end\n end\n\n it 'passes the cluster 3 config to \"terraform apply\"' do\n expect(Helper).to have_received(:run!).with(cluster3_apply_cmd_staging)\n end\n\n it 'passes the cluster 4 config to \"terraform apply\"' do\n expect(Helper).to have_received(:run!).with(cluster4_apply_cmd_production)\n end\n end\n end\nend\n",
|
|
"newContent": "require_relative \"../support/spec_helper\"\n\nmodule Dalmatian\n RSpec.describe \"tests local configuration\" do\n def fake_parameter_store\n double(\n \"parameter_store\",\n get_parameter: \"\",\n get_parameters_by_path: {}\n )\n end\n\n def tfvar_arg_string(tfvars)\n Terraform.tfvar_arg_string(tfvars)\n end\n\n def terraform_apply_cmd(tfvar_string)\n \"#{tfvar_string} terraform apply\"\n end\n\n def stub_git_checkout\n allow(Helper).to receive(:run!).with(\"git checkout feature/experiment\")\n end\n\n def stub_workspace_creation_cmds\n %w[\n new-dedicated-cluster-example-domain-name-com-hz\n new-dedicated-cluster-test-s3\n new-dedicated-cluster-test-vpn-vpn-cg\n new-dedicated-cluster-ecs-production\n new-dedicated-cluster-ecs-staging\n new-dedicated-cluster-0-production\n new-dedicated-cluster-0-staging\n new-dedicated-cluster-test-service-production\n new-dedicated-cluster-test-service-staging\n new-dedicated-cluster-test-1-waf-staging\n new-dedicated-cluster-test-1-waf-production\n new-dedicated-cluster-testservice-rds-staging\n new-dedicated-cluster-testservice-rds-production\n new-dedicated-cluster-testredis-elasticache-cluster-staging\n new-dedicated-cluster-testredis-elasticache-cluster-production\n new-dedicated-cluster-testos-opensearch-cluster-staging\n new-dedicated-cluster-testos-opensearch-cluster-production\n new-dedicated-cluster-test-lb-1-shared-loadbalancer-staging\n new-dedicated-cluster-test-lb-1-shared-loadbalancer-production\n shared-new-cluster-ecs-production\n shared-new-cluster-ecs-staging\n existing-shared-cluster-staging-0-staging\n existing-shared-cluster-production-0-production\n ].each do |workspace_name|\n allow(Helper).to receive(:run!).with(\"terraform workspace new #{workspace_name}\")\n end\n end\n\n def infrastructure_defaults\n {\n \"region\" => \"eu-west-2\",\n \"cidr\" => \"10.0.0.0/16\",\n \"root_domain_zone\" => \"dalmatian.dxw.net\",\n \"internal_domain_zone\" => \"dalmatian.internal\",\n \"ecs_private_subnets\" => [\n {\n \"availability_zone\" => \"eu-west-2a\",\n \"cidr\" => \"10.0.128.0/24\"\n },\n {\n \"availability_zone\" => \"eu-west-2b\",\n \"cidr\" => \"10.0.129.0/24\"\n },\n {\n \"availability_zone\" => \"eu-west-2c\",\n \"cidr\" => \"10.0.130.0/24\"\n }\n ],\n \"extra_public_subnets\" => [\n {\n \"availability_zone\" => \"eu-west-2a\",\n \"cidr\" => \"10.0.0.0/24\"\n },\n {\n \"availability_zone\" => \"eu-west-2b\",\n \"cidr\" => \"10.0.1.0/24\"\n },\n {\n \"availability_zone\" => \"eu-west-2c\",\n \"cidr\" => \"10.0.2.0/24\"\n }\n ],\n \"instances_key_name\" => \"dalmatian-ecs-instances\",\n \"instance_type\" => \"t2.medium\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"max_instance_lifetime\" => \"86400\",\n \"associate_public_ip_address\" => \"0\",\n \"docker_storage_size\" => \"40\",\n \"dockerhub_email\" => \"\",\n \"dockerhub_token\" => \"\",\n \"enable_efs\" => \"false\",\n \"encrypt_efs\" => \"true\",\n \"efs_dirs\" => [],\n \"monitoring_docs_path\" => \"https://github.com/dxw/dalmatian/docs/monitoring-alarms/\"\n }\n end\n\n let(:cluster1_apply_cmd_hz) do\n terraform_apply_cmd(\n tfvar_arg_string(\n \"account_id\" => \"123456789012\",\n \"cluster_id\" => \"new-dedicated-cluster\",\n \"dalmatian_role\" => \"dalmatian-admin\",\n \"hosted_zone\" => {\n \"domain\" => \"example-domain-name.com\",\n \"ns_records\" => [\n {\n \"name\" => \"delegated\",\n \"value\" => [\n \"ns1.aws.com\"\n ]\n }\n ],\n \"a_records\" => [\n {\n \"name\" => \"some-service\",\n \"value\" => [\n \"1.2.3.4\"\n ]\n },\n {\n \"name\" => \"mail\",\n \"value\" => [\n \"5.6.7.8\"\n ]\n }\n ],\n \"alias_records\" => [\n {\n \"name\" => \"example-domain-name.com\",\n \"value\" => \"cf-distribution.aws.net\"\n },\n {\n \"name\" => \"www\",\n \"value\" => \"cf-distribution.aws.net\"\n }\n ],\n \"cname_records\" => [\n {\n \"name\" => \"alb\",\n \"value\" => [\n \"aws-alb.aws.net\"\n ]\n }\n ],\n \"mx_records\" => [\n {\n \"name\" => \"mail\",\n \"value\" => [\n \"0 mail.example-domain-name.com\"\n ]\n }\n ],\n \"txt_records\" => [\n {\n \"name\" => \"mail\",\n \"value\" => [\n \"v=spf1 a ip4:9.10.11.0/24 mx ~all\"\n ]\n }\n ],\n \"srv_records\" => [\n {\n \"name\" => \"@\",\n \"value\" => [\n \"_imaps._tcp.gmail.com. 86400 IN SRV 5 0 993 imap.gmail.com\"\n ]\n }\n ]\n }\n )\n )\n end\n\n let(:cluster1_apply_cmd_s3) do\n terraform_apply_cmd(\n tfvar_arg_string(\n \"account_id\" => \"123456789012\",\n \"cluster_id\" => \"new-dedicated-cluster\",\n \"dalmatian_role\" => \"dalmatian-admin\",\n \"s3\" => {\n \"name\" => \"test\",\n \"enable_s3_versioning\" => true,\n \"encrypted\" => true,\n \"acl\" => \"private\",\n \"policy\" => {\n \"staging\" => {\n \"rw\" => {\n \"services\" => [\n \"test-service\"\n ]\n }\n }\n },\n \"service_cloudfront_read_access\" => [\n \"test-service-staging\"\n ],\n \"cloudfront\" => {\n \"create\" => true,\n \"domain_names\" => [\n \"example.com\",\n \"example2.com\"\n ],\n \"certificate\" => \"arn:aws:acm:lb-region-0:000000000000:certificate/00000000-0000-0000-0000-000000000000\"\n }\n }\n )\n )\n end\n\n let(:cluster1_apply_cmd_vpn_cg) do\n terraform_apply_cmd(\n tfvar_arg_string(\n \"account_id\" => \"123456789012\",\n \"cluster_id\" => \"new-dedicated-cluster\",\n \"dalmatian_role\" => \"dalmatian-admin\",\n \"vpn_customer_gateway\" => {\n \"name\" => \"test-vpn\",\n \"bgp_asn\" => 65000,\n \"ip_address\" => \"1.2.3.4\"\n }\n )\n )\n end\n\n let(:cluster1_apply_cmd_production) do\n terraform_apply_cmd(\n tfvar_arg_string(\n infrastructure_defaults.merge(\n \"instance_type\" => \"t2.medium\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"environment\" => \"production\",\n \"cluster_name\" => \"new-dedicated-cluster-production\",\n \"account_id\" => \"123456789012\",\n \"infrastructure_name\" => \"new-dedicated-cluster\",\n \"dalmatian_role\" => \"dalmatian-admin\"\n )\n )\n )\n end\n\n let(:cluster1_apply_cmd_staging) do\n terraform_apply_cmd(\n tfvar_arg_string(\n infrastructure_defaults.merge(\n \"instance_type\" => \"t2.small\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"track_revision\" => \"feature/experiment\",\n \"extra_ecs_clusters\" => [\n {\n \"name\" => \"test\",\n \"subnets_name\" => \"extra_private_subnets\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"instance_type\" => \"t3.small\"\n }\n ],\n \"tinyproxy\" => {\n \"create\" => true\n },\n \"environment\" => \"staging\",\n \"cluster_name\" => \"new-dedicated-cluster-staging\",\n \"account_id\" => \"123456789012\",\n \"infrastructure_name\" => \"new-dedicated-cluster\",\n \"dalmatian_role\" => \"dalmatian-admin\"\n )\n )\n )\n end\n\n let(:cluster1_apply_cmd_production_waf) do\n terraform_apply_cmd(\n tfvar_arg_string(\n infrastructure_defaults.merge(\n \"instance_type\" => \"t2.medium\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"environment\" => \"production\",\n \"account_id\" => \"123456789012\",\n \"infrastructure_name\" => \"new-dedicated-cluster\",\n \"dalmatian_role\" => \"dalmatian-admin\",\n \"waf\" => {\n \"name\" => \"test-1\",\n \"action\" => \"count\",\n \"ip_deny_list\" => [],\n \"aws_managed_rules\" => [\n {\n \"name\" => \"AWSManagedRulesSQLiRuleSet\",\n \"excluded_path_patterns\" => [\n \"/wp-admin/async-upload.php\"\n ]\n },\n {\n \"name\" => \"AWSManagedRulesCommonRuleSet\",\n \"exclude_rules\" => [\n \"SizeRestrictions_BODY\"\n ]\n }\n ],\n \"associations\" => {\n shared_loadbalancers: [\n \"test-lb-1\"\n ],\n service_cloudfront: [\n \"test-service\"\n ]\n }\n }\n )\n )\n )\n end\n\n let(:cluster1_apply_cmd_staging_waf) do\n terraform_apply_cmd(\n tfvar_arg_string(\n infrastructure_defaults.merge(\n \"instance_type\" => \"t2.small\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"track_revision\" => \"feature/experiment\",\n \"extra_ecs_clusters\" => [\n {\n \"name\" => \"test\",\n \"subnets_name\" => \"extra_private_subnets\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"instance_type\" => \"t3.small\"\n }\n ],\n \"tinyproxy\" => {\n \"create\" => true\n },\n \"environment\" => \"staging\",\n \"account_id\" => \"123456789012\",\n \"infrastructure_name\" => \"new-dedicated-cluster\",\n \"dalmatian_role\" => \"dalmatian-admin\",\n \"waf\" => {\n \"name\" => \"test-1\",\n \"action\" => \"count\",\n \"ip_deny_list\" => [],\n \"aws_managed_rules\" => [\n {\n \"name\" => \"AWSManagedRulesSQLiRuleSet\",\n \"excluded_path_patterns\" => [\n \"/wp-admin/async-upload.php\"\n ]\n },\n {\n \"name\" => \"AWSManagedRulesCommonRuleSet\",\n \"exclude_rules\" => [\n \"SizeRestrictions_BODY\"\n ]\n }\n ],\n \"associations\" => {\n shared_loadbalancers: [\n \"test-lb-1\"\n ],\n service_cloudfront: [\n \"test-service\"\n ]\n }\n }\n )\n )\n )\n end\n\n let(:cluster1_apply_cmd_production_rds) do\n terraform_apply_cmd(\n tfvar_arg_string(\n infrastructure_defaults.merge(\n \"instance_type\" => \"t2.medium\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"environment\" => \"production\",\n \"account_id\" => \"123456789012\",\n \"infrastructure_name\" => \"new-dedicated-cluster\",\n \"dalmatian_role\" => \"dalmatian-admin\",\n \"rds\" => {\n \"identifier\" => \"testservice\",\n \"in_use_by\" => [\n \"test-service\"\n ],\n \"clusters_in_use\" => {\n \"production\" => [\n \"test\"\n ],\n \"staging\" => [\n \"test\"\n ]\n },\n \"instance_class\" => {\n \"production\" => \"db.t2.small\",\n \"staging\" => \"db.t2.micro\"\n },\n \"engine\" => \"postgres\",\n \"engine_version\" => \"11.4\",\n \"allocated_storage\" => 20,\n \"storage_encrypted\" => true,\n \"storage_type\" => \"gp3\",\n \"db_name\" => \"testapp\",\n \"port\" => 5432,\n \"maintenance_window\" => \"mon:19:00-mon:19:30\",\n \"backup_window\" => \"09:00-10:00\",\n \"backup_retention_period\" => 31,\n \"force_ssl\" => true,\n \"parameter_store_path_db_url_name\" => \"DATABASE_URL\",\n \"sql_backup_scheduled_task_environment_variables\" => [\n {\n \"name\" => \"foo\",\n \"value\" => \"bar\"\n }\n ],\n \"check_sql_backup_scheduled_task_environment_variables\" => [\n {\n \"name\" => \"foo\",\n \"value\" => \"bar\"\n }\n ],\n \"sync_sql_backup_to_azure\" => false,\n \"replication_bucket_destination_arn\" => \"\",\n \"replication_kms_key_id\" => \"\",\n \"codebuild_access\" => [\n \"service-name\"\n ]\n }\n )\n )\n )\n end\n\n let(:cluster1_apply_cmd_staging_rds) do\n terraform_apply_cmd(\n tfvar_arg_string(\n infrastructure_defaults.merge(\n \"instance_type\" => \"t2.small\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"track_revision\" => \"feature/experiment\",\n \"extra_ecs_clusters\" => [\n {\n \"name\" => \"test\",\n \"subnets_name\" => \"extra_private_subnets\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"instance_type\" => \"t3.small\"\n }\n ],\n \"tinyproxy\" => {\n \"create\" => true\n },\n \"environment\" => \"staging\",\n \"account_id\" => \"123456789012\",\n \"infrastructure_name\" => \"new-dedicated-cluster\",\n \"dalmatian_role\" => \"dalmatian-admin\",\n \"rds\" => {\n \"identifier\" => \"testservice\",\n \"in_use_by\" => [\n \"test-service\"\n ],\n \"clusters_in_use\" => {\n \"production\" => [\n \"test\"\n ],\n \"staging\" => [\n \"test\"\n ]\n },\n \"instance_class\" => {\n \"production\" => \"db.t2.small\",\n \"staging\" => \"db.t2.micro\"\n },\n \"engine\" => \"postgres\",\n \"engine_version\" => \"11.4\",\n \"allocated_storage\" => 20,\n \"storage_encrypted\" => true,\n \"storage_type\" => \"gp3\",\n \"db_name\" => \"testapp\",\n \"port\" => 5432,\n \"maintenance_window\" => \"mon:19:00-mon:19:30\",\n \"backup_window\" => \"09:00-10:00\",\n \"backup_retention_period\" => 31,\n \"force_ssl\" => true,\n \"parameter_store_path_db_url_name\" => \"DATABASE_URL\",\n \"sql_backup_scheduled_task_environment_variables\" => [\n {\n \"name\" => \"foo\",\n \"value\" => \"bar\"\n }\n ],\n \"check_sql_backup_scheduled_task_environment_variables\" => [\n {\n \"name\" => \"foo\",\n \"value\" => \"bar\"\n }\n ],\n \"sync_sql_backup_to_azure\" => false,\n \"replication_bucket_destination_arn\" => \"\",\n \"replication_kms_key_id\" => \"\",\n \"codebuild_access\" => [\n \"service-name\"\n ]\n }\n )\n )\n )\n end\n\n let(:cluster1_apply_cmd_production_elasticache_cluster) do\n terraform_apply_cmd(\n tfvar_arg_string(\n infrastructure_defaults.merge(\n \"instance_type\" => \"t2.medium\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"environment\" => \"production\",\n \"account_id\" => \"123456789012\",\n \"infrastructure_name\" => \"new-dedicated-cluster\",\n \"dalmatian_role\" => \"dalmatian-admin\",\n \"elasticache_cluster\" => {\n \"identifier\" => \"testredis\",\n \"in_use_by\" => [\n \"test-service\"\n ],\n \"node_type\" => \"cache.t2.micro\",\n \"node_count\" => 1,\n \"engine\" => \"redis\",\n \"engine_version\" => \"5.0.6\",\n \"parameters\" => [],\n \"port\" => 6379,\n \"maintenance_window\" => \"mon:19:00-mon:22:00\",\n \"snapshot_window\" => \"09:00-10:00\",\n \"parameter_store_path_elasticache_cluster_url_name\" => \"REDIS_URL\"\n }\n )\n )\n )\n end\n\n let(:cluster1_apply_cmd_staging_elasticache_cluster) do\n terraform_apply_cmd(\n tfvar_arg_string(\n infrastructure_defaults.merge(\n \"instance_type\" => \"t2.small\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"track_revision\" => \"feature/experiment\",\n \"extra_ecs_clusters\" => [\n {\n \"name\" => \"test\",\n \"subnets_name\" => \"extra_private_subnets\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"instance_type\" => \"t3.small\"\n }\n ],\n \"tinyproxy\" => {\n \"create\" => true\n },\n \"environment\" => \"staging\",\n \"account_id\" => \"123456789012\",\n \"infrastructure_name\" => \"new-dedicated-cluster\",\n \"dalmatian_role\" => \"dalmatian-admin\",\n \"elasticache_cluster\" => {\n \"identifier\" => \"testredis\",\n \"in_use_by\" => [\n \"test-service\"\n ],\n \"node_type\" => \"cache.t2.micro\",\n \"node_count\" => 1,\n \"engine\" => \"redis\",\n \"engine_version\" => \"5.0.6\",\n \"parameters\" => [],\n \"port\" => 6379,\n \"maintenance_window\" => \"mon:19:00-mon:22:00\",\n \"snapshot_window\" => \"09:00-10:00\",\n \"parameter_store_path_elasticache_cluster_url_name\" => \"REDIS_URL\"\n }\n )\n )\n )\n end\n\n let(:cluster1_apply_cmd_production_opensearch_cluster) do\n terraform_apply_cmd(\n tfvar_arg_string(\n infrastructure_defaults.merge(\n \"instance_type\" => \"t2.medium\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"environment\" => \"production\",\n \"account_id\" => \"123456789012\",\n \"infrastructure_name\" => \"new-dedicated-cluster\",\n \"dalmatian_role\" => \"dalmatian-admin\",\n \"opensearch_cluster\" => {\n \"identifier\" => \"testos\",\n \"in_use_by\" => [\n \"test-service\"\n ],\n \"version\" => \"1.2\",\n \"master_enabled\" => true,\n \"master_count\" => \"1\",\n \"master_type\" => \"c6g.large.search\",\n \"instance_count\" => \"3\",\n \"instance_type\" => \"t3.small.search\",\n \"warm_enabled\" => true,\n \"warm_count\" => \"2\",\n \"warm_type\" => \"ultrawarm1.medium.search\",\n \"parameter_store_path_opensearch_cluster_url_name\" => \"ELASTICSEARCH_URL\",\n \"volume_size\" => \"20\"\n }\n )\n )\n )\n end\n\n let(:cluster1_apply_cmd_staging_opensearch_cluster) do\n terraform_apply_cmd(\n tfvar_arg_string(\n infrastructure_defaults.merge(\n \"instance_type\" => \"t2.small\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"track_revision\" => \"feature/experiment\",\n \"extra_ecs_clusters\" => [\n {\n \"name\" => \"test\",\n \"subnets_name\" => \"extra_private_subnets\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"instance_type\" => \"t3.small\"\n }\n ],\n \"tinyproxy\" => {\n \"create\" => true\n },\n \"environment\" => \"staging\",\n \"account_id\" => \"123456789012\",\n \"infrastructure_name\" => \"new-dedicated-cluster\",\n \"dalmatian_role\" => \"dalmatian-admin\",\n \"opensearch_cluster\" => {\n \"identifier\" => \"testos\",\n \"in_use_by\" => [\n \"test-service\"\n ],\n \"version\" => \"1.2\",\n \"master_enabled\" => true,\n \"master_count\" => \"1\",\n \"master_type\" => \"c6g.large.search\",\n \"instance_count\" => \"3\",\n \"instance_type\" => \"t3.small.search\",\n \"warm_enabled\" => true,\n \"warm_count\" => \"2\",\n \"warm_type\" => \"ultrawarm1.medium.search\",\n \"parameter_store_path_opensearch_cluster_url_name\" => \"ELASTICSEARCH_URL\",\n \"volume_size\" => \"20\"\n }\n )\n )\n )\n end\n\n let(:cluster1_apply_cmd_production_service) do\n terraform_apply_cmd(\n tfvar_arg_string(\n infrastructure_defaults.merge(\n \"instance_type\" => \"t2.medium\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"environment\" => \"production\",\n \"cluster_name\" => \"new-dedicated-cluster-production\",\n \"account_id\" => \"123456789012\",\n \"infrastructure_name\" => \"new-dedicated-cluster\",\n \"dalmatian_role\" => \"dalmatian-admin\",\n \"service\" => {\n \"name\" => \"test-service\",\n \"blue_green\" => {\n \"production\" => {\n \"enabled\" => true,\n \"db_copy\" => {\n \"from_db_host_ps_key\" => \"/test-app/other-test-service/production/DB_HOST\",\n \"from_db_name_ps_key\" => \"/test-app/other-test-service/production/DB_NAME\",\n \"from_db_user_ps_key\" => \"/test-app/other-test-service/production/DB_USER\",\n \"from_db_pass_ps_key\" => \"/test-app/other-test-service/production/DB_PASSWORD\",\n \"blue_green_db_name_ps_key\" => \"/test-app/test-service/production/DB_HOST\",\n \"blue_green_db_user_ps_key\" => \"/test-app/test-service/production/DB_USER\",\n \"blue_green_db_pass_ps_key\" => \"/test-app/test-service/production/DB_PASSWORD\",\n \"sql_backups_s3_bucket\" => \"new-dedicated-cluster-testservice-production-sql-backup\"\n },\n \"db_rewrites\" => [\n {\n \"from\" => \"other-test-service.example.com\",\n \"to\" => \"test-service.example.com\"\n }\n ],\n \"directory_copy\" => [\n {\n \"from\" => \"/mnt/efs/other-test-service-media\",\n \"to\" => \"/mnt/efs/test-service-media\",\n \"chown\" => \"33:33\"\n }\n ],\n \"asset_copy_trigger_ps_key\" => \"/test-app/test-service/production/BLUE_GREEN_ASSET_COPY_TRIGGER\"\n },\n \"staging\" => {\n \"enabled\" => false\n }\n },\n \"launch_on\" => [\"production\", \"staging\"],\n \"launch_on_cluster\" => \"test\",\n \"cluster_min_servers\" => {\n \"production\" => \"2\",\n \"staging\" => \"2\"\n },\n \"parameter_store_path\" => {\n \"production\" => \"\",\n \"staging\" => \"/test-path\"\n },\n \"parameter_store_key\" => {\n \"production\" => \"\",\n \"staging\" => \"arn:aws:kms:eu-west-2:000000000000:key/00000000-0000-0000-0000-000000000000\"\n },\n \"daemon\" => false,\n \"monitoring\" => {\n \"production\" => {\n \"opsgenie_alerts\" => {\n \"enabled\" => true,\n \"cloudfront_5xx\" => {\n \"enabled\" => true,\n \"threshold\" => \"95\",\n \"evaluation_periods\" => \"15\"\n }\n },\n \"ghost_inspector\" => {\n \"enabled\" => true\n }\n },\n \"staging\" => {\n \"opsgenie_alerts\" => {\n \"enabled\" => false,\n \"cloudfront_5xx\" => {\n \"enabled\" => true,\n \"threshold\" => \"95\",\n \"evaluation_periods\" => \"15\"\n }\n },\n \"ghost_inspector\" => {\n \"enabled\" => false\n }\n }\n },\n \"cloudfront\" => {\n \"production\" => {\n \"create\" => true,\n \"managed_cache_policy\" => \"CachingDisabled\",\n \"managed_origin_policy\" => \"AllViewerExceptHostHeader\",\n \"managed_response_headers_policy\" => \"CORS-with-preflight-and-SecurityHeadersPolicy\",\n \"tls_protocol_version\" => \"TLSv1.2_2019\",\n \"origin_keepalive_timeout\" => \"60\",\n \"origin_read_timeout\" => \"60\",\n \"basic_auth\" => false,\n \"basic_auth_users_extra\" => {},\n \"viewer_request_functions\" => [\n {\n \"name\" => \"default\",\n \"true_client_ip_header\" => true,\n \"ip_subnet_allow_list\" => [\n \"0.0.0.0/0\"\n ],\n \"redirects\" => [\n {\n \"from_hostname_pattern\" => \"example-old-domain-name.*\",\n \"from_path_pattern\" => \"/*\",\n \"to_hostname\" => \"example-domain-name.co.uk\",\n \"to_path\" => \"/${path}\"\n }\n ]\n }\n ],\n \"offline_page_http_status\" => {\n \"500\" => \"/error-pages/500.html\",\n \"501\" => \"/error-pages/501.html\",\n \"502\" => \"/error-pages/502.html\",\n \"503\" => \"/error-pages/503.html\",\n \"504\" => \"/error-pages/504.html\"\n },\n \"custom_origins\" => [\n {\n \"origin\" => \"test-media-production.s3.amazonaws.com\",\n \"id\" => \"test-media-production-s3\"\n }\n ],\n \"bypass_protection\" => {\n \"enabled\" => true,\n \"exclude_domains\" => [\n \"example.com\"\n ]\n },\n \"custom_behaviors\" => [\n {\n \"target_origin_id\" => \"test-media-production-s3\",\n \"min_ttl\" => 1200,\n \"default_ttl\" => 3600,\n \"max_ttl\" => 86400,\n \"associate_viewer_request_function\" => \"default\",\n \"managed_cache_policy\" => \"CachingDisabled\",\n \"managed_origin_policy\" => \"AllViewerExceptHostHeader\",\n \"managed_response_headers_policy\" => \"CORS-with-preflight-and-SecurityHeadersPolicy\",\n \"path_pattern\" => \"/media/*\"\n }\n ]\n },\n \"staging\" => {\n \"create\" => true,\n \"managed_cache_policy\" => \"CachingDisabled\",\n \"managed_origin_policy\" => \"AllViewerExceptHostHeader\",\n \"managed_response_headers_policy\" => \"CORS-with-preflight-and-SecurityHeadersPolicy\",\n \"tls_protocol_version\" => \"TLSv1.2_2021\",\n \"origin_keepalive_timeout\" => \"10\",\n \"origin_read_timeout\" => \"40\",\n \"basic_auth\" => true,\n \"basic_auth_users_extra\" => {},\n \"viewer_request_functions\" => [\n {\n \"name\" => \"default\",\n \"true_client_ip_header\" => true,\n \"ip_subnet_allow_list\" => [\n \"0.0.0.0/0\"\n ],\n \"redirects\" => [\n {\n \"from_hostname_pattern\" => \"example-old-domain-name.*\",\n \"from_path_pattern\" => \"/*\",\n \"to_hostname\" => \"example-domain-name.co.uk\",\n \"to_path\" => \"/${path}\"\n }\n ]\n }\n ],\n \"offline_page_http_status\" => {\n \"500\" => \"/error-pages/500.html\",\n \"501\" => \"/error-pages/501.html\",\n \"502\" => \"/error-pages/502.html\",\n \"503\" => \"/error-pages/503.html\",\n \"504\" => \"/error-pages/504.html\"\n },\n \"custom_origins\" => [\n {\n \"origin\" => \"test-media-staging.s3.amazonaws.com\",\n \"id\" => \"test-media-staging-s3\"\n }\n ],\n \"bypass_protection\" => {\n \"enabled\" => false,\n \"exclude_domains\" => []\n },\n \"custom_behaviors\" => [\n {\n \"target_origin_id\" => \"test-media-staging-s3\",\n \"min_ttl\" => 1200,\n \"default_ttl\" => 3600,\n \"max_ttl\" => 86400,\n \"associate_viewer_request_function\" => \"default\",\n \"managed_cache_policy\" => \"\",\n \"managed_origin_policy\" => \"\",\n \"managed_response_headers_policy\" => \"\",\n \"path_pattern\" => \"/media/*\"\n }\n ]\n }\n },\n \"s3_policy\" => {\n \"production\" => {},\n \"staging\" => {\n \"rw\" => [\n \"test\"\n ]\n }\n },\n \"shared_loadbalancer_name\" => \"test-lb-1\",\n \"lb_ip_whitelist\" => [\n {\n \"name\" => \"public\",\n \"cidr\" => \"0.0.0.0/0\"\n }\n ],\n \"lb_idle_timeout\" => \"60\",\n \"global_accelerator\" => {\n \"production\" => true,\n \"staging\" => false\n },\n \"health_check_path\" => \"/check\",\n \"health_check_grace_period\" => \"0\",\n \"deregistration_delay\" => \"60\",\n \"serve_from_subdirectory\" => \"/test-subdir\",\n \"domain_names\" => {\n \"production\" => [],\n \"staging\" => [\n \"example-domain-name.co.uk\"\n ]\n },\n \"proxy_configuration\" => {\n \"production\" => {},\n \"staging\" => {\n \"https_proxy\" => \"dalmatian_tinyproxy\",\n \"http_proxy\" => \"http://my.test-proxy.com:8888\",\n \"no_proxy\" => [\n \"*.example.com\",\n \"93.184.216.34/32\"\n ]\n }\n },\n \"home_directory\" => \"/home/user\",\n \"lb_ssl_certificate\" => {\n \"production\" => \"\",\n \"staging\" => \"arn:aws:acm:lb-region-0:000000000000:certificate/00000000-0000-0000-0000-000000000000\"\n },\n \"lb_ssl_policy\" => {\n \"production\" => \"ELBSecurityPolicy-TLS-1-2-2017-01\",\n \"staging\" => \"ELBSecurityPolicy-TLS-1-2-2017-01\"\n },\n \"cloudfront_ssl_certificate\" => {\n \"production\" => \"\",\n \"staging\" => \"arn:aws:acm:us-east-1:000000000000:certificate/00000000-0000-0000-0000-000000000000\"\n },\n \"image_source\" => \"build_from_github_repo\",\n \"image_location\" => \"git@github.com:dxw/dalmatian-test-app\",\n \"track_revision\" => {\n \"production\" => \"\",\n \"staging\" => \"\"\n },\n \"custom_codestar_connection_arn\" => \"arn:aws:codestar-connections:eu-west-2:000000000000:connection/00000000-0000-0000-0000-000000000000\",\n \"codepipeline_use_github_v1\" => false,\n \"codepipeline_codebuild_run_in_vpc\" => false,\n \"codepipeline_codebuild_use_service_env\" => false,\n \"buildspec\" => \"buildspec.yml\",\n \"container_port\" => \"3100\",\n \"container_command\" => [\n \"/docker-entrypoint.sh\",\n \"rails\",\n \"server\"\n ],\n \"container_volumes\" => [\n {\n \"name\" => \"test-volume\",\n \"host_path\" => \"/mnt/test\",\n \"container_path\" => \"/test\"\n }\n ],\n \"container_extra_hosts\" => [\n {\n \"hostname\" => \"example.com\",\n \"ipAddress\" => \"127.0.0.1\"\n }\n ],\n \"container_count\" => \"2\",\n \"enable_max_one_container_per_instance\" => true,\n \"scheduled_tasks\" => [\n {\n \"name\" => \"old-scheduled-task\",\n \"command\" => [\n \"rake\",\n \"do:cron\"\n ],\n \"schedule_expression\" =>\n {\n \"production\" => \"cron(0 4 * * ? *)\",\n \"staging\" => \"cron(0 4 * * ? *)\"\n }\n },\n {\n \"name\" => \"test-scheduled-task\",\n \"command\" => [\n \"rake\",\n \"do:something\"\n ],\n \"schedule_expression\" => {\n \"staging\" => \"cron(0 12 * * ? *)\",\n \"production\" => \"cron(1 2 * * ? *)\"\n }\n }\n ],\n \"workers\" => [\n {\n \"name\" => \"test-worker\",\n \"command\" => [\n \"bundle\",\n \"exec\",\n \"sidekiq\"\n ]\n }\n ]\n }\n )\n )\n )\n end\n\n let(:cluster1_apply_cmd_staging_service) do\n terraform_apply_cmd(\n tfvar_arg_string(\n infrastructure_defaults.merge(\n \"instance_type\" => \"t2.small\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"track_revision\" => \"feature/experiment\",\n \"extra_ecs_clusters\" => [\n {\n \"name\" => \"test\",\n \"subnets_name\" => \"extra_private_subnets\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"instance_type\" => \"t3.small\"\n }\n ],\n \"tinyproxy\" => {\n \"create\" => true\n },\n \"environment\" => \"staging\",\n \"cluster_name\" => \"new-dedicated-cluster-staging\",\n \"account_id\" => \"123456789012\",\n \"infrastructure_name\" => \"new-dedicated-cluster\",\n \"dalmatian_role\" => \"dalmatian-admin\",\n \"service\" => {\n \"name\" => \"test-service\",\n \"blue_green\" => {\n \"production\" => {\n \"enabled\" => true,\n \"db_copy\" => {\n \"from_db_host_ps_key\" => \"/test-app/other-test-service/production/DB_HOST\",\n \"from_db_name_ps_key\" => \"/test-app/other-test-service/production/DB_NAME\",\n \"from_db_user_ps_key\" => \"/test-app/other-test-service/production/DB_USER\",\n \"from_db_pass_ps_key\" => \"/test-app/other-test-service/production/DB_PASSWORD\",\n \"blue_green_db_name_ps_key\" => \"/test-app/test-service/production/DB_HOST\",\n \"blue_green_db_user_ps_key\" => \"/test-app/test-service/production/DB_USER\",\n \"blue_green_db_pass_ps_key\" => \"/test-app/test-service/production/DB_PASSWORD\",\n \"sql_backups_s3_bucket\" => \"new-dedicated-cluster-testservice-production-sql-backup\"\n },\n \"db_rewrites\" => [\n {\n \"from\" => \"other-test-service.example.com\",\n \"to\" => \"test-service.example.com\"\n }\n ],\n \"directory_copy\" => [\n {\n \"from\" => \"/mnt/efs/other-test-service-media\",\n \"to\" => \"/mnt/efs/test-service-media\",\n \"chown\" => \"33:33\"\n }\n ],\n \"asset_copy_trigger_ps_key\" => \"/test-app/test-service/production/BLUE_GREEN_ASSET_COPY_TRIGGER\"\n },\n \"staging\" => {\n \"enabled\" => false\n }\n },\n \"launch_on\" => [\"production\", \"staging\"],\n \"launch_on_cluster\" => \"test\",\n \"cluster_min_servers\" => {\n \"production\" => \"2\",\n \"staging\" => \"2\"\n },\n \"parameter_store_path\" => {\n \"production\" => \"\",\n \"staging\" => \"/test-path\"\n },\n \"parameter_store_key\" => {\n \"production\" => \"\",\n \"staging\" => \"arn:aws:kms:eu-west-2:000000000000:key/00000000-0000-0000-0000-000000000000\"\n },\n \"daemon\" => false,\n \"monitoring\" => {\n \"production\" => {\n \"opsgenie_alerts\" => {\n \"enabled\" => true,\n \"cloudfront_5xx\" => {\n \"enabled\" => true,\n \"threshold\" => \"95\",\n \"evaluation_periods\" => \"15\"\n }\n },\n \"ghost_inspector\" => {\n \"enabled\" => true\n }\n },\n \"staging\" => {\n \"opsgenie_alerts\" => {\n \"enabled\" => false,\n \"cloudfront_5xx\" => {\n \"enabled\" => true,\n \"threshold\" => \"95\",\n \"evaluation_periods\" => \"15\"\n }\n },\n \"ghost_inspector\" => {\n \"enabled\" => false\n }\n }\n },\n \"cloudfront\" => {\n \"production\" => {\n \"create\" => true,\n \"managed_cache_policy\" => \"CachingDisabled\",\n \"managed_origin_policy\" => \"AllViewerExceptHostHeader\",\n \"managed_response_headers_policy\" => \"CORS-with-preflight-and-SecurityHeadersPolicy\",\n \"tls_protocol_version\" => \"TLSv1.2_2019\",\n \"origin_keepalive_timeout\" => \"60\",\n \"origin_read_timeout\" => \"60\",\n \"basic_auth\" => false,\n \"basic_auth_users_extra\" => {},\n \"viewer_request_functions\" => [\n {\n \"name\" => \"default\",\n \"true_client_ip_header\" => true,\n \"ip_subnet_allow_list\" => [\n \"0.0.0.0/0\"\n ],\n \"redirects\" => [\n {\n \"from_hostname_pattern\" => \"example-old-domain-name.*\",\n \"from_path_pattern\" => \"/*\",\n \"to_hostname\" => \"example-domain-name.co.uk\",\n \"to_path\" => \"/${path}\"\n }\n ]\n }\n ],\n \"offline_page_http_status\" => {\n \"500\" => \"/error-pages/500.html\",\n \"501\" => \"/error-pages/501.html\",\n \"502\" => \"/error-pages/502.html\",\n \"503\" => \"/error-pages/503.html\",\n \"504\" => \"/error-pages/504.html\"\n },\n \"custom_origins\" => [\n {\n \"origin\" => \"test-media-production.s3.amazonaws.com\",\n \"id\" => \"test-media-production-s3\"\n }\n ],\n \"bypass_protection\" => {\n \"enabled\" => true,\n \"exclude_domains\" => [\n \"example.com\"\n ]\n },\n \"custom_behaviors\" => [\n {\n \"target_origin_id\" => \"test-media-production-s3\",\n \"min_ttl\" => 1200,\n \"default_ttl\" => 3600,\n \"max_ttl\" => 86400,\n \"associate_viewer_request_function\" => \"default\",\n \"managed_cache_policy\" => \"CachingDisabled\",\n \"managed_origin_policy\" => \"AllViewerExceptHostHeader\",\n \"managed_response_headers_policy\" => \"CORS-with-preflight-and-SecurityHeadersPolicy\",\n \"path_pattern\" => \"/media/*\"\n }\n ]\n },\n \"staging\" => {\n \"create\" => true,\n \"managed_cache_policy\" => \"CachingDisabled\",\n \"managed_origin_policy\" => \"AllViewerExceptHostHeader\",\n \"managed_response_headers_policy\" => \"CORS-with-preflight-and-SecurityHeadersPolicy\",\n \"tls_protocol_version\" => \"TLSv1.2_2021\",\n \"origin_keepalive_timeout\" => \"10\",\n \"origin_read_timeout\" => \"40\",\n \"basic_auth\" => true,\n \"basic_auth_users_extra\" => {},\n \"viewer_request_functions\" => [\n {\n \"name\" => \"default\",\n \"true_client_ip_header\" => true,\n \"ip_subnet_allow_list\" => [\n \"0.0.0.0/0\"\n ],\n \"redirects\" => [\n {\n \"from_hostname_pattern\" => \"example-old-domain-name.*\",\n \"from_path_pattern\" => \"/*\",\n \"to_hostname\" => \"example-domain-name.co.uk\",\n \"to_path\" => \"/${path}\"\n }\n ]\n }\n ],\n \"offline_page_http_status\" => {\n \"500\" => \"/error-pages/500.html\",\n \"501\" => \"/error-pages/501.html\",\n \"502\" => \"/error-pages/502.html\",\n \"503\" => \"/error-pages/503.html\",\n \"504\" => \"/error-pages/504.html\"\n },\n \"custom_origins\" => [\n {\n \"origin\" => \"test-media-staging.s3.amazonaws.com\",\n \"id\" => \"test-media-staging-s3\"\n }\n ],\n \"bypass_protection\" => {\n \"enabled\" => false,\n \"exclude_domains\" => []\n },\n \"custom_behaviors\" => [\n {\n \"target_origin_id\" => \"test-media-staging-s3\",\n \"min_ttl\" => 1200,\n \"default_ttl\" => 3600,\n \"max_ttl\" => 86400,\n \"associate_viewer_request_function\" => \"default\",\n \"managed_cache_policy\" => \"\",\n \"managed_origin_policy\" => \"\",\n \"managed_response_headers_policy\" => \"\",\n \"path_pattern\" => \"/media/*\"\n }\n ]\n }\n },\n \"s3_policy\" => {\n \"production\" => {},\n \"staging\" => {\n \"rw\" => [\n \"test\"\n ]\n }\n },\n \"shared_loadbalancer_name\" => \"test-lb-1\",\n \"lb_ip_whitelist\" => [\n {\n \"name\" => \"public\",\n \"cidr\" => \"0.0.0.0/0\"\n }\n ],\n \"lb_idle_timeout\" => \"60\",\n \"global_accelerator\" => {\n \"production\" => true,\n \"staging\" => false\n },\n \"health_check_path\" => \"/check\",\n \"health_check_grace_period\" => \"0\",\n \"deregistration_delay\" => \"60\",\n \"serve_from_subdirectory\" => \"/test-subdir\",\n \"domain_names\" => {\n \"production\" => [],\n \"staging\" => [\n \"example-domain-name.co.uk\"\n ]\n },\n \"proxy_configuration\" => {\n \"production\" => {},\n \"staging\" => {\n \"https_proxy\" => \"dalmatian_tinyproxy\",\n \"http_proxy\" => \"http://my.test-proxy.com:8888\",\n \"no_proxy\" => [\n \"*.example.com\",\n \"93.184.216.34/32\"\n ]\n }\n },\n \"home_directory\" => \"/home/user\",\n \"lb_ssl_certificate\" => {\n \"production\" => \"\",\n \"staging\" => \"arn:aws:acm:lb-region-0:000000000000:certificate/00000000-0000-0000-0000-000000000000\"\n },\n \"lb_ssl_policy\" => {\n \"production\" => \"ELBSecurityPolicy-TLS-1-2-2017-01\",\n \"staging\" => \"ELBSecurityPolicy-TLS-1-2-2017-01\"\n },\n \"cloudfront_ssl_certificate\" => {\n \"production\" => \"\",\n \"staging\" => \"arn:aws:acm:us-east-1:000000000000:certificate/00000000-0000-0000-0000-000000000000\"\n },\n \"image_source\" => \"build_from_github_repo\",\n \"image_location\" => \"git@github.com:dxw/dalmatian-test-app\",\n \"track_revision\" => {\n \"production\" => \"\",\n \"staging\" => \"\"\n },\n \"custom_codestar_connection_arn\" => \"arn:aws:codestar-connections:eu-west-2:000000000000:connection/00000000-0000-0000-0000-000000000000\",\n \"codepipeline_use_github_v1\" => false,\n \"codepipeline_codebuild_run_in_vpc\" => false,\n \"codepipeline_codebuild_use_service_env\" => false,\n \"buildspec\" => \"buildspec.yml\",\n \"container_port\" => \"3100\",\n \"container_command\" => [\n \"/docker-entrypoint.sh\",\n \"rails\",\n \"server\"\n ],\n \"container_volumes\" => [\n {\n \"name\" => \"test-volume\",\n \"host_path\" => \"/mnt/test\",\n \"container_path\" => \"/test\"\n }\n ],\n \"container_extra_hosts\" => [\n {\n \"hostname\" => \"example.com\",\n \"ipAddress\" => \"127.0.0.1\"\n }\n ],\n \"container_count\" => \"2\",\n \"enable_max_one_container_per_instance\" => true,\n \"scheduled_tasks\" => [\n {\n \"name\" => \"old-scheduled-task\",\n \"command\" => [\n \"rake\",\n \"do:cron\"\n ],\n \"schedule_expression\" =>\n {\n \"production\" => \"cron(0 4 * * ? *)\",\n \"staging\" => \"cron(0 4 * * ? *)\"\n }\n },\n {\n \"name\" => \"test-scheduled-task\",\n \"command\" => [\n \"rake\",\n \"do:something\"\n ],\n \"schedule_expression\" => {\n \"staging\" => \"cron(0 12 * * ? *)\",\n \"production\" => \"cron(1 2 * * ? *)\"\n }\n }\n ],\n \"workers\" => [\n {\n \"name\" => \"test-worker\",\n \"command\" => [\n \"bundle\",\n \"exec\",\n \"sidekiq\"\n ]\n }\n ]\n }\n )\n )\n )\n end\n\n let(:cluster1_apply_cmd_production_shared_loadbalancer) do\n terraform_apply_cmd(\n tfvar_arg_string(\n infrastructure_defaults.merge(\n \"instance_type\" => \"t2.medium\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"environment\" => \"production\",\n \"account_id\" => \"123456789012\",\n \"infrastructure_name\" => \"new-dedicated-cluster\",\n \"dalmatian_role\" => \"dalmatian-admin\",\n \"shared_loadbalancer\" => {\n \"name\" => \"test-lb-1\",\n \"in_use_by\" => [\n \"test-service\"\n ],\n \"clusters_in_use\" => {\n \"production\" => [\n \"test\"\n ],\n \"staging\" => [\n \"test\"\n ]\n },\n \"subnets_name\" => \"\",\n \"domain_names\" => {\n \"test-service\" => {\n \"production\" => [],\n \"staging\" => [\n \"example-domain-name.co.uk\"\n ]\n }\n },\n \"internal\" => false,\n \"ip_whitelist\" => [\n {\n \"name\" => \"public\",\n \"cidr\" => \"0.0.0.0/0\"\n }\n ],\n \"idle_timeout\" => \"60\",\n \"global_accelerator\" => {\n \"production\" => true,\n \"staging\" => false\n },\n \"ssl_policy\" => \"ELBSecurityPolicy-TLS-1-2-2017-01\"\n }\n )\n )\n )\n end\n\n let(:cluster1_apply_cmd_staging_shared_loadbalancer) do\n terraform_apply_cmd(\n tfvar_arg_string(\n infrastructure_defaults.merge(\n \"instance_type\" => \"t2.small\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"track_revision\" => \"feature/experiment\",\n \"extra_ecs_clusters\" => [\n {\n \"name\" => \"test\",\n \"subnets_name\" => \"extra_private_subnets\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"instance_type\" => \"t3.small\"\n }\n ],\n \"tinyproxy\" => {\n \"create\" => true\n },\n \"environment\" => \"staging\",\n \"account_id\" => \"123456789012\",\n \"infrastructure_name\" => \"new-dedicated-cluster\",\n \"dalmatian_role\" => \"dalmatian-admin\",\n \"shared_loadbalancer\" => {\n \"name\" => \"test-lb-1\",\n \"in_use_by\" => [\n \"test-service\"\n ],\n \"clusters_in_use\" => {\n \"production\" => [\n \"test\"\n ],\n \"staging\" => [\n \"test\"\n ]\n },\n \"subnets_name\" => \"\",\n \"domain_names\" => {\n \"test-service\" => {\n \"production\" => [],\n \"staging\" => [\n \"example-domain-name.co.uk\"\n ]\n }\n },\n \"internal\" => false,\n \"ip_whitelist\" => [\n {\n \"name\" => \"public\",\n \"cidr\" => \"0.0.0.0/0\"\n }\n ],\n \"idle_timeout\" => \"60\",\n \"global_accelerator\" => {\n \"production\" => true,\n \"staging\" => false\n },\n \"ssl_policy\" => \"ELBSecurityPolicy-TLS-1-2-2017-01\"\n }\n )\n )\n )\n end\n\n let(:cluster2_apply_cmd_production) do\n terraform_apply_cmd(\n tfvar_arg_string(\n infrastructure_defaults.merge(\n \"instance_type\" => \"t2.medium\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"10\",\n \"environment\" => \"production\",\n \"cluster_name\" => \"shared-new-cluster-production\",\n \"account_id\" => \"123456789012\",\n \"infrastructure_name\" => \"shared-new-cluster\",\n \"dalmatian_role\" => \"dalmatian-admin\"\n )\n )\n )\n end\n\n let(:cluster2_apply_cmd_staging) do\n terraform_apply_cmd(\n tfvar_arg_string(\n infrastructure_defaults.merge(\n \"instance_type\" => \"t2.small\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"10\",\n \"environment\" => \"staging\",\n \"cluster_name\" => \"shared-new-cluster-staging\",\n \"account_id\" => \"123456789012\",\n \"infrastructure_name\" => \"shared-new-cluster\",\n \"dalmatian_role\" => \"dalmatian-admin\"\n )\n )\n )\n end\n\n let(:cluster3_apply_cmd_staging) do\n terraform_apply_cmd(\n tfvar_arg_string(\n infrastructure_defaults.merge(\n \"example_var\" => \"foo\",\n \"environment\" => \"staging\",\n \"cluster_name\" => \"shared-cluster-staging\",\n \"account_id\" => \"123456789012\",\n \"infrastructure_name\" => \"existing-shared-cluster-staging\",\n \"dalmatian_role\" => \"dalmatian-admin\"\n )\n )\n )\n end\n\n let(:cluster4_apply_cmd_production) do\n terraform_apply_cmd(\n tfvar_arg_string(\n infrastructure_defaults.merge(\n \"example_var\" => \"bar\",\n \"environment\" => \"production\",\n \"cluster_name\" => \"shared-cluster-production\",\n \"account_id\" => \"123456789012\",\n \"infrastructure_name\" => \"existing-shared-cluster-production\",\n \"dalmatian_role\" => \"dalmatian-admin\"\n )\n )\n )\n end\n\n before do\n allow(Logger).to receive(:info)\n stub_git_checkout\n stub_workspace_creation_cmds\n\n allow(Helper).to receive(:run!).with(cluster1_apply_cmd_hz)\n\n allow(Helper).to receive(:run!).with(cluster1_apply_cmd_s3)\n\n allow(Helper).to receive(:run!).with(cluster1_apply_cmd_vpn_cg)\n\n allow(Helper).to receive(:run!).with(cluster1_apply_cmd_production)\n allow(Helper).to receive(:run!).with(cluster1_apply_cmd_staging)\n\n allow(Helper).to receive(:run!).with(cluster1_apply_cmd_production_waf)\n allow(Helper).to receive(:run!).with(cluster1_apply_cmd_staging_waf)\n\n allow(Helper).to receive(:run!).with(cluster1_apply_cmd_production_rds)\n allow(Helper).to receive(:run!).with(cluster1_apply_cmd_staging_rds)\n\n allow(Helper).to receive(:run!).with(cluster1_apply_cmd_production_elasticache_cluster)\n allow(Helper).to receive(:run!).with(cluster1_apply_cmd_staging_elasticache_cluster)\n\n allow(Helper).to receive(:run!).with(cluster1_apply_cmd_production_opensearch_cluster)\n allow(Helper).to receive(:run!).with(cluster1_apply_cmd_staging_opensearch_cluster)\n\n allow(Helper).to receive(:run!).with(cluster1_apply_cmd_production_service)\n allow(Helper).to receive(:run!).with(cluster1_apply_cmd_staging_service)\n\n allow(Helper).to receive(:run!).with(cluster1_apply_cmd_production_shared_loadbalancer)\n allow(Helper).to receive(:run!).with(cluster1_apply_cmd_staging_shared_loadbalancer)\n\n allow(Helper).to receive(:run!).with(cluster2_apply_cmd_production)\n allow(Helper).to receive(:run!).with(cluster2_apply_cmd_staging)\n\n allow(Helper).to receive(:run!).with(cluster3_apply_cmd_staging)\n\n allow(Helper).to receive(:run!).with(cluster4_apply_cmd_production)\n\n Infrastructure.new(\n ConfigurationReader.new(path: \"./dalmatian.yml.example\", parameter_store: fake_parameter_store).infrastructures\n ).deploy(auto_approve: false, plan: false)\n end\n\n describe 'use of \"terraform apply\"' do\n it 'passes the hosted zone config to \"terraform apply\"' do\n expect(Helper).to have_received(:run!).with(cluster1_apply_cmd_hz)\n end\n\n it 'passes the s3 config to \"terraform apply\"' do\n expect(Helper).to have_received(:run!).with(cluster1_apply_cmd_s3)\n end\n\n it 'passes the vpn customer gateway config to \"terraform apply\"' do\n expect(Helper).to have_received(:run!).with(cluster1_apply_cmd_vpn_cg)\n end\n\n it 'passes the base config to \"terraform apply\"' do\n expect(Helper).to have_received(:run!).with(cluster1_apply_cmd_production).twice\n expect(Helper).to have_received(:run!).with(cluster1_apply_cmd_staging).twice\n end\n\n it 'passes the waf config to \"terraform apply\"' do\n aggregate_failures do\n expect(Helper).to have_received(:run!).with(cluster1_apply_cmd_production_waf)\n expect(Helper).to have_received(:run!).with(cluster1_apply_cmd_staging_waf)\n end\n end\n\n it 'passes the rds config to \"terraform apply\"' do\n aggregate_failures do\n expect(Helper).to have_received(:run!).with(cluster1_apply_cmd_production_rds)\n expect(Helper).to have_received(:run!).with(cluster1_apply_cmd_staging_rds)\n end\n end\n\n it 'passes the elasticache config to \"terraform apply\"' do\n aggregate_failures do\n expect(Helper).to have_received(:run!)\n .with(cluster1_apply_cmd_production_elasticache_cluster)\n expect(Helper).to have_received(:run!)\n .with(cluster1_apply_cmd_staging_elasticache_cluster)\n end\n end\n\n it 'passes the opensearch config to \"terraform apply\"' do\n aggregate_failures do\n expect(Helper).to have_received(:run!)\n .with(cluster1_apply_cmd_production_opensearch_cluster)\n expect(Helper).to have_received(:run!)\n .with(cluster1_apply_cmd_staging_opensearch_cluster)\n end\n end\n\n it 'passes the service config to \"terraform apply\"' do\n aggregate_failures do\n expect(Helper).to have_received(:run!).with(cluster1_apply_cmd_production_service)\n expect(Helper).to have_received(:run!).with(cluster1_apply_cmd_staging_service)\n end\n end\n\n it 'passes the loadbalancer config to \"terraform apply\"' do\n aggregate_failures do\n expect(Helper).to have_received(:run!)\n .with(cluster1_apply_cmd_production_shared_loadbalancer)\n expect(Helper).to have_received(:run!)\n .with(cluster1_apply_cmd_staging_shared_loadbalancer)\n end\n end\n\n it 'passes the cluster 2 config to \"terraform apply\"' do\n aggregate_failures do\n expect(Helper).to have_received(:run!).with(cluster2_apply_cmd_production)\n expect(Helper).to have_received(:run!).with(cluster2_apply_cmd_staging)\n end\n end\n\n it 'passes the cluster 3 config to \"terraform apply\"' do\n expect(Helper).to have_received(:run!).with(cluster3_apply_cmd_staging)\n end\n\n it 'passes the cluster 4 config to \"terraform apply\"' do\n expect(Helper).to have_received(:run!).with(cluster4_apply_cmd_production)\n end\n end\n end\nend\n",
|
|
"diffStat": {
|
|
"model_added_lines": 4,
|
|
"model_removed_lines": 0,
|
|
"model_added_chars": 204,
|
|
"model_removed_chars": 0,
|
|
"user_added_lines": 1,
|
|
"user_removed_lines": 1663,
|
|
"user_added_chars": 37,
|
|
"user_removed_chars": 58754
|
|
},
|
|
"isNewFile": false
|
|
},
|
|
"displayName": "Edit",
|
|
"description": "Replaces text within a file. By default, replaces a single occurrence, but can replace multiple occurrences when `expected_replacements` is specified. This tool requires providing significant context around the change to ensure precise targeting. Always use the read_file tool to examine the file's current content before attempting a text replacement.\n \n The user has the ability to modify the `new_string` content. If modified, this will be stated in the response.\n \n Expectation for required parameters:\n 1. `old_string` MUST be the exact literal text to replace (including all whitespace, indentation, newlines, and surrounding code etc.).\n 2. `new_string` MUST be the exact literal text to replace `old_string` with (also including all whitespace, indentation, newlines, and surrounding code etc.). Ensure the resulting code is correct and idiomatic and that `old_string` and `new_string` are different.\n 3. `instruction` is the detailed instruction of what needs to be changed. It is important to Make it specific and detailed so developers or large language models can understand what needs to be changed and perform the changes on their own if necessary. \n 4. NEVER escape `old_string` or `new_string`, that would break the exact literal text requirement.\n **Important:** If ANY of the above are not satisfied, the tool will fail. CRITICAL for `old_string`: Must uniquely identify the single instance to change. Include at least 3 lines of context BEFORE and AFTER the target text, matching whitespace and indentation precisely. If this string matches multiple locations, or does not match exactly, the tool will fail.\n 5. Prefer to break down complex and long changes into multiple smaller atomic calls to this tool. Always check the content of the file after changes or not finding a string to match.\n **Multiple replacements:** Set `expected_replacements` to the number of occurrences you want to replace. The tool will replace ALL occurrences that match `old_string` exactly. Ensure the number of replacements matches your expectation.",
|
|
"renderOutputAsMarkdown": true
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"id": "ef455eeb-416d-496a-94f0-1c809cd9bf64",
|
|
"timestamp": "2026-02-20T17:15:10.636Z",
|
|
"type": "gemini",
|
|
"content": "RDS hash updated in both files. `replication_bucket_destination_arn` and `replication_kms_key_id` are in `to_params`, so adding them to the specs should help. Running tests now.",
|
|
"thoughts": [
|
|
{
|
|
"subject": "Reviewing the Files",
|
|
"description": "I've just updated the RDS hash in the files, which is a good start. However, reviewing `lib/dalmatian/rds.rb`, I see both `replication_bucket_destination_arn` and `replication_kms_key_id` are also present in the `to_params` method. I need to take this into account.",
|
|
"timestamp": "2026-02-20T17:15:10.527Z"
|
|
},
|
|
{
|
|
"subject": "Analyzing the Parameters",
|
|
"description": "I've been thinking about the parameters of `to_params` in `lib/dalmatian/rds.rb`, specifically the `replication_bucket_destination_arn` and `replication_kms_key_id` values. I added them to the specs recently, which should improve coverage. Time to re-run the tests!",
|
|
"timestamp": "2026-02-20T17:15:10.546Z"
|
|
}
|
|
],
|
|
"tokens": {
|
|
"input": 59181,
|
|
"output": 65,
|
|
"cached": 56453,
|
|
"thoughts": 84,
|
|
"tool": 0,
|
|
"total": 59330
|
|
},
|
|
"model": "gemini-3-flash-preview",
|
|
"toolCalls": [
|
|
{
|
|
"id": "run_shell_command_1771607710633_0",
|
|
"name": "run_shell_command",
|
|
"args": {
|
|
"command": "./scripts/bin/test -l"
|
|
},
|
|
"result": [
|
|
{
|
|
"functionResponse": {
|
|
"id": "run_shell_command_1771607710633_0",
|
|
"name": "run_shell_command",
|
|
"response": {
|
|
"output": "Output too large. Showing first 8,000 and last 32,000 characters. For full output see: /Users/bob/.gemini/tmp/dalmatian/tool-outputs/session-b86444e1-3f32-4f39-9c46-1ce1d2631b8b/run_shell_command_1771607710633_0.txt\nOutput: ==> Linting YAML...\n\n==> Linting shell scripts...\n\n==> Checking Terraform for JSON errors...\n- Checking ./terraform/policies/iam-read.json... Passed\n- Checking ./terraform/policies/s3-rw-with-versioning.json... Passed\n- Checking ./terraform/policies/codestar-connection-use.json... Passed\n- Checking ./terraform/policies/iam-create-access-key.json... Passed\n- Checking ./terraform/policies/codebuild.json... Passed\n- Checking ./terraform/policies/kms-encrypt-decrypt.json... Passed\n- Checking ./terraform/policies/iam-change-password.json... Passed\n- Checking ./terraform/policies/administrator-access.json... Passed\n- Checking ./terraform/policies/assume_roles/aws-backup.json... Passed\n- Checking ./terraform/policies/assume_roles/autoscaling.json... Passed\n- Checking ./terraform/policies/assume_roles/events.json... Passed\n- Checking ./terraform/policies/assume_roles/ecs.json... Passed\n- Checking ./terraform/policies/assume_roles/codepipeline.json... Passed\n- Checking ./terraform/policies/iam-mfa.json... Passed\n- Checking ./terraform/policies/route53-read.json... Passed\n- Checking ./terraform/policies/s3-full-access.json... Passed\n- Checking ./terraform/policies/parameter-store-read-decrypt.json... Passed\n- Checking ./terraform/policies/s3-read.json... Passed\n- Checking ./terraform/policies/parameter-store-RW-encrypt-decrypt.json... Passed\n- Checking ./terraform/policies/all-read-with-billing.json... Passed\n- Checking ./terraform/policies/codebuild-start-build.json... Passed\n- Checking ./terraform/policies/all-read.json... Passed\n\n==> Linting Terraform...\n\n==> Running Ruby tests...\n/Users/bob/.rbenv/versions/2.7.1/bin/ruby -I/Users/bob/.bundles/ruby/2.7.0/gems/rspec-core-3.12.2/lib:/Users/bob/.bundles/ruby/2.7.0/gems/rspec-support-3.12.1/lib /Users/bob/.bundles/ruby/2.7.0/gems/rspec-core-3.12.2/exe/rspec --pattern spec/\\*\\*\\{,/\\*/\\*\\*\\}/\\*_spec.rb\n\ntests local configuration\n use of \"terraform apply\"\n passes the hosted zone config to \"terraform apply\"\n passes the s3 config to \"terraform apply\"\n passes the vpn customer gateway config to \"terraform apply\"\n passes the base config to \"terraform apply\"\n passes the waf config to \"terraform apply\"\n passes the rds config to \"terraform apply\"\n passes the elasticache config to \"terraform apply\"\n passes the opensearch config to \"terraform apply\"\n passes the service config to \"terraform apply\"\n passes the loadbalancer config to \"terraform apply\"\n passes the cluster 2 config to \"terraform apply\"\n passes the cluster 3 config to \"terraform apply\"\n passes the cluster 4 config to \"terraform apply\"\n\ntests remote configuration\n retrieves the remotely held full configuration\n proceeds with deploying the infrastructure as per the cached full configuration\n\ntests local configuration\n invokes \"terraform validate\" with the expected cluster options (FAILED - 1)\n invokes \"terraform validate\" with the expected source options (FAILED - 2)\n use of \"terraform plan\"\n passes the hosted zone config to \"terraform plan\" (FAILED - 3)\n passes the s3 config to \"terraform plan\" (FAILED - 4)\n passes the vpn customer gateway config to \"terraform plan\" (FAILED - 5)\n passes the base config to \"terraform plan\" (FAILED - 6)\n passes the waf config to \"terraform plan\" (FAILED - 7)\n passes the rds config to \"terraform plan\" (FAILED - 8)\n passes the elasticache config to \"terraform plan\" (FAILED - 9)\n passes the opensearch config to \"terraform plan\" (FAILED - 10)\n passes the services config to \"terraform plan\" (FAILED - 11)\n passes the loadbalancer config to \"terraform plan\" (FAILED - 12)\n passes the cluster 2 config to \"terraform plan\" (FAILED - 13)\n passes the cluster 3 config to \"terraform plan\" (FAILED - 14)\n passes the cluster 4 config to \"terraform plan\" (FAILED - 15)\n\nDalmatian::Account\n initialisation\n gathering user input\n asks the user for AWS credentials\n asks the user for the AWS account id to use\n asks the user for an account alias\n #call\n changes to the bootstrapping directory\n runs terraform init with upgrade option\n creates the new workspace using the given aws account id and alias\n runs terraform apply with the user-supplied vars\n\nDalmatian::CacheHandlerSelector\n ::new_for(remote_reference)\n when the remote reference is for a git repo\n asks for an instance of GitCacheHandler\n when the remote reference is for an S3 bucket\n asks for an instance of S3CacheHandler\n when the remote reference is for a URL\n asks for an instance of UrlCacheHandler\n when the type is unknown\n raises an error\n\nCacheHandler\n when a subclass class does not implement #cache_remote_configuration\n raises a helpful error\n\nDalmatian::CI\n CI::PATH\n is a constant\n #deploy\n changes to the ci directory\n runs terraform init with upgrade option\n creates the new workspace using the given aws account id and alias\n runs terraform apply with the user-supplied vars\n #test\n runs terraform plan with the user-supplied vars\n\nDalmatian::ClusterDeployment\n #call\n changes to the ecs directory\n asks Terraform to ensure that the workspace is in place\n when the environment includes a git reference as \"track_revision\"\n does NOT attempt to check out that commit\n when in _plan_ mode\n invokes Terraform.plan using the _dalmatian-read_ role\n when NOT in _plan_ mode\n invokes Terraform.apply using the _dalmatian-admin_\n when in _auto_approve_ mode\n asks Terraform to use auto_approve mode\n\nDalmatian::Cluster\n on initialisation\n makes Hosted zones, S3, Sources, Services, Loadbalancers, WAF and Rds\n #target_directory\n is a standard _ecs_ path\n #id\n is the primary key of the cluster definition is used\n #name\n when the cluster has an explicitly provided _name_ property\n that property is used\n when the cluster does not have an explicitly provided _name_ property\n the primary key of the cluster definition is used\n #account_id\n is the aws account key for deployment\n #sources\n represents any links to remote sources\n #environments\n represents the attributes of each environment's cluster section\n #fetch\n when the source is remotely held\n logs the plan to clone the source into the infrastructure pth\n deletes any existing source at the infrastructure location\n clones each source into the infrastructure location\n changes to the infrastructure directory for each source\n runs rake terrafile\n changes back to the APP_ROOT\n when the source is a local file path\n does not re-clone the source\n does not run terrafile\n when the specified local directory exists\n logs the fact that the local source is in place\n when the specificed local directory does not exist\n logs an error that the local source is missing\n #deploy\n deploys source infrastructure for each source and each service in each environment\n when a cluster should be created\n deploys cluster infrastructure for each environment\n when the _plan_ option IS invoked\n creates Cluster Deployments with plan settings\n when the _auto_approve_ option IS invoked\n creates Cluster Deployments with auto_approve settings\n handling of tests\n when the _test_ option is NOT invoked\n does not run cluster tests\n does not run cluster tests\n does not run cluster tests\n does not run source tests\n does not run waf tests\n does not run rds tests\n does not run service tests\n does not run service tests\n when the test option IS invoked\n runs tests\n when a cluster should NOT be created\n does not deploy cluster infrastructure\n when test option is invoked\n tests sources and services for each environment\n\nDalmatian::ClusterTest\n #call\n changes to the ecs directory\n logs our intention to run Terraform init\n runs \n\n... [72,347 characters omitted] ...\n\nn_zone='dalmatian.internal' TF_VAR_ecs_private_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.128.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.129.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.130.0/24\\\"}]' TF_VAR_extra_public_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.0.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.1.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.2.0/24\\\"}]' TF_VAR_instances_key_name='dalmatian-ecs-instances' TF_VAR_instance_type='t2.medium' TF_VAR_min_servers='2' TF_VAR_max_servers='4' TF_VAR_max_instance_lifetime='86400' TF_VAR_associate_public_ip_address='0' TF_VAR_docker_storage_size='40' TF_VAR_dockerhub_email='' TF_VAR_dockerhub_token='' TF_VAR_enable_efs='false' TF_VAR_encrypt_efs='true' TF_VAR_efs_dirs='[]' TF_VAR_monitoring_docs_path='https://github.com/dxw/dalmatian/docs/monitoring-alarms/' TF_VAR_account_id='123456789012' TF_VAR_infrastructure_name='new-dedicated-cluster' TF_VAR_dalmatian_role='dalmatian-read' TF_VAR_environment='production' TF_VAR_rds='{identifier =\\\"testservice\\\",in_use_by =[\\\"test-service\\\"],clusters_in_use ={production =[\\\"test\\\"],staging =[\\\"test\\\"]},instance_class ={production =\\\"db.t2.small\\\",staging =\\\"db.t2.micro\\\"},engine =\\\"postgres\\\",engine_version =\\\"11.4\\\",allocated_storage =20,storage_encrypted =true,storage_type =\\\"gp3\\\",db_name =\\\"testapp\\\",port =5432,maintenance_window =\\\"mon:19:00-mon:19:30\\\",backup_window =\\\"09:00-10:00\\\",backup_retention_period =31,force_ssl =true,parameter_store_path_db_url_name =\\\"DATABASE_URL\\\",sql_backup_scheduled_task_environment_variables =[{name =\\\"foo\\\",value =\\\"bar\\\"}],check_sql_backup_scheduled_task_environment_variables =[{name =\\\"foo\\\",value =\\\"bar\\\"}],sync_sql_backup_to_azure =false,codebuild_access =[\\\"service-name\\\"]}' terraform validate\")\n Please stub a default value first if message might be received with other args as well. \n # ./lib/dalmatian/terraform.rb:17:in `validate'\n # ./lib/dalmatian/testable.rb:25:in `terraform_validate'\n # ./lib/dalmatian/testable.rb:9:in `call'\n # ./lib/dalmatian/cluster.rb:353:in `test_rds'\n # ./lib/dalmatian/cluster.rb:261:in `deploy_rds'\n # ./lib/dalmatian/cluster.rb:70:in `block (2 levels) in deploy'\n # ./lib/dalmatian/cluster.rb:68:in `each'\n # ./lib/dalmatian/cluster.rb:68:in `block in deploy'\n # ./lib/dalmatian/cluster.rb:59:in `each'\n # ./lib/dalmatian/cluster.rb:59:in `deploy'\n # ./lib/dalmatian/infrastructure.rb:24:in `block in deploy'\n # ./lib/dalmatian/infrastructure.rb:22:in `each'\n # ./lib/dalmatian/infrastructure.rb:22:in `deploy'\n # ./lib/dalmatian/infrastructure.rb:18:in `test'\n # ./spec/integration/tests_local_configuration_spec.rb:3116:in `block (2 levels) in <module:Dalmatian>'\n # ./spec/support/spec_helper.rb:24:in `block (3 levels) in <top (required)>'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:24:in `block in modify'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:15:in `synchronize'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:15:in `modify'\n # ./spec/support/spec_helper.rb:20:in `block (2 levels) in <top (required)>'\n # /Users/bob/.bundles/ruby/2.7.0/gems/webmock-3.19.1/lib/webmock/rspec.rb:39:in `block (2 levels) in <top (required)>'\n\n 11) tests local configuration use of \"terraform plan\" passes the services config to \"terraform plan\"\n Failure/Error: Helper.run!(cmd)\n \n #<Dalmatian::Helper (class)> received :run! with unexpected arguments\n expected: (\"TF_VAR_region='eu-west-2' TF_VAR_cidr='10.0.0.0/16' TF_VAR_root_domain_zone='dalmatian.dxw.net' TF_VAR_internal_domain_zone='dalmatian.internal' TF_VAR_ecs_private_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.128.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.129.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.130.0/24\\\"}]' TF_VAR_extra_public_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.0.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.1.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.2.0/24\\\"}]' TF_VAR_instances_key_name='dalmatian-ecs-instances' TF_VAR_instance_type='t2.medium' TF_VAR_min_servers='2' TF_VAR_max_servers='4' TF_VAR_max_instance_lifetime='86400' TF_VAR_associate_public_ip_address='0' TF_VAR_docker_storage_size='40' TF_VAR_dockerhub_email='' TF_VAR_dockerhub_token='' TF_VAR_enable_efs='false' TF_VAR_encrypt_efs='true' TF_VAR_efs_dirs='[]' TF_VAR_monitoring_docs_path='https://github.com/dxw/dalmatian/docs/monitoring-alarms/' TF_VAR_example_var='bar' TF_VAR_environment='production' TF_VAR_cluster_name='shared-cluster-production' TF_VAR_account_id='123456789012' TF_VAR_infrastructure_name='existing-shared-cluster-production' TF_VAR_dalmatian_role='dalmatian-read' terraform plan\")\n got: (\"TF_VAR_region='eu-west-2' TF_VAR_cidr='10.0.0.0/16' TF_VAR_root_domain_zone='dalmatian.dxw.net' TF_VAR_internal_domain_zone='dalmatian.internal' TF_VAR_ecs_private_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.128.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.129.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.130.0/24\\\"}]' TF_VAR_extra_public_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.0.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.1.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.2.0/24\\\"}]' TF_VAR_instances_key_name='dalmatian-ecs-instances' TF_VAR_instance_type='t2.medium' TF_VAR_min_servers='2' TF_VAR_max_servers='4' TF_VAR_max_instance_lifetime='86400' TF_VAR_associate_public_ip_address='0' TF_VAR_docker_storage_size='40' TF_VAR_dockerhub_email='' TF_VAR_dockerhub_token='' TF_VAR_enable_efs='false' TF_VAR_encrypt_efs='true' TF_VAR_efs_dirs='[]' TF_VAR_monitoring_docs_path='https://github.com/dxw/dalmatian/docs/monitoring-alarms/' TF_VAR_account_id='123456789012' TF_VAR_infrastructure_name='new-dedicated-cluster' TF_VAR_dalmatian_role='dalmatian-read' TF_VAR_environment='production' TF_VAR_rds='{identifier =\\\"testservice\\\",in_use_by =[\\\"test-service\\\"],clusters_in_use ={production =[\\\"test\\\"],staging =[\\\"test\\\"]},instance_class ={production =\\\"db.t2.small\\\",staging =\\\"db.t2.micro\\\"},engine =\\\"postgres\\\",engine_version =\\\"11.4\\\",allocated_storage =20,storage_encrypted =true,storage_type =\\\"gp3\\\",db_name =\\\"testapp\\\",port =5432,maintenance_window =\\\"mon:19:00-mon:19:30\\\",backup_window =\\\"09:00-10:00\\\",backup_retention_period =31,force_ssl =true,parameter_store_path_db_url_name =\\\"DATABASE_URL\\\",sql_backup_scheduled_task_environment_variables =[{name =\\\"foo\\\",value =\\\"bar\\\"}],check_sql_backup_scheduled_task_environment_variables =[{name =\\\"foo\\\",value =\\\"bar\\\"}],sync_sql_backup_to_azure =false,codebuild_access =[\\\"service-name\\\"]}' terraform validate\")\n Please stub a default value first if message might be received with other args as well. \n # ./lib/dalmatian/terraform.rb:17:in `validate'\n # ./lib/dalmatian/testable.rb:25:in `terraform_validate'\n # ./lib/dalmatian/testable.rb:9:in `call'\n # ./lib/dalmatian/cluster.rb:353:in `test_rds'\n # ./lib/dalmatian/cluster.rb:261:in `deploy_rds'\n # ./lib/dalmatian/cluster.rb:70:in `block (2 levels) in deploy'\n # ./lib/dalmatian/cluster.rb:68:in `each'\n # ./lib/dalmatian/cluster.rb:68:in `block in deploy'\n # ./lib/dalmatian/cluster.rb:59:in `each'\n # ./lib/dalmatian/cluster.rb:59:in `deploy'\n # ./lib/dalmatian/infrastructure.rb:24:in `block in deploy'\n # ./lib/dalmatian/infrastructure.rb:22:in `each'\n # ./lib/dalmatian/infrastructure.rb:22:in `deploy'\n # ./lib/dalmatian/infrastructure.rb:18:in `test'\n # ./spec/integration/tests_local_configuration_spec.rb:3116:in `block (2 levels) in <module:Dalmatian>'\n # ./spec/support/spec_helper.rb:24:in `block (3 levels) in <top (required)>'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:24:in `block in modify'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:15:in `synchronize'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:15:in `modify'\n # ./spec/support/spec_helper.rb:20:in `block (2 levels) in <top (required)>'\n # /Users/bob/.bundles/ruby/2.7.0/gems/webmock-3.19.1/lib/webmock/rspec.rb:39:in `block (2 levels) in <top (required)>'\n\n 12) tests local configuration use of \"terraform plan\" passes the loadbalancer config to \"terraform plan\"\n Failure/Error: Helper.run!(cmd)\n \n #<Dalmatian::Helper (class)> received :run! with unexpected arguments\n expected: (\"TF_VAR_region='eu-west-2' TF_VAR_cidr='10.0.0.0/16' TF_VAR_root_domain_zone='dalmatian.dxw.net' TF_VAR_internal_domain_zone='dalmatian.internal' TF_VAR_ecs_private_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.128.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.129.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.130.0/24\\\"}]' TF_VAR_extra_public_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.0.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.1.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.2.0/24\\\"}]' TF_VAR_instances_key_name='dalmatian-ecs-instances' TF_VAR_instance_type='t2.medium' TF_VAR_min_servers='2' TF_VAR_max_servers='4' TF_VAR_max_instance_lifetime='86400' TF_VAR_associate_public_ip_address='0' TF_VAR_docker_storage_size='40' TF_VAR_dockerhub_email='' TF_VAR_dockerhub_token='' TF_VAR_enable_efs='false' TF_VAR_encrypt_efs='true' TF_VAR_efs_dirs='[]' TF_VAR_monitoring_docs_path='https://github.com/dxw/dalmatian/docs/monitoring-alarms/' TF_VAR_example_var='bar' TF_VAR_environment='production' TF_VAR_cluster_name='shared-cluster-production' TF_VAR_account_id='123456789012' TF_VAR_infrastructure_name='existing-shared-cluster-production' TF_VAR_dalmatian_role='dalmatian-read' terraform plan\")\n got: (\"TF_VAR_region='eu-west-2' TF_VAR_cidr='10.0.0.0/16' TF_VAR_root_domain_zone='dalmatian.dxw.net' TF_VAR_internal_domain_zone='dalmatian.internal' TF_VAR_ecs_private_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.128.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.129.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.130.0/24\\\"}]' TF_VAR_extra_public_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.0.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.1.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.2.0/24\\\"}]' TF_VAR_instances_key_name='dalmatian-ecs-instances' TF_VAR_instance_type='t2.medium' TF_VAR_min_servers='2' TF_VAR_max_servers='4' TF_VAR_max_instance_lifetime='86400' TF_VAR_associate_public_ip_address='0' TF_VAR_docker_storage_size='40' TF_VAR_dockerhub_email='' TF_VAR_dockerhub_token='' TF_VAR_enable_efs='false' TF_VAR_encrypt_efs='true' TF_VAR_efs_dirs='[]' TF_VAR_monitoring_docs_path='https://github.com/dxw/dalmatian/docs/monitoring-alarms/' TF_VAR_account_id='123456789012' TF_VAR_infrastructure_name='new-dedicated-cluster' TF_VAR_dalmatian_role='dalmatian-read' TF_VAR_environment='production' TF_VAR_rds='{identifier =\\\"testservice\\\",in_use_by =[\\\"test-service\\\"],clusters_in_use ={production =[\\\"test\\\"],staging =[\\\"test\\\"]},instance_class ={production =\\\"db.t2.small\\\",staging =\\\"db.t2.micro\\\"},engine =\\\"postgres\\\",engine_version =\\\"11.4\\\",allocated_storage =20,storage_encrypted =true,storage_type =\\\"gp3\\\",db_name =\\\"testapp\\\",port =5432,maintenance_window =\\\"mon:19:00-mon:19:30\\\",backup_window =\\\"09:00-10:00\\\",backup_retention_period =31,force_ssl =true,parameter_store_path_db_url_name =\\\"DATABASE_URL\\\",sql_backup_scheduled_task_environment_variables =[{name =\\\"foo\\\",value =\\\"bar\\\"}],check_sql_backup_scheduled_task_environment_variables =[{name =\\\"foo\\\",value =\\\"bar\\\"}],sync_sql_backup_to_azure =false,codebuild_access =[\\\"service-name\\\"]}' terraform validate\")\n Please stub a default value first if message might be received with other args as well. \n # ./lib/dalmatian/terraform.rb:17:in `validate'\n # ./lib/dalmatian/testable.rb:25:in `terraform_validate'\n # ./lib/dalmatian/testable.rb:9:in `call'\n # ./lib/dalmatian/cluster.rb:353:in `test_rds'\n # ./lib/dalmatian/cluster.rb:261:in `deploy_rds'\n # ./lib/dalmatian/cluster.rb:70:in `block (2 levels) in deploy'\n # ./lib/dalmatian/cluster.rb:68:in `each'\n # ./lib/dalmatian/cluster.rb:68:in `block in deploy'\n # ./lib/dalmatian/cluster.rb:59:in `each'\n # ./lib/dalmatian/cluster.rb:59:in `deploy'\n # ./lib/dalmatian/infrastructure.rb:24:in `block in deploy'\n # ./lib/dalmatian/infrastructure.rb:22:in `each'\n # ./lib/dalmatian/infrastructure.rb:22:in `deploy'\n # ./lib/dalmatian/infrastructure.rb:18:in `test'\n # ./spec/integration/tests_local_configuration_spec.rb:3116:in `block (2 levels) in <module:Dalmatian>'\n # ./spec/support/spec_helper.rb:24:in `block (3 levels) in <top (required)>'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:24:in `block in modify'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:15:in `synchronize'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:15:in `modify'\n # ./spec/support/spec_helper.rb:20:in `block (2 levels) in <top (required)>'\n # /Users/bob/.bundles/ruby/2.7.0/gems/webmock-3.19.1/lib/webmock/rspec.rb:39:in `block (2 levels) in <top (required)>'\n\n 13) tests local configuration use of \"terraform plan\" passes the cluster 2 config to \"terraform plan\"\n Failure/Error: Helper.run!(cmd)\n \n #<Dalmatian::Helper (class)> received :run! with unexpected arguments\n expected: (\"TF_VAR_region='eu-west-2' TF_VAR_cidr='10.0.0.0/16' TF_VAR_root_domain_zone='dalmatian.dxw.net' TF_VAR_internal_domain_zone='dalmatian.internal' TF_VAR_ecs_private_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.128.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.129.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.130.0/24\\\"}]' TF_VAR_extra_public_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.0.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.1.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.2.0/24\\\"}]' TF_VAR_instances_key_name='dalmatian-ecs-instances' TF_VAR_instance_type='t2.medium' TF_VAR_min_servers='2' TF_VAR_max_servers='4' TF_VAR_max_instance_lifetime='86400' TF_VAR_associate_public_ip_address='0' TF_VAR_docker_storage_size='40' TF_VAR_dockerhub_email='' TF_VAR_dockerhub_token='' TF_VAR_enable_efs='false' TF_VAR_encrypt_efs='true' TF_VAR_efs_dirs='[]' TF_VAR_monitoring_docs_path='https://github.com/dxw/dalmatian/docs/monitoring-alarms/' TF_VAR_example_var='bar' TF_VAR_environment='production' TF_VAR_cluster_name='shared-cluster-production' TF_VAR_account_id='123456789012' TF_VAR_infrastructure_name='existing-shared-cluster-production' TF_VAR_dalmatian_role='dalmatian-read' terraform plan\")\n got: (\"TF_VAR_region='eu-west-2' TF_VAR_cidr='10.0.0.0/16' TF_VAR_root_domain_zone='dalmatian.dxw.net' TF_VAR_internal_domain_zone='dalmatian.internal' TF_VAR_ecs_private_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.128.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.129.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.130.0/24\\\"}]' TF_VAR_extra_public_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.0.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.1.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.2.0/24\\\"}]' TF_VAR_instances_key_name='dalmatian-ecs-instances' TF_VAR_instance_type='t2.medium' TF_VAR_min_servers='2' TF_VAR_max_servers='4' TF_VAR_max_instance_lifetime='86400' TF_VAR_associate_public_ip_address='0' TF_VAR_docker_storage_size='40' TF_VAR_dockerhub_email='' TF_VAR_dockerhub_token='' TF_VAR_enable_efs='false' TF_VAR_encrypt_efs='true' TF_VAR_efs_dirs='[]' TF_VAR_monitoring_docs_path='https://github.com/dxw/dalmatian/docs/monitoring-alarms/' TF_VAR_account_id='123456789012' TF_VAR_infrastructure_name='new-dedicated-cluster' TF_VAR_dalmatian_role='dalmatian-read' TF_VAR_environment='production' TF_VAR_rds='{identifier =\\\"testservice\\\",in_use_by =[\\\"test-service\\\"],clusters_in_use ={production =[\\\"test\\\"],staging =[\\\"test\\\"]},instance_class ={production =\\\"db.t2.small\\\",staging =\\\"db.t2.micro\\\"},engine =\\\"postgres\\\",engine_version =\\\"11.4\\\",allocated_storage =20,storage_encrypted =true,storage_type =\\\"gp3\\\",db_name =\\\"testapp\\\",port =5432,maintenance_window =\\\"mon:19:00-mon:19:30\\\",backup_window =\\\"09:00-10:00\\\",backup_retention_period =31,force_ssl =true,parameter_store_path_db_url_name =\\\"DATABASE_URL\\\",sql_backup_scheduled_task_environment_variables =[{name =\\\"foo\\\",value =\\\"bar\\\"}],check_sql_backup_scheduled_task_environment_variables =[{name =\\\"foo\\\",value =\\\"bar\\\"}],sync_sql_backup_to_azure =false,codebuild_access =[\\\"service-name\\\"]}' terraform validate\")\n Please stub a default value first if message might be received with other args as well. \n # ./lib/dalmatian/terraform.rb:17:in `validate'\n # ./lib/dalmatian/testable.rb:25:in `terraform_validate'\n # ./lib/dalmatian/testable.rb:9:in `call'\n # ./lib/dalmatian/cluster.rb:353:in `test_rds'\n # ./lib/dalmatian/cluster.rb:261:in `deploy_rds'\n # ./lib/dalmatian/cluster.rb:70:in `block (2 levels) in deploy'\n # ./lib/dalmatian/cluster.rb:68:in `each'\n # ./lib/dalmatian/cluster.rb:68:in `block in deploy'\n # ./lib/dalmatian/cluster.rb:59:in `each'\n # ./lib/dalmatian/cluster.rb:59:in `deploy'\n # ./lib/dalmatian/infrastructure.rb:24:in `block in deploy'\n # ./lib/dalmatian/infrastructure.rb:22:in `each'\n # ./lib/dalmatian/infrastructure.rb:22:in `deploy'\n # ./lib/dalmatian/infrastructure.rb:18:in `test'\n # ./spec/integration/tests_local_configuration_spec.rb:3116:in `block (2 levels) in <module:Dalmatian>'\n # ./spec/support/spec_helper.rb:24:in `block (3 levels) in <top (required)>'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:24:in `block in modify'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:15:in `synchronize'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:15:in `modify'\n # ./spec/support/spec_helper.rb:20:in `block (2 levels) in <top (required)>'\n # /Users/bob/.bundles/ruby/2.7.0/gems/webmock-3.19.1/lib/webmock/rspec.rb:39:in `block (2 levels) in <top (required)>'\n\n 14) tests local configuration use of \"terraform plan\" passes the cluster 3 config to \"terraform plan\"\n Failure/Error: Helper.run!(cmd)\n \n #<Dalmatian::Helper (class)> received :run! with unexpected arguments\n expected: (\"TF_VAR_region='eu-west-2' TF_VAR_cidr='10.0.0.0/16' TF_VAR_root_domain_zone='dalmatian.dxw.net' TF_VAR_internal_domain_zone='dalmatian.internal' TF_VAR_ecs_private_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.128.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.129.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.130.0/24\\\"}]' TF_VAR_extra_public_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.0.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.1.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.2.0/24\\\"}]' TF_VAR_instances_key_name='dalmatian-ecs-instances' TF_VAR_instance_type='t2.medium' TF_VAR_min_servers='2' TF_VAR_max_servers='4' TF_VAR_max_instance_lifetime='86400' TF_VAR_associate_public_ip_address='0' TF_VAR_docker_storage_size='40' TF_VAR_dockerhub_email='' TF_VAR_dockerhub_token='' TF_VAR_enable_efs='false' TF_VAR_encrypt_efs='true' TF_VAR_efs_dirs='[]' TF_VAR_monitoring_docs_path='https://github.com/dxw/dalmatian/docs/monitoring-alarms/' TF_VAR_example_var='bar' TF_VAR_environment='production' TF_VAR_cluster_name='shared-cluster-production' TF_VAR_account_id='123456789012' TF_VAR_infrastructure_name='existing-shared-cluster-production' TF_VAR_dalmatian_role='dalmatian-read' terraform plan\")\n got: (\"TF_VAR_region='eu-west-2' TF_VAR_cidr='10.0.0.0/16' TF_VAR_root_domain_zone='dalmatian.dxw.net' TF_VAR_internal_domain_zone='dalmatian.internal' TF_VAR_ecs_private_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.128.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.129.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.130.0/24\\\"}]' TF_VAR_extra_public_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.0.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.1.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.2.0/24\\\"}]' TF_VAR_instances_key_name='dalmatian-ecs-instances' TF_VAR_instance_type='t2.medium' TF_VAR_min_servers='2' TF_VAR_max_servers='4' TF_VAR_max_instance_lifetime='86400' TF_VAR_associate_public_ip_address='0' TF_VAR_docker_storage_size='40' TF_VAR_dockerhub_email='' TF_VAR_dockerhub_token='' TF_VAR_enable_efs='false' TF_VAR_encrypt_efs='true' TF_VAR_efs_dirs='[]' TF_VAR_monitoring_docs_path='https://github.com/dxw/dalmatian/docs/monitoring-alarms/' TF_VAR_account_id='123456789012' TF_VAR_infrastructure_name='new-dedicated-cluster' TF_VAR_dalmatian_role='dalmatian-read' TF_VAR_environment='production' TF_VAR_rds='{identifier =\\\"testservice\\\",in_use_by =[\\\"test-service\\\"],clusters_in_use ={production =[\\\"test\\\"],staging =[\\\"test\\\"]},instance_class ={production =\\\"db.t2.small\\\",staging =\\\"db.t2.micro\\\"},engine =\\\"postgres\\\",engine_version =\\\"11.4\\\",allocated_storage =20,storage_encrypted =true,storage_type =\\\"gp3\\\",db_name =\\\"testapp\\\",port =5432,maintenance_window =\\\"mon:19:00-mon:19:30\\\",backup_window =\\\"09:00-10:00\\\",backup_retention_period =31,force_ssl =true,parameter_store_path_db_url_name =\\\"DATABASE_URL\\\",sql_backup_scheduled_task_environment_variables =[{name =\\\"foo\\\",value =\\\"bar\\\"}],check_sql_backup_scheduled_task_environment_variables =[{name =\\\"foo\\\",value =\\\"bar\\\"}],sync_sql_backup_to_azure =false,codebuild_access =[\\\"service-name\\\"]}' terraform validate\")\n Please stub a default value first if message might be received with other args as well. \n # ./lib/dalmatian/terraform.rb:17:in `validate'\n # ./lib/dalmatian/testable.rb:25:in `terraform_validate'\n # ./lib/dalmatian/testable.rb:9:in `call'\n # ./lib/dalmatian/cluster.rb:353:in `test_rds'\n # ./lib/dalmatian/cluster.rb:261:in `deploy_rds'\n # ./lib/dalmatian/cluster.rb:70:in `block (2 levels) in deploy'\n # ./lib/dalmatian/cluster.rb:68:in `each'\n # ./lib/dalmatian/cluster.rb:68:in `block in deploy'\n # ./lib/dalmatian/cluster.rb:59:in `each'\n # ./lib/dalmatian/cluster.rb:59:in `deploy'\n # ./lib/dalmatian/infrastructure.rb:24:in `block in deploy'\n # ./lib/dalmatian/infrastructure.rb:22:in `each'\n # ./lib/dalmatian/infrastructure.rb:22:in `deploy'\n # ./lib/dalmatian/infrastructure.rb:18:in `test'\n # ./spec/integration/tests_local_configuration_spec.rb:3116:in `block (2 levels) in <module:Dalmatian>'\n # ./spec/support/spec_helper.rb:24:in `block (3 levels) in <top (required)>'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:24:in `block in modify'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:15:in `synchronize'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:15:in `modify'\n # ./spec/support/spec_helper.rb:20:in `block (2 levels) in <top (required)>'\n # /Users/bob/.bundles/ruby/2.7.0/gems/webmock-3.19.1/lib/webmock/rspec.rb:39:in `block (2 levels) in <top (required)>'\n\n 15) tests local configuration use of \"terraform plan\" passes the cluster 4 config to \"terraform plan\"\n Failure/Error: Helper.run!(cmd)\n \n #<Dalmatian::Helper (class)> received :run! with unexpected arguments\n expected: (\"TF_VAR_region='eu-west-2' TF_VAR_cidr='10.0.0.0/16' TF_VAR_root_domain_zone='dalmatian.dxw.net' TF_VAR_internal_domain_zone='dalmatian.internal' TF_VAR_ecs_private_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.128.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.129.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.130.0/24\\\"}]' TF_VAR_extra_public_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.0.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.1.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.2.0/24\\\"}]' TF_VAR_instances_key_name='dalmatian-ecs-instances' TF_VAR_instance_type='t2.medium' TF_VAR_min_servers='2' TF_VAR_max_servers='4' TF_VAR_max_instance_lifetime='86400' TF_VAR_associate_public_ip_address='0' TF_VAR_docker_storage_size='40' TF_VAR_dockerhub_email='' TF_VAR_dockerhub_token='' TF_VAR_enable_efs='false' TF_VAR_encrypt_efs='true' TF_VAR_efs_dirs='[]' TF_VAR_monitoring_docs_path='https://github.com/dxw/dalmatian/docs/monitoring-alarms/' TF_VAR_example_var='bar' TF_VAR_environment='production' TF_VAR_cluster_name='shared-cluster-production' TF_VAR_account_id='123456789012' TF_VAR_infrastructure_name='existing-shared-cluster-production' TF_VAR_dalmatian_role='dalmatian-read' terraform plan\")\n got: (\"TF_VAR_region='eu-west-2' TF_VAR_cidr='10.0.0.0/16' TF_VAR_root_domain_zone='dalmatian.dxw.net' TF_VAR_internal_domain_zone='dalmatian.internal' TF_VAR_ecs_private_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.128.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.129.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.130.0/24\\\"}]' TF_VAR_extra_public_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.0.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.1.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.2.0/24\\\"}]' TF_VAR_instances_key_name='dalmatian-ecs-instances' TF_VAR_instance_type='t2.medium' TF_VAR_min_servers='2' TF_VAR_max_servers='4' TF_VAR_max_instance_lifetime='86400' TF_VAR_associate_public_ip_address='0' TF_VAR_docker_storage_size='40' TF_VAR_dockerhub_email='' TF_VAR_dockerhub_token='' TF_VAR_enable_efs='false' TF_VAR_encrypt_efs='true' TF_VAR_efs_dirs='[]' TF_VAR_monitoring_docs_path='https://github.com/dxw/dalmatian/docs/monitoring-alarms/' TF_VAR_account_id='123456789012' TF_VAR_infrastructure_name='new-dedicated-cluster' TF_VAR_dalmatian_role='dalmatian-read' TF_VAR_environment='production' TF_VAR_rds='{identifier =\\\"testservice\\\",in_use_by =[\\\"test-service\\\"],clusters_in_use ={production =[\\\"test\\\"],staging =[\\\"test\\\"]},instance_class ={production =\\\"db.t2.small\\\",staging =\\\"db.t2.micro\\\"},engine =\\\"postgres\\\",engine_version =\\\"11.4\\\",allocated_storage =20,storage_encrypted =true,storage_type =\\\"gp3\\\",db_name =\\\"testapp\\\",port =5432,maintenance_window =\\\"mon:19:00-mon:19:30\\\",backup_window =\\\"09:00-10:00\\\",backup_retention_period =31,force_ssl =true,parameter_store_path_db_url_name =\\\"DATABASE_URL\\\",sql_backup_scheduled_task_environment_variables =[{name =\\\"foo\\\",value =\\\"bar\\\"}],check_sql_backup_scheduled_task_environment_variables =[{name =\\\"foo\\\",value =\\\"bar\\\"}],sync_sql_backup_to_azure =false,codebuild_access =[\\\"service-name\\\"]}' terraform validate\")\n Please stub a default value first if message might be received with other args as well. \n # ./lib/dalmatian/terraform.rb:17:in `validate'\n # ./lib/dalmatian/testable.rb:25:in `terraform_validate'\n # ./lib/dalmatian/testable.rb:9:in `call'\n # ./lib/dalmatian/cluster.rb:353:in `test_rds'\n # ./lib/dalmatian/cluster.rb:261:in `deploy_rds'\n # ./lib/dalmatian/cluster.rb:70:in `block (2 levels) in deploy'\n # ./lib/dalmatian/cluster.rb:68:in `each'\n # ./lib/dalmatian/cluster.rb:68:in `block in deploy'\n # ./lib/dalmatian/cluster.rb:59:in `each'\n # ./lib/dalmatian/cluster.rb:59:in `deploy'\n # ./lib/dalmatian/infrastructure.rb:24:in `block in deploy'\n # ./lib/dalmatian/infrastructure.rb:22:in `each'\n # ./lib/dalmatian/infrastructure.rb:22:in `deploy'\n # ./lib/dalmatian/infrastructure.rb:18:in `test'\n # ./spec/integration/tests_local_configuration_spec.rb:3116:in `block (2 levels) in <module:Dalmatian>'\n # ./spec/support/spec_helper.rb:24:in `block (3 levels) in <top (required)>'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:24:in `block in modify'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:15:in `synchronize'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:15:in `modify'\n # ./spec/support/spec_helper.rb:20:in `block (2 levels) in <top (required)>'\n # /Users/bob/.bundles/ruby/2.7.0/gems/webmock-3.19.1/lib/webmock/rspec.rb:39:in `block (2 levels) in <top (required)>'\n\nFinished in 2.7 seconds (files took 0.81132 seconds to load)\n478 examples, 15 failures\n\nFailed examples:\n\nrspec ./spec/integration/tests_local_configuration_spec.rb:3119 # tests local configuration invokes \"terraform validate\" with the expected cluster options\nrspec ./spec/integration/tests_local_configuration_spec.rb:3155 # tests local configuration invokes \"terraform validate\" with the expected source options\nrspec ./spec/integration/tests_local_configuration_spec.rb:3161 # tests local configuration use of \"terraform plan\" passes the hosted zone config to \"terraform plan\"\nrspec ./spec/integration/tests_local_configuration_spec.rb:3167 # tests local configuration use of \"terraform plan\" passes the s3 config to \"terraform plan\"\nrspec ./spec/integration/tests_local_configuration_spec.rb:3173 # tests local configuration use of \"terraform plan\" passes the vpn customer gateway config to \"terraform plan\"\nrspec ./spec/integration/tests_local_configuration_spec.rb:3179 # tests local configuration use of \"terraform plan\" passes the base config to \"terraform plan\"\nrspec ./spec/integration/tests_local_configuration_spec.rb:3186 # tests local configuration use of \"terraform plan\" passes the waf config to \"terraform plan\"\nrspec ./spec/integration/tests_local_configuration_spec.rb:3193 # tests local configuration use of \"terraform plan\" passes the rds config to \"terraform plan\"\nrspec ./spec/integration/tests_local_configuration_spec.rb:3200 # tests local configuration use of \"terraform plan\" passes the elasticache config to \"terraform plan\"\nrspec ./spec/integration/tests_local_configuration_spec.rb:3209 # tests local configuration use of \"terraform plan\" passes the opensearch config to \"terraform plan\"\nrspec ./spec/integration/tests_local_configuration_spec.rb:3218 # tests local configuration use of \"terraform plan\" passes the services config to \"terraform plan\"\nrspec ./spec/integration/tests_local_configuration_spec.rb:3225 # tests local configuration use of \"terraform plan\" passes the loadbalancer config to \"terraform plan\"\nrspec ./spec/integration/tests_local_configuration_spec.rb:3234 # tests local configuration use of \"terraform plan\" passes the cluster 2 config to \"terraform plan\"\nrspec ./spec/integration/tests_local_configuration_spec.rb:3241 # tests local configuration use of \"terraform plan\" passes the cluster 3 config to \"terraform plan\"\nrspec ./spec/integration/tests_local_configuration_spec.rb:3245 # tests local configuration use of \"terraform plan\" passes the cluster 4 config to \"terraform plan\"\n\nCoverage report generated for RSpec to /Users/bob/git/dxw/dalmatian/coverage. 4253 / 4389 LOC (96.9%) covered.\nStopped processing SimpleCov as a previous error not related to SimpleCov has been detected\n/Users/bob/.rbenv/versions/2.7.1/bin/ruby -I/Users/bob/.bundles/ruby/2.7.0/gems/rspec-core-3.12.2/lib:/Users/bob/.bundles/ruby/2.7.0/gems/rspec-support-3.12.1/lib /Users/bob/.bundles/ruby/2.7.0/gems/rspec-core-3.12.2/exe/rspec --pattern spec/\\*\\*\\{,/\\*/\\*\\*\\}/\\*_spec.rb failed\nExit Code: 1\nProcess Group PGID: 48580"
|
|
}
|
|
}
|
|
}
|
|
],
|
|
"status": "success",
|
|
"timestamp": "2026-02-20T17:15:24.111Z",
|
|
"resultDisplay": "==> Linting YAML...\n\n==> Linting shell scripts...\n\n==> Checking Terraform for JSON errors...\n- Checking ./terraform/policies/iam-read.json... Passed\n- Checking ./terraform/policies/s3-rw-with-versioning.json... Passed\n- Checking ./terraform/policies/codestar-connection-use.json... Passed\n- Checking ./terraform/policies/iam-create-access-key.json... Passed\n- Checking ./terraform/policies/codebuild.json... Passed\n- Checking ./terraform/policies/kms-encrypt-decrypt.json... Passed\n- Checking ./terraform/policies/iam-change-password.json... Passed\n- Checking ./terraform/policies/administrator-access.json... Passed\n- Checking ./terraform/policies/assume_roles/aws-backup.json... Passed\n- Checking ./terraform/policies/assume_roles/autoscaling.json... Passed\n- Checking ./terraform/policies/assume_roles/events.json... Passed\n- Checking ./terraform/policies/assume_roles/ecs.json... Passed\n- Checking ./terraform/policies/assume_roles/codepipeline.json... Passed\n- Checking ./terraform/policies/iam-mfa.json... Passed\n- Checking ./terraform/policies/route53-read.json... Passed\n- Checking ./terraform/policies/s3-full-access.json... Passed\n- Checking ./terraform/policies/parameter-store-read-decrypt.json... Passed\n- Checking ./terraform/policies/s3-read.json... Passed\n- Checking ./terraform/policies/parameter-store-RW-encrypt-decrypt.json... Passed\n- Checking ./terraform/policies/all-read-with-billing.json... Passed\n- Checking ./terraform/policies/codebuild-start-build.json... Passed\n- Checking ./terraform/policies/all-read.json... Passed\n\n==> Linting Terraform...\n\n==> Running Ruby tests...\n/Users/bob/.rbenv/versions/2.7.1/bin/ruby -I/Users/bob/.bundles/ruby/2.7.0/gems/rspec-core-3.12.2/lib:/Users/bob/.bundles/ruby/2.7.0/gems/rspec-support-3.12.1/lib /Users/bob/.bundles/ruby/2.7.0/gems/rspec-core-3.12.2/exe/rspec --pattern spec/\\*\\*\\{,/\\*/\\*\\*\\}/\\*_spec.rb\n\ntests local configuration\n use of \"terraform apply\"\n passes the hosted zone config to \"terraform apply\"\n passes the s3 config to \"terraform apply\"\n passes the vpn customer gateway config to \"terraform apply\"\n passes the base config to \"terraform apply\"\n passes the waf config to \"terraform apply\"\n passes the rds config to \"terraform apply\"\n passes the elasticache config to \"terraform apply\"\n passes the opensearch config to \"terraform apply\"\n passes the service config to \"terraform apply\"\n passes the loadbalancer config to \"terraform apply\"\n passes the cluster 2 config to \"terraform apply\"\n passes the cluster 3 config to \"terraform apply\"\n passes the cluster 4 config to \"terraform apply\"\n\ntests remote configuration\n retrieves the remotely held full configuration\n proceeds with deploying the infrastructure as per the cached full configuration\n\ntests local configuration\n invokes \"terraform validate\" with the expected cluster options (FAILED - 1)\n invokes \"terraform validate\" with the expected source options (FAILED - 2)\n use of \"terraform plan\"\n passes the hosted zone config to \"terraform plan\" (FAILED - 3)\n passes the s3 config to \"terraform plan\" (FAILED - 4)\n passes the vpn customer gateway config to \"terraform plan\" (FAILED - 5)\n passes the base config to \"terraform plan\" (FAILED - 6)\n passes the waf config to \"terraform plan\" (FAILED - 7)\n passes the rds config to \"terraform plan\" (FAILED - 8)\n passes the elasticache config to \"terraform plan\" (FAILED - 9)\n passes the opensearch config to \"terraform plan\" (FAILED - 10)\n passes the services config to \"terraform plan\" (FAILED - 11)\n passes the loadbalancer config to \"terraform plan\" (FAILED - 12)\n passes the cluster 2 config to \"terraform plan\" (FAILED - 13)\n passes the cluster 3 config to \"terraform plan\" (FAILED - 14)\n passes the cluster 4 config to \"terraform plan\" (FAILED - 15)\n\nDalmatian::Account\n initialisation\n gathering user input\n asks the user for AWS credentials\n asks the user for the AWS account id to use\n asks the user for an account alias\n #call\n changes to the bootstrapping directory\n runs terraform init with upgrade option\n creates the new workspace using the given aws account id and alias\n runs terraform apply with the user-supplied vars\n\nDalmatian::CacheHandlerSelector\n ::new_for(remote_reference)\n when the remote reference is for a git repo\n asks for an instance of GitCacheHandler\n when the remote reference is for an S3 bucket\n asks for an instance of S3CacheHandler\n when the remote reference is for a URL\n asks for an instance of UrlCacheHandler\n when the type is unknown\n raises an error\n\nCacheHandler\n when a subclass class does not implement #cache_remote_configuration\n raises a helpful error\n\nDalmatian::CI\n CI::PATH\n is a constant\n #deploy\n changes to the ci directory\n runs terraform init with upgrade option\n creates the new workspace using the given aws account id and alias\n runs terraform apply with the user-supplied vars\n #test\n runs terraform plan with the user-supplied vars\n\nDalmatian::ClusterDeployment\n #call\n changes to the ecs directory\n asks Terraform to ensure that the workspace is in place\n when the environment includes a git reference as \"track_revision\"\n does NOT attempt to check out that commit\n when in _plan_ mode\n invokes Terraform.plan using the _dalmatian-read_ role\n when NOT in _plan_ mode\n invokes Terraform.apply using the _dalmatian-admin_\n when in _auto_approve_ mode\n asks Terraform to use auto_approve mode\n\nDalmatian::Cluster\n on initialisation\n makes Hosted zones, S3, Sources, Services, Loadbalancers, WAF and Rds\n #target_directory\n is a standard _ecs_ path\n #id\n is the primary key of the cluster definition is used\n #name\n when the cluster has an explicitly provided _name_ property\n that property is used\n when the cluster does not have an explicitly provided _name_ property\n the primary key of the cluster definition is used\n #account_id\n is the aws account key for deployment\n #sources\n represents any links to remote sources\n #environments\n represents the attributes of each environment's cluster section\n #fetch\n when the source is remotely held\n logs the plan to clone the source into the infrastructure pth\n deletes any existing source at the infrastructure location\n clones each source into the infrastructure location\n changes to the infrastructure directory for each source\n runs rake terrafile\n changes back to the APP_ROOT\n when the source is a local file path\n does not re-clone the source\n does not run terrafile\n when the specified local directory exists\n logs the fact that the local source is in place\n when the specificed local directory does not exist\n logs an error that the local source is missing\n #deploy\n deploys source infrastructure for each source and each service in each environment\n when a cluster should be created\n deploys cluster infrastructure for each environment\n when the _plan_ option IS invoked\n creates Cluster Deployments with plan settings\n when the _auto_approve_ option IS invoked\n creates Cluster Deployments with auto_approve settings\n handling of tests\n when the _test_ option is NOT invoked\n does not run cluster tests\n does not run cluster tests\n does not run cluster tests\n does not run source tests\n does not run waf tests\n does not run rds tests\n does not run service tests\n does not run service tests\n when the test option IS invoked\n runs tests\n when a cluster should NOT be created\n does not deploy cluster infrastructure\n when test option is invoked\n tests sources and services for each environment\n\nDalmatian::ClusterTest\n #call\n changes to the ecs directory\n logs our intention to run Terraform init\n runs Terraform init, with upgrade option\n ensures presence of workspace\n logs our intention to run Terraform fmt\n runs Terraform fmt with check and diff options\n logs our intention to run Terraform validate\n runs Terraform validate, with upgrade option\n changes back to the app root directory\n when the environment includes a git reference as \"track_revision\"\n does NOT attempt to check out that commit\n\nDalmatian::ConfigurationReader\n when a full configuration is provided in a local file\n #call\n has no need to use a cache handler\n returns the loaded configuration\n when a reference to a remote configuration is provided\n and the reference is provided in a local file\n uses the CacheHandlerSelector to provide the appropriate retrieval mechanism\n calls on the selected cache handler\n returns the configuration returned by the cache_handler\n and the reference is provided using environment variables\n passes the provided remote reference to the CacheHandlerSelector\n and references are provided in both environment variables and config file\n prefers the environment variable references over the config file\n and no references are provided\n raises an error\n and the remote reference is missing its _type_\n raises an error\n #ci\n when a parameter path prefix is given\n overwrites the ci:variables config with those retrieved from the param store\n leaves other ci:variables in place\n when a parameter path prefix is NOT given\n does NOT overwrite any ci:variables from the param store\n\nDalmatian::ElasticacheCluster\n #identifier\n uses elasticache identifier\n #in_use_by\n uses elasticache_cluster in_use_by list\n #node_type\n uses elasticache_cluster node_type\n #node_count\n uses elasticache_cluster node_count\n #engine\n uses elasticache_cluster engine\n #engine_version\n uses the elasticache_cluster engine_version\n #parameters\n uses the elasticache_cluster parameters list\n #port\n uses the elasticache_cluster port\n #maintenance_window\n uses the elasticache_cluster maintenance_window\n #snapshot_window\n uses the elasticache_cluster snapshot_window\n #parameter_store_path_elasticache_cluster_url_name\n uses the elasticache_cluster parameter_store_path_elasticache_cluster_url_name\n #to_params\n provides a hash of attributes for use in deployment\n\nDalmatian::ElasticacheClusterTest\n #call\n changes to the elasticache-cluster directory\n logs our intention to run Terraform init\n runs Terraform init, with upgrade option\n ensures presence of workspace\n logs our intention to run Terraform fmt\n runs Terraform fmt with check and diff options\n logs our intention to run Terraform validate\n runs Terraform validate, with upgrade option\n changes back to the app root directory\n\nDalmatian::GitCacheHandler\n #call\n deletes any old cache\n uses git clone to save the remote config to a local cache\n logs the cloning action\n logs the path to the cached configuration\n returns the cached full configuration to the caller (configuration reader)\n reads the cached full configuration from the disk in order to return to caller\n when no special cache path is given\n uses the default cache path of ./.dalmatian_cache/remote_config\n\nDalmatian::Helper\n ::git_clone(source, destination)\n when source and destination args are not provided\n raises an error with usage info\n when given source and destination args\n passes the request to the git CLI\n ::git_checkout(revision)\n checks out the given revision using run!\n ::get(source, destination)\n when source and destination args are not provided\n raises an error with usage info\n when given source and destination args\n opens the source url\n opens a new file at the destination\n writes the source resource into that file\n reads the information from the fetched resource\n ::run!\n passes given cmd to Kernel.system\n when the call to Kernel.system returns _false_\n raise a helpful error\n ::run_with_output!(cmd)\n passes given cmd to Open3.capture3\n when the system call returns a zero exit status\n returns the systems output to STDOUT\n when the system call returns a non-zero exit status\n also returns STDOUT ignoring the exit code and STDERR\n when the system call raises an ENOENT error\n catches this and raises a helpful Error\n ::change_to(path)\n passes the given path to Dir.chdir\n ::to_bool(str)\n when given nil\n returns false\n when given an empty string\n returns false\n when given lower case string _true_\n returns true\n when given mixed case string _True_\n returns true\n when given the object true\n returns true\n when given the object false\n returns false\n ::tflint\n runs the tflint cmd\n ::terrafile\n runs rake terrafile\n ::ask\n delegates to HighLine#ask\n ::ask_in_confidence\n delegates to HighLine#ask\n passes a block to mask the answer\n\nDalmatian::HostedZoneDeployment\n #call\n changes to hosted-zone infrastructure directory\n asks Terraform to ensure that the workspace is in place\n when in _plan_ mode\n invokes Terraform.plan with the _dalmatian-read_ role\n when NOT in _plan_ mode\n invokes Terraform.apply with the _dalmatian-admin_ role\n when in _auto_approve_ mode\n asks Terraform to use auto_approve mode\n\nDalmatian::HostedZone\n #domain\n uses hosted_zone domain\n #ns_records\n uses hosted_zone ns_records\n #a_records\n uses hosted_zone a_records\n #alias_records\n uses hosted_zone alias_records\n #cname_records\n uses hosted_zone cname_records\n #mx_records\n uses hosted_zone mx_records\n #txt_records\n uses hosted_zone txt_records\n #srv_records\n uses hosted_zone srv_records\n #to_params\n provides a hash of attributes for use in deployment\n\nDalmatian::HostedZoneTest\n #call\n changes to the hosted-zone directory\n logs our intention to run Terraform init\n runs Terraform init, with upgrade option\n ensures presence of workspace\n logs our intention to run Terraform fmt\n runs Terraform fmt with check and diff options\n logs our intention to run Terraform validate\n runs Terraform validate, with upgrade option\n changes back to the app root directory\n\nDalmatian::Infrastructure\n Infrastructure::PATH\n is a constant\n Infrastructure::APP_ROOT\n is a constant\n initialisation\n when configuration is not provided\n builds one using the defaults\n #clusters\n creates one cluster for each cluster description provided\n key operations on clusters\n #fetch\n asks all clusters to #fetch\n #test\n asks all clusters to #deploy with _plan_ and _test_ options\n #deploy\n when no parameters given\n asks all clusters to #deploy with _plan_, _test_ and _auto-approve_ disabled\n when parameters are given\n asks all clusters to #deploy with the given options\n when a particular infrastructure is named for deployment\n asks only the named cluster to #deploy with the given options\n\nDalmatian::Logger\n ::error(msg)\n raises an error with a red message\n ::info(msg)\n puts the given given message in white\n ::success(msg)\n puts the given given message in green\n ::warn(msg)\n puts the given given message in yellow\n\nDalmatian::OpensearchCluster\n #identifier\n uses opensearch identifier\n #in_use_by\n uses opensearch_cluster in_use_by list\n #version\n uses opensearch_cluster version\n #master_enabled\n uses opensearch_cluster master_enabled bool\n #master_count\n uses opensearch_cluster master_count\n #master_type\n uses opensearch_cluster master_type\n #instance_count\n uses opensearch_cluster instance_count\n #instance_type\n uses opensearch_cluster instance_type\n #warm_enabled\n uses opensearch_cluster warm_enabled bool\n #warm_count\n uses opensearch_cluster warm_count\n #warm_type\n uses opensearch_cluster warm_type\n #parameter_store_path_opensearch_cluster_url_name\n uses opensearch_cluster parameter_store_path_opensearch_cluster_url_name\n #volume_size\n uses opensearch_cluster volume_size\n #to_params\n provides a hash of attributes for use in deployment\n\nDalmatian::OpensearchClusterTest\n #call\n changes to the opensearch-cluster directory\n logs our intention to run Terraform init\n runs Terraform init, with upgrade option\n ensures presence of workspace\n logs our intention to run Terraform fmt\n runs Terraform fmt with check and diff options\n logs our intention to run Terraform validate\n runs Terraform validate, with upgrade option\n changes back to the app root directory\n\nDalmatian::ParameterStore\n ::get_parameter(name: \"\", with_decryption: true)\n when getting a single parameter from Parameter Store\n runs aws ssm get-parameter\n ::get_parameters_by_path(path: \"\", with_decryption: true)\n when getting parameters by path from Parameter Store\n runs aws ssm get-parameter\n\nDalmatian::RdsDeployment\n #call\n changes to rds infrastructure directory\n asks Terraform to ensure that the workspace is in place\n when in _plan_ mode\n invokes Terraform.plan with the _dalmatian-read_ role\n when NOT in _plan_ mode\n invokes Terraform.apply with the _dalmatian-admin_ role\n when in _auto_approve_ mode\n asks Terraform to use auto_approve mode\n\nDalmatian::Rds\n #identifier\n uses rds identifier\n #in_use_by\n uses rds in_use_by list\n #clusters_in_use\n uses rds clusters_in_use list\n #instance_class\n uses rds instance_class\n #engine\n uses rds engine\n #engine_version\n uses the rds engine_version\n #allocated_storage\n uses the rds allocated_storage\n #storage_encrypted\n uses the rds storage_encrypted bool\n #storage_type\n uses the rds storage_type gp3\n #db_name\n uses the rds db_name\n #port\n uses the rds port\n #maintenance_window\n uses the rds maintenance_window\n #backup_window\n uses the rds backup_window\n #backup_retention_period\n uses the rds backup_retention_period\n #force_ssl\n uses the rds force_ssl bool\n #parameter_store_path_db_url_name\n uses the rds parameter_store_path_db_url_name\n #sql_backup_scheduled_task_environment_variables\n uses the rds sql_backup_scheduled_task_environment_variables\n #check_sql_backup_scheduled_task_environment_variables\n uses the rds check_sql_backup_scheduled_task_environment_variables\n #sync_sql_backup_to_azure\n will have offsite backups disabled by default\n #replication_bucket_destination_arn\n uses the rds replication_bucket_destination_arn\n #replication_kms_key_id\n uses the rds replication_kms_key_id\n #codebuild_access\n uses the rds codebuild_access\n #to_params\n provides a hash of attributes for use in deployment\n\nDalmatian::RdsTest\n #call\n changes to the ecs-services directory\n logs our intention to run Terraform init\n runs Terraform init, with upgrade option\n ensures presence of workspace\n logs our intention to run Terraform fmt\n runs Terraform fmt with check and diff options\n logs our intention to run Terraform validate\n runs Terraform validate, with upgrade option\n changes back to the app root directory\n\nDalmatian::RemoteReferenceValues\n when the reference is for a git repo\n returns a git shaped configuration\n if _filename_ is not present\n supplies the default of _dalmatian.yml_\n when the reference is for an S3 bucket\n returns an S3 shaped configuration\n if _key_ is not present\n supplies the default of _dalmatian.yml_\n when the reference is for a URL\n returns a git shaped configuration\n\nDalmatian::S3CacheHandler\n #call\n deletes any old cache\n uses the AWS S3 cmd to save the remote config to a local cache\n logs the cloning action\n logs the path to the cached configuration\n returns the cached full configuration to the caller (configuration reader)\n reads the cached full configuration from the disk in order to return to caller\n\nDalmatian::S3Deployment\n #call\n changes to s3 infrastructure directory\n asks Terraform to ensure that the workspace is in place\n when in _plan_ mode\n invokes Terraform.plan with the _dalmatian-read_ role\n when NOT in _plan_ mode\n invokes Terraform.apply with the _dalmatian-admin_ role\n when in _auto_approve_ mode\n asks Terraform to use auto_approve mode\n\nDalmatian::S3\n #name\n uses s3 name\n #enable_s3_versioning\n uses enable_s3_versioning bool\n #encrypted\n uses s3 encrypted bool\n #acl\n uses s3 acl\n #policy\n uses s3 policy\n #service_cloudfront_read_access\n uses s3 service_cloudfront_read_access\n #cloudfront\n uses s3 cloudfront\n #to_params\n provides a hash of attributes for use in deployment\n\nDalmatian::S3Test\n #call\n changes to the s3 directory\n logs our intention to run Terraform init\n runs Terraform init, with upgrade option\n ensures presence of workspace\n logs our intention to run Terraform fmt\n runs Terraform fmt with check and diff options\n logs our intention to run Terraform validate\n runs Terraform validate, with upgrade option\n changes back to the app root directory\n\nDalmatian::ServiceDeployment\n #call\n changes to ecs-services infrastructure directory\n asks Terraform to ensure that the workspace is in place\n when in _plan_ mode\n invokes Terraform.plan with the _dalmatian-read_ role\n when NOT in _plan_ mode\n invokes Terraform.apply with the _dalmatian-admin_ role\n when in _auto_approve_ mode\n asks Terraform to use auto_approve mode\n\nDalmatian::Service\n #name\n uses service name\n #blue_green\n uses the service blue_green map\n #parameter_store_path\n uses service parameter_store_path\n #parameter_store_key\n uses service parameter_store_key\n #daemon\n uses the service daemon bool\n #monitoring\n uses the service monitoring hash\n #cloudfront\n recasts the service config in environment groups\n includes the appropriate \"custom_origins\" values in each environment\n Uses an AWS cloudfront managed cache policy\n Uses an AWS cloudfront managed origin policy\n Uses an AWS cloudfront managed response headers policy\n mirroring of elements into each environment group\n includes the \"create\" value\n includes the \"tls_protocol_version\" value\n includes the \"origin_keepalive_timeout\" value\n includes the \"origin_read_timeout\" value\n includes the \"basic_auth\" value\n includes the \"basic_auth_users_extra\" value\n includes the \"viewer_request_functions\" values\n includes the \"offline_page_http_status\" value\n bypass_protection\n uses the \"bypass_protection\" configuration\n custom_behaviors\n converts list of \"path_patterns\" to a single \"path_pattern\"\n #shared_loadbalancer_name\n returns shared loadbalancer name if the service is in use by a shared loadbalancer\n returns empty string if the service is not in use by a shared loadbalancer\n #s3_policy\n uses the service s3_policy map\n #lb_ip_whitelistt\n uses the service lb_ip_whitelist list\n #lb_idle_timeout\n uses the service lb_idle_timeout\n #global_accelerator\n uses service global_accelerator value\n #health_check_path\n uses the service health_check_path\n #health_check_grace_period\n uses the service health_check_grace_period\n #deregistration_delay\n uses the service deregistration_delay\n #serve_from_subdirectory\n uses the service serve_from_subdirectory\n #domain_names\n groups the domain names from the service domain_list into environments\n #proxy_configuration\n groups the proxy configurations from the service proxy_configuration list into environments\n #home_directory\n uses the service home_directory\n #lb_ssl_certificate\n groups the certificate arns from the service lb_ssl_certificate list into environments\n #lb_ssl_policy\n sets the default ssl policy for each environment\n #cloudfront_ssl_certificate\n groups the certificate arns from the service cloudfront_ssl_certificate list into environments\n #image_source\n uses the service image source\n #launch_on\n uses the service 'launch_on' specification\n #launch_on_cluster\n uses the service 'launch_on_cluster' string\n #cluster_min_servers\n uses the service 'cluster_min_servers' string\n #image_location\n uses the service image location\n #track_revision\n uses the service track_revision string\n #custom_codestar_connection_arn\n uses the service custom_codestar_connection_arn\n #codepipeline_use_github_v1\n uses the service codepipeline_use_github_v1\n #codepipeline_codebuild_run_in_vpc\n uses the service codepipeline_codebuild_run_in_vpc\n #codepipeline_codebuild_use_service_env\n uses the service codepipeline_codebuild_use_service_env\n #buildspec\n uses the service buildspec\n #container_port\n uses the service container port\n #container_command\n uses the service container command\n #container_volumes\n uses the service container volumes\n #container_extra_hosts\n uses the service container extra hosts\n #container_count\n uses the service container_count\n #enable_max_one_container_per_instance\n uses the service enable_max_one_container_per_instance\n #scheduled_tasks\n uses the service scheduled tasks\n #workers\n uses the service workers\n #cluster_name\n delegates to the cluster\n #cluster_id\n delegates to the cluster\n #account_id\n delegates to the cluster\n #to_params\n provides a hash of attributes for use in deployment\n\nDalmatian::ServiceTest\n #call\n changes to the ecs-services directory\n logs our intention to run Terraform init\n runs Terraform init, with upgrade option\n ensures presence of workspace\n logs our intention to run Terraform fmt\n runs Terraform fmt with check and diff options\n logs our intention to run Terraform validate\n runs Terraform validate, with upgrade option\n changes back to the app root directory\n\nDalmatian::SharedLoadbalancerDeployment\n #call\n changes to shared-loadbalancer infrastructure directory\n asks Terraform to ensure that the workspace is in place\n when in _plan_ mode\n invokes Terraform.plan with the _dalmatian-read_ role\n when NOT in _plan_ mode\n invokes Terraform.apply with the _dalmatian-admin_ role\n when in _auto_approve_ mode\n asks Terraform to use auto_approve mode\n\nDalmatian::SharedLoadbalancer\n #name\n uses shared_loadbalancer name\n #in_use_by\n uses shared_loadbalancer in_use_by list\n #clusters_in_use\n uses shared_loadbalancer clusters_in_use list\n #subnets_name\n uses shared_loadbalancer subnets_name value\n #domain_names\n uses shared_loadbalancer domain_names list provided by Services\n #internal\n uses shared_loadbalancer internal value\n #ip_whitelist\n uses shared_loadbalancer ip_whitelist list\n #idle_timeout\n uses shared_loadbalancer idle_timeout value\n #global_accelerator\n uses shared_loadbalancer global_accelerator value\n #ssl_policy\n has the default ssl policy defined\n #to_params\n provides a hash of attributes for use in deployment\n\nDalmatian::SharedLoadbalancerTest\n #call\n changes to the shared-loadbalancer directory\n logs our intention to run Terraform init\n runs Terraform init, with upgrade option\n ensures presence of workspace\n logs our intention to run Terraform fmt\n runs Terraform fmt with check and diff options\n logs our intention to run Terraform validate\n runs Terraform validate, with upgrade option\n changes back to the app root directory\n\nDalmatian::SourceDeployment\n #call\n changes to infrastructure config directory\n asks Terraform to ensure that the workspace is in place\n when the environment includes a git reference as \"track_revision\"\n checks out that commit\n passes the \"track_revision\" reference along to Terraform\n when in _plan_ mode\n invokes Terraform.plan with the _dalmatian-read_ role\n when NOT in _plan_ mode\n invokes Terraform.apply with the _dalmatian-admin_ role\n when in _auto_approve_ mode\n asks Terraform to use auto_approve mode\n\nDalmatian::Source\n #name\n uses the cluster name and its own position in the cluster's list of sources\n #cluster_name\n delegates to the cluster\n #cluster_id\n delegates to the cluster\n #account_id\n delegates to the cluster\n\nDalmatian::SourceTest\n #call\n changes to the ecs directory\n logs our intention to run Terraform init\n runs Terraform init, with upgrade option\n ensures presence of workspace\n logs our intention to run Terraform fmt\n runs Terraform fmt with check and diff options\n logs our intention to run Terraform validate\n runs Terraform validate, with upgrade option\n changes back to the app root directory\n when the environment includes a git reference as \"track_revision\"\n checks out that commit\n passes the \"track_revision\" reference along to Terraform.validate\n\nDalmatian::Terraform\n ::init(upgrade: false)\n when asked to upgrade\n passes terraform init the upgrade flag\n when not asked to upgrade\n does not pass terraform init the upgrade flag\n ::fmt(args = nil)\n when passed some additional arguments\n passes terraform fmt the upgrade flag\n when passed NO additional arguments\n invokes terraform fmt with no arguments\n ::validate(tfvars)\n passes the given _var-file_ to terraform\n reformats the given tfvars and passes them to terraform as args\n ::ensure_presence_of_workspace(workspace_name)\n logs our intention to create the workspace\n asks Terraform to create the workspace\n when the workspace already exists (and an error is rescued)\n logs our intention to _select_ rather than _create_ the workspace\n asks Terraform to select the existing workspace\n ::plan(tfvars)\n passes the given _var-file_ to terraform\n reformats the given tfvars and passes them to terraform as args\n ::apply(tfvars, auto_approve=false)\n passes the given _var-file_ to terraform\n reformats the given tfvars and passes them to terraform as args\n when auto-approve is set to true\n passes the _auto-approve_ flag to terraform apply\n ::destroy(tfvars)\n passes the given _var-file_ to terraform\n reformats the given tfvars and passes them to terraform as args\n ::list_workspaces\n changes to the bootstrapping directory\n runs the terraform cmd to list workspaces\n\nDalmatian::UrlCacheHandler\n #call\n deletes any old cache\n uses the helper to GET a URI\n logs the cloning action\n logs the path to the cached configuration\n returns the cached full configuration to the caller (configuration reader)\n reads the cached full configuration from the disk in order to return to caller\n\nDalmatian::VpnCustomerGatewayDeployment\n #call\n changes to vpn-customer-gateway infrastructure directory\n asks Terraform to ensure that the workspace is in place\n when in _plan_ mode\n invokes Terraform.plan with the _dalmatian-read_ role\n when NOT in _plan_ mode\n invokes Terraform.apply with the _dalmatian-admin_ role\n when in _auto_approve_ mode\n asks Terraform to use auto_approve mode\n\nDalmatian::VpnCustomerGateway\n #name\n uses vpn_customer_gateway name\n #bgp_asn\n uses vpn_customer_gateway bgp_asn\n #ip_address\n uses vpn_customer_gateway ip_address\n #to_params\n provides a hash of attributes for use in deployment\n\nDalmatian::VpnCustomerGatewayTest\n #call\n changes to the vpn-customer-gateway directory\n logs our intention to run Terraform init\n runs Terraform init, with upgrade option\n ensures presence of workspace\n logs our intention to run Terraform fmt\n runs Terraform fmt with check and diff options\n logs our intention to run Terraform validate\n runs Terraform validate, with upgrade option\n changes back to the app root directory\n\nDalmatian::WAFDeployment\n #call\n changes to waf infrastructure directory\n asks Terraform to ensure that the workspace is in place\n when in _plan_ mode\n invokes Terraform.plan with the _dalmatian-read_ role\n when NOT in _plan_ mode\n invokes Terraform.apply with the _dalmatian-admin_ role\n when in _auto_approve_ mode\n asks Terraform to use auto_approve mode\n\nDalmatian::WAF\n #name\n uses waf name\n #action\n uses waf action\n #ip_deny_list\n has a list of IP addresses to block\n #aws_managed_rules\n uses waf aws_managed_rules list\n #associations\n uses waf associations list\n #to_params\n provides a hash of attributes for use in deployment\n\nDalmatian::WAFTest\n #call\n changes to the ecs-services directory\n logs our intention to run Terraform init\n runs Terraform init, with upgrade option\n ensures presence of workspace\n logs our intention to run Terraform fmt\n runs Terraform fmt with check and diff options\n logs our intention to run Terraform validate\n runs Terraform validate, with upgrade option\n changes back to the app root directory\n\nFailures:\n\n 1) tests local configuration invokes \"terraform validate\" with the expected cluster options\n Failure/Error: Helper.run!(cmd)\n \n #<Dalmatian::Helper (class)> received :run! with unexpected arguments\n expected: (\"TF_VAR_region='eu-west-2' TF_VAR_cidr='10.0.0.0/16' TF_VAR_root_domain_zone='dalmatian.dxw.net' TF_VAR_internal_domain_zone='dalmatian.internal' TF_VAR_ecs_private_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.128.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.129.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.130.0/24\\\"}]' TF_VAR_extra_public_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.0.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.1.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.2.0/24\\\"}]' TF_VAR_instances_key_name='dalmatian-ecs-instances' TF_VAR_instance_type='t2.medium' TF_VAR_min_servers='2' TF_VAR_max_servers='4' TF_VAR_max_instance_lifetime='86400' TF_VAR_associate_public_ip_address='0' TF_VAR_docker_storage_size='40' TF_VAR_dockerhub_email='' TF_VAR_dockerhub_token='' TF_VAR_enable_efs='false' TF_VAR_encrypt_efs='true' TF_VAR_efs_dirs='[]' TF_VAR_monitoring_docs_path='https://github.com/dxw/dalmatian/docs/monitoring-alarms/' TF_VAR_example_var='bar' TF_VAR_environment='production' TF_VAR_cluster_name='shared-cluster-production' TF_VAR_account_id='123456789012' TF_VAR_infrastructure_name='existing-shared-cluster-production' TF_VAR_dalmatian_role='dalmatian-read' terraform plan\")\n got: (\"TF_VAR_region='eu-west-2' TF_VAR_cidr='10.0.0.0/16' TF_VAR_root_domain_zone='dalmatian.dxw.net' TF_VAR_internal_domain_zone='dalmatian.internal' TF_VAR_ecs_private_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.128.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.129.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.130.0/24\\\"}]' TF_VAR_extra_public_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.0.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.1.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.2.0/24\\\"}]' TF_VAR_instances_key_name='dalmatian-ecs-instances' TF_VAR_instance_type='t2.medium' TF_VAR_min_servers='2' TF_VAR_max_servers='4' TF_VAR_max_instance_lifetime='86400' TF_VAR_associate_public_ip_address='0' TF_VAR_docker_storage_size='40' TF_VAR_dockerhub_email='' TF_VAR_dockerhub_token='' TF_VAR_enable_efs='false' TF_VAR_encrypt_efs='true' TF_VAR_efs_dirs='[]' TF_VAR_monitoring_docs_path='https://github.com/dxw/dalmatian/docs/monitoring-alarms/' TF_VAR_account_id='123456789012' TF_VAR_infrastructure_name='new-dedicated-cluster' TF_VAR_dalmatian_role='dalmatian-read' TF_VAR_environment='production' TF_VAR_rds='{identifier =\\\"testservice\\\",in_use_by =[\\\"test-service\\\"],clusters_in_use ={production =[\\\"test\\\"],staging =[\\\"test\\\"]},instance_class ={production =\\\"db.t2.small\\\",staging =\\\"db.t2.micro\\\"},engine =\\\"postgres\\\",engine_version =\\\"11.4\\\",allocated_storage =20,storage_encrypted =true,storage_type =\\\"gp3\\\",db_name =\\\"testapp\\\",port =5432,maintenance_window =\\\"mon:19:00-mon:19:30\\\",backup_window =\\\"09:00-10:00\\\",backup_retention_period =31,force_ssl =true,parameter_store_path_db_url_name =\\\"DATABASE_URL\\\",sql_backup_scheduled_task_environment_variables =[{name =\\\"foo\\\",value =\\\"bar\\\"}],check_sql_backup_scheduled_task_environment_variables =[{name =\\\"foo\\\",value =\\\"bar\\\"}],sync_sql_backup_to_azure =false,codebuild_access =[\\\"service-name\\\"]}' terraform validate\")\n Please stub a default value first if message might be received with other args as well. \n # ./lib/dalmatian/terraform.rb:17:in `validate'\n # ./lib/dalmatian/testable.rb:25:in `terraform_validate'\n # ./lib/dalmatian/testable.rb:9:in `call'\n # ./lib/dalmatian/cluster.rb:353:in `test_rds'\n # ./lib/dalmatian/cluster.rb:261:in `deploy_rds'\n # ./lib/dalmatian/cluster.rb:70:in `block (2 levels) in deploy'\n # ./lib/dalmatian/cluster.rb:68:in `each'\n # ./lib/dalmatian/cluster.rb:68:in `block in deploy'\n # ./lib/dalmatian/cluster.rb:59:in `each'\n # ./lib/dalmatian/cluster.rb:59:in `deploy'\n # ./lib/dalmatian/infrastructure.rb:24:in `block in deploy'\n # ./lib/dalmatian/infrastructure.rb:22:in `each'\n # ./lib/dalmatian/infrastructure.rb:22:in `deploy'\n # ./lib/dalmatian/infrastructure.rb:18:in `test'\n # ./spec/integration/tests_local_configuration_spec.rb:3116:in `block (2 levels) in <module:Dalmatian>'\n # ./spec/support/spec_helper.rb:24:in `block (3 levels) in <top (required)>'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:24:in `block in modify'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:15:in `synchronize'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:15:in `modify'\n # ./spec/support/spec_helper.rb:20:in `block (2 levels) in <top (required)>'\n # /Users/bob/.bundles/ruby/2.7.0/gems/webmock-3.19.1/lib/webmock/rspec.rb:39:in `block (2 levels) in <top (required)>'\n\n 2) tests local configuration invokes \"terraform validate\" with the expected source options\n Failure/Error: Helper.run!(cmd)\n \n #<Dalmatian::Helper (class)> received :run! with unexpected arguments\n expected: (\"TF_VAR_region='eu-west-2' TF_VAR_cidr='10.0.0.0/16' TF_VAR_root_domain_zone='dalmatian.dxw.net' TF_VAR_internal_domain_zone='dalmatian.internal' TF_VAR_ecs_private_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.128.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.129.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.130.0/24\\\"}]' TF_VAR_extra_public_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.0.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.1.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.2.0/24\\\"}]' TF_VAR_instances_key_name='dalmatian-ecs-instances' TF_VAR_instance_type='t2.medium' TF_VAR_min_servers='2' TF_VAR_max_servers='4' TF_VAR_max_instance_lifetime='86400' TF_VAR_associate_public_ip_address='0' TF_VAR_docker_storage_size='40' TF_VAR_dockerhub_email='' TF_VAR_dockerhub_token='' TF_VAR_enable_efs='false' TF_VAR_encrypt_efs='true' TF_VAR_efs_dirs='[]' TF_VAR_monitoring_docs_path='https://github.com/dxw/dalmatian/docs/monitoring-alarms/' TF_VAR_example_var='bar' TF_VAR_environment='production' TF_VAR_cluster_name='shared-cluster-production' TF_VAR_account_id='123456789012' TF_VAR_infrastructure_name='existing-shared-cluster-production' TF_VAR_dalmatian_role='dalmatian-read' terraform plan\")\n got: (\"TF_VAR_region='eu-west-2' TF_VAR_cidr='10.0.0.0/16' TF_VAR_root_domain_zone='dalmatian.dxw.net' TF_VAR_internal_domain_zone='dalmatian.internal' TF_VAR_ecs_private_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.128.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.129.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.130.0/24\\\"}]' TF_VAR_extra_public_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.0.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.1.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.2.0/24\\\"}]' TF_VAR_instances_key_name='dalmatian-ecs-instances' TF_VAR_instance_type='t2.medium' TF_VAR_min_servers='2' TF_VAR_max_servers='4' TF_VAR_max_instance_lifetime='86400' TF_VAR_associate_public_ip_address='0' TF_VAR_docker_storage_size='40' TF_VAR_dockerhub_email='' TF_VAR_dockerhub_token='' TF_VAR_enable_efs='false' TF_VAR_encrypt_efs='true' TF_VAR_efs_dirs='[]' TF_VAR_monitoring_docs_path='https://github.com/dxw/dalmatian/docs/monitoring-alarms/' TF_VAR_account_id='123456789012' TF_VAR_infrastructure_name='new-dedicated-cluster' TF_VAR_dalmatian_role='dalmatian-read' TF_VAR_environment='production' TF_VAR_rds='{identifier =\\\"testservice\\\",in_use_by =[\\\"test-service\\\"],clusters_in_use ={production =[\\\"test\\\"],staging =[\\\"test\\\"]},instance_class ={production =\\\"db.t2.small\\\",staging =\\\"db.t2.micro\\\"},engine =\\\"postgres\\\",engine_version =\\\"11.4\\\",allocated_storage =20,storage_encrypted =true,storage_type =\\\"gp3\\\",db_name =\\\"testapp\\\",port =5432,maintenance_window =\\\"mon:19:00-mon:19:30\\\",backup_window =\\\"09:00-10:00\\\",backup_retention_period =31,force_ssl =true,parameter_store_path_db_url_name =\\\"DATABASE_URL\\\",sql_backup_scheduled_task_environment_variables =[{name =\\\"foo\\\",value =\\\"bar\\\"}],check_sql_backup_scheduled_task_environment_variables =[{name =\\\"foo\\\",value =\\\"bar\\\"}],sync_sql_backup_to_azure =false,codebuild_access =[\\\"service-name\\\"]}' terraform validate\")\n Please stub a default value first if message might be received with other args as well. \n # ./lib/dalmatian/terraform.rb:17:in `validate'\n # ./lib/dalmatian/testable.rb:25:in `terraform_validate'\n # ./lib/dalmatian/testable.rb:9:in `call'\n # ./lib/dalmatian/cluster.rb:353:in `test_rds'\n # ./lib/dalmatian/cluster.rb:261:in `deploy_rds'\n # ./lib/dalmatian/cluster.rb:70:in `block (2 levels) in deploy'\n # ./lib/dalmatian/cluster.rb:68:in `each'\n # ./lib/dalmatian/cluster.rb:68:in `block in deploy'\n # ./lib/dalmatian/cluster.rb:59:in `each'\n # ./lib/dalmatian/cluster.rb:59:in `deploy'\n # ./lib/dalmatian/infrastructure.rb:24:in `block in deploy'\n # ./lib/dalmatian/infrastructure.rb:22:in `each'\n # ./lib/dalmatian/infrastructure.rb:22:in `deploy'\n # ./lib/dalmatian/infrastructure.rb:18:in `test'\n # ./spec/integration/tests_local_configuration_spec.rb:3116:in `block (2 levels) in <module:Dalmatian>'\n # ./spec/support/spec_helper.rb:24:in `block (3 levels) in <top (required)>'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:24:in `block in modify'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:15:in `synchronize'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:15:in `modify'\n # ./spec/support/spec_helper.rb:20:in `block (2 levels) in <top (required)>'\n # /Users/bob/.bundles/ruby/2.7.0/gems/webmock-3.19.1/lib/webmock/rspec.rb:39:in `block (2 levels) in <top (required)>'\n\n 3) tests local configuration use of \"terraform plan\" passes the hosted zone config to \"terraform plan\"\n Failure/Error: Helper.run!(cmd)\n \n #<Dalmatian::Helper (class)> received :run! with unexpected arguments\n expected: (\"TF_VAR_region='eu-west-2' TF_VAR_cidr='10.0.0.0/16' TF_VAR_root_domain_zone='dalmatian.dxw.net' TF_VAR_internal_domain_zone='dalmatian.internal' TF_VAR_ecs_private_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.128.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.129.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.130.0/24\\\"}]' TF_VAR_extra_public_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.0.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.1.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.2.0/24\\\"}]' TF_VAR_instances_key_name='dalmatian-ecs-instances' TF_VAR_instance_type='t2.medium' TF_VAR_min_servers='2' TF_VAR_max_servers='4' TF_VAR_max_instance_lifetime='86400' TF_VAR_associate_public_ip_address='0' TF_VAR_docker_storage_size='40' TF_VAR_dockerhub_email='' TF_VAR_dockerhub_token='' TF_VAR_enable_efs='false' TF_VAR_encrypt_efs='true' TF_VAR_efs_dirs='[]' TF_VAR_monitoring_docs_path='https://github.com/dxw/dalmatian/docs/monitoring-alarms/' TF_VAR_example_var='bar' TF_VAR_environment='production' TF_VAR_cluster_name='shared-cluster-production' TF_VAR_account_id='123456789012' TF_VAR_infrastructure_name='existing-shared-cluster-production' TF_VAR_dalmatian_role='dalmatian-read' terraform plan\")\n got: (\"TF_VAR_region='eu-west-2' TF_VAR_cidr='10.0.0.0/16' TF_VAR_root_domain_zone='dalmatian.dxw.net' TF_VAR_internal_domain_zone='dalmatian.internal' TF_VAR_ecs_private_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.128.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.129.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.130.0/24\\\"}]' TF_VAR_extra_public_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.0.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.1.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.2.0/24\\\"}]' TF_VAR_instances_key_name='dalmatian-ecs-instances' TF_VAR_instance_type='t2.medium' TF_VAR_min_servers='2' TF_VAR_max_servers='4' TF_VAR_max_instance_lifetime='86400' TF_VAR_associate_public_ip_address='0' TF_VAR_docker_storage_size='40' TF_VAR_dockerhub_email='' TF_VAR_dockerhub_token='' TF_VAR_enable_efs='false' TF_VAR_encrypt_efs='true' TF_VAR_efs_dirs='[]' TF_VAR_monitoring_docs_path='https://github.com/dxw/dalmatian/docs/monitoring-alarms/' TF_VAR_account_id='123456789012' TF_VAR_infrastructure_name='new-dedicated-cluster' TF_VAR_dalmatian_role='dalmatian-read' TF_VAR_environment='production' TF_VAR_rds='{identifier =\\\"testservice\\\",in_use_by =[\\\"test-service\\\"],clusters_in_use ={production =[\\\"test\\\"],staging =[\\\"test\\\"]},instance_class ={production =\\\"db.t2.small\\\",staging =\\\"db.t2.micro\\\"},engine =\\\"postgres\\\",engine_version =\\\"11.4\\\",allocated_storage =20,storage_encrypted =true,storage_type =\\\"gp3\\\",db_name =\\\"testapp\\\",port =5432,maintenance_window =\\\"mon:19:00-mon:19:30\\\",backup_window =\\\"09:00-10:00\\\",backup_retention_period =31,force_ssl =true,parameter_store_path_db_url_name =\\\"DATABASE_URL\\\",sql_backup_scheduled_task_environment_variables =[{name =\\\"foo\\\",value =\\\"bar\\\"}],check_sql_backup_scheduled_task_environment_variables =[{name =\\\"foo\\\",value =\\\"bar\\\"}],sync_sql_backup_to_azure =false,codebuild_access =[\\\"service-name\\\"]}' terraform validate\")\n Please stub a default value first if message might be received with other args as well. \n # ./lib/dalmatian/terraform.rb:17:in `validate'\n # ./lib/dalmatian/testable.rb:25:in `terraform_validate'\n # ./lib/dalmatian/testable.rb:9:in `call'\n # ./lib/dalmatian/cluster.rb:353:in `test_rds'\n # ./lib/dalmatian/cluster.rb:261:in `deploy_rds'\n # ./lib/dalmatian/cluster.rb:70:in `block (2 levels) in deploy'\n # ./lib/dalmatian/cluster.rb:68:in `each'\n # ./lib/dalmatian/cluster.rb:68:in `block in deploy'\n # ./lib/dalmatian/cluster.rb:59:in `each'\n # ./lib/dalmatian/cluster.rb:59:in `deploy'\n # ./lib/dalmatian/infrastructure.rb:24:in `block in deploy'\n # ./lib/dalmatian/infrastructure.rb:22:in `each'\n # ./lib/dalmatian/infrastructure.rb:22:in `deploy'\n # ./lib/dalmatian/infrastructure.rb:18:in `test'\n # ./spec/integration/tests_local_configuration_spec.rb:3116:in `block (2 levels) in <module:Dalmatian>'\n # ./spec/support/spec_helper.rb:24:in `block (3 levels) in <top (required)>'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:24:in `block in modify'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:15:in `synchronize'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:15:in `modify'\n # ./spec/support/spec_helper.rb:20:in `block (2 levels) in <top (required)>'\n # /Users/bob/.bundles/ruby/2.7.0/gems/webmock-3.19.1/lib/webmock/rspec.rb:39:in `block (2 levels) in <top (required)>'\n\n 4) tests local configuration use of \"terraform plan\" passes the s3 config to \"terraform plan\"\n Failure/Error: Helper.run!(cmd)\n \n #<Dalmatian::Helper (class)> received :run! with unexpected arguments\n expected: (\"TF_VAR_region='eu-west-2' TF_VAR_cidr='10.0.0.0/16' TF_VAR_root_domain_zone='dalmatian.dxw.net' TF_VAR_internal_domain_zone='dalmatian.internal' TF_VAR_ecs_private_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.128.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.129.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.130.0/24\\\"}]' TF_VAR_extra_public_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.0.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.1.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.2.0/24\\\"}]' TF_VAR_instances_key_name='dalmatian-ecs-instances' TF_VAR_instance_type='t2.medium' TF_VAR_min_servers='2' TF_VAR_max_servers='4' TF_VAR_max_instance_lifetime='86400' TF_VAR_associate_public_ip_address='0' TF_VAR_docker_storage_size='40' TF_VAR_dockerhub_email='' TF_VAR_dockerhub_token='' TF_VAR_enable_efs='false' TF_VAR_encrypt_efs='true' TF_VAR_efs_dirs='[]' TF_VAR_monitoring_docs_path='https://github.com/dxw/dalmatian/docs/monitoring-alarms/' TF_VAR_example_var='bar' TF_VAR_environment='production' TF_VAR_cluster_name='shared-cluster-production' TF_VAR_account_id='123456789012' TF_VAR_infrastructure_name='existing-shared-cluster-production' TF_VAR_dalmatian_role='dalmatian-read' terraform plan\")\n got: (\"TF_VAR_region='eu-west-2' TF_VAR_cidr='10.0.0.0/16' TF_VAR_root_domain_zone='dalmatian.dxw.net' TF_VAR_internal_domain_zone='dalmatian.internal' TF_VAR_ecs_private_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.128.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.129.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.130.0/24\\\"}]' TF_VAR_extra_public_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.0.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.1.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.2.0/24\\\"}]' TF_VAR_instances_key_name='dalmatian-ecs-instances' TF_VAR_instance_type='t2.medium' TF_VAR_min_servers='2' TF_VAR_max_servers='4' TF_VAR_max_instance_lifetime='86400' TF_VAR_associate_public_ip_address='0' TF_VAR_docker_storage_size='40' TF_VAR_dockerhub_email='' TF_VAR_dockerhub_token='' TF_VAR_enable_efs='false' TF_VAR_encrypt_efs='true' TF_VAR_efs_dirs='[]' TF_VAR_monitoring_docs_path='https://github.com/dxw/dalmatian/docs/monitoring-alarms/' TF_VAR_account_id='123456789012' TF_VAR_infrastructure_name='new-dedicated-cluster' TF_VAR_dalmatian_role='dalmatian-read' TF_VAR_environment='production' TF_VAR_rds='{identifier =\\\"testservice\\\",in_use_by =[\\\"test-service\\\"],clusters_in_use ={production =[\\\"test\\\"],staging =[\\\"test\\\"]},instance_class ={production =\\\"db.t2.small\\\",staging =\\\"db.t2.micro\\\"},engine =\\\"postgres\\\",engine_version =\\\"11.4\\\",allocated_storage =20,storage_encrypted =true,storage_type =\\\"gp3\\\",db_name =\\\"testapp\\\",port =5432,maintenance_window =\\\"mon:19:00-mon:19:30\\\",backup_window =\\\"09:00-10:00\\\",backup_retention_period =31,force_ssl =true,parameter_store_path_db_url_name =\\\"DATABASE_URL\\\",sql_backup_scheduled_task_environment_variables =[{name =\\\"foo\\\",value =\\\"bar\\\"}],check_sql_backup_scheduled_task_environment_variables =[{name =\\\"foo\\\",value =\\\"bar\\\"}],sync_sql_backup_to_azure =false,codebuild_access =[\\\"service-name\\\"]}' terraform validate\")\n Please stub a default value first if message might be received with other args as well. \n # ./lib/dalmatian/terraform.rb:17:in `validate'\n # ./lib/dalmatian/testable.rb:25:in `terraform_validate'\n # ./lib/dalmatian/testable.rb:9:in `call'\n # ./lib/dalmatian/cluster.rb:353:in `test_rds'\n # ./lib/dalmatian/cluster.rb:261:in `deploy_rds'\n # ./lib/dalmatian/cluster.rb:70:in `block (2 levels) in deploy'\n # ./lib/dalmatian/cluster.rb:68:in `each'\n # ./lib/dalmatian/cluster.rb:68:in `block in deploy'\n # ./lib/dalmatian/cluster.rb:59:in `each'\n # ./lib/dalmatian/cluster.rb:59:in `deploy'\n # ./lib/dalmatian/infrastructure.rb:24:in `block in deploy'\n # ./lib/dalmatian/infrastructure.rb:22:in `each'\n # ./lib/dalmatian/infrastructure.rb:22:in `deploy'\n # ./lib/dalmatian/infrastructure.rb:18:in `test'\n # ./spec/integration/tests_local_configuration_spec.rb:3116:in `block (2 levels) in <module:Dalmatian>'\n # ./spec/support/spec_helper.rb:24:in `block (3 levels) in <top (required)>'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:24:in `block in modify'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:15:in `synchronize'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:15:in `modify'\n # ./spec/support/spec_helper.rb:20:in `block (2 levels) in <top (required)>'\n # /Users/bob/.bundles/ruby/2.7.0/gems/webmock-3.19.1/lib/webmock/rspec.rb:39:in `block (2 levels) in <top (required)>'\n\n 5) tests local configuration use of \"terraform plan\" passes the vpn customer gateway config to \"terraform plan\"\n Failure/Error: Helper.run!(cmd)\n \n #<Dalmatian::Helper (class)> received :run! with unexpected arguments\n expected: (\"TF_VAR_region='eu-west-2' TF_VAR_cidr='10.0.0.0/16' TF_VAR_root_domain_zone='dalmatian.dxw.net' TF_VAR_internal_domain_zone='dalmatian.internal' TF_VAR_ecs_private_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.128.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.129.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.130.0/24\\\"}]' TF_VAR_extra_public_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.0.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.1.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.2.0/24\\\"}]' TF_VAR_instances_key_name='dalmatian-ecs-instances' TF_VAR_instance_type='t2.medium' TF_VAR_min_servers='2' TF_VAR_max_servers='4' TF_VAR_max_instance_lifetime='86400' TF_VAR_associate_public_ip_address='0' TF_VAR_docker_storage_size='40' TF_VAR_dockerhub_email='' TF_VAR_dockerhub_token='' TF_VAR_enable_efs='false' TF_VAR_encrypt_efs='true' TF_VAR_efs_dirs='[]' TF_VAR_monitoring_docs_path='https://github.com/dxw/dalmatian/docs/monitoring-alarms/' TF_VAR_example_var='bar' TF_VAR_environment='production' TF_VAR_cluster_name='shared-cluster-production' TF_VAR_account_id='123456789012' TF_VAR_infrastructure_name='existing-shared-cluster-production' TF_VAR_dalmatian_role='dalmatian-read' terraform plan\")\n got: (\"TF_VAR_region='eu-west-2' TF_VAR_cidr='10.0.0.0/16' TF_VAR_root_domain_zone='dalmatian.dxw.net' TF_VAR_internal_domain_zone='dalmatian.internal' TF_VAR_ecs_private_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.128.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.129.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.130.0/24\\\"}]' TF_VAR_extra_public_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.0.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.1.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.2.0/24\\\"}]' TF_VAR_instances_key_name='dalmatian-ecs-instances' TF_VAR_instance_type='t2.medium' TF_VAR_min_servers='2' TF_VAR_max_servers='4' TF_VAR_max_instance_lifetime='86400' TF_VAR_associate_public_ip_address='0' TF_VAR_docker_storage_size='40' TF_VAR_dockerhub_email='' TF_VAR_dockerhub_token='' TF_VAR_enable_efs='false' TF_VAR_encrypt_efs='true' TF_VAR_efs_dirs='[]' TF_VAR_monitoring_docs_path='https://github.com/dxw/dalmatian/docs/monitoring-alarms/' TF_VAR_account_id='123456789012' TF_VAR_infrastructure_name='new-dedicated-cluster' TF_VAR_dalmatian_role='dalmatian-read' TF_VAR_environment='production' TF_VAR_rds='{identifier =\\\"testservice\\\",in_use_by =[\\\"test-service\\\"],clusters_in_use ={production =[\\\"test\\\"],staging =[\\\"test\\\"]},instance_class ={production =\\\"db.t2.small\\\",staging =\\\"db.t2.micro\\\"},engine =\\\"postgres\\\",engine_version =\\\"11.4\\\",allocated_storage =20,storage_encrypted =true,storage_type =\\\"gp3\\\",db_name =\\\"testapp\\\",port =5432,maintenance_window =\\\"mon:19:00-mon:19:30\\\",backup_window =\\\"09:00-10:00\\\",backup_retention_period =31,force_ssl =true,parameter_store_path_db_url_name =\\\"DATABASE_URL\\\",sql_backup_scheduled_task_environment_variables =[{name =\\\"foo\\\",value =\\\"bar\\\"}],check_sql_backup_scheduled_task_environment_variables =[{name =\\\"foo\\\",value =\\\"bar\\\"}],sync_sql_backup_to_azure =false,codebuild_access =[\\\"service-name\\\"]}' terraform validate\")\n Please stub a default value first if message might be received with other args as well. \n # ./lib/dalmatian/terraform.rb:17:in `validate'\n # ./lib/dalmatian/testable.rb:25:in `terraform_validate'\n # ./lib/dalmatian/testable.rb:9:in `call'\n # ./lib/dalmatian/cluster.rb:353:in `test_rds'\n # ./lib/dalmatian/cluster.rb:261:in `deploy_rds'\n # ./lib/dalmatian/cluster.rb:70:in `block (2 levels) in deploy'\n # ./lib/dalmatian/cluster.rb:68:in `each'\n # ./lib/dalmatian/cluster.rb:68:in `block in deploy'\n # ./lib/dalmatian/cluster.rb:59:in `each'\n # ./lib/dalmatian/cluster.rb:59:in `deploy'\n # ./lib/dalmatian/infrastructure.rb:24:in `block in deploy'\n # ./lib/dalmatian/infrastructure.rb:22:in `each'\n # ./lib/dalmatian/infrastructure.rb:22:in `deploy'\n # ./lib/dalmatian/infrastructure.rb:18:in `test'\n # ./spec/integration/tests_local_configuration_spec.rb:3116:in `block (2 levels) in <module:Dalmatian>'\n # ./spec/support/spec_helper.rb:24:in `block (3 levels) in <top (required)>'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:24:in `block in modify'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:15:in `synchronize'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:15:in `modify'\n # ./spec/support/spec_helper.rb:20:in `block (2 levels) in <top (required)>'\n # /Users/bob/.bundles/ruby/2.7.0/gems/webmock-3.19.1/lib/webmock/rspec.rb:39:in `block (2 levels) in <top (required)>'\n\n 6) tests local configuration use of \"terraform plan\" passes the base config to \"terraform plan\"\n Failure/Error: Helper.run!(cmd)\n \n #<Dalmatian::Helper (class)> received :run! with unexpected arguments\n expected: (\"TF_VAR_region='eu-west-2' TF_VAR_cidr='10.0.0.0/16' TF_VAR_root_domain_zone='dalmatian.dxw.net' TF_VAR_internal_domain_zone='dalmatian.internal' TF_VAR_ecs_private_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.128.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.129.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.130.0/24\\\"}]' TF_VAR_extra_public_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.0.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.1.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.2.0/24\\\"}]' TF_VAR_instances_key_name='dalmatian-ecs-instances' TF_VAR_instance_type='t2.medium' TF_VAR_min_servers='2' TF_VAR_max_servers='4' TF_VAR_max_instance_lifetime='86400' TF_VAR_associate_public_ip_address='0' TF_VAR_docker_storage_size='40' TF_VAR_dockerhub_email='' TF_VAR_dockerhub_token='' TF_VAR_enable_efs='false' TF_VAR_encrypt_efs='true' TF_VAR_efs_dirs='[]' TF_VAR_monitoring_docs_path='https://github.com/dxw/dalmatian/docs/monitoring-alarms/' TF_VAR_example_var='bar' TF_VAR_environment='production' TF_VAR_cluster_name='shared-cluster-production' TF_VAR_account_id='123456789012' TF_VAR_infrastructure_name='existing-shared-cluster-production' TF_VAR_dalmatian_role='dalmatian-read' terraform plan\")\n got: (\"TF_VAR_region='eu-west-2' TF_VAR_cidr='10.0.0.0/16' TF_VAR_root_domain_zone='dalmatian.dxw.net' TF_VAR_internal_domain_zone='dalmatian.internal' TF_VAR_ecs_private_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.128.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.129.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.130.0/24\\\"}]' TF_VAR_extra_public_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.0.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.1.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.2.0/24\\\"}]' TF_VAR_instances_key_name='dalmatian-ecs-instances' TF_VAR_instance_type='t2.medium' TF_VAR_min_servers='2' TF_VAR_max_servers='4' TF_VAR_max_instance_lifetime='86400' TF_VAR_associate_public_ip_address='0' TF_VAR_docker_storage_size='40' TF_VAR_dockerhub_email='' TF_VAR_dockerhub_token='' TF_VAR_enable_efs='false' TF_VAR_encrypt_efs='true' TF_VAR_efs_dirs='[]' TF_VAR_monitoring_docs_path='https://github.com/dxw/dalmatian/docs/monitoring-alarms/' TF_VAR_account_id='123456789012' TF_VAR_infrastructure_name='new-dedicated-cluster' TF_VAR_dalmatian_role='dalmatian-read' TF_VAR_environment='production' TF_VAR_rds='{identifier =\\\"testservice\\\",in_use_by =[\\\"test-service\\\"],clusters_in_use ={production =[\\\"test\\\"],staging =[\\\"test\\\"]},instance_class ={production =\\\"db.t2.small\\\",staging =\\\"db.t2.micro\\\"},engine =\\\"postgres\\\",engine_version =\\\"11.4\\\",allocated_storage =20,storage_encrypted =true,storage_type =\\\"gp3\\\",db_name =\\\"testapp\\\",port =5432,maintenance_window =\\\"mon:19:00-mon:19:30\\\",backup_window =\\\"09:00-10:00\\\",backup_retention_period =31,force_ssl =true,parameter_store_path_db_url_name =\\\"DATABASE_URL\\\",sql_backup_scheduled_task_environment_variables =[{name =\\\"foo\\\",value =\\\"bar\\\"}],check_sql_backup_scheduled_task_environment_variables =[{name =\\\"foo\\\",value =\\\"bar\\\"}],sync_sql_backup_to_azure =false,codebuild_access =[\\\"service-name\\\"]}' terraform validate\")\n Please stub a default value first if message might be received with other args as well. \n # ./lib/dalmatian/terraform.rb:17:in `validate'\n # ./lib/dalmatian/testable.rb:25:in `terraform_validate'\n # ./lib/dalmatian/testable.rb:9:in `call'\n # ./lib/dalmatian/cluster.rb:353:in `test_rds'\n # ./lib/dalmatian/cluster.rb:261:in `deploy_rds'\n # ./lib/dalmatian/cluster.rb:70:in `block (2 levels) in deploy'\n # ./lib/dalmatian/cluster.rb:68:in `each'\n # ./lib/dalmatian/cluster.rb:68:in `block in deploy'\n # ./lib/dalmatian/cluster.rb:59:in `each'\n # ./lib/dalmatian/cluster.rb:59:in `deploy'\n # ./lib/dalmatian/infrastructure.rb:24:in `block in deploy'\n # ./lib/dalmatian/infrastructure.rb:22:in `each'\n # ./lib/dalmatian/infrastructure.rb:22:in `deploy'\n # ./lib/dalmatian/infrastructure.rb:18:in `test'\n # ./spec/integration/tests_local_configuration_spec.rb:3116:in `block (2 levels) in <module:Dalmatian>'\n # ./spec/support/spec_helper.rb:24:in `block (3 levels) in <top (required)>'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:24:in `block in modify'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:15:in `synchronize'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:15:in `modify'\n # ./spec/support/spec_helper.rb:20:in `block (2 levels) in <top (required)>'\n # /Users/bob/.bundles/ruby/2.7.0/gems/webmock-3.19.1/lib/webmock/rspec.rb:39:in `block (2 levels) in <top (required)>'\n\n 7) tests local configuration use of \"terraform plan\" passes the waf config to \"terraform plan\"\n Failure/Error: Helper.run!(cmd)\n \n #<Dalmatian::Helper (class)> received :run! with unexpected arguments\n expected: (\"TF_VAR_region='eu-west-2' TF_VAR_cidr='10.0.0.0/16' TF_VAR_root_domain_zone='dalmatian.dxw.net' TF_VAR_internal_domain_zone='dalmatian.internal' TF_VAR_ecs_private_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.128.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.129.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.130.0/24\\\"}]' TF_VAR_extra_public_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.0.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.1.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.2.0/24\\\"}]' TF_VAR_instances_key_name='dalmatian-ecs-instances' TF_VAR_instance_type='t2.medium' TF_VAR_min_servers='2' TF_VAR_max_servers='4' TF_VAR_max_instance_lifetime='86400' TF_VAR_associate_public_ip_address='0' TF_VAR_docker_storage_size='40' TF_VAR_dockerhub_email='' TF_VAR_dockerhub_token='' TF_VAR_enable_efs='false' TF_VAR_encrypt_efs='true' TF_VAR_efs_dirs='[]' TF_VAR_monitoring_docs_path='https://github.com/dxw/dalmatian/docs/monitoring-alarms/' TF_VAR_example_var='bar' TF_VAR_environment='production' TF_VAR_cluster_name='shared-cluster-production' TF_VAR_account_id='123456789012' TF_VAR_infrastructure_name='existing-shared-cluster-production' TF_VAR_dalmatian_role='dalmatian-read' terraform plan\")\n got: (\"TF_VAR_region='eu-west-2' TF_VAR_cidr='10.0.0.0/16' TF_VAR_root_domain_zone='dalmatian.dxw.net' TF_VAR_internal_domain_zone='dalmatian.internal' TF_VAR_ecs_private_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.128.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.129.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.130.0/24\\\"}]' TF_VAR_extra_public_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.0.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.1.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.2.0/24\\\"}]' TF_VAR_instances_key_name='dalmatian-ecs-instances' TF_VAR_instance_type='t2.medium' TF_VAR_min_servers='2' TF_VAR_max_servers='4' TF_VAR_max_instance_lifetime='86400' TF_VAR_associate_public_ip_address='0' TF_VAR_docker_storage_size='40' TF_VAR_dockerhub_email='' TF_VAR_dockerhub_token='' TF_VAR_enable_efs='false' TF_VAR_encrypt_efs='true' TF_VAR_efs_dirs='[]' TF_VAR_monitoring_docs_path='https://github.com/dxw/dalmatian/docs/monitoring-alarms/' TF_VAR_account_id='123456789012' TF_VAR_infrastructure_name='new-dedicated-cluster' TF_VAR_dalmatian_role='dalmatian-read' TF_VAR_environment='production' TF_VAR_rds='{identifier =\\\"testservice\\\",in_use_by =[\\\"test-service\\\"],clusters_in_use ={production =[\\\"test\\\"],staging =[\\\"test\\\"]},instance_class ={production =\\\"db.t2.small\\\",staging =\\\"db.t2.micro\\\"},engine =\\\"postgres\\\",engine_version =\\\"11.4\\\",allocated_storage =20,storage_encrypted =true,storage_type =\\\"gp3\\\",db_name =\\\"testapp\\\",port =5432,maintenance_window =\\\"mon:19:00-mon:19:30\\\",backup_window =\\\"09:00-10:00\\\",backup_retention_period =31,force_ssl =true,parameter_store_path_db_url_name =\\\"DATABASE_URL\\\",sql_backup_scheduled_task_environment_variables =[{name =\\\"foo\\\",value =\\\"bar\\\"}],check_sql_backup_scheduled_task_environment_variables =[{name =\\\"foo\\\",value =\\\"bar\\\"}],sync_sql_backup_to_azure =false,codebuild_access =[\\\"service-name\\\"]}' terraform validate\")\n Please stub a default value first if message might be received with other args as well. \n # ./lib/dalmatian/terraform.rb:17:in `validate'\n # ./lib/dalmatian/testable.rb:25:in `terraform_validate'\n # ./lib/dalmatian/testable.rb:9:in `call'\n # ./lib/dalmatian/cluster.rb:353:in `test_rds'\n # ./lib/dalmatian/cluster.rb:261:in `deploy_rds'\n # ./lib/dalmatian/cluster.rb:70:in `block (2 levels) in deploy'\n # ./lib/dalmatian/cluster.rb:68:in `each'\n # ./lib/dalmatian/cluster.rb:68:in `block in deploy'\n # ./lib/dalmatian/cluster.rb:59:in `each'\n # ./lib/dalmatian/cluster.rb:59:in `deploy'\n # ./lib/dalmatian/infrastructure.rb:24:in `block in deploy'\n # ./lib/dalmatian/infrastructure.rb:22:in `each'\n # ./lib/dalmatian/infrastructure.rb:22:in `deploy'\n # ./lib/dalmatian/infrastructure.rb:18:in `test'\n # ./spec/integration/tests_local_configuration_spec.rb:3116:in `block (2 levels) in <module:Dalmatian>'\n # ./spec/support/spec_helper.rb:24:in `block (3 levels) in <top (required)>'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:24:in `block in modify'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:15:in `synchronize'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:15:in `modify'\n # ./spec/support/spec_helper.rb:20:in `block (2 levels) in <top (required)>'\n # /Users/bob/.bundles/ruby/2.7.0/gems/webmock-3.19.1/lib/webmock/rspec.rb:39:in `block (2 levels) in <top (required)>'\n\n 8) tests local configuration use of \"terraform plan\" passes the rds config to \"terraform plan\"\n Failure/Error: Helper.run!(cmd)\n \n #<Dalmatian::Helper (class)> received :run! with unexpected arguments\n expected: (\"TF_VAR_region='eu-west-2' TF_VAR_cidr='10.0.0.0/16' TF_VAR_root_domain_zone='dalmatian.dxw.net' TF_VAR_internal_domain_zone='dalmatian.internal' TF_VAR_ecs_private_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.128.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.129.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.130.0/24\\\"}]' TF_VAR_extra_public_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.0.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.1.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.2.0/24\\\"}]' TF_VAR_instances_key_name='dalmatian-ecs-instances' TF_VAR_instance_type='t2.medium' TF_VAR_min_servers='2' TF_VAR_max_servers='4' TF_VAR_max_instance_lifetime='86400' TF_VAR_associate_public_ip_address='0' TF_VAR_docker_storage_size='40' TF_VAR_dockerhub_email='' TF_VAR_dockerhub_token='' TF_VAR_enable_efs='false' TF_VAR_encrypt_efs='true' TF_VAR_efs_dirs='[]' TF_VAR_monitoring_docs_path='https://github.com/dxw/dalmatian/docs/monitoring-alarms/' TF_VAR_example_var='bar' TF_VAR_environment='production' TF_VAR_cluster_name='shared-cluster-production' TF_VAR_account_id='123456789012' TF_VAR_infrastructure_name='existing-shared-cluster-production' TF_VAR_dalmatian_role='dalmatian-read' terraform plan\")\n got: (\"TF_VAR_region='eu-west-2' TF_VAR_cidr='10.0.0.0/16' TF_VAR_root_domain_zone='dalmatian.dxw.net' TF_VAR_internal_domain_zone='dalmatian.internal' TF_VAR_ecs_private_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.128.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.129.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.130.0/24\\\"}]' TF_VAR_extra_public_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.0.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.1.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.2.0/24\\\"}]' TF_VAR_instances_key_name='dalmatian-ecs-instances' TF_VAR_instance_type='t2.medium' TF_VAR_min_servers='2' TF_VAR_max_servers='4' TF_VAR_max_instance_lifetime='86400' TF_VAR_associate_public_ip_address='0' TF_VAR_docker_storage_size='40' TF_VAR_dockerhub_email='' TF_VAR_dockerhub_token='' TF_VAR_enable_efs='false' TF_VAR_encrypt_efs='true' TF_VAR_efs_dirs='[]' TF_VAR_monitoring_docs_path='https://github.com/dxw/dalmatian/docs/monitoring-alarms/' TF_VAR_account_id='123456789012' TF_VAR_infrastructure_name='new-dedicated-cluster' TF_VAR_dalmatian_role='dalmatian-read' TF_VAR_environment='production' TF_VAR_rds='{identifier =\\\"testservice\\\",in_use_by =[\\\"test-service\\\"],clusters_in_use ={production =[\\\"test\\\"],staging =[\\\"test\\\"]},instance_class ={production =\\\"db.t2.small\\\",staging =\\\"db.t2.micro\\\"},engine =\\\"postgres\\\",engine_version =\\\"11.4\\\",allocated_storage =20,storage_encrypted =true,storage_type =\\\"gp3\\\",db_name =\\\"testapp\\\",port =5432,maintenance_window =\\\"mon:19:00-mon:19:30\\\",backup_window =\\\"09:00-10:00\\\",backup_retention_period =31,force_ssl =true,parameter_store_path_db_url_name =\\\"DATABASE_URL\\\",sql_backup_scheduled_task_environment_variables =[{name =\\\"foo\\\",value =\\\"bar\\\"}],check_sql_backup_scheduled_task_environment_variables =[{name =\\\"foo\\\",value =\\\"bar\\\"}],sync_sql_backup_to_azure =false,codebuild_access =[\\\"service-name\\\"]}' terraform validate\")\n Please stub a default value first if message might be received with other args as well. \n # ./lib/dalmatian/terraform.rb:17:in `validate'\n # ./lib/dalmatian/testable.rb:25:in `terraform_validate'\n # ./lib/dalmatian/testable.rb:9:in `call'\n # ./lib/dalmatian/cluster.rb:353:in `test_rds'\n # ./lib/dalmatian/cluster.rb:261:in `deploy_rds'\n # ./lib/dalmatian/cluster.rb:70:in `block (2 levels) in deploy'\n # ./lib/dalmatian/cluster.rb:68:in `each'\n # ./lib/dalmatian/cluster.rb:68:in `block in deploy'\n # ./lib/dalmatian/cluster.rb:59:in `each'\n # ./lib/dalmatian/cluster.rb:59:in `deploy'\n # ./lib/dalmatian/infrastructure.rb:24:in `block in deploy'\n # ./lib/dalmatian/infrastructure.rb:22:in `each'\n # ./lib/dalmatian/infrastructure.rb:22:in `deploy'\n # ./lib/dalmatian/infrastructure.rb:18:in `test'\n # ./spec/integration/tests_local_configuration_spec.rb:3116:in `block (2 levels) in <module:Dalmatian>'\n # ./spec/support/spec_helper.rb:24:in `block (3 levels) in <top (required)>'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:24:in `block in modify'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:15:in `synchronize'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:15:in `modify'\n # ./spec/support/spec_helper.rb:20:in `block (2 levels) in <top (required)>'\n # /Users/bob/.bundles/ruby/2.7.0/gems/webmock-3.19.1/lib/webmock/rspec.rb:39:in `block (2 levels) in <top (required)>'\n\n 9) tests local configuration use of \"terraform plan\" passes the elasticache config to \"terraform plan\"\n Failure/Error: Helper.run!(cmd)\n \n #<Dalmatian::Helper (class)> received :run! with unexpected arguments\n expected: (\"TF_VAR_region='eu-west-2' TF_VAR_cidr='10.0.0.0/16' TF_VAR_root_domain_zone='dalmatian.dxw.net' TF_VAR_internal_domain_zone='dalmatian.internal' TF_VAR_ecs_private_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.128.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.129.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.130.0/24\\\"}]' TF_VAR_extra_public_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.0.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.1.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.2.0/24\\\"}]' TF_VAR_instances_key_name='dalmatian-ecs-instances' TF_VAR_instance_type='t2.medium' TF_VAR_min_servers='2' TF_VAR_max_servers='4' TF_VAR_max_instance_lifetime='86400' TF_VAR_associate_public_ip_address='0' TF_VAR_docker_storage_size='40' TF_VAR_dockerhub_email='' TF_VAR_dockerhub_token='' TF_VAR_enable_efs='false' TF_VAR_encrypt_efs='true' TF_VAR_efs_dirs='[]' TF_VAR_monitoring_docs_path='https://github.com/dxw/dalmatian/docs/monitoring-alarms/' TF_VAR_example_var='bar' TF_VAR_environment='production' TF_VAR_cluster_name='shared-cluster-production' TF_VAR_account_id='123456789012' TF_VAR_infrastructure_name='existing-shared-cluster-production' TF_VAR_dalmatian_role='dalmatian-read' terraform plan\")\n got: (\"TF_VAR_region='eu-west-2' TF_VAR_cidr='10.0.0.0/16' TF_VAR_root_domain_zone='dalmatian.dxw.net' TF_VAR_internal_domain_zone='dalmatian.internal' TF_VAR_ecs_private_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.128.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.129.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.130.0/24\\\"}]' TF_VAR_extra_public_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.0.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.1.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.2.0/24\\\"}]' TF_VAR_instances_key_name='dalmatian-ecs-instances' TF_VAR_instance_type='t2.medium' TF_VAR_min_servers='2' TF_VAR_max_servers='4' TF_VAR_max_instance_lifetime='86400' TF_VAR_associate_public_ip_address='0' TF_VAR_docker_storage_size='40' TF_VAR_dockerhub_email='' TF_VAR_dockerhub_token='' TF_VAR_enable_efs='false' TF_VAR_encrypt_efs='true' TF_VAR_efs_dirs='[]' TF_VAR_monitoring_docs_path='https://github.com/dxw/dalmatian/docs/monitoring-alarms/' TF_VAR_account_id='123456789012' TF_VAR_infrastructure_name='new-dedicated-cluster' TF_VAR_dalmatian_role='dalmatian-read' TF_VAR_environment='production' TF_VAR_rds='{identifier =\\\"testservice\\\",in_use_by =[\\\"test-service\\\"],clusters_in_use ={production =[\\\"test\\\"],staging =[\\\"test\\\"]},instance_class ={production =\\\"db.t2.small\\\",staging =\\\"db.t2.micro\\\"},engine =\\\"postgres\\\",engine_version =\\\"11.4\\\",allocated_storage =20,storage_encrypted =true,storage_type =\\\"gp3\\\",db_name =\\\"testapp\\\",port =5432,maintenance_window =\\\"mon:19:00-mon:19:30\\\",backup_window =\\\"09:00-10:00\\\",backup_retention_period =31,force_ssl =true,parameter_store_path_db_url_name =\\\"DATABASE_URL\\\",sql_backup_scheduled_task_environment_variables =[{name =\\\"foo\\\",value =\\\"bar\\\"}],check_sql_backup_scheduled_task_environment_variables =[{name =\\\"foo\\\",value =\\\"bar\\\"}],sync_sql_backup_to_azure =false,codebuild_access =[\\\"service-name\\\"]}' terraform validate\")\n Please stub a default value first if message might be received with other args as well. \n # ./lib/dalmatian/terraform.rb:17:in `validate'\n # ./lib/dalmatian/testable.rb:25:in `terraform_validate'\n # ./lib/dalmatian/testable.rb:9:in `call'\n # ./lib/dalmatian/cluster.rb:353:in `test_rds'\n # ./lib/dalmatian/cluster.rb:261:in `deploy_rds'\n # ./lib/dalmatian/cluster.rb:70:in `block (2 levels) in deploy'\n # ./lib/dalmatian/cluster.rb:68:in `each'\n # ./lib/dalmatian/cluster.rb:68:in `block in deploy'\n # ./lib/dalmatian/cluster.rb:59:in `each'\n # ./lib/dalmatian/cluster.rb:59:in `deploy'\n # ./lib/dalmatian/infrastructure.rb:24:in `block in deploy'\n # ./lib/dalmatian/infrastructure.rb:22:in `each'\n # ./lib/dalmatian/infrastructure.rb:22:in `deploy'\n # ./lib/dalmatian/infrastructure.rb:18:in `test'\n # ./spec/integration/tests_local_configuration_spec.rb:3116:in `block (2 levels) in <module:Dalmatian>'\n # ./spec/support/spec_helper.rb:24:in `block (3 levels) in <top (required)>'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:24:in `block in modify'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:15:in `synchronize'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:15:in `modify'\n # ./spec/support/spec_helper.rb:20:in `block (2 levels) in <top (required)>'\n # /Users/bob/.bundles/ruby/2.7.0/gems/webmock-3.19.1/lib/webmock/rspec.rb:39:in `block (2 levels) in <top (required)>'\n\n 10) tests local configuration use of \"terraform plan\" passes the opensearch config to \"terraform plan\"\n Failure/Error: Helper.run!(cmd)\n \n #<Dalmatian::Helper (class)> received :run! with unexpected arguments\n expected: (\"TF_VAR_region='eu-west-2' TF_VAR_cidr='10.0.0.0/16' TF_VAR_root_domain_zone='dalmatian.dxw.net' TF_VAR_internal_domain_zone='dalmatian.internal' TF_VAR_ecs_private_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.128.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.129.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.130.0/24\\\"}]' TF_VAR_extra_public_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.0.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.1.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.2.0/24\\\"}]' TF_VAR_instances_key_name='dalmatian-ecs-instances' TF_VAR_instance_type='t2.medium' TF_VAR_min_servers='2' TF_VAR_max_servers='4' TF_VAR_max_instance_lifetime='86400' TF_VAR_associate_public_ip_address='0' TF_VAR_docker_storage_size='40' TF_VAR_dockerhub_email='' TF_VAR_dockerhub_token='' TF_VAR_enable_efs='false' TF_VAR_encrypt_efs='true' TF_VAR_efs_dirs='[]' TF_VAR_monitoring_docs_path='https://github.com/dxw/dalmatian/docs/monitoring-alarms/' TF_VAR_example_var='bar' TF_VAR_environment='production' TF_VAR_cluster_name='shared-cluster-production' TF_VAR_account_id='123456789012' TF_VAR_infrastructure_name='existing-shared-cluster-production' TF_VAR_dalmatian_role='dalmatian-read' terraform plan\")\n got: (\"TF_VAR_region='eu-west-2' TF_VAR_cidr='10.0.0.0/16' TF_VAR_root_domain_zone='dalmatian.dxw.net' TF_VAR_internal_domain_zone='dalmatian.internal' TF_VAR_ecs_private_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.128.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.129.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.130.0/24\\\"}]' TF_VAR_extra_public_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.0.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.1.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.2.0/24\\\"}]' TF_VAR_instances_key_name='dalmatian-ecs-instances' TF_VAR_instance_type='t2.medium' TF_VAR_min_servers='2' TF_VAR_max_servers='4' TF_VAR_max_instance_lifetime='86400' TF_VAR_associate_public_ip_address='0' TF_VAR_docker_storage_size='40' TF_VAR_dockerhub_email='' TF_VAR_dockerhub_token='' TF_VAR_enable_efs='false' TF_VAR_encrypt_efs='true' TF_VAR_efs_dirs='[]' TF_VAR_monitoring_docs_path='https://github.com/dxw/dalmatian/docs/monitoring-alarms/' TF_VAR_account_id='123456789012' TF_VAR_infrastructure_name='new-dedicated-cluster' TF_VAR_dalmatian_role='dalmatian-read' TF_VAR_environment='production' TF_VAR_rds='{identifier =\\\"testservice\\\",in_use_by =[\\\"test-service\\\"],clusters_in_use ={production =[\\\"test\\\"],staging =[\\\"test\\\"]},instance_class ={production =\\\"db.t2.small\\\",staging =\\\"db.t2.micro\\\"},engine =\\\"postgres\\\",engine_version =\\\"11.4\\\",allocated_storage =20,storage_encrypted =true,storage_type =\\\"gp3\\\",db_name =\\\"testapp\\\",port =5432,maintenance_window =\\\"mon:19:00-mon:19:30\\\",backup_window =\\\"09:00-10:00\\\",backup_retention_period =31,force_ssl =true,parameter_store_path_db_url_name =\\\"DATABASE_URL\\\",sql_backup_scheduled_task_environment_variables =[{name =\\\"foo\\\",value =\\\"bar\\\"}],check_sql_backup_scheduled_task_environment_variables =[{name =\\\"foo\\\",value =\\\"bar\\\"}],sync_sql_backup_to_azure =false,codebuild_access =[\\\"service-name\\\"]}' terraform validate\")\n Please stub a default value first if message might be received with other args as well. \n # ./lib/dalmatian/terraform.rb:17:in `validate'\n # ./lib/dalmatian/testable.rb:25:in `terraform_validate'\n # ./lib/dalmatian/testable.rb:9:in `call'\n # ./lib/dalmatian/cluster.rb:353:in `test_rds'\n # ./lib/dalmatian/cluster.rb:261:in `deploy_rds'\n # ./lib/dalmatian/cluster.rb:70:in `block (2 levels) in deploy'\n # ./lib/dalmatian/cluster.rb:68:in `each'\n # ./lib/dalmatian/cluster.rb:68:in `block in deploy'\n # ./lib/dalmatian/cluster.rb:59:in `each'\n # ./lib/dalmatian/cluster.rb:59:in `deploy'\n # ./lib/dalmatian/infrastructure.rb:24:in `block in deploy'\n # ./lib/dalmatian/infrastructure.rb:22:in `each'\n # ./lib/dalmatian/infrastructure.rb:22:in `deploy'\n # ./lib/dalmatian/infrastructure.rb:18:in `test'\n # ./spec/integration/tests_local_configuration_spec.rb:3116:in `block (2 levels) in <module:Dalmatian>'\n # ./spec/support/spec_helper.rb:24:in `block (3 levels) in <top (required)>'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:24:in `block in modify'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:15:in `synchronize'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:15:in `modify'\n # ./spec/support/spec_helper.rb:20:in `block (2 levels) in <top (required)>'\n # /Users/bob/.bundles/ruby/2.7.0/gems/webmock-3.19.1/lib/webmock/rspec.rb:39:in `block (2 levels) in <top (required)>'\n\n 11) tests local configuration use of \"terraform plan\" passes the services config to \"terraform plan\"\n Failure/Error: Helper.run!(cmd)\n \n #<Dalmatian::Helper (class)> received :run! with unexpected arguments\n expected: (\"TF_VAR_region='eu-west-2' TF_VAR_cidr='10.0.0.0/16' TF_VAR_root_domain_zone='dalmatian.dxw.net' TF_VAR_internal_domain_zone='dalmatian.internal' TF_VAR_ecs_private_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.128.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.129.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.130.0/24\\\"}]' TF_VAR_extra_public_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.0.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.1.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.2.0/24\\\"}]' TF_VAR_instances_key_name='dalmatian-ecs-instances' TF_VAR_instance_type='t2.medium' TF_VAR_min_servers='2' TF_VAR_max_servers='4' TF_VAR_max_instance_lifetime='86400' TF_VAR_associate_public_ip_address='0' TF_VAR_docker_storage_size='40' TF_VAR_dockerhub_email='' TF_VAR_dockerhub_token='' TF_VAR_enable_efs='false' TF_VAR_encrypt_efs='true' TF_VAR_efs_dirs='[]' TF_VAR_monitoring_docs_path='https://github.com/dxw/dalmatian/docs/monitoring-alarms/' TF_VAR_example_var='bar' TF_VAR_environment='production' TF_VAR_cluster_name='shared-cluster-production' TF_VAR_account_id='123456789012' TF_VAR_infrastructure_name='existing-shared-cluster-production' TF_VAR_dalmatian_role='dalmatian-read' terraform plan\")\n got: (\"TF_VAR_region='eu-west-2' TF_VAR_cidr='10.0.0.0/16' TF_VAR_root_domain_zone='dalmatian.dxw.net' TF_VAR_internal_domain_zone='dalmatian.internal' TF_VAR_ecs_private_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.128.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.129.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.130.0/24\\\"}]' TF_VAR_extra_public_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.0.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.1.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.2.0/24\\\"}]' TF_VAR_instances_key_name='dalmatian-ecs-instances' TF_VAR_instance_type='t2.medium' TF_VAR_min_servers='2' TF_VAR_max_servers='4' TF_VAR_max_instance_lifetime='86400' TF_VAR_associate_public_ip_address='0' TF_VAR_docker_storage_size='40' TF_VAR_dockerhub_email='' TF_VAR_dockerhub_token='' TF_VAR_enable_efs='false' TF_VAR_encrypt_efs='true' TF_VAR_efs_dirs='[]' TF_VAR_monitoring_docs_path='https://github.com/dxw/dalmatian/docs/monitoring-alarms/' TF_VAR_account_id='123456789012' TF_VAR_infrastructure_name='new-dedicated-cluster' TF_VAR_dalmatian_role='dalmatian-read' TF_VAR_environment='production' TF_VAR_rds='{identifier =\\\"testservice\\\",in_use_by =[\\\"test-service\\\"],clusters_in_use ={production =[\\\"test\\\"],staging =[\\\"test\\\"]},instance_class ={production =\\\"db.t2.small\\\",staging =\\\"db.t2.micro\\\"},engine =\\\"postgres\\\",engine_version =\\\"11.4\\\",allocated_storage =20,storage_encrypted =true,storage_type =\\\"gp3\\\",db_name =\\\"testapp\\\",port =5432,maintenance_window =\\\"mon:19:00-mon:19:30\\\",backup_window =\\\"09:00-10:00\\\",backup_retention_period =31,force_ssl =true,parameter_store_path_db_url_name =\\\"DATABASE_URL\\\",sql_backup_scheduled_task_environment_variables =[{name =\\\"foo\\\",value =\\\"bar\\\"}],check_sql_backup_scheduled_task_environment_variables =[{name =\\\"foo\\\",value =\\\"bar\\\"}],sync_sql_backup_to_azure =false,codebuild_access =[\\\"service-name\\\"]}' terraform validate\")\n Please stub a default value first if message might be received with other args as well. \n # ./lib/dalmatian/terraform.rb:17:in `validate'\n # ./lib/dalmatian/testable.rb:25:in `terraform_validate'\n # ./lib/dalmatian/testable.rb:9:in `call'\n # ./lib/dalmatian/cluster.rb:353:in `test_rds'\n # ./lib/dalmatian/cluster.rb:261:in `deploy_rds'\n # ./lib/dalmatian/cluster.rb:70:in `block (2 levels) in deploy'\n # ./lib/dalmatian/cluster.rb:68:in `each'\n # ./lib/dalmatian/cluster.rb:68:in `block in deploy'\n # ./lib/dalmatian/cluster.rb:59:in `each'\n # ./lib/dalmatian/cluster.rb:59:in `deploy'\n # ./lib/dalmatian/infrastructure.rb:24:in `block in deploy'\n # ./lib/dalmatian/infrastructure.rb:22:in `each'\n # ./lib/dalmatian/infrastructure.rb:22:in `deploy'\n # ./lib/dalmatian/infrastructure.rb:18:in `test'\n # ./spec/integration/tests_local_configuration_spec.rb:3116:in `block (2 levels) in <module:Dalmatian>'\n # ./spec/support/spec_helper.rb:24:in `block (3 levels) in <top (required)>'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:24:in `block in modify'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:15:in `synchronize'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:15:in `modify'\n # ./spec/support/spec_helper.rb:20:in `block (2 levels) in <top (required)>'\n # /Users/bob/.bundles/ruby/2.7.0/gems/webmock-3.19.1/lib/webmock/rspec.rb:39:in `block (2 levels) in <top (required)>'\n\n 12) tests local configuration use of \"terraform plan\" passes the loadbalancer config to \"terraform plan\"\n Failure/Error: Helper.run!(cmd)\n \n #<Dalmatian::Helper (class)> received :run! with unexpected arguments\n expected: (\"TF_VAR_region='eu-west-2' TF_VAR_cidr='10.0.0.0/16' TF_VAR_root_domain_zone='dalmatian.dxw.net' TF_VAR_internal_domain_zone='dalmatian.internal' TF_VAR_ecs_private_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.128.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.129.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.130.0/24\\\"}]' TF_VAR_extra_public_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.0.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.1.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.2.0/24\\\"}]' TF_VAR_instances_key_name='dalmatian-ecs-instances' TF_VAR_instance_type='t2.medium' TF_VAR_min_servers='2' TF_VAR_max_servers='4' TF_VAR_max_instance_lifetime='86400' TF_VAR_associate_public_ip_address='0' TF_VAR_docker_storage_size='40' TF_VAR_dockerhub_email='' TF_VAR_dockerhub_token='' TF_VAR_enable_efs='false' TF_VAR_encrypt_efs='true' TF_VAR_efs_dirs='[]' TF_VAR_monitoring_docs_path='https://github.com/dxw/dalmatian/docs/monitoring-alarms/' TF_VAR_example_var='bar' TF_VAR_environment='production' TF_VAR_cluster_name='shared-cluster-production' TF_VAR_account_id='123456789012' TF_VAR_infrastructure_name='existing-shared-cluster-production' TF_VAR_dalmatian_role='dalmatian-read' terraform plan\")\n got: (\"TF_VAR_region='eu-west-2' TF_VAR_cidr='10.0.0.0/16' TF_VAR_root_domain_zone='dalmatian.dxw.net' TF_VAR_internal_domain_zone='dalmatian.internal' TF_VAR_ecs_private_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.128.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.129.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.130.0/24\\\"}]' TF_VAR_extra_public_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.0.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.1.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.2.0/24\\\"}]' TF_VAR_instances_key_name='dalmatian-ecs-instances' TF_VAR_instance_type='t2.medium' TF_VAR_min_servers='2' TF_VAR_max_servers='4' TF_VAR_max_instance_lifetime='86400' TF_VAR_associate_public_ip_address='0' TF_VAR_docker_storage_size='40' TF_VAR_dockerhub_email='' TF_VAR_dockerhub_token='' TF_VAR_enable_efs='false' TF_VAR_encrypt_efs='true' TF_VAR_efs_dirs='[]' TF_VAR_monitoring_docs_path='https://github.com/dxw/dalmatian/docs/monitoring-alarms/' TF_VAR_account_id='123456789012' TF_VAR_infrastructure_name='new-dedicated-cluster' TF_VAR_dalmatian_role='dalmatian-read' TF_VAR_environment='production' TF_VAR_rds='{identifier =\\\"testservice\\\",in_use_by =[\\\"test-service\\\"],clusters_in_use ={production =[\\\"test\\\"],staging =[\\\"test\\\"]},instance_class ={production =\\\"db.t2.small\\\",staging =\\\"db.t2.micro\\\"},engine =\\\"postgres\\\",engine_version =\\\"11.4\\\",allocated_storage =20,storage_encrypted =true,storage_type =\\\"gp3\\\",db_name =\\\"testapp\\\",port =5432,maintenance_window =\\\"mon:19:00-mon:19:30\\\",backup_window =\\\"09:00-10:00\\\",backup_retention_period =31,force_ssl =true,parameter_store_path_db_url_name =\\\"DATABASE_URL\\\",sql_backup_scheduled_task_environment_variables =[{name =\\\"foo\\\",value =\\\"bar\\\"}],check_sql_backup_scheduled_task_environment_variables =[{name =\\\"foo\\\",value =\\\"bar\\\"}],sync_sql_backup_to_azure =false,codebuild_access =[\\\"service-name\\\"]}' terraform validate\")\n Please stub a default value first if message might be received with other args as well. \n # ./lib/dalmatian/terraform.rb:17:in `validate'\n # ./lib/dalmatian/testable.rb:25:in `terraform_validate'\n # ./lib/dalmatian/testable.rb:9:in `call'\n # ./lib/dalmatian/cluster.rb:353:in `test_rds'\n # ./lib/dalmatian/cluster.rb:261:in `deploy_rds'\n # ./lib/dalmatian/cluster.rb:70:in `block (2 levels) in deploy'\n # ./lib/dalmatian/cluster.rb:68:in `each'\n # ./lib/dalmatian/cluster.rb:68:in `block in deploy'\n # ./lib/dalmatian/cluster.rb:59:in `each'\n # ./lib/dalmatian/cluster.rb:59:in `deploy'\n # ./lib/dalmatian/infrastructure.rb:24:in `block in deploy'\n # ./lib/dalmatian/infrastructure.rb:22:in `each'\n # ./lib/dalmatian/infrastructure.rb:22:in `deploy'\n # ./lib/dalmatian/infrastructure.rb:18:in `test'\n # ./spec/integration/tests_local_configuration_spec.rb:3116:in `block (2 levels) in <module:Dalmatian>'\n # ./spec/support/spec_helper.rb:24:in `block (3 levels) in <top (required)>'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:24:in `block in modify'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:15:in `synchronize'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:15:in `modify'\n # ./spec/support/spec_helper.rb:20:in `block (2 levels) in <top (required)>'\n # /Users/bob/.bundles/ruby/2.7.0/gems/webmock-3.19.1/lib/webmock/rspec.rb:39:in `block (2 levels) in <top (required)>'\n\n 13) tests local configuration use of \"terraform plan\" passes the cluster 2 config to \"terraform plan\"\n Failure/Error: Helper.run!(cmd)\n \n #<Dalmatian::Helper (class)> received :run! with unexpected arguments\n expected: (\"TF_VAR_region='eu-west-2' TF_VAR_cidr='10.0.0.0/16' TF_VAR_root_domain_zone='dalmatian.dxw.net' TF_VAR_internal_domain_zone='dalmatian.internal' TF_VAR_ecs_private_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.128.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.129.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.130.0/24\\\"}]' TF_VAR_extra_public_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.0.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.1.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.2.0/24\\\"}]' TF_VAR_instances_key_name='dalmatian-ecs-instances' TF_VAR_instance_type='t2.medium' TF_VAR_min_servers='2' TF_VAR_max_servers='4' TF_VAR_max_instance_lifetime='86400' TF_VAR_associate_public_ip_address='0' TF_VAR_docker_storage_size='40' TF_VAR_dockerhub_email='' TF_VAR_dockerhub_token='' TF_VAR_enable_efs='false' TF_VAR_encrypt_efs='true' TF_VAR_efs_dirs='[]' TF_VAR_monitoring_docs_path='https://github.com/dxw/dalmatian/docs/monitoring-alarms/' TF_VAR_example_var='bar' TF_VAR_environment='production' TF_VAR_cluster_name='shared-cluster-production' TF_VAR_account_id='123456789012' TF_VAR_infrastructure_name='existing-shared-cluster-production' TF_VAR_dalmatian_role='dalmatian-read' terraform plan\")\n got: (\"TF_VAR_region='eu-west-2' TF_VAR_cidr='10.0.0.0/16' TF_VAR_root_domain_zone='dalmatian.dxw.net' TF_VAR_internal_domain_zone='dalmatian.internal' TF_VAR_ecs_private_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.128.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.129.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.130.0/24\\\"}]' TF_VAR_extra_public_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.0.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.1.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.2.0/24\\\"}]' TF_VAR_instances_key_name='dalmatian-ecs-instances' TF_VAR_instance_type='t2.medium' TF_VAR_min_servers='2' TF_VAR_max_servers='4' TF_VAR_max_instance_lifetime='86400' TF_VAR_associate_public_ip_address='0' TF_VAR_docker_storage_size='40' TF_VAR_dockerhub_email='' TF_VAR_dockerhub_token='' TF_VAR_enable_efs='false' TF_VAR_encrypt_efs='true' TF_VAR_efs_dirs='[]' TF_VAR_monitoring_docs_path='https://github.com/dxw/dalmatian/docs/monitoring-alarms/' TF_VAR_account_id='123456789012' TF_VAR_infrastructure_name='new-dedicated-cluster' TF_VAR_dalmatian_role='dalmatian-read' TF_VAR_environment='production' TF_VAR_rds='{identifier =\\\"testservice\\\",in_use_by =[\\\"test-service\\\"],clusters_in_use ={production =[\\\"test\\\"],staging =[\\\"test\\\"]},instance_class ={production =\\\"db.t2.small\\\",staging =\\\"db.t2.micro\\\"},engine =\\\"postgres\\\",engine_version =\\\"11.4\\\",allocated_storage =20,storage_encrypted =true,storage_type =\\\"gp3\\\",db_name =\\\"testapp\\\",port =5432,maintenance_window =\\\"mon:19:00-mon:19:30\\\",backup_window =\\\"09:00-10:00\\\",backup_retention_period =31,force_ssl =true,parameter_store_path_db_url_name =\\\"DATABASE_URL\\\",sql_backup_scheduled_task_environment_variables =[{name =\\\"foo\\\",value =\\\"bar\\\"}],check_sql_backup_scheduled_task_environment_variables =[{name =\\\"foo\\\",value =\\\"bar\\\"}],sync_sql_backup_to_azure =false,codebuild_access =[\\\"service-name\\\"]}' terraform validate\")\n Please stub a default value first if message might be received with other args as well. \n # ./lib/dalmatian/terraform.rb:17:in `validate'\n # ./lib/dalmatian/testable.rb:25:in `terraform_validate'\n # ./lib/dalmatian/testable.rb:9:in `call'\n # ./lib/dalmatian/cluster.rb:353:in `test_rds'\n # ./lib/dalmatian/cluster.rb:261:in `deploy_rds'\n # ./lib/dalmatian/cluster.rb:70:in `block (2 levels) in deploy'\n # ./lib/dalmatian/cluster.rb:68:in `each'\n # ./lib/dalmatian/cluster.rb:68:in `block in deploy'\n # ./lib/dalmatian/cluster.rb:59:in `each'\n # ./lib/dalmatian/cluster.rb:59:in `deploy'\n # ./lib/dalmatian/infrastructure.rb:24:in `block in deploy'\n # ./lib/dalmatian/infrastructure.rb:22:in `each'\n # ./lib/dalmatian/infrastructure.rb:22:in `deploy'\n # ./lib/dalmatian/infrastructure.rb:18:in `test'\n # ./spec/integration/tests_local_configuration_spec.rb:3116:in `block (2 levels) in <module:Dalmatian>'\n # ./spec/support/spec_helper.rb:24:in `block (3 levels) in <top (required)>'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:24:in `block in modify'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:15:in `synchronize'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:15:in `modify'\n # ./spec/support/spec_helper.rb:20:in `block (2 levels) in <top (required)>'\n # /Users/bob/.bundles/ruby/2.7.0/gems/webmock-3.19.1/lib/webmock/rspec.rb:39:in `block (2 levels) in <top (required)>'\n\n 14) tests local configuration use of \"terraform plan\" passes the cluster 3 config to \"terraform plan\"\n Failure/Error: Helper.run!(cmd)\n \n #<Dalmatian::Helper (class)> received :run! with unexpected arguments\n expected: (\"TF_VAR_region='eu-west-2' TF_VAR_cidr='10.0.0.0/16' TF_VAR_root_domain_zone='dalmatian.dxw.net' TF_VAR_internal_domain_zone='dalmatian.internal' TF_VAR_ecs_private_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.128.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.129.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.130.0/24\\\"}]' TF_VAR_extra_public_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.0.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.1.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.2.0/24\\\"}]' TF_VAR_instances_key_name='dalmatian-ecs-instances' TF_VAR_instance_type='t2.medium' TF_VAR_min_servers='2' TF_VAR_max_servers='4' TF_VAR_max_instance_lifetime='86400' TF_VAR_associate_public_ip_address='0' TF_VAR_docker_storage_size='40' TF_VAR_dockerhub_email='' TF_VAR_dockerhub_token='' TF_VAR_enable_efs='false' TF_VAR_encrypt_efs='true' TF_VAR_efs_dirs='[]' TF_VAR_monitoring_docs_path='https://github.com/dxw/dalmatian/docs/monitoring-alarms/' TF_VAR_example_var='bar' TF_VAR_environment='production' TF_VAR_cluster_name='shared-cluster-production' TF_VAR_account_id='123456789012' TF_VAR_infrastructure_name='existing-shared-cluster-production' TF_VAR_dalmatian_role='dalmatian-read' terraform plan\")\n got: (\"TF_VAR_region='eu-west-2' TF_VAR_cidr='10.0.0.0/16' TF_VAR_root_domain_zone='dalmatian.dxw.net' TF_VAR_internal_domain_zone='dalmatian.internal' TF_VAR_ecs_private_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.128.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.129.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.130.0/24\\\"}]' TF_VAR_extra_public_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.0.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.1.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.2.0/24\\\"}]' TF_VAR_instances_key_name='dalmatian-ecs-instances' TF_VAR_instance_type='t2.medium' TF_VAR_min_servers='2' TF_VAR_max_servers='4' TF_VAR_max_instance_lifetime='86400' TF_VAR_associate_public_ip_address='0' TF_VAR_docker_storage_size='40' TF_VAR_dockerhub_email='' TF_VAR_dockerhub_token='' TF_VAR_enable_efs='false' TF_VAR_encrypt_efs='true' TF_VAR_efs_dirs='[]' TF_VAR_monitoring_docs_path='https://github.com/dxw/dalmatian/docs/monitoring-alarms/' TF_VAR_account_id='123456789012' TF_VAR_infrastructure_name='new-dedicated-cluster' TF_VAR_dalmatian_role='dalmatian-read' TF_VAR_environment='production' TF_VAR_rds='{identifier =\\\"testservice\\\",in_use_by =[\\\"test-service\\\"],clusters_in_use ={production =[\\\"test\\\"],staging =[\\\"test\\\"]},instance_class ={production =\\\"db.t2.small\\\",staging =\\\"db.t2.micro\\\"},engine =\\\"postgres\\\",engine_version =\\\"11.4\\\",allocated_storage =20,storage_encrypted =true,storage_type =\\\"gp3\\\",db_name =\\\"testapp\\\",port =5432,maintenance_window =\\\"mon:19:00-mon:19:30\\\",backup_window =\\\"09:00-10:00\\\",backup_retention_period =31,force_ssl =true,parameter_store_path_db_url_name =\\\"DATABASE_URL\\\",sql_backup_scheduled_task_environment_variables =[{name =\\\"foo\\\",value =\\\"bar\\\"}],check_sql_backup_scheduled_task_environment_variables =[{name =\\\"foo\\\",value =\\\"bar\\\"}],sync_sql_backup_to_azure =false,codebuild_access =[\\\"service-name\\\"]}' terraform validate\")\n Please stub a default value first if message might be received with other args as well. \n # ./lib/dalmatian/terraform.rb:17:in `validate'\n # ./lib/dalmatian/testable.rb:25:in `terraform_validate'\n # ./lib/dalmatian/testable.rb:9:in `call'\n # ./lib/dalmatian/cluster.rb:353:in `test_rds'\n # ./lib/dalmatian/cluster.rb:261:in `deploy_rds'\n # ./lib/dalmatian/cluster.rb:70:in `block (2 levels) in deploy'\n # ./lib/dalmatian/cluster.rb:68:in `each'\n # ./lib/dalmatian/cluster.rb:68:in `block in deploy'\n # ./lib/dalmatian/cluster.rb:59:in `each'\n # ./lib/dalmatian/cluster.rb:59:in `deploy'\n # ./lib/dalmatian/infrastructure.rb:24:in `block in deploy'\n # ./lib/dalmatian/infrastructure.rb:22:in `each'\n # ./lib/dalmatian/infrastructure.rb:22:in `deploy'\n # ./lib/dalmatian/infrastructure.rb:18:in `test'\n # ./spec/integration/tests_local_configuration_spec.rb:3116:in `block (2 levels) in <module:Dalmatian>'\n # ./spec/support/spec_helper.rb:24:in `block (3 levels) in <top (required)>'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:24:in `block in modify'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:15:in `synchronize'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:15:in `modify'\n # ./spec/support/spec_helper.rb:20:in `block (2 levels) in <top (required)>'\n # /Users/bob/.bundles/ruby/2.7.0/gems/webmock-3.19.1/lib/webmock/rspec.rb:39:in `block (2 levels) in <top (required)>'\n\n 15) tests local configuration use of \"terraform plan\" passes the cluster 4 config to \"terraform plan\"\n Failure/Error: Helper.run!(cmd)\n \n #<Dalmatian::Helper (class)> received :run! with unexpected arguments\n expected: (\"TF_VAR_region='eu-west-2' TF_VAR_cidr='10.0.0.0/16' TF_VAR_root_domain_zone='dalmatian.dxw.net' TF_VAR_internal_domain_zone='dalmatian.internal' TF_VAR_ecs_private_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.128.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.129.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.130.0/24\\\"}]' TF_VAR_extra_public_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.0.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.1.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.2.0/24\\\"}]' TF_VAR_instances_key_name='dalmatian-ecs-instances' TF_VAR_instance_type='t2.medium' TF_VAR_min_servers='2' TF_VAR_max_servers='4' TF_VAR_max_instance_lifetime='86400' TF_VAR_associate_public_ip_address='0' TF_VAR_docker_storage_size='40' TF_VAR_dockerhub_email='' TF_VAR_dockerhub_token='' TF_VAR_enable_efs='false' TF_VAR_encrypt_efs='true' TF_VAR_efs_dirs='[]' TF_VAR_monitoring_docs_path='https://github.com/dxw/dalmatian/docs/monitoring-alarms/' TF_VAR_example_var='bar' TF_VAR_environment='production' TF_VAR_cluster_name='shared-cluster-production' TF_VAR_account_id='123456789012' TF_VAR_infrastructure_name='existing-shared-cluster-production' TF_VAR_dalmatian_role='dalmatian-read' terraform plan\")\n got: (\"TF_VAR_region='eu-west-2' TF_VAR_cidr='10.0.0.0/16' TF_VAR_root_domain_zone='dalmatian.dxw.net' TF_VAR_internal_domain_zone='dalmatian.internal' TF_VAR_ecs_private_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.128.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.129.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.130.0/24\\\"}]' TF_VAR_extra_public_subnets='[{availability_zone =\\\"eu-west-2a\\\",cidr =\\\"10.0.0.0/24\\\"},{availability_zone =\\\"eu-west-2b\\\",cidr =\\\"10.0.1.0/24\\\"},{availability_zone =\\\"eu-west-2c\\\",cidr =\\\"10.0.2.0/24\\\"}]' TF_VAR_instances_key_name='dalmatian-ecs-instances' TF_VAR_instance_type='t2.medium' TF_VAR_min_servers='2' TF_VAR_max_servers='4' TF_VAR_max_instance_lifetime='86400' TF_VAR_associate_public_ip_address='0' TF_VAR_docker_storage_size='40' TF_VAR_dockerhub_email='' TF_VAR_dockerhub_token='' TF_VAR_enable_efs='false' TF_VAR_encrypt_efs='true' TF_VAR_efs_dirs='[]' TF_VAR_monitoring_docs_path='https://github.com/dxw/dalmatian/docs/monitoring-alarms/' TF_VAR_account_id='123456789012' TF_VAR_infrastructure_name='new-dedicated-cluster' TF_VAR_dalmatian_role='dalmatian-read' TF_VAR_environment='production' TF_VAR_rds='{identifier =\\\"testservice\\\",in_use_by =[\\\"test-service\\\"],clusters_in_use ={production =[\\\"test\\\"],staging =[\\\"test\\\"]},instance_class ={production =\\\"db.t2.small\\\",staging =\\\"db.t2.micro\\\"},engine =\\\"postgres\\\",engine_version =\\\"11.4\\\",allocated_storage =20,storage_encrypted =true,storage_type =\\\"gp3\\\",db_name =\\\"testapp\\\",port =5432,maintenance_window =\\\"mon:19:00-mon:19:30\\\",backup_window =\\\"09:00-10:00\\\",backup_retention_period =31,force_ssl =true,parameter_store_path_db_url_name =\\\"DATABASE_URL\\\",sql_backup_scheduled_task_environment_variables =[{name =\\\"foo\\\",value =\\\"bar\\\"}],check_sql_backup_scheduled_task_environment_variables =[{name =\\\"foo\\\",value =\\\"bar\\\"}],sync_sql_backup_to_azure =false,codebuild_access =[\\\"service-name\\\"]}' terraform validate\")\n Please stub a default value first if message might be received with other args as well. \n # ./lib/dalmatian/terraform.rb:17:in `validate'\n # ./lib/dalmatian/testable.rb:25:in `terraform_validate'\n # ./lib/dalmatian/testable.rb:9:in `call'\n # ./lib/dalmatian/cluster.rb:353:in `test_rds'\n # ./lib/dalmatian/cluster.rb:261:in `deploy_rds'\n # ./lib/dalmatian/cluster.rb:70:in `block (2 levels) in deploy'\n # ./lib/dalmatian/cluster.rb:68:in `each'\n # ./lib/dalmatian/cluster.rb:68:in `block in deploy'\n # ./lib/dalmatian/cluster.rb:59:in `each'\n # ./lib/dalmatian/cluster.rb:59:in `deploy'\n # ./lib/dalmatian/infrastructure.rb:24:in `block in deploy'\n # ./lib/dalmatian/infrastructure.rb:22:in `each'\n # ./lib/dalmatian/infrastructure.rb:22:in `deploy'\n # ./lib/dalmatian/infrastructure.rb:18:in `test'\n # ./spec/integration/tests_local_configuration_spec.rb:3116:in `block (2 levels) in <module:Dalmatian>'\n # ./spec/support/spec_helper.rb:24:in `block (3 levels) in <top (required)>'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:24:in `block in modify'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:15:in `synchronize'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:15:in `modify'\n # ./spec/support/spec_helper.rb:20:in `block (2 levels) in <top (required)>'\n # /Users/bob/.bundles/ruby/2.7.0/gems/webmock-3.19.1/lib/webmock/rspec.rb:39:in `block (2 levels) in <top (required)>'\n\nFinished in 2.7 seconds (files took 0.81132 seconds to load)\n478 examples, 15 failures\n\nFailed examples:\n\nrspec ./spec/integration/tests_local_configuration_spec.rb:3119 # tests local configuration invokes \"terraform validate\" with the expected cluster options\nrspec ./spec/integration/tests_local_configuration_spec.rb:3155 # tests local configuration invokes \"terraform validate\" with the expected source options\nrspec ./spec/integration/tests_local_configuration_spec.rb:3161 # tests local configuration use of \"terraform plan\" passes the hosted zone config to \"terraform plan\"\nrspec ./spec/integration/tests_local_configuration_spec.rb:3167 # tests local configuration use of \"terraform plan\" passes the s3 config to \"terraform plan\"\nrspec ./spec/integration/tests_local_configuration_spec.rb:3173 # tests local configuration use of \"terraform plan\" passes the vpn customer gateway config to \"terraform plan\"\nrspec ./spec/integration/tests_local_configuration_spec.rb:3179 # tests local configuration use of \"terraform plan\" passes the base config to \"terraform plan\"\nrspec ./spec/integration/tests_local_configuration_spec.rb:3186 # tests local configuration use of \"terraform plan\" passes the waf config to \"terraform plan\"\nrspec ./spec/integration/tests_local_configuration_spec.rb:3193 # tests local configuration use of \"terraform plan\" passes the rds config to \"terraform plan\"\nrspec ./spec/integration/tests_local_configuration_spec.rb:3200 # tests local configuration use of \"terraform plan\" passes the elasticache config to \"terraform plan\"\nrspec ./spec/integration/tests_local_configuration_spec.rb:3209 # tests local configuration use of \"terraform plan\" passes the opensearch config to \"terraform plan\"\nrspec ./spec/integration/tests_local_configuration_spec.rb:3218 # tests local configuration use of \"terraform plan\" passes the services config to \"terraform plan\"\nrspec ./spec/integration/tests_local_configuration_spec.rb:3225 # tests local configuration use of \"terraform plan\" passes the loadbalancer config to \"terraform plan\"\nrspec ./spec/integration/tests_local_configuration_spec.rb:3234 # tests local configuration use of \"terraform plan\" passes the cluster 2 config to \"terraform plan\"\nrspec ./spec/integration/tests_local_configuration_spec.rb:3241 # tests local configuration use of \"terraform plan\" passes the cluster 3 config to \"terraform plan\"\nrspec ./spec/integration/tests_local_configuration_spec.rb:3245 # tests local configuration use of \"terraform plan\" passes the cluster 4 config to \"terraform plan\"\n\nCoverage report generated for RSpec to /Users/bob/git/dxw/dalmatian/coverage. 4253 / 4389 LOC (96.9%) covered.\nStopped processing SimpleCov as a previous error not related to SimpleCov has been detected\n/Users/bob/.rbenv/versions/2.7.1/bin/ruby -I/Users/bob/.bundles/ruby/2.7.0/gems/rspec-core-3.12.2/lib:/Users/bob/.bundles/ruby/2.7.0/gems/rspec-support-3.12.1/lib /Users/bob/.bundles/ruby/2.7.0/gems/rspec-core-3.12.2/exe/rspec --pattern spec/\\*\\*\\{,/\\*/\\*\\*\\}/\\*_spec.rb failed",
|
|
"displayName": "Shell",
|
|
"description": "This tool executes a given shell command as `bash -c <command>`. To run a command in the background, set the `is_background` parameter to true. Do NOT use `&` to background commands. Command is executed as a subprocess that leads its own process group. Command process group can be terminated as `kill -- -PGID` or signaled as `kill -s SIGNAL -- -PGID`.\n\n Efficiency Guidelines:\n - Quiet Flags: Always prefer silent or quiet flags (e.g., `npm install --silent`, `git --no-pager`) to reduce output volume while still capturing necessary information.\n - Pagination: Always disable terminal pagination to ensure commands terminate (e.g., use `git --no-pager`, `systemctl --no-pager`, or set `PAGER=cat`).\n\n The following information is returned:\n\n Output: Combined stdout/stderr. Can be `(empty)` or partial on error and for any unwaited background processes.\n Exit Code: Only included if non-zero (command failed).\n Error: Only included if a process-level error occurred (e.g., spawn failure).\n Signal: Only included if process was terminated by a signal.\n Background PIDs: Only included if background processes were started.\n Process Group PGID: Only included if available.",
|
|
"renderOutputAsMarkdown": false
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"id": "ab891c3b-db77-4d26-b429-0566a09b55a4",
|
|
"timestamp": "2026-02-20T17:15:31.720Z",
|
|
"type": "gemini",
|
|
"content": "`deploys_local_configuration_spec.rb` passed, but `tests_local_configuration_spec.rb` has 15 `terraform validate` failures. `Infrastructure#test` calls `deploy` with `test: true`, which triggers `test_rds` and its subsequent `terraform validate`. I need to verify if I correctly updated the `rds` hash in the `cluster1_validate_cmd_production_rds` definition within `spec/integration/tests_local_configuration_spec.rb`.",
|
|
"thoughts": [
|
|
{
|
|
"subject": "Examining Test Failures",
|
|
"description": "I've got a bit of good news, `deploys_local_configuration_spec.rb` is green. However, the `tests_local_configuration_spec.rb` is still a problem, with 15 failures. Upon closer inspection, it seems they're all related to `terraform validate`.",
|
|
"timestamp": "2026-02-20T17:15:27.323Z"
|
|
},
|
|
{
|
|
"subject": "Verifying the Root Cause",
|
|
"description": "I've been poring over the test failures, and it seems I've isolated the issue. The failures in `tests_local_configuration_spec.rb` are, as suspected, stemming from `terraform validate` calls. Specifically, the test is expecting a `terraform plan` execution but is receiving a `terraform validate` instead. Looking at the code, the `test` method does call `terraform validate`, so I need to find out why.",
|
|
"timestamp": "2026-02-20T17:15:31.475Z"
|
|
},
|
|
{
|
|
"subject": "Revising Command Expectations",
|
|
"description": "Now I think I've got it. The `tests_local_configuration_spec.rb` test suite expects `terraform plan`, but the code path goes through `deploy_rds`, which calls `test_rds`, and `test_rds` calls `terraform validate`. I mistakenly updated the `validate` command expectations! I need to change these specs.",
|
|
"timestamp": "2026-02-20T17:15:31.516Z"
|
|
}
|
|
],
|
|
"tokens": {
|
|
"input": 73546,
|
|
"output": 138,
|
|
"cached": 58544,
|
|
"thoughts": 521,
|
|
"tool": 0,
|
|
"total": 74205
|
|
},
|
|
"model": "gemini-3-flash-preview",
|
|
"toolCalls": [
|
|
{
|
|
"id": "read_file_1771607731714_0",
|
|
"name": "read_file",
|
|
"args": {
|
|
"file_path": "spec/integration/tests_local_configuration_spec.rb",
|
|
"offset": 352,
|
|
"limit": 100
|
|
},
|
|
"result": [
|
|
{
|
|
"functionResponse": {
|
|
"id": "read_file_1771607731714_0",
|
|
"name": "read_file",
|
|
"response": {
|
|
"output": "\nIMPORTANT: The file content has been truncated.\nStatus: Showing lines 353-452 of 3251 total lines.\nAction: To read more of the file, you can use the 'offset' and 'limit' parameters in a subsequent 'read_file' call. For example, to read the next section of the file, use offset: 452.\n\n--- FILE CONTENT (truncated) ---\n terraform_validate_cmd(\n tfvar_arg_string(\n infrastructure_defaults.merge(\n \"instance_type\" => \"t2.medium\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"account_id\" => \"123456789012\",\n \"infrastructure_name\" => \"new-dedicated-cluster\",\n \"dalmatian_role\" => \"dalmatian-read\",\n \"environment\" => \"production\",\n \"rds\" => {\n \"identifier\" => \"testservice\",\n \"in_use_by\" => [\n \"test-service\"\n ],\n \"clusters_in_use\" => {\n \"production\" => [\n \"test\"\n ],\n \"staging\" => [\n \"test\"\n ]\n },\n \"instance_class\" => {\n \"production\" => \"db.t2.small\",\n \"staging\" => \"db.t2.micro\"\n },\n \"engine\" => \"postgres\",\n \"engine_version\" => \"11.4\",\n \"allocated_storage\" => 20,\n \"storage_encrypted\" => true,\n \"storage_type\" => \"gp3\",\n \"db_name\" => \"testapp\",\n \"port\" => 5432,\n \"maintenance_window\" => \"mon:19:00-mon:19:30\",\n \"backup_window\" => \"09:00-10:00\",\n \"backup_retention_period\" => 31,\n \"force_ssl\" => true,\n \"parameter_store_path_db_url_name\" => \"DATABASE_URL\",\n \"sql_backup_scheduled_task_environment_variables\" => [\n {\n \"name\" => \"foo\",\n \"value\" => \"bar\"\n }\n ],\n \"check_sql_backup_scheduled_task_environment_variables\" => [\n {\n \"name\" => \"foo\",\n \"value\" => \"bar\"\n }\n ],\n \"sync_sql_backup_to_azure\" => false,\n \"replication_bucket_destination_arn\" => \"\",\n \"replication_kms_key_id\" => \"\",\n \"codebuild_access\" => [\n \"service-name\"\n ]\n }\n )\n )\n )\n end\n\n let(:cluster1_validate_cmd_staging_waf) do\n terraform_validate_cmd(\n tfvar_arg_string(\n infrastructure_defaults.merge(\n \"instance_type\" => \"t2.small\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"track_revision\" => \"feature/experiment\",\n \"extra_ecs_clusters\" => [\n {\n \"name\" => \"test\",\n \"subnets_name\" => \"extra_private_subnets\",\n \"min_servers\" => \"2\",\n \"max_servers\" => \"4\",\n \"instance_type\" => \"t3.small\"\n }\n ],\n \"tinyproxy\" => {\n \"create\" => true\n },\n \"account_id\" => \"123456789012\",\n \"infrastructure_name\" => \"new-dedicated-cluster\",\n \"dalmatian_role\" => \"dalmatian-read\",\n \"environment\" => \"staging\",\n \"waf\" => {\n \"name\" => \"test-1\",\n \"action\" => \"count\",\n \"ip_deny_list\" => [],\n \"aws_managed_rules\" => [\n {\n \"name\" => \"AWSManagedRulesSQLiRuleSet\",\n \"excluded_path_patterns\" => [\n \"/wp-admin/async-upload.php\"\n ]\n },\n {\n \"name\" => \"AWSManagedRulesCommonRuleSet\","
|
|
}
|
|
}
|
|
}
|
|
],
|
|
"status": "success",
|
|
"timestamp": "2026-02-20T17:15:31.742Z",
|
|
"resultDisplay": "Read lines 353-452 of 3251 from spec/integration/tests_local_configuration_spec.rb",
|
|
"displayName": "ReadFile",
|
|
"description": "Reads and returns the content of a specified file. If the file is large, the content will be truncated. The tool's response will clearly indicate if truncation has occurred and will provide details on how to read more of the file using the 'offset' and 'limit' parameters. Handles text, images (PNG, JPG, GIF, WEBP, SVG, BMP), audio files (MP3, WAV, AIFF, AAC, OGG, FLAC), and PDF files. For text files, it can read specific line ranges.",
|
|
"renderOutputAsMarkdown": true
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"id": "104c4af7-1ecf-4b98-8290-a42ec92e0191",
|
|
"timestamp": "2026-02-20T17:15:34.621Z",
|
|
"type": "gemini",
|
|
"content": "I missed some; `RdsTest` calls `terraform validate`. Checking `lib/dalmatian/rds_test.rb`.",
|
|
"thoughts": [
|
|
{
|
|
"subject": "Analyzing Missing Context",
|
|
"description": "I've realized I skipped over some key information. I see a failure message indicating the use of `TF_VAR_rds` and `terraform validate`. I'm now focusing on the `RdsTest` and its connection to `terraform validate`. I'm now diving into `lib/dalmatian/rds_test.rb` to better understand this.",
|
|
"timestamp": "2026-02-20T17:15:34.527Z"
|
|
}
|
|
],
|
|
"tokens": {
|
|
"input": 74729,
|
|
"output": 50,
|
|
"cached": 58324,
|
|
"thoughts": 69,
|
|
"tool": 0,
|
|
"total": 74848
|
|
},
|
|
"model": "gemini-3-flash-preview",
|
|
"toolCalls": [
|
|
{
|
|
"id": "read_file_1771607734617_0",
|
|
"name": "read_file",
|
|
"args": {
|
|
"file_path": "lib/dalmatian/rds_test.rb"
|
|
},
|
|
"result": [
|
|
{
|
|
"functionResponse": {
|
|
"id": "read_file_1771607734617_0",
|
|
"name": "read_file",
|
|
"response": {
|
|
"output": "module Dalmatian\n class RdsTest\n include Testable\n\n def initialize(\n rds:,\n env:,\n helper: Helper,\n logger: Logger,\n terraform: Terraform\n )\n @rds = rds\n @env = env\n @helper = helper\n @logger = logger\n @terraform = terraform\n end\n\n private\n\n attr_reader :rds, :env, :helper, :logger, :terraform\n\n def env_config\n env_details.merge(\n \"account_id\" => rds.account_id,\n \"infrastructure_name\" => rds.cluster_id,\n \"dalmatian_role\" => \"dalmatian-read\",\n \"environment\" => env_name,\n \"rds\" => {\n \"identifier\" => rds.identifier,\n \"in_use_by\" => rds.in_use_by,\n \"clusters_in_use\" => rds.clusters_in_use,\n \"instance_class\" => rds.instance_class,\n \"engine\" => rds.engine,\n \"engine_version\" => rds.engine_version,\n \"allocated_storage\" => rds.allocated_storage,\n \"storage_encrypted\" => rds.storage_encrypted,\n \"storage_type\" => rds.storage_type,\n \"db_name\" => rds.db_name,\n \"port\" => rds.port,\n \"maintenance_window\" => rds.maintenance_window,\n \"backup_window\" => rds.backup_window,\n \"backup_retention_period\" => rds.backup_retention_period,\n \"force_ssl\" => rds.force_ssl,\n \"parameter_store_path_db_url_name\" => rds.parameter_store_path_db_url_name,\n \"sql_backup_scheduled_task_environment_variables\" => rds.sql_backup_scheduled_task_environment_variables,\n \"check_sql_backup_scheduled_task_environment_variables\" => rds.check_sql_backup_scheduled_task_environment_variables,\n \"sync_sql_backup_to_azure\" => rds.sync_sql_backup_to_azure,\n \"codebuild_access\" => rds.codebuild_access\n }\n )\n end\n\n def checkout_revision_if_required\n false\n end\n\n def workspace_name\n [rds.cluster_id, rds.identifier, \"rds\", env_name].join(\"-\")\n end\n\n def target_directory\n File.join(\n Infrastructure::APP_ROOT,\n Infrastructure::PATH,\n \"rds\"\n )\n end\n end\nend\n"
|
|
}
|
|
}
|
|
}
|
|
],
|
|
"status": "success",
|
|
"timestamp": "2026-02-20T17:15:34.645Z",
|
|
"resultDisplay": "",
|
|
"displayName": "ReadFile",
|
|
"description": "Reads and returns the content of a specified file. If the file is large, the content will be truncated. The tool's response will clearly indicate if truncation has occurred and will provide details on how to read more of the file using the 'offset' and 'limit' parameters. Handles text, images (PNG, JPG, GIF, WEBP, SVG, BMP), audio files (MP3, WAV, AIFF, AAC, OGG, FLAC), and PDF files. For text files, it can read specific line ranges.",
|
|
"renderOutputAsMarkdown": true
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"id": "6cf4f08a-fe09-43c4-a6ad-c61d85e0132d",
|
|
"timestamp": "2026-02-20T17:15:44.736Z",
|
|
"type": "gemini",
|
|
"content": "`RdsTest#env_config` manually builds the RDS hash and is missing the new fields, unlike `RdsDeployment`, which uses `rds.to_params`. I'll update `lib/dalmatian/rds_test.rb` to use `rds.to_params` to stay DRY and fix the missing fields.",
|
|
"thoughts": [
|
|
{
|
|
"subject": "Investigating the Data Structure",
|
|
"description": "I've discovered the `RdsTest#env_config` method, lines 31-52, constructs the RDS hash manually, and it seems to omit the two crucial new fields. I'm now examining the `RdsDeployment` class and how it utilizes `rds.to_params` to understand the data flow.",
|
|
"timestamp": "2026-02-20T17:15:37.696Z"
|
|
},
|
|
{
|
|
"subject": "Refactoring the Implementation",
|
|
"description": "I'm leaning towards modifying `RdsTest` to leverage `rds.to_params` instead of manually constructing the hash. This seems more elegant and reduces redundancy. However, I'm now verifying that `to_params` encompasses all the necessary data fields, to make sure nothing crucial is lost in translation.",
|
|
"timestamp": "2026-02-20T17:15:39.872Z"
|
|
},
|
|
{
|
|
"subject": "Considering a Code Update",
|
|
"description": "Okay, it's clear now that using `rds.to_params` is the right move for `RdsTest`. It'll keep things cleaner. I'm ready to update the file and add the new fields, ensuring data integrity. I'll test everything afterwards, of course!",
|
|
"timestamp": "2026-02-20T17:15:42.540Z"
|
|
},
|
|
{
|
|
"subject": "Updating the Implementation",
|
|
"description": "Now I'm completely sure, the `to_params` method in `Rds` has everything I need. Therefore, the plan is confirmed: I'm updating `RdsTest` to leverage `rds.to_params`. This approach not only aligns with the existing architecture but also simplifies the code. The next step is to update the file and add the missing fields, and then test the changes.",
|
|
"timestamp": "2026-02-20T17:15:42.587Z"
|
|
}
|
|
],
|
|
"tokens": {
|
|
"input": 75429,
|
|
"output": 687,
|
|
"cached": 72077,
|
|
"thoughts": 786,
|
|
"tool": 0,
|
|
"total": 76902
|
|
},
|
|
"model": "gemini-3-flash-preview",
|
|
"toolCalls": [
|
|
{
|
|
"id": "replace_1771607744730_0",
|
|
"name": "replace",
|
|
"args": {
|
|
"file_path": "/Users/bob/git/dxw/dalmatian/lib/dalmatian/rds_test.rb",
|
|
"new_string": " def env_config\n env_details.merge(\n \"account_id\" => rds.account_id,\n \"infrastructure_name\" => rds.cluster_id,\n \"dalmatian_role\" => \"dalmatian-read\",\n \"environment\" => env_name,\n \"rds\" => rds.to_params\n )\n end",
|
|
"instruction": "In RdsTest#env_config, use rds.to_params to build the RDS configuration hash instead of manually listing all fields. This ensures consistency with RdsDeployment and automatically includes any new fields added to the RDS model.",
|
|
"old_string": " def env_config\n env_details.merge(\n \"account_id\" => rds.account_id,\n \"infrastructure_name\" => rds.cluster_id,\n \"dalmatian_role\" => \"dalmatian-read\",\n \"environment\" => env_name,\n \"rds\" => {\n \"identifier\" => rds.identifier,\n \"in_use_by\" => rds.in_use_by,\n \"clusters_in_use\" => rds.clusters_in_use,\n \"instance_class\" => rds.instance_class,\n \"engine\" => rds.engine,\n \"engine_version\" => rds.engine_version,\n \"allocated_storage\" => rds.allocated_storage,\n \"storage_encrypted\" => rds.storage_encrypted,\n \"storage_type\" => rds.storage_type,\n \"db_name\" => rds.db_name,\n \"port\" => rds.port,\n \"maintenance_window\" => rds.maintenance_window,\n \"backup_window\" => rds.backup_window,\n \"backup_retention_period\" => rds.backup_retention_period,\n \"force_ssl\" => rds.force_ssl,\n \"parameter_store_path_db_url_name\" => rds.parameter_store_path_db_url_name,\n \"sql_backup_scheduled_task_environment_variables\" => rds.sql_backup_scheduled_task_environment_variables,\n \"check_sql_backup_scheduled_task_environment_variables\" => rds.check_sql_backup_scheduled_task_environment_variables,\n \"sync_sql_backup_to_azure\" => rds.sync_sql_backup_to_azure,\n \"codebuild_access\" => rds.codebuild_access\n }\n )\n end"
|
|
},
|
|
"result": [
|
|
{
|
|
"functionResponse": {
|
|
"id": "replace_1771607744730_0",
|
|
"name": "replace",
|
|
"response": {
|
|
"output": "Successfully modified file: /Users/bob/git/dxw/dalmatian/lib/dalmatian/rds_test.rb (1 replacements)."
|
|
}
|
|
}
|
|
}
|
|
],
|
|
"status": "success",
|
|
"timestamp": "2026-02-20T17:15:44.764Z",
|
|
"resultDisplay": {
|
|
"fileDiff": "Index: rds_test.rb\n===================================================================\n--- rds_test.rb\tCurrent\n+++ rds_test.rb\tProposed\n@@ -26,28 +26,7 @@\n \"infrastructure_name\" => rds.cluster_id,\n \"dalmatian_role\" => \"dalmatian-read\",\n \"environment\" => env_name,\n- \"rds\" => {\n- \"identifier\" => rds.identifier,\n- \"in_use_by\" => rds.in_use_by,\n- \"clusters_in_use\" => rds.clusters_in_use,\n- \"instance_class\" => rds.instance_class,\n- \"engine\" => rds.engine,\n- \"engine_version\" => rds.engine_version,\n- \"allocated_storage\" => rds.allocated_storage,\n- \"storage_encrypted\" => rds.storage_encrypted,\n- \"storage_type\" => rds.storage_type,\n- \"db_name\" => rds.db_name,\n- \"port\" => rds.port,\n- \"maintenance_window\" => rds.maintenance_window,\n- \"backup_window\" => rds.backup_window,\n- \"backup_retention_period\" => rds.backup_retention_period,\n- \"force_ssl\" => rds.force_ssl,\n- \"parameter_store_path_db_url_name\" => rds.parameter_store_path_db_url_name,\n- \"sql_backup_scheduled_task_environment_variables\" => rds.sql_backup_scheduled_task_environment_variables,\n- \"check_sql_backup_scheduled_task_environment_variables\" => rds.check_sql_backup_scheduled_task_environment_variables,\n- \"sync_sql_backup_to_azure\" => rds.sync_sql_backup_to_azure,\n- \"codebuild_access\" => rds.codebuild_access\n- }\n+ \"rds\" => rds.to_params\n )\n end\n \n",
|
|
"fileName": "rds_test.rb",
|
|
"filePath": "/Users/bob/git/dxw/dalmatian/lib/dalmatian/rds_test.rb",
|
|
"originalContent": "module Dalmatian\n class RdsTest\n include Testable\n\n def initialize(\n rds:,\n env:,\n helper: Helper,\n logger: Logger,\n terraform: Terraform\n )\n @rds = rds\n @env = env\n @helper = helper\n @logger = logger\n @terraform = terraform\n end\n\n private\n\n attr_reader :rds, :env, :helper, :logger, :terraform\n\n def env_config\n env_details.merge(\n \"account_id\" => rds.account_id,\n \"infrastructure_name\" => rds.cluster_id,\n \"dalmatian_role\" => \"dalmatian-read\",\n \"environment\" => env_name,\n \"rds\" => {\n \"identifier\" => rds.identifier,\n \"in_use_by\" => rds.in_use_by,\n \"clusters_in_use\" => rds.clusters_in_use,\n \"instance_class\" => rds.instance_class,\n \"engine\" => rds.engine,\n \"engine_version\" => rds.engine_version,\n \"allocated_storage\" => rds.allocated_storage,\n \"storage_encrypted\" => rds.storage_encrypted,\n \"storage_type\" => rds.storage_type,\n \"db_name\" => rds.db_name,\n \"port\" => rds.port,\n \"maintenance_window\" => rds.maintenance_window,\n \"backup_window\" => rds.backup_window,\n \"backup_retention_period\" => rds.backup_retention_period,\n \"force_ssl\" => rds.force_ssl,\n \"parameter_store_path_db_url_name\" => rds.parameter_store_path_db_url_name,\n \"sql_backup_scheduled_task_environment_variables\" => rds.sql_backup_scheduled_task_environment_variables,\n \"check_sql_backup_scheduled_task_environment_variables\" => rds.check_sql_backup_scheduled_task_environment_variables,\n \"sync_sql_backup_to_azure\" => rds.sync_sql_backup_to_azure,\n \"codebuild_access\" => rds.codebuild_access\n }\n )\n end\n\n def checkout_revision_if_required\n false\n end\n\n def workspace_name\n [rds.cluster_id, rds.identifier, \"rds\", env_name].join(\"-\")\n end\n\n def target_directory\n File.join(\n Infrastructure::APP_ROOT,\n Infrastructure::PATH,\n \"rds\"\n )\n end\n end\nend\n",
|
|
"newContent": "module Dalmatian\n class RdsTest\n include Testable\n\n def initialize(\n rds:,\n env:,\n helper: Helper,\n logger: Logger,\n terraform: Terraform\n )\n @rds = rds\n @env = env\n @helper = helper\n @logger = logger\n @terraform = terraform\n end\n\n private\n\n attr_reader :rds, :env, :helper, :logger, :terraform\n\n def env_config\n env_details.merge(\n \"account_id\" => rds.account_id,\n \"infrastructure_name\" => rds.cluster_id,\n \"dalmatian_role\" => \"dalmatian-read\",\n \"environment\" => env_name,\n \"rds\" => rds.to_params\n )\n end\n\n def checkout_revision_if_required\n false\n end\n\n def workspace_name\n [rds.cluster_id, rds.identifier, \"rds\", env_name].join(\"-\")\n end\n\n def target_directory\n File.join(\n Infrastructure::APP_ROOT,\n Infrastructure::PATH,\n \"rds\"\n )\n end\n end\nend\n",
|
|
"diffStat": {
|
|
"model_added_lines": 1,
|
|
"model_removed_lines": 22,
|
|
"model_added_chars": 30,
|
|
"model_removed_chars": 1166,
|
|
"user_added_lines": 1,
|
|
"user_removed_lines": 41,
|
|
"user_added_chars": 7,
|
|
"user_removed_chars": 636
|
|
},
|
|
"isNewFile": false
|
|
},
|
|
"displayName": "Edit",
|
|
"description": "Replaces text within a file. By default, replaces a single occurrence, but can replace multiple occurrences when `expected_replacements` is specified. This tool requires providing significant context around the change to ensure precise targeting. Always use the read_file tool to examine the file's current content before attempting a text replacement.\n \n The user has the ability to modify the `new_string` content. If modified, this will be stated in the response.\n \n Expectation for required parameters:\n 1. `old_string` MUST be the exact literal text to replace (including all whitespace, indentation, newlines, and surrounding code etc.).\n 2. `new_string` MUST be the exact literal text to replace `old_string` with (also including all whitespace, indentation, newlines, and surrounding code etc.). Ensure the resulting code is correct and idiomatic and that `old_string` and `new_string` are different.\n 3. `instruction` is the detailed instruction of what needs to be changed. It is important to Make it specific and detailed so developers or large language models can understand what needs to be changed and perform the changes on their own if necessary. \n 4. NEVER escape `old_string` or `new_string`, that would break the exact literal text requirement.\n **Important:** If ANY of the above are not satisfied, the tool will fail. CRITICAL for `old_string`: Must uniquely identify the single instance to change. Include at least 3 lines of context BEFORE and AFTER the target text, matching whitespace and indentation precisely. If this string matches multiple locations, or does not match exactly, the tool will fail.\n 5. Prefer to break down complex and long changes into multiple smaller atomic calls to this tool. Always check the content of the file after changes or not finding a string to match.\n **Multiple replacements:** Set `expected_replacements` to the number of occurrences you want to replace. The tool will replace ALL occurrences that match `old_string` exactly. Ensure the number of replacements matches your expectation.",
|
|
"renderOutputAsMarkdown": true
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"id": "7d819300-9864-4001-8d06-179adcea5060",
|
|
"timestamp": "2026-02-20T17:15:47.062Z",
|
|
"type": "gemini",
|
|
"content": "Tests again.",
|
|
"thoughts": [
|
|
{
|
|
"subject": "Restarting the Tests",
|
|
"description": "I've decided to re-initiate the testing phase. I'm focusing on refining the parameters to ensure a more comprehensive analysis this time around. I'm tweaking a few key variables and expect to see more robust results shortly.",
|
|
"timestamp": "2026-02-20T17:15:46.954Z"
|
|
}
|
|
],
|
|
"tokens": {
|
|
"input": 76161,
|
|
"output": 22,
|
|
"cached": 71536,
|
|
"thoughts": 9,
|
|
"tool": 0,
|
|
"total": 76192
|
|
},
|
|
"model": "gemini-3-flash-preview",
|
|
"toolCalls": [
|
|
{
|
|
"id": "run_shell_command_1771607747058_0",
|
|
"name": "run_shell_command",
|
|
"args": {
|
|
"command": "./scripts/bin/test -l"
|
|
},
|
|
"result": [
|
|
{
|
|
"functionResponse": {
|
|
"id": "run_shell_command_1771607747058_0",
|
|
"name": "run_shell_command",
|
|
"response": {
|
|
"output": "Output too large. Showing first 8,000 and last 32,000 characters. For full output see: /Users/bob/.gemini/tmp/dalmatian/tool-outputs/session-b86444e1-3f32-4f39-9c46-1ce1d2631b8b/run_shell_command_1771607747058_0.txt\nOutput: ==> Linting YAML...\n\n==> Linting shell scripts...\n\n==> Checking Terraform for JSON errors...\n- Checking ./terraform/policies/iam-read.json... Passed\n- Checking ./terraform/policies/s3-rw-with-versioning.json... Passed\n- Checking ./terraform/policies/codestar-connection-use.json... Passed\n- Checking ./terraform/policies/iam-create-access-key.json... Passed\n- Checking ./terraform/policies/codebuild.json... Passed\n- Checking ./terraform/policies/kms-encrypt-decrypt.json... Passed\n- Checking ./terraform/policies/iam-change-password.json... Passed\n- Checking ./terraform/policies/administrator-access.json... Passed\n- Checking ./terraform/policies/assume_roles/aws-backup.json... Passed\n- Checking ./terraform/policies/assume_roles/autoscaling.json... Passed\n- Checking ./terraform/policies/assume_roles/events.json... Passed\n- Checking ./terraform/policies/assume_roles/ecs.json... Passed\n- Checking ./terraform/policies/assume_roles/codepipeline.json... Passed\n- Checking ./terraform/policies/iam-mfa.json... Passed\n- Checking ./terraform/policies/route53-read.json... Passed\n- Checking ./terraform/policies/s3-full-access.json... Passed\n- Checking ./terraform/policies/parameter-store-read-decrypt.json... Passed\n- Checking ./terraform/policies/s3-read.json... Passed\n- Checking ./terraform/policies/parameter-store-RW-encrypt-decrypt.json... Passed\n- Checking ./terraform/policies/all-read-with-billing.json... Passed\n- Checking ./terraform/policies/codebuild-start-build.json... Passed\n- Checking ./terraform/policies/all-read.json... Passed\n\n==> Linting Terraform...\n\n==> Running Ruby tests...\n/Users/bob/.rbenv/versions/2.7.1/bin/ruby -I/Users/bob/.bundles/ruby/2.7.0/gems/rspec-core-3.12.2/lib:/Users/bob/.bundles/ruby/2.7.0/gems/rspec-support-3.12.1/lib /Users/bob/.bundles/ruby/2.7.0/gems/rspec-core-3.12.2/exe/rspec --pattern spec/\\*\\*\\{,/\\*/\\*\\*\\}/\\*_spec.rb\n\ntests local configuration\n use of \"terraform apply\"\n passes the hosted zone config to \"terraform apply\"\n passes the s3 config to \"terraform apply\"\n passes the vpn customer gateway config to \"terraform apply\"\n passes the base config to \"terraform apply\"\n passes the waf config to \"terraform apply\"\n passes the rds config to \"terraform apply\"\n passes the elasticache config to \"terraform apply\"\n passes the opensearch config to \"terraform apply\"\n passes the service config to \"terraform apply\"\n passes the loadbalancer config to \"terraform apply\"\n passes the cluster 2 config to \"terraform apply\"\n passes the cluster 3 config to \"terraform apply\"\n passes the cluster 4 config to \"terraform apply\"\n\ntests remote configuration\n retrieves the remotely held full configuration\n proceeds with deploying the infrastructure as per the cached full configuration\n\ntests local configuration\n invokes \"terraform validate\" with the expected cluster options\n invokes \"terraform validate\" with the expected source options\n use of \"terraform plan\"\n passes the hosted zone config to \"terraform plan\"\n passes the s3 config to \"terraform plan\"\n passes the vpn customer gateway config to \"terraform plan\"\n passes the base config to \"terraform plan\"\n passes the waf config to \"terraform plan\"\n passes the rds config to \"terraform plan\"\n passes the elasticache config to \"terraform plan\"\n passes the opensearch config to \"terraform plan\"\n passes the services config to \"terraform plan\"\n passes the loadbalancer config to \"terraform plan\"\n passes the cluster 2 config to \"terraform plan\"\n passes the cluster 3 config to \"terraform plan\"\n passes the cluster 4 config to \"terraform plan\"\n\nDalmatian::Account\n initialisation\n gathering user input\n asks the user for AWS credentials\n asks the user for the AWS account id to use\n asks the user for an account alias\n #call\n changes to the bootstrapping directory\n runs terraform init with upgrade option\n creates the new workspace using the given aws account id and alias\n runs terraform apply with the user-supplied vars\n\nDalmatian::CacheHandlerSelector\n ::new_for(remote_reference)\n when the remote reference is for a git repo\n asks for an instance of GitCacheHandler\n when the remote reference is for an S3 bucket\n asks for an instance of S3CacheHandler\n when the remote reference is for a URL\n asks for an instance of UrlCacheHandler\n when the type is unknown\n raises an error\n\nCacheHandler\n when a subclass class does not implement #cache_remote_configuration\n raises a helpful error\n\nDalmatian::CI\n CI::PATH\n is a constant\n #deploy\n changes to the ci directory\n runs terraform init with upgrade option\n creates the new workspace using the given aws account id and alias\n runs terraform apply with the user-supplied vars\n #test\n runs terraform plan with the user-supplied vars\n\nDalmatian::ClusterDeployment\n #call\n changes to the ecs directory\n asks Terraform to ensure that the workspace is in place\n when the environment includes a git reference as \"track_revision\"\n does NOT attempt to check out that commit\n when in _plan_ mode\n invokes Terraform.plan using the _dalmatian-read_ role\n when NOT in _plan_ mode\n invokes Terraform.apply using the _dalmatian-admin_\n when in _auto_approve_ mode\n asks Terraform to use auto_approve mode\n\nDalmatian::Cluster\n on initialisation\n makes Hosted zones, S3, Sources, Services, Loadbalancers, WAF and Rds\n #target_directory\n is a standard _ecs_ path\n #id\n is the primary key of the cluster definition is used\n #name\n when the cluster has an explicitly provided _name_ property\n that property is used\n when the cluster does not have an explicitly provided _name_ property\n the primary key of the cluster definition is used\n #account_id\n is the aws account key for deployment\n #sources\n represents any links to remote sources\n #environments\n represents the attributes of each environment's cluster section\n #fetch\n when the source is remotely held\n logs the plan to clone the source into the infrastructure pth\n deletes any existing source at the infrastructure location\n clones each source into the infrastructure location\n changes to the infrastructure directory for each source\n runs rake terrafile\n changes back to the APP_ROOT\n when the source is a local file path\n does not re-clone the source\n does not run terrafile\n when the specified local directory exists\n logs the fact that the local source is in place\n when the specificed local directory does not exist\n logs an error that the local source is missing\n #deploy\n deploys source infrastructure for each source and each service in each environment\n when a cluster should be created\n deploys cluster infrastructure for each environment\n when the _plan_ option IS invoked\n creates Cluster Deployments with plan settings\n when the _auto_approve_ option IS invoked\n creates Cluster Deployments with auto_approve settings\n handling of tests\n when the _test_ option is NOT invoked\n does not run cluster tests\n does not run cluster tests\n does not run cluster tests\n does not run source tests\n does not run waf tests\n does not run rds tests\n does not run service tests\n does not run service tests\n when the test option IS invoked\n runs tests\n when a cluster should NOT be created\n does not deploy cluster infrastructure\n when test option is invoked\n tests sources and services for each environment\n\nDalmatian::ClusterTest\n #call\n changes to the ecs directory\n logs our intention to run Terraform init\n runs Terraform init, with upgrade option\n ensures presence of workspace\n logs our intention to run Terraform fmt\n runs Terraform fmt with check and diff options\n logs our intention to run Terraf\n\n... [4,266 characters omitted] ...\n\nth)\n passes the given path to Dir.chdir\n ::to_bool(str)\n when given nil\n returns false\n when given an empty string\n returns false\n when given lower case string _true_\n returns true\n when given mixed case string _True_\n returns true\n when given the object true\n returns true\n when given the object false\n returns false\n ::tflint\n runs the tflint cmd\n ::terrafile\n runs rake terrafile\n ::ask\n delegates to HighLine#ask\n ::ask_in_confidence\n delegates to HighLine#ask\n passes a block to mask the answer\n\nDalmatian::HostedZoneDeployment\n #call\n changes to hosted-zone infrastructure directory\n asks Terraform to ensure that the workspace is in place\n when in _plan_ mode\n invokes Terraform.plan with the _dalmatian-read_ role\n when NOT in _plan_ mode\n invokes Terraform.apply with the _dalmatian-admin_ role\n when in _auto_approve_ mode\n asks Terraform to use auto_approve mode\n\nDalmatian::HostedZone\n #domain\n uses hosted_zone domain\n #ns_records\n uses hosted_zone ns_records\n #a_records\n uses hosted_zone a_records\n #alias_records\n uses hosted_zone alias_records\n #cname_records\n uses hosted_zone cname_records\n #mx_records\n uses hosted_zone mx_records\n #txt_records\n uses hosted_zone txt_records\n #srv_records\n uses hosted_zone srv_records\n #to_params\n provides a hash of attributes for use in deployment\n\nDalmatian::HostedZoneTest\n #call\n changes to the hosted-zone directory\n logs our intention to run Terraform init\n runs Terraform init, with upgrade option\n ensures presence of workspace\n logs our intention to run Terraform fmt\n runs Terraform fmt with check and diff options\n logs our intention to run Terraform validate\n runs Terraform validate, with upgrade option\n changes back to the app root directory\n\nDalmatian::Infrastructure\n Infrastructure::PATH\n is a constant\n Infrastructure::APP_ROOT\n is a constant\n initialisation\n when configuration is not provided\n builds one using the defaults\n #clusters\n creates one cluster for each cluster description provided\n key operations on clusters\n #fetch\n asks all clusters to #fetch\n #test\n asks all clusters to #deploy with _plan_ and _test_ options\n #deploy\n when no parameters given\n asks all clusters to #deploy with _plan_, _test_ and _auto-approve_ disabled\n when parameters are given\n asks all clusters to #deploy with the given options\n when a particular infrastructure is named for deployment\n asks only the named cluster to #deploy with the given options\n\nDalmatian::Logger\n ::error(msg)\n raises an error with a red message\n ::info(msg)\n puts the given given message in white\n ::success(msg)\n puts the given given message in green\n ::warn(msg)\n puts the given given message in yellow\n\nDalmatian::OpensearchCluster\n #identifier\n uses opensearch identifier\n #in_use_by\n uses opensearch_cluster in_use_by list\n #version\n uses opensearch_cluster version\n #master_enabled\n uses opensearch_cluster master_enabled bool\n #master_count\n uses opensearch_cluster master_count\n #master_type\n uses opensearch_cluster master_type\n #instance_count\n uses opensearch_cluster instance_count\n #instance_type\n uses opensearch_cluster instance_type\n #warm_enabled\n uses opensearch_cluster warm_enabled bool\n #warm_count\n uses opensearch_cluster warm_count\n #warm_type\n uses opensearch_cluster warm_type\n #parameter_store_path_opensearch_cluster_url_name\n uses opensearch_cluster parameter_store_path_opensearch_cluster_url_name\n #volume_size\n uses opensearch_cluster volume_size\n #to_params\n provides a hash of attributes for use in deployment\n\nDalmatian::OpensearchClusterTest\n #call\n changes to the opensearch-cluster directory\n logs our intention to run Terraform init\n runs Terraform init, with upgrade option\n ensures presence of workspace\n logs our intention to run Terraform fmt\n runs Terraform fmt with check and diff options\n logs our intention to run Terraform validate\n runs Terraform validate, with upgrade option\n changes back to the app root directory\n\nDalmatian::ParameterStore\n ::get_parameter(name: \"\", with_decryption: true)\n when getting a single parameter from Parameter Store\n runs aws ssm get-parameter\n ::get_parameters_by_path(path: \"\", with_decryption: true)\n when getting parameters by path from Parameter Store\n runs aws ssm get-parameter\n\nDalmatian::RdsDeployment\n #call\n changes to rds infrastructure directory\n asks Terraform to ensure that the workspace is in place\n when in _plan_ mode\n invokes Terraform.plan with the _dalmatian-read_ role\n when NOT in _plan_ mode\n invokes Terraform.apply with the _dalmatian-admin_ role\n when in _auto_approve_ mode\n asks Terraform to use auto_approve mode\n\nDalmatian::Rds\n #identifier\n uses rds identifier\n #in_use_by\n uses rds in_use_by list\n #clusters_in_use\n uses rds clusters_in_use list\n #instance_class\n uses rds instance_class\n #engine\n uses rds engine\n #engine_version\n uses the rds engine_version\n #allocated_storage\n uses the rds allocated_storage\n #storage_encrypted\n uses the rds storage_encrypted bool\n #storage_type\n uses the rds storage_type gp3\n #db_name\n uses the rds db_name\n #port\n uses the rds port\n #maintenance_window\n uses the rds maintenance_window\n #backup_window\n uses the rds backup_window\n #backup_retention_period\n uses the rds backup_retention_period\n #force_ssl\n uses the rds force_ssl bool\n #parameter_store_path_db_url_name\n uses the rds parameter_store_path_db_url_name\n #sql_backup_scheduled_task_environment_variables\n uses the rds sql_backup_scheduled_task_environment_variables\n #check_sql_backup_scheduled_task_environment_variables\n uses the rds check_sql_backup_scheduled_task_environment_variables\n #sync_sql_backup_to_azure\n will have offsite backups disabled by default\n #replication_bucket_destination_arn\n uses the rds replication_bucket_destination_arn\n #replication_kms_key_id\n uses the rds replication_kms_key_id\n #codebuild_access\n uses the rds codebuild_access\n #to_params\n provides a hash of attributes for use in deployment\n\nDalmatian::RdsTest\n #call\n changes to the ecs-services directory (FAILED - 1)\n logs our intention to run Terraform init (FAILED - 2)\n runs Terraform init, with upgrade option (FAILED - 3)\n ensures presence of workspace (FAILED - 4)\n logs our intention to run Terraform fmt (FAILED - 5)\n runs Terraform fmt with check and diff options (FAILED - 6)\n logs our intention to run Terraform validate (FAILED - 7)\n runs Terraform validate, with upgrade option (FAILED - 8)\n changes back to the app root directory (FAILED - 9)\n\nDalmatian::RemoteReferenceValues\n when the reference is for a git repo\n returns a git shaped configuration\n if _filename_ is not present\n supplies the default of _dalmatian.yml_\n when the reference is for an S3 bucket\n returns an S3 shaped configuration\n if _key_ is not present\n supplies the default of _dalmatian.yml_\n when the reference is for a URL\n returns a git shaped configuration\n\nDalmatian::S3CacheHandler\n #call\n deletes any old cache\n uses the AWS S3 cmd to save the remote config to a local cache\n logs the cloning action\n logs the path to the cached configuration\n returns the cached full configuration to the caller (configuration reader)\n reads the cached full configuration from the disk in order to return to caller\n\nDalmatian::S3Deployment\n #call\n changes to s3 infrastructure directory\n asks Terraform to ensure that the workspace is in place\n when in _plan_ mode\n invokes Terraform.plan with the _dalmatian-read_ role\n when NOT in _plan_ mode\n invokes Terraform.apply with the _dalmatian-admin_ role\n when in _auto_approve_ mode\n asks Terraform to use auto_approve mode\n\nDalmatian::S3\n #name\n uses s3 name\n #enable_s3_versioning\n uses enable_s3_versioning bool\n #encrypted\n uses s3 encrypted bool\n #acl\n uses s3 acl\n #policy\n uses s3 policy\n #service_cloudfront_read_access\n uses s3 service_cloudfront_read_access\n #cloudfront\n uses s3 cloudfront\n #to_params\n provides a hash of attributes for use in deployment\n\nDalmatian::S3Test\n #call\n changes to the s3 directory\n logs our intention to run Terraform init\n runs Terraform init, with upgrade option\n ensures presence of workspace\n logs our intention to run Terraform fmt\n runs Terraform fmt with check and diff options\n logs our intention to run Terraform validate\n runs Terraform validate, with upgrade option\n changes back to the app root directory\n\nDalmatian::ServiceDeployment\n #call\n changes to ecs-services infrastructure directory\n asks Terraform to ensure that the workspace is in place\n when in _plan_ mode\n invokes Terraform.plan with the _dalmatian-read_ role\n when NOT in _plan_ mode\n invokes Terraform.apply with the _dalmatian-admin_ role\n when in _auto_approve_ mode\n asks Terraform to use auto_approve mode\n\nDalmatian::Service\n #name\n uses service name\n #blue_green\n uses the service blue_green map\n #parameter_store_path\n uses service parameter_store_path\n #parameter_store_key\n uses service parameter_store_key\n #daemon\n uses the service daemon bool\n #monitoring\n uses the service monitoring hash\n #cloudfront\n recasts the service config in environment groups\n includes the appropriate \"custom_origins\" values in each environment\n Uses an AWS cloudfront managed cache policy\n Uses an AWS cloudfront managed origin policy\n Uses an AWS cloudfront managed response headers policy\n mirroring of elements into each environment group\n includes the \"create\" value\n includes the \"tls_protocol_version\" value\n includes the \"origin_keepalive_timeout\" value\n includes the \"origin_read_timeout\" value\n includes the \"basic_auth\" value\n includes the \"basic_auth_users_extra\" value\n includes the \"viewer_request_functions\" values\n includes the \"offline_page_http_status\" value\n bypass_protection\n uses the \"bypass_protection\" configuration\n custom_behaviors\n converts list of \"path_patterns\" to a single \"path_pattern\"\n #shared_loadbalancer_name\n returns shared loadbalancer name if the service is in use by a shared loadbalancer\n returns empty string if the service is not in use by a shared loadbalancer\n #s3_policy\n uses the service s3_policy map\n #lb_ip_whitelistt\n uses the service lb_ip_whitelist list\n #lb_idle_timeout\n uses the service lb_idle_timeout\n #global_accelerator\n uses service global_accelerator value\n #health_check_path\n uses the service health_check_path\n #health_check_grace_period\n uses the service health_check_grace_period\n #deregistration_delay\n uses the service deregistration_delay\n #serve_from_subdirectory\n uses the service serve_from_subdirectory\n #domain_names\n groups the domain names from the service domain_list into environments\n #proxy_configuration\n groups the proxy configurations from the service proxy_configuration list into environments\n #home_directory\n uses the service home_directory\n #lb_ssl_certificate\n groups the certificate arns from the service lb_ssl_certificate list into environments\n #lb_ssl_policy\n sets the default ssl policy for each environment\n #cloudfront_ssl_certificate\n groups the certificate arns from the service cloudfront_ssl_certificate list into environments\n #image_source\n uses the service image source\n #launch_on\n uses the service 'launch_on' specification\n #launch_on_cluster\n uses the service 'launch_on_cluster' string\n #cluster_min_servers\n uses the service 'cluster_min_servers' string\n #image_location\n uses the service image location\n #track_revision\n uses the service track_revision string\n #custom_codestar_connection_arn\n uses the service custom_codestar_connection_arn\n #codepipeline_use_github_v1\n uses the service codepipeline_use_github_v1\n #codepipeline_codebuild_run_in_vpc\n uses the service codepipeline_codebuild_run_in_vpc\n #codepipeline_codebuild_use_service_env\n uses the service codepipeline_codebuild_use_service_env\n #buildspec\n uses the service buildspec\n #container_port\n uses the service container port\n #container_command\n uses the service container command\n #container_volumes\n uses the service container volumes\n #container_extra_hosts\n uses the service container extra hosts\n #container_count\n uses the service container_count\n #enable_max_one_container_per_instance\n uses the service enable_max_one_container_per_instance\n #scheduled_tasks\n uses the service scheduled tasks\n #workers\n uses the service workers\n #cluster_name\n delegates to the cluster\n #cluster_id\n delegates to the cluster\n #account_id\n delegates to the cluster\n #to_params\n provides a hash of attributes for use in deployment\n\nDalmatian::ServiceTest\n #call\n changes to the ecs-services directory\n logs our intention to run Terraform init\n runs Terraform init, with upgrade option\n ensures presence of workspace\n logs our intention to run Terraform fmt\n runs Terraform fmt with check and diff options\n logs our intention to run Terraform validate\n runs Terraform validate, with upgrade option\n changes back to the app root directory\n\nDalmatian::SharedLoadbalancerDeployment\n #call\n changes to shared-loadbalancer infrastructure directory\n asks Terraform to ensure that the workspace is in place\n when in _plan_ mode\n invokes Terraform.plan with the _dalmatian-read_ role\n when NOT in _plan_ mode\n invokes Terraform.apply with the _dalmatian-admin_ role\n when in _auto_approve_ mode\n asks Terraform to use auto_approve mode\n\nDalmatian::SharedLoadbalancer\n #name\n uses shared_loadbalancer name\n #in_use_by\n uses shared_loadbalancer in_use_by list\n #clusters_in_use\n uses shared_loadbalancer clusters_in_use list\n #subnets_name\n uses shared_loadbalancer subnets_name value\n #domain_names\n uses shared_loadbalancer domain_names list provided by Services\n #internal\n uses shared_loadbalancer internal value\n #ip_whitelist\n uses shared_loadbalancer ip_whitelist list\n #idle_timeout\n uses shared_loadbalancer idle_timeout value\n #global_accelerator\n uses shared_loadbalancer global_accelerator value\n #ssl_policy\n has the default ssl policy defined\n #to_params\n provides a hash of attributes for use in deployment\n\nDalmatian::SharedLoadbalancerTest\n #call\n changes to the shared-loadbalancer directory\n logs our intention to run Terraform init\n runs Terraform init, with upgrade option\n ensures presence of workspace\n logs our intention to run Terraform fmt\n runs Terraform fmt with check and diff options\n logs our intention to run Terraform validate\n runs Terraform validate, with upgrade option\n changes back to the app root directory\n\nDalmatian::SourceDeployment\n #call\n changes to infrastructure config directory\n asks Terraform to ensure that the workspace is in place\n when the environment includes a git reference as \"track_revision\"\n checks out that commit\n passes the \"track_revision\" reference along to Terraform\n when in _plan_ mode\n invokes Terraform.plan with the _dalmatian-read_ role\n when NOT in _plan_ mode\n invokes Terraform.apply with the _dalmatian-admin_ role\n when in _auto_approve_ mode\n asks Terraform to use auto_approve mode\n\nDalmatian::Source\n #name\n uses the cluster name and its own position in the cluster's list of sources\n #cluster_name\n delegates to the cluster\n #cluster_id\n delegates to the cluster\n #account_id\n delegates to the cluster\n\nDalmatian::SourceTest\n #call\n changes to the ecs directory\n logs our intention to run Terraform init\n runs Terraform init, with upgrade option\n ensures presence of workspace\n logs our intention to run Terraform fmt\n runs Terraform fmt with check and diff options\n logs our intention to run Terraform validate\n runs Terraform validate, with upgrade option\n changes back to the app root directory\n when the environment includes a git reference as \"track_revision\"\n checks out that commit\n passes the \"track_revision\" reference along to Terraform.validate\n\nDalmatian::Terraform\n ::init(upgrade: false)\n when asked to upgrade\n passes terraform init the upgrade flag\n when not asked to upgrade\n does not pass terraform init the upgrade flag\n ::fmt(args = nil)\n when passed some additional arguments\n passes terraform fmt the upgrade flag\n when passed NO additional arguments\n invokes terraform fmt with no arguments\n ::validate(tfvars)\n passes the given _var-file_ to terraform\n reformats the given tfvars and passes them to terraform as args\n ::ensure_presence_of_workspace(workspace_name)\n logs our intention to create the workspace\n asks Terraform to create the workspace\n when the workspace already exists (and an error is rescued)\n logs our intention to _select_ rather than _create_ the workspace\n asks Terraform to select the existing workspace\n ::plan(tfvars)\n passes the given _var-file_ to terraform\n reformats the given tfvars and passes them to terraform as args\n ::apply(tfvars, auto_approve=false)\n passes the given _var-file_ to terraform\n reformats the given tfvars and passes them to terraform as args\n when auto-approve is set to true\n passes the _auto-approve_ flag to terraform apply\n ::destroy(tfvars)\n passes the given _var-file_ to terraform\n reformats the given tfvars and passes them to terraform as args\n ::list_workspaces\n changes to the bootstrapping directory\n runs the terraform cmd to list workspaces\n\nDalmatian::UrlCacheHandler\n #call\n deletes any old cache\n uses the helper to GET a URI\n logs the cloning action\n logs the path to the cached configuration\n returns the cached full configuration to the caller (configuration reader)\n reads the cached full configuration from the disk in order to return to caller\n\nDalmatian::VpnCustomerGatewayDeployment\n #call\n changes to vpn-customer-gateway infrastructure directory\n asks Terraform to ensure that the workspace is in place\n when in _plan_ mode\n invokes Terraform.plan with the _dalmatian-read_ role\n when NOT in _plan_ mode\n invokes Terraform.apply with the _dalmatian-admin_ role\n when in _auto_approve_ mode\n asks Terraform to use auto_approve mode\n\nDalmatian::VpnCustomerGateway\n #name\n uses vpn_customer_gateway name\n #bgp_asn\n uses vpn_customer_gateway bgp_asn\n #ip_address\n uses vpn_customer_gateway ip_address\n #to_params\n provides a hash of attributes for use in deployment\n\nDalmatian::VpnCustomerGatewayTest\n #call\n changes to the vpn-customer-gateway directory\n logs our intention to run Terraform init\n runs Terraform init, with upgrade option\n ensures presence of workspace\n logs our intention to run Terraform fmt\n runs Terraform fmt with check and diff options\n logs our intention to run Terraform validate\n runs Terraform validate, with upgrade option\n changes back to the app root directory\n\nDalmatian::WAFDeployment\n #call\n changes to waf infrastructure directory\n asks Terraform to ensure that the workspace is in place\n when in _plan_ mode\n invokes Terraform.plan with the _dalmatian-read_ role\n when NOT in _plan_ mode\n invokes Terraform.apply with the _dalmatian-admin_ role\n when in _auto_approve_ mode\n asks Terraform to use auto_approve mode\n\nDalmatian::WAF\n #name\n uses waf name\n #action\n uses waf action\n #ip_deny_list\n has a list of IP addresses to block\n #aws_managed_rules\n uses waf aws_managed_rules list\n #associations\n uses waf associations list\n #to_params\n provides a hash of attributes for use in deployment\n\nDalmatian::WAFTest\n #call\n changes to the ecs-services directory\n logs our intention to run Terraform init\n runs Terraform init, with upgrade option\n ensures presence of workspace\n logs our intention to run Terraform fmt\n runs Terraform fmt with check and diff options\n logs our intention to run Terraform validate\n runs Terraform validate, with upgrade option\n changes back to the app root directory\n\nFailures:\n\n 1) Dalmatian::RdsTest#call changes to the ecs-services directory\n Failure/Error: \"rds\" => rds.to_params\n #<InstanceDouble(Dalmatian::Rds) (anonymous)> received unexpected message :to_params with (no args)\n # ./lib/dalmatian/rds_test.rb:29:in `env_config'\n # ./lib/dalmatian/testable.rb:25:in `terraform_validate'\n # ./lib/dalmatian/testable.rb:9:in `call'\n # ./spec/unit/rds_test_spec.rb:89:in `block (3 levels) in <module:Dalmatian>'\n # ./spec/support/spec_helper.rb:24:in `block (3 levels) in <top (required)>'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:24:in `block in modify'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:15:in `synchronize'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:15:in `modify'\n # ./spec/support/spec_helper.rb:20:in `block (2 levels) in <top (required)>'\n # /Users/bob/.bundles/ruby/2.7.0/gems/webmock-3.19.1/lib/webmock/rspec.rb:39:in `block (2 levels) in <top (required)>'\n\n 2) Dalmatian::RdsTest#call logs our intention to run Terraform init\n Failure/Error: \"rds\" => rds.to_params\n #<InstanceDouble(Dalmatian::Rds) (anonymous)> received unexpected message :to_params with (no args)\n # ./lib/dalmatian/rds_test.rb:29:in `env_config'\n # ./lib/dalmatian/testable.rb:25:in `terraform_validate'\n # ./lib/dalmatian/testable.rb:9:in `call'\n # ./spec/unit/rds_test_spec.rb:89:in `block (3 levels) in <module:Dalmatian>'\n # ./spec/support/spec_helper.rb:24:in `block (3 levels) in <top (required)>'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:24:in `block in modify'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:15:in `synchronize'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:15:in `modify'\n # ./spec/support/spec_helper.rb:20:in `block (2 levels) in <top (required)>'\n # /Users/bob/.bundles/ruby/2.7.0/gems/webmock-3.19.1/lib/webmock/rspec.rb:39:in `block (2 levels) in <top (required)>'\n\n 3) Dalmatian::RdsTest#call runs Terraform init, with upgrade option\n Failure/Error: \"rds\" => rds.to_params\n #<InstanceDouble(Dalmatian::Rds) (anonymous)> received unexpected message :to_params with (no args)\n # ./lib/dalmatian/rds_test.rb:29:in `env_config'\n # ./lib/dalmatian/testable.rb:25:in `terraform_validate'\n # ./lib/dalmatian/testable.rb:9:in `call'\n # ./spec/unit/rds_test_spec.rb:89:in `block (3 levels) in <module:Dalmatian>'\n # ./spec/support/spec_helper.rb:24:in `block (3 levels) in <top (required)>'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:24:in `block in modify'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:15:in `synchronize'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:15:in `modify'\n # ./spec/support/spec_helper.rb:20:in `block (2 levels) in <top (required)>'\n # /Users/bob/.bundles/ruby/2.7.0/gems/webmock-3.19.1/lib/webmock/rspec.rb:39:in `block (2 levels) in <top (required)>'\n\n 4) Dalmatian::RdsTest#call ensures presence of workspace\n Failure/Error: \"rds\" => rds.to_params\n #<InstanceDouble(Dalmatian::Rds) (anonymous)> received unexpected message :to_params with (no args)\n # ./lib/dalmatian/rds_test.rb:29:in `env_config'\n # ./lib/dalmatian/testable.rb:25:in `terraform_validate'\n # ./lib/dalmatian/testable.rb:9:in `call'\n # ./spec/unit/rds_test_spec.rb:89:in `block (3 levels) in <module:Dalmatian>'\n # ./spec/support/spec_helper.rb:24:in `block (3 levels) in <top (required)>'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:24:in `block in modify'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:15:in `synchronize'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:15:in `modify'\n # ./spec/support/spec_helper.rb:20:in `block (2 levels) in <top (required)>'\n # /Users/bob/.bundles/ruby/2.7.0/gems/webmock-3.19.1/lib/webmock/rspec.rb:39:in `block (2 levels) in <top (required)>'\n\n 5) Dalmatian::RdsTest#call logs our intention to run Terraform fmt\n Failure/Error: \"rds\" => rds.to_params\n #<InstanceDouble(Dalmatian::Rds) (anonymous)> received unexpected message :to_params with (no args)\n # ./lib/dalmatian/rds_test.rb:29:in `env_config'\n # ./lib/dalmatian/testable.rb:25:in `terraform_validate'\n # ./lib/dalmatian/testable.rb:9:in `call'\n # ./spec/unit/rds_test_spec.rb:89:in `block (3 levels) in <module:Dalmatian>'\n # ./spec/support/spec_helper.rb:24:in `block (3 levels) in <top (required)>'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:24:in `block in modify'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:15:in `synchronize'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:15:in `modify'\n # ./spec/support/spec_helper.rb:20:in `block (2 levels) in <top (required)>'\n # /Users/bob/.bundles/ruby/2.7.0/gems/webmock-3.19.1/lib/webmock/rspec.rb:39:in `block (2 levels) in <top (required)>'\n\n 6) Dalmatian::RdsTest#call runs Terraform fmt with check and diff options\n Failure/Error: \"rds\" => rds.to_params\n #<InstanceDouble(Dalmatian::Rds) (anonymous)> received unexpected message :to_params with (no args)\n # ./lib/dalmatian/rds_test.rb:29:in `env_config'\n # ./lib/dalmatian/testable.rb:25:in `terraform_validate'\n # ./lib/dalmatian/testable.rb:9:in `call'\n # ./spec/unit/rds_test_spec.rb:89:in `block (3 levels) in <module:Dalmatian>'\n # ./spec/support/spec_helper.rb:24:in `block (3 levels) in <top (required)>'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:24:in `block in modify'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:15:in `synchronize'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:15:in `modify'\n # ./spec/support/spec_helper.rb:20:in `block (2 levels) in <top (required)>'\n # /Users/bob/.bundles/ruby/2.7.0/gems/webmock-3.19.1/lib/webmock/rspec.rb:39:in `block (2 levels) in <top (required)>'\n\n 7) Dalmatian::RdsTest#call logs our intention to run Terraform validate\n Failure/Error: \"rds\" => rds.to_params\n #<InstanceDouble(Dalmatian::Rds) (anonymous)> received unexpected message :to_params with (no args)\n # ./lib/dalmatian/rds_test.rb:29:in `env_config'\n # ./lib/dalmatian/testable.rb:25:in `terraform_validate'\n # ./lib/dalmatian/testable.rb:9:in `call'\n # ./spec/unit/rds_test_spec.rb:89:in `block (3 levels) in <module:Dalmatian>'\n # ./spec/support/spec_helper.rb:24:in `block (3 levels) in <top (required)>'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:24:in `block in modify'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:15:in `synchronize'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:15:in `modify'\n # ./spec/support/spec_helper.rb:20:in `block (2 levels) in <top (required)>'\n # /Users/bob/.bundles/ruby/2.7.0/gems/webmock-3.19.1/lib/webmock/rspec.rb:39:in `block (2 levels) in <top (required)>'\n\n 8) Dalmatian::RdsTest#call runs Terraform validate, with upgrade option\n Failure/Error: \"rds\" => rds.to_params\n #<InstanceDouble(Dalmatian::Rds) (anonymous)> received unexpected message :to_params with (no args)\n # ./lib/dalmatian/rds_test.rb:29:in `env_config'\n # ./lib/dalmatian/testable.rb:25:in `terraform_validate'\n # ./lib/dalmatian/testable.rb:9:in `call'\n # ./spec/unit/rds_test_spec.rb:89:in `block (3 levels) in <module:Dalmatian>'\n # ./spec/support/spec_helper.rb:24:in `block (3 levels) in <top (required)>'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:24:in `block in modify'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:15:in `synchronize'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:15:in `modify'\n # ./spec/support/spec_helper.rb:20:in `block (2 levels) in <top (required)>'\n # /Users/bob/.bundles/ruby/2.7.0/gems/webmock-3.19.1/lib/webmock/rspec.rb:39:in `block (2 levels) in <top (required)>'\n\n 9) Dalmatian::RdsTest#call changes back to the app root directory\n Failure/Error: \"rds\" => rds.to_params\n #<InstanceDouble(Dalmatian::Rds) (anonymous)> received unexpected message :to_params with (no args)\n # ./lib/dalmatian/rds_test.rb:29:in `env_config'\n # ./lib/dalmatian/testable.rb:25:in `terraform_validate'\n # ./lib/dalmatian/testable.rb:9:in `call'\n # ./spec/unit/rds_test_spec.rb:89:in `block (3 levels) in <module:Dalmatian>'\n # ./spec/support/spec_helper.rb:24:in `block (3 levels) in <top (required)>'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:24:in `block in modify'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:15:in `synchronize'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:15:in `modify'\n # ./spec/support/spec_helper.rb:20:in `block (2 levels) in <top (required)>'\n # /Users/bob/.bundles/ruby/2.7.0/gems/webmock-3.19.1/lib/webmock/rspec.rb:39:in `block (2 levels) in <top (required)>'\n\nFinished in 3.24 seconds (files took 0.75528 seconds to load)\n478 examples, 9 failures\n\nFailed examples:\n\nrspec ./spec/unit/rds_test_spec.rb:91 # Dalmatian::RdsTest#call changes to the ecs-services directory\nrspec ./spec/unit/rds_test_spec.rb:101 # Dalmatian::RdsTest#call logs our intention to run Terraform init\nrspec ./spec/unit/rds_test_spec.rb:107 # Dalmatian::RdsTest#call runs Terraform init, with upgrade option\nrspec ./spec/unit/rds_test_spec.rb:111 # Dalmatian::RdsTest#call ensures presence of workspace\nrspec ./spec/unit/rds_test_spec.rb:116 # Dalmatian::RdsTest#call logs our intention to run Terraform fmt\nrspec ./spec/unit/rds_test_spec.rb:122 # Dalmatian::RdsTest#call runs Terraform fmt with check and diff options\nrspec ./spec/unit/rds_test_spec.rb:126 # Dalmatian::RdsTest#call logs our intention to run Terraform validate\nrspec ./spec/unit/rds_test_spec.rb:132 # Dalmatian::RdsTest#call runs Terraform validate, with upgrade option\nrspec ./spec/unit/rds_test_spec.rb:190 # Dalmatian::RdsTest#call changes back to the app root directory\n\nCoverage report generated for RSpec to /Users/bob/git/dxw/dalmatian/coverage. 4299 / 4389 LOC (97.95%) covered.\nStopped processing SimpleCov as a previous error not related to SimpleCov has been detected\n/Users/bob/.rbenv/versions/2.7.1/bin/ruby -I/Users/bob/.bundles/ruby/2.7.0/gems/rspec-core-3.12.2/lib:/Users/bob/.bundles/ruby/2.7.0/gems/rspec-support-3.12.1/lib /Users/bob/.bundles/ruby/2.7.0/gems/rspec-core-3.12.2/exe/rspec --pattern spec/\\*\\*\\{,/\\*/\\*\\*\\}/\\*_spec.rb failed\nExit Code: 1\nProcess Group PGID: 48790"
|
|
}
|
|
}
|
|
}
|
|
],
|
|
"status": "success",
|
|
"timestamp": "2026-02-20T17:16:08.081Z",
|
|
"resultDisplay": "==> Linting YAML...\n\n==> Linting shell scripts...\n\n==> Checking Terraform for JSON errors...\n- Checking ./terraform/policies/iam-read.json... Passed\n- Checking ./terraform/policies/s3-rw-with-versioning.json... Passed\n- Checking ./terraform/policies/codestar-connection-use.json... Passed\n- Checking ./terraform/policies/iam-create-access-key.json... Passed\n- Checking ./terraform/policies/codebuild.json... Passed\n- Checking ./terraform/policies/kms-encrypt-decrypt.json... Passed\n- Checking ./terraform/policies/iam-change-password.json... Passed\n- Checking ./terraform/policies/administrator-access.json... Passed\n- Checking ./terraform/policies/assume_roles/aws-backup.json... Passed\n- Checking ./terraform/policies/assume_roles/autoscaling.json... Passed\n- Checking ./terraform/policies/assume_roles/events.json... Passed\n- Checking ./terraform/policies/assume_roles/ecs.json... Passed\n- Checking ./terraform/policies/assume_roles/codepipeline.json... Passed\n- Checking ./terraform/policies/iam-mfa.json... Passed\n- Checking ./terraform/policies/route53-read.json... Passed\n- Checking ./terraform/policies/s3-full-access.json... Passed\n- Checking ./terraform/policies/parameter-store-read-decrypt.json... Passed\n- Checking ./terraform/policies/s3-read.json... Passed\n- Checking ./terraform/policies/parameter-store-RW-encrypt-decrypt.json... Passed\n- Checking ./terraform/policies/all-read-with-billing.json... Passed\n- Checking ./terraform/policies/codebuild-start-build.json... Passed\n- Checking ./terraform/policies/all-read.json... Passed\n\n==> Linting Terraform...\n\n==> Running Ruby tests...\n/Users/bob/.rbenv/versions/2.7.1/bin/ruby -I/Users/bob/.bundles/ruby/2.7.0/gems/rspec-core-3.12.2/lib:/Users/bob/.bundles/ruby/2.7.0/gems/rspec-support-3.12.1/lib /Users/bob/.bundles/ruby/2.7.0/gems/rspec-core-3.12.2/exe/rspec --pattern spec/\\*\\*\\{,/\\*/\\*\\*\\}/\\*_spec.rb\n\ntests local configuration\n use of \"terraform apply\"\n passes the hosted zone config to \"terraform apply\"\n passes the s3 config to \"terraform apply\"\n passes the vpn customer gateway config to \"terraform apply\"\n passes the base config to \"terraform apply\"\n passes the waf config to \"terraform apply\"\n passes the rds config to \"terraform apply\"\n passes the elasticache config to \"terraform apply\"\n passes the opensearch config to \"terraform apply\"\n passes the service config to \"terraform apply\"\n passes the loadbalancer config to \"terraform apply\"\n passes the cluster 2 config to \"terraform apply\"\n passes the cluster 3 config to \"terraform apply\"\n passes the cluster 4 config to \"terraform apply\"\n\ntests remote configuration\n retrieves the remotely held full configuration\n proceeds with deploying the infrastructure as per the cached full configuration\n\ntests local configuration\n invokes \"terraform validate\" with the expected cluster options\n invokes \"terraform validate\" with the expected source options\n use of \"terraform plan\"\n passes the hosted zone config to \"terraform plan\"\n passes the s3 config to \"terraform plan\"\n passes the vpn customer gateway config to \"terraform plan\"\n passes the base config to \"terraform plan\"\n passes the waf config to \"terraform plan\"\n passes the rds config to \"terraform plan\"\n passes the elasticache config to \"terraform plan\"\n passes the opensearch config to \"terraform plan\"\n passes the services config to \"terraform plan\"\n passes the loadbalancer config to \"terraform plan\"\n passes the cluster 2 config to \"terraform plan\"\n passes the cluster 3 config to \"terraform plan\"\n passes the cluster 4 config to \"terraform plan\"\n\nDalmatian::Account\n initialisation\n gathering user input\n asks the user for AWS credentials\n asks the user for the AWS account id to use\n asks the user for an account alias\n #call\n changes to the bootstrapping directory\n runs terraform init with upgrade option\n creates the new workspace using the given aws account id and alias\n runs terraform apply with the user-supplied vars\n\nDalmatian::CacheHandlerSelector\n ::new_for(remote_reference)\n when the remote reference is for a git repo\n asks for an instance of GitCacheHandler\n when the remote reference is for an S3 bucket\n asks for an instance of S3CacheHandler\n when the remote reference is for a URL\n asks for an instance of UrlCacheHandler\n when the type is unknown\n raises an error\n\nCacheHandler\n when a subclass class does not implement #cache_remote_configuration\n raises a helpful error\n\nDalmatian::CI\n CI::PATH\n is a constant\n #deploy\n changes to the ci directory\n runs terraform init with upgrade option\n creates the new workspace using the given aws account id and alias\n runs terraform apply with the user-supplied vars\n #test\n runs terraform plan with the user-supplied vars\n\nDalmatian::ClusterDeployment\n #call\n changes to the ecs directory\n asks Terraform to ensure that the workspace is in place\n when the environment includes a git reference as \"track_revision\"\n does NOT attempt to check out that commit\n when in _plan_ mode\n invokes Terraform.plan using the _dalmatian-read_ role\n when NOT in _plan_ mode\n invokes Terraform.apply using the _dalmatian-admin_\n when in _auto_approve_ mode\n asks Terraform to use auto_approve mode\n\nDalmatian::Cluster\n on initialisation\n makes Hosted zones, S3, Sources, Services, Loadbalancers, WAF and Rds\n #target_directory\n is a standard _ecs_ path\n #id\n is the primary key of the cluster definition is used\n #name\n when the cluster has an explicitly provided _name_ property\n that property is used\n when the cluster does not have an explicitly provided _name_ property\n the primary key of the cluster definition is used\n #account_id\n is the aws account key for deployment\n #sources\n represents any links to remote sources\n #environments\n represents the attributes of each environment's cluster section\n #fetch\n when the source is remotely held\n logs the plan to clone the source into the infrastructure pth\n deletes any existing source at the infrastructure location\n clones each source into the infrastructure location\n changes to the infrastructure directory for each source\n runs rake terrafile\n changes back to the APP_ROOT\n when the source is a local file path\n does not re-clone the source\n does not run terrafile\n when the specified local directory exists\n logs the fact that the local source is in place\n when the specificed local directory does not exist\n logs an error that the local source is missing\n #deploy\n deploys source infrastructure for each source and each service in each environment\n when a cluster should be created\n deploys cluster infrastructure for each environment\n when the _plan_ option IS invoked\n creates Cluster Deployments with plan settings\n when the _auto_approve_ option IS invoked\n creates Cluster Deployments with auto_approve settings\n handling of tests\n when the _test_ option is NOT invoked\n does not run cluster tests\n does not run cluster tests\n does not run cluster tests\n does not run source tests\n does not run waf tests\n does not run rds tests\n does not run service tests\n does not run service tests\n when the test option IS invoked\n runs tests\n when a cluster should NOT be created\n does not deploy cluster infrastructure\n when test option is invoked\n tests sources and services for each environment\n\nDalmatian::ClusterTest\n #call\n changes to the ecs directory\n logs our intention to run Terraform init\n runs Terraform init, with upgrade option\n ensures presence of workspace\n logs our intention to run Terraform fmt\n runs Terraform fmt with check and diff options\n logs our intention to run Terraform validate\n runs Terraform validate, with upgrade option\n changes back to the app root directory\n when the environment includes a git reference as \"track_revision\"\n does NOT attempt to check out that commit\n\nDalmatian::ConfigurationReader\n when a full configuration is provided in a local file\n #call\n has no need to use a cache handler\n returns the loaded configuration\n when a reference to a remote configuration is provided\n and the reference is provided in a local file\n uses the CacheHandlerSelector to provide the appropriate retrieval mechanism\n calls on the selected cache handler\n returns the configuration returned by the cache_handler\n and the reference is provided using environment variables\n passes the provided remote reference to the CacheHandlerSelector\n and references are provided in both environment variables and config file\n prefers the environment variable references over the config file\n and no references are provided\n raises an error\n and the remote reference is missing its _type_\n raises an error\n #ci\n when a parameter path prefix is given\n overwrites the ci:variables config with those retrieved from the param store\n leaves other ci:variables in place\n when a parameter path prefix is NOT given\n does NOT overwrite any ci:variables from the param store\n\nDalmatian::ElasticacheCluster\n #identifier\n uses elasticache identifier\n #in_use_by\n uses elasticache_cluster in_use_by list\n #node_type\n uses elasticache_cluster node_type\n #node_count\n uses elasticache_cluster node_count\n #engine\n uses elasticache_cluster engine\n #engine_version\n uses the elasticache_cluster engine_version\n #parameters\n uses the elasticache_cluster parameters list\n #port\n uses the elasticache_cluster port\n #maintenance_window\n uses the elasticache_cluster maintenance_window\n #snapshot_window\n uses the elasticache_cluster snapshot_window\n #parameter_store_path_elasticache_cluster_url_name\n uses the elasticache_cluster parameter_store_path_elasticache_cluster_url_name\n #to_params\n provides a hash of attributes for use in deployment\n\nDalmatian::ElasticacheClusterTest\n #call\n changes to the elasticache-cluster directory\n logs our intention to run Terraform init\n runs Terraform init, with upgrade option\n ensures presence of workspace\n logs our intention to run Terraform fmt\n runs Terraform fmt with check and diff options\n logs our intention to run Terraform validate\n runs Terraform validate, with upgrade option\n changes back to the app root directory\n\nDalmatian::GitCacheHandler\n #call\n deletes any old cache\n uses git clone to save the remote config to a local cache\n logs the cloning action\n logs the path to the cached configuration\n returns the cached full configuration to the caller (configuration reader)\n reads the cached full configuration from the disk in order to return to caller\n when no special cache path is given\n uses the default cache path of ./.dalmatian_cache/remote_config\n\nDalmatian::Helper\n ::git_clone(source, destination)\n when source and destination args are not provided\n raises an error with usage info\n when given source and destination args\n passes the request to the git CLI\n ::git_checkout(revision)\n checks out the given revision using run!\n ::get(source, destination)\n when source and destination args are not provided\n raises an error with usage info\n when given source and destination args\n opens the source url\n opens a new file at the destination\n writes the source resource into that file\n reads the information from the fetched resource\n ::run!\n passes given cmd to Kernel.system\n when the call to Kernel.system returns _false_\n raise a helpful error\n ::run_with_output!(cmd)\n passes given cmd to Open3.capture3\n when the system call returns a zero exit status\n returns the systems output to STDOUT\n when the system call returns a non-zero exit status\n also returns STDOUT ignoring the exit code and STDERR\n when the system call raises an ENOENT error\n catches this and raises a helpful Error\n ::change_to(path)\n passes the given path to Dir.chdir\n ::to_bool(str)\n when given nil\n returns false\n when given an empty string\n returns false\n when given lower case string _true_\n returns true\n when given mixed case string _True_\n returns true\n when given the object true\n returns true\n when given the object false\n returns false\n ::tflint\n runs the tflint cmd\n ::terrafile\n runs rake terrafile\n ::ask\n delegates to HighLine#ask\n ::ask_in_confidence\n delegates to HighLine#ask\n passes a block to mask the answer\n\nDalmatian::HostedZoneDeployment\n #call\n changes to hosted-zone infrastructure directory\n asks Terraform to ensure that the workspace is in place\n when in _plan_ mode\n invokes Terraform.plan with the _dalmatian-read_ role\n when NOT in _plan_ mode\n invokes Terraform.apply with the _dalmatian-admin_ role\n when in _auto_approve_ mode\n asks Terraform to use auto_approve mode\n\nDalmatian::HostedZone\n #domain\n uses hosted_zone domain\n #ns_records\n uses hosted_zone ns_records\n #a_records\n uses hosted_zone a_records\n #alias_records\n uses hosted_zone alias_records\n #cname_records\n uses hosted_zone cname_records\n #mx_records\n uses hosted_zone mx_records\n #txt_records\n uses hosted_zone txt_records\n #srv_records\n uses hosted_zone srv_records\n #to_params\n provides a hash of attributes for use in deployment\n\nDalmatian::HostedZoneTest\n #call\n changes to the hosted-zone directory\n logs our intention to run Terraform init\n runs Terraform init, with upgrade option\n ensures presence of workspace\n logs our intention to run Terraform fmt\n runs Terraform fmt with check and diff options\n logs our intention to run Terraform validate\n runs Terraform validate, with upgrade option\n changes back to the app root directory\n\nDalmatian::Infrastructure\n Infrastructure::PATH\n is a constant\n Infrastructure::APP_ROOT\n is a constant\n initialisation\n when configuration is not provided\n builds one using the defaults\n #clusters\n creates one cluster for each cluster description provided\n key operations on clusters\n #fetch\n asks all clusters to #fetch\n #test\n asks all clusters to #deploy with _plan_ and _test_ options\n #deploy\n when no parameters given\n asks all clusters to #deploy with _plan_, _test_ and _auto-approve_ disabled\n when parameters are given\n asks all clusters to #deploy with the given options\n when a particular infrastructure is named for deployment\n asks only the named cluster to #deploy with the given options\n\nDalmatian::Logger\n ::error(msg)\n raises an error with a red message\n ::info(msg)\n puts the given given message in white\n ::success(msg)\n puts the given given message in green\n ::warn(msg)\n puts the given given message in yellow\n\nDalmatian::OpensearchCluster\n #identifier\n uses opensearch identifier\n #in_use_by\n uses opensearch_cluster in_use_by list\n #version\n uses opensearch_cluster version\n #master_enabled\n uses opensearch_cluster master_enabled bool\n #master_count\n uses opensearch_cluster master_count\n #master_type\n uses opensearch_cluster master_type\n #instance_count\n uses opensearch_cluster instance_count\n #instance_type\n uses opensearch_cluster instance_type\n #warm_enabled\n uses opensearch_cluster warm_enabled bool\n #warm_count\n uses opensearch_cluster warm_count\n #warm_type\n uses opensearch_cluster warm_type\n #parameter_store_path_opensearch_cluster_url_name\n uses opensearch_cluster parameter_store_path_opensearch_cluster_url_name\n #volume_size\n uses opensearch_cluster volume_size\n #to_params\n provides a hash of attributes for use in deployment\n\nDalmatian::OpensearchClusterTest\n #call\n changes to the opensearch-cluster directory\n logs our intention to run Terraform init\n runs Terraform init, with upgrade option\n ensures presence of workspace\n logs our intention to run Terraform fmt\n runs Terraform fmt with check and diff options\n logs our intention to run Terraform validate\n runs Terraform validate, with upgrade option\n changes back to the app root directory\n\nDalmatian::ParameterStore\n ::get_parameter(name: \"\", with_decryption: true)\n when getting a single parameter from Parameter Store\n runs aws ssm get-parameter\n ::get_parameters_by_path(path: \"\", with_decryption: true)\n when getting parameters by path from Parameter Store\n runs aws ssm get-parameter\n\nDalmatian::RdsDeployment\n #call\n changes to rds infrastructure directory\n asks Terraform to ensure that the workspace is in place\n when in _plan_ mode\n invokes Terraform.plan with the _dalmatian-read_ role\n when NOT in _plan_ mode\n invokes Terraform.apply with the _dalmatian-admin_ role\n when in _auto_approve_ mode\n asks Terraform to use auto_approve mode\n\nDalmatian::Rds\n #identifier\n uses rds identifier\n #in_use_by\n uses rds in_use_by list\n #clusters_in_use\n uses rds clusters_in_use list\n #instance_class\n uses rds instance_class\n #engine\n uses rds engine\n #engine_version\n uses the rds engine_version\n #allocated_storage\n uses the rds allocated_storage\n #storage_encrypted\n uses the rds storage_encrypted bool\n #storage_type\n uses the rds storage_type gp3\n #db_name\n uses the rds db_name\n #port\n uses the rds port\n #maintenance_window\n uses the rds maintenance_window\n #backup_window\n uses the rds backup_window\n #backup_retention_period\n uses the rds backup_retention_period\n #force_ssl\n uses the rds force_ssl bool\n #parameter_store_path_db_url_name\n uses the rds parameter_store_path_db_url_name\n #sql_backup_scheduled_task_environment_variables\n uses the rds sql_backup_scheduled_task_environment_variables\n #check_sql_backup_scheduled_task_environment_variables\n uses the rds check_sql_backup_scheduled_task_environment_variables\n #sync_sql_backup_to_azure\n will have offsite backups disabled by default\n #replication_bucket_destination_arn\n uses the rds replication_bucket_destination_arn\n #replication_kms_key_id\n uses the rds replication_kms_key_id\n #codebuild_access\n uses the rds codebuild_access\n #to_params\n provides a hash of attributes for use in deployment\n\nDalmatian::RdsTest\n #call\n changes to the ecs-services directory (FAILED - 1)\n logs our intention to run Terraform init (FAILED - 2)\n runs Terraform init, with upgrade option (FAILED - 3)\n ensures presence of workspace (FAILED - 4)\n logs our intention to run Terraform fmt (FAILED - 5)\n runs Terraform fmt with check and diff options (FAILED - 6)\n logs our intention to run Terraform validate (FAILED - 7)\n runs Terraform validate, with upgrade option (FAILED - 8)\n changes back to the app root directory (FAILED - 9)\n\nDalmatian::RemoteReferenceValues\n when the reference is for a git repo\n returns a git shaped configuration\n if _filename_ is not present\n supplies the default of _dalmatian.yml_\n when the reference is for an S3 bucket\n returns an S3 shaped configuration\n if _key_ is not present\n supplies the default of _dalmatian.yml_\n when the reference is for a URL\n returns a git shaped configuration\n\nDalmatian::S3CacheHandler\n #call\n deletes any old cache\n uses the AWS S3 cmd to save the remote config to a local cache\n logs the cloning action\n logs the path to the cached configuration\n returns the cached full configuration to the caller (configuration reader)\n reads the cached full configuration from the disk in order to return to caller\n\nDalmatian::S3Deployment\n #call\n changes to s3 infrastructure directory\n asks Terraform to ensure that the workspace is in place\n when in _plan_ mode\n invokes Terraform.plan with the _dalmatian-read_ role\n when NOT in _plan_ mode\n invokes Terraform.apply with the _dalmatian-admin_ role\n when in _auto_approve_ mode\n asks Terraform to use auto_approve mode\n\nDalmatian::S3\n #name\n uses s3 name\n #enable_s3_versioning\n uses enable_s3_versioning bool\n #encrypted\n uses s3 encrypted bool\n #acl\n uses s3 acl\n #policy\n uses s3 policy\n #service_cloudfront_read_access\n uses s3 service_cloudfront_read_access\n #cloudfront\n uses s3 cloudfront\n #to_params\n provides a hash of attributes for use in deployment\n\nDalmatian::S3Test\n #call\n changes to the s3 directory\n logs our intention to run Terraform init\n runs Terraform init, with upgrade option\n ensures presence of workspace\n logs our intention to run Terraform fmt\n runs Terraform fmt with check and diff options\n logs our intention to run Terraform validate\n runs Terraform validate, with upgrade option\n changes back to the app root directory\n\nDalmatian::ServiceDeployment\n #call\n changes to ecs-services infrastructure directory\n asks Terraform to ensure that the workspace is in place\n when in _plan_ mode\n invokes Terraform.plan with the _dalmatian-read_ role\n when NOT in _plan_ mode\n invokes Terraform.apply with the _dalmatian-admin_ role\n when in _auto_approve_ mode\n asks Terraform to use auto_approve mode\n\nDalmatian::Service\n #name\n uses service name\n #blue_green\n uses the service blue_green map\n #parameter_store_path\n uses service parameter_store_path\n #parameter_store_key\n uses service parameter_store_key\n #daemon\n uses the service daemon bool\n #monitoring\n uses the service monitoring hash\n #cloudfront\n recasts the service config in environment groups\n includes the appropriate \"custom_origins\" values in each environment\n Uses an AWS cloudfront managed cache policy\n Uses an AWS cloudfront managed origin policy\n Uses an AWS cloudfront managed response headers policy\n mirroring of elements into each environment group\n includes the \"create\" value\n includes the \"tls_protocol_version\" value\n includes the \"origin_keepalive_timeout\" value\n includes the \"origin_read_timeout\" value\n includes the \"basic_auth\" value\n includes the \"basic_auth_users_extra\" value\n includes the \"viewer_request_functions\" values\n includes the \"offline_page_http_status\" value\n bypass_protection\n uses the \"bypass_protection\" configuration\n custom_behaviors\n converts list of \"path_patterns\" to a single \"path_pattern\"\n #shared_loadbalancer_name\n returns shared loadbalancer name if the service is in use by a shared loadbalancer\n returns empty string if the service is not in use by a shared loadbalancer\n #s3_policy\n uses the service s3_policy map\n #lb_ip_whitelistt\n uses the service lb_ip_whitelist list\n #lb_idle_timeout\n uses the service lb_idle_timeout\n #global_accelerator\n uses service global_accelerator value\n #health_check_path\n uses the service health_check_path\n #health_check_grace_period\n uses the service health_check_grace_period\n #deregistration_delay\n uses the service deregistration_delay\n #serve_from_subdirectory\n uses the service serve_from_subdirectory\n #domain_names\n groups the domain names from the service domain_list into environments\n #proxy_configuration\n groups the proxy configurations from the service proxy_configuration list into environments\n #home_directory\n uses the service home_directory\n #lb_ssl_certificate\n groups the certificate arns from the service lb_ssl_certificate list into environments\n #lb_ssl_policy\n sets the default ssl policy for each environment\n #cloudfront_ssl_certificate\n groups the certificate arns from the service cloudfront_ssl_certificate list into environments\n #image_source\n uses the service image source\n #launch_on\n uses the service 'launch_on' specification\n #launch_on_cluster\n uses the service 'launch_on_cluster' string\n #cluster_min_servers\n uses the service 'cluster_min_servers' string\n #image_location\n uses the service image location\n #track_revision\n uses the service track_revision string\n #custom_codestar_connection_arn\n uses the service custom_codestar_connection_arn\n #codepipeline_use_github_v1\n uses the service codepipeline_use_github_v1\n #codepipeline_codebuild_run_in_vpc\n uses the service codepipeline_codebuild_run_in_vpc\n #codepipeline_codebuild_use_service_env\n uses the service codepipeline_codebuild_use_service_env\n #buildspec\n uses the service buildspec\n #container_port\n uses the service container port\n #container_command\n uses the service container command\n #container_volumes\n uses the service container volumes\n #container_extra_hosts\n uses the service container extra hosts\n #container_count\n uses the service container_count\n #enable_max_one_container_per_instance\n uses the service enable_max_one_container_per_instance\n #scheduled_tasks\n uses the service scheduled tasks\n #workers\n uses the service workers\n #cluster_name\n delegates to the cluster\n #cluster_id\n delegates to the cluster\n #account_id\n delegates to the cluster\n #to_params\n provides a hash of attributes for use in deployment\n\nDalmatian::ServiceTest\n #call\n changes to the ecs-services directory\n logs our intention to run Terraform init\n runs Terraform init, with upgrade option\n ensures presence of workspace\n logs our intention to run Terraform fmt\n runs Terraform fmt with check and diff options\n logs our intention to run Terraform validate\n runs Terraform validate, with upgrade option\n changes back to the app root directory\n\nDalmatian::SharedLoadbalancerDeployment\n #call\n changes to shared-loadbalancer infrastructure directory\n asks Terraform to ensure that the workspace is in place\n when in _plan_ mode\n invokes Terraform.plan with the _dalmatian-read_ role\n when NOT in _plan_ mode\n invokes Terraform.apply with the _dalmatian-admin_ role\n when in _auto_approve_ mode\n asks Terraform to use auto_approve mode\n\nDalmatian::SharedLoadbalancer\n #name\n uses shared_loadbalancer name\n #in_use_by\n uses shared_loadbalancer in_use_by list\n #clusters_in_use\n uses shared_loadbalancer clusters_in_use list\n #subnets_name\n uses shared_loadbalancer subnets_name value\n #domain_names\n uses shared_loadbalancer domain_names list provided by Services\n #internal\n uses shared_loadbalancer internal value\n #ip_whitelist\n uses shared_loadbalancer ip_whitelist list\n #idle_timeout\n uses shared_loadbalancer idle_timeout value\n #global_accelerator\n uses shared_loadbalancer global_accelerator value\n #ssl_policy\n has the default ssl policy defined\n #to_params\n provides a hash of attributes for use in deployment\n\nDalmatian::SharedLoadbalancerTest\n #call\n changes to the shared-loadbalancer directory\n logs our intention to run Terraform init\n runs Terraform init, with upgrade option\n ensures presence of workspace\n logs our intention to run Terraform fmt\n runs Terraform fmt with check and diff options\n logs our intention to run Terraform validate\n runs Terraform validate, with upgrade option\n changes back to the app root directory\n\nDalmatian::SourceDeployment\n #call\n changes to infrastructure config directory\n asks Terraform to ensure that the workspace is in place\n when the environment includes a git reference as \"track_revision\"\n checks out that commit\n passes the \"track_revision\" reference along to Terraform\n when in _plan_ mode\n invokes Terraform.plan with the _dalmatian-read_ role\n when NOT in _plan_ mode\n invokes Terraform.apply with the _dalmatian-admin_ role\n when in _auto_approve_ mode\n asks Terraform to use auto_approve mode\n\nDalmatian::Source\n #name\n uses the cluster name and its own position in the cluster's list of sources\n #cluster_name\n delegates to the cluster\n #cluster_id\n delegates to the cluster\n #account_id\n delegates to the cluster\n\nDalmatian::SourceTest\n #call\n changes to the ecs directory\n logs our intention to run Terraform init\n runs Terraform init, with upgrade option\n ensures presence of workspace\n logs our intention to run Terraform fmt\n runs Terraform fmt with check and diff options\n logs our intention to run Terraform validate\n runs Terraform validate, with upgrade option\n changes back to the app root directory\n when the environment includes a git reference as \"track_revision\"\n checks out that commit\n passes the \"track_revision\" reference along to Terraform.validate\n\nDalmatian::Terraform\n ::init(upgrade: false)\n when asked to upgrade\n passes terraform init the upgrade flag\n when not asked to upgrade\n does not pass terraform init the upgrade flag\n ::fmt(args = nil)\n when passed some additional arguments\n passes terraform fmt the upgrade flag\n when passed NO additional arguments\n invokes terraform fmt with no arguments\n ::validate(tfvars)\n passes the given _var-file_ to terraform\n reformats the given tfvars and passes them to terraform as args\n ::ensure_presence_of_workspace(workspace_name)\n logs our intention to create the workspace\n asks Terraform to create the workspace\n when the workspace already exists (and an error is rescued)\n logs our intention to _select_ rather than _create_ the workspace\n asks Terraform to select the existing workspace\n ::plan(tfvars)\n passes the given _var-file_ to terraform\n reformats the given tfvars and passes them to terraform as args\n ::apply(tfvars, auto_approve=false)\n passes the given _var-file_ to terraform\n reformats the given tfvars and passes them to terraform as args\n when auto-approve is set to true\n passes the _auto-approve_ flag to terraform apply\n ::destroy(tfvars)\n passes the given _var-file_ to terraform\n reformats the given tfvars and passes them to terraform as args\n ::list_workspaces\n changes to the bootstrapping directory\n runs the terraform cmd to list workspaces\n\nDalmatian::UrlCacheHandler\n #call\n deletes any old cache\n uses the helper to GET a URI\n logs the cloning action\n logs the path to the cached configuration\n returns the cached full configuration to the caller (configuration reader)\n reads the cached full configuration from the disk in order to return to caller\n\nDalmatian::VpnCustomerGatewayDeployment\n #call\n changes to vpn-customer-gateway infrastructure directory\n asks Terraform to ensure that the workspace is in place\n when in _plan_ mode\n invokes Terraform.plan with the _dalmatian-read_ role\n when NOT in _plan_ mode\n invokes Terraform.apply with the _dalmatian-admin_ role\n when in _auto_approve_ mode\n asks Terraform to use auto_approve mode\n\nDalmatian::VpnCustomerGateway\n #name\n uses vpn_customer_gateway name\n #bgp_asn\n uses vpn_customer_gateway bgp_asn\n #ip_address\n uses vpn_customer_gateway ip_address\n #to_params\n provides a hash of attributes for use in deployment\n\nDalmatian::VpnCustomerGatewayTest\n #call\n changes to the vpn-customer-gateway directory\n logs our intention to run Terraform init\n runs Terraform init, with upgrade option\n ensures presence of workspace\n logs our intention to run Terraform fmt\n runs Terraform fmt with check and diff options\n logs our intention to run Terraform validate\n runs Terraform validate, with upgrade option\n changes back to the app root directory\n\nDalmatian::WAFDeployment\n #call\n changes to waf infrastructure directory\n asks Terraform to ensure that the workspace is in place\n when in _plan_ mode\n invokes Terraform.plan with the _dalmatian-read_ role\n when NOT in _plan_ mode\n invokes Terraform.apply with the _dalmatian-admin_ role\n when in _auto_approve_ mode\n asks Terraform to use auto_approve mode\n\nDalmatian::WAF\n #name\n uses waf name\n #action\n uses waf action\n #ip_deny_list\n has a list of IP addresses to block\n #aws_managed_rules\n uses waf aws_managed_rules list\n #associations\n uses waf associations list\n #to_params\n provides a hash of attributes for use in deployment\n\nDalmatian::WAFTest\n #call\n changes to the ecs-services directory\n logs our intention to run Terraform init\n runs Terraform init, with upgrade option\n ensures presence of workspace\n logs our intention to run Terraform fmt\n runs Terraform fmt with check and diff options\n logs our intention to run Terraform validate\n runs Terraform validate, with upgrade option\n changes back to the app root directory\n\nFailures:\n\n 1) Dalmatian::RdsTest#call changes to the ecs-services directory\n Failure/Error: \"rds\" => rds.to_params\n #<InstanceDouble(Dalmatian::Rds) (anonymous)> received unexpected message :to_params with (no args)\n # ./lib/dalmatian/rds_test.rb:29:in `env_config'\n # ./lib/dalmatian/testable.rb:25:in `terraform_validate'\n # ./lib/dalmatian/testable.rb:9:in `call'\n # ./spec/unit/rds_test_spec.rb:89:in `block (3 levels) in <module:Dalmatian>'\n # ./spec/support/spec_helper.rb:24:in `block (3 levels) in <top (required)>'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:24:in `block in modify'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:15:in `synchronize'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:15:in `modify'\n # ./spec/support/spec_helper.rb:20:in `block (2 levels) in <top (required)>'\n # /Users/bob/.bundles/ruby/2.7.0/gems/webmock-3.19.1/lib/webmock/rspec.rb:39:in `block (2 levels) in <top (required)>'\n\n 2) Dalmatian::RdsTest#call logs our intention to run Terraform init\n Failure/Error: \"rds\" => rds.to_params\n #<InstanceDouble(Dalmatian::Rds) (anonymous)> received unexpected message :to_params with (no args)\n # ./lib/dalmatian/rds_test.rb:29:in `env_config'\n # ./lib/dalmatian/testable.rb:25:in `terraform_validate'\n # ./lib/dalmatian/testable.rb:9:in `call'\n # ./spec/unit/rds_test_spec.rb:89:in `block (3 levels) in <module:Dalmatian>'\n # ./spec/support/spec_helper.rb:24:in `block (3 levels) in <top (required)>'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:24:in `block in modify'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:15:in `synchronize'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:15:in `modify'\n # ./spec/support/spec_helper.rb:20:in `block (2 levels) in <top (required)>'\n # /Users/bob/.bundles/ruby/2.7.0/gems/webmock-3.19.1/lib/webmock/rspec.rb:39:in `block (2 levels) in <top (required)>'\n\n 3) Dalmatian::RdsTest#call runs Terraform init, with upgrade option\n Failure/Error: \"rds\" => rds.to_params\n #<InstanceDouble(Dalmatian::Rds) (anonymous)> received unexpected message :to_params with (no args)\n # ./lib/dalmatian/rds_test.rb:29:in `env_config'\n # ./lib/dalmatian/testable.rb:25:in `terraform_validate'\n # ./lib/dalmatian/testable.rb:9:in `call'\n # ./spec/unit/rds_test_spec.rb:89:in `block (3 levels) in <module:Dalmatian>'\n # ./spec/support/spec_helper.rb:24:in `block (3 levels) in <top (required)>'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:24:in `block in modify'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:15:in `synchronize'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:15:in `modify'\n # ./spec/support/spec_helper.rb:20:in `block (2 levels) in <top (required)>'\n # /Users/bob/.bundles/ruby/2.7.0/gems/webmock-3.19.1/lib/webmock/rspec.rb:39:in `block (2 levels) in <top (required)>'\n\n 4) Dalmatian::RdsTest#call ensures presence of workspace\n Failure/Error: \"rds\" => rds.to_params\n #<InstanceDouble(Dalmatian::Rds) (anonymous)> received unexpected message :to_params with (no args)\n # ./lib/dalmatian/rds_test.rb:29:in `env_config'\n # ./lib/dalmatian/testable.rb:25:in `terraform_validate'\n # ./lib/dalmatian/testable.rb:9:in `call'\n # ./spec/unit/rds_test_spec.rb:89:in `block (3 levels) in <module:Dalmatian>'\n # ./spec/support/spec_helper.rb:24:in `block (3 levels) in <top (required)>'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:24:in `block in modify'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:15:in `synchronize'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:15:in `modify'\n # ./spec/support/spec_helper.rb:20:in `block (2 levels) in <top (required)>'\n # /Users/bob/.bundles/ruby/2.7.0/gems/webmock-3.19.1/lib/webmock/rspec.rb:39:in `block (2 levels) in <top (required)>'\n\n 5) Dalmatian::RdsTest#call logs our intention to run Terraform fmt\n Failure/Error: \"rds\" => rds.to_params\n #<InstanceDouble(Dalmatian::Rds) (anonymous)> received unexpected message :to_params with (no args)\n # ./lib/dalmatian/rds_test.rb:29:in `env_config'\n # ./lib/dalmatian/testable.rb:25:in `terraform_validate'\n # ./lib/dalmatian/testable.rb:9:in `call'\n # ./spec/unit/rds_test_spec.rb:89:in `block (3 levels) in <module:Dalmatian>'\n # ./spec/support/spec_helper.rb:24:in `block (3 levels) in <top (required)>'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:24:in `block in modify'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:15:in `synchronize'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:15:in `modify'\n # ./spec/support/spec_helper.rb:20:in `block (2 levels) in <top (required)>'\n # /Users/bob/.bundles/ruby/2.7.0/gems/webmock-3.19.1/lib/webmock/rspec.rb:39:in `block (2 levels) in <top (required)>'\n\n 6) Dalmatian::RdsTest#call runs Terraform fmt with check and diff options\n Failure/Error: \"rds\" => rds.to_params\n #<InstanceDouble(Dalmatian::Rds) (anonymous)> received unexpected message :to_params with (no args)\n # ./lib/dalmatian/rds_test.rb:29:in `env_config'\n # ./lib/dalmatian/testable.rb:25:in `terraform_validate'\n # ./lib/dalmatian/testable.rb:9:in `call'\n # ./spec/unit/rds_test_spec.rb:89:in `block (3 levels) in <module:Dalmatian>'\n # ./spec/support/spec_helper.rb:24:in `block (3 levels) in <top (required)>'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:24:in `block in modify'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:15:in `synchronize'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:15:in `modify'\n # ./spec/support/spec_helper.rb:20:in `block (2 levels) in <top (required)>'\n # /Users/bob/.bundles/ruby/2.7.0/gems/webmock-3.19.1/lib/webmock/rspec.rb:39:in `block (2 levels) in <top (required)>'\n\n 7) Dalmatian::RdsTest#call logs our intention to run Terraform validate\n Failure/Error: \"rds\" => rds.to_params\n #<InstanceDouble(Dalmatian::Rds) (anonymous)> received unexpected message :to_params with (no args)\n # ./lib/dalmatian/rds_test.rb:29:in `env_config'\n # ./lib/dalmatian/testable.rb:25:in `terraform_validate'\n # ./lib/dalmatian/testable.rb:9:in `call'\n # ./spec/unit/rds_test_spec.rb:89:in `block (3 levels) in <module:Dalmatian>'\n # ./spec/support/spec_helper.rb:24:in `block (3 levels) in <top (required)>'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:24:in `block in modify'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:15:in `synchronize'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:15:in `modify'\n # ./spec/support/spec_helper.rb:20:in `block (2 levels) in <top (required)>'\n # /Users/bob/.bundles/ruby/2.7.0/gems/webmock-3.19.1/lib/webmock/rspec.rb:39:in `block (2 levels) in <top (required)>'\n\n 8) Dalmatian::RdsTest#call runs Terraform validate, with upgrade option\n Failure/Error: \"rds\" => rds.to_params\n #<InstanceDouble(Dalmatian::Rds) (anonymous)> received unexpected message :to_params with (no args)\n # ./lib/dalmatian/rds_test.rb:29:in `env_config'\n # ./lib/dalmatian/testable.rb:25:in `terraform_validate'\n # ./lib/dalmatian/testable.rb:9:in `call'\n # ./spec/unit/rds_test_spec.rb:89:in `block (3 levels) in <module:Dalmatian>'\n # ./spec/support/spec_helper.rb:24:in `block (3 levels) in <top (required)>'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:24:in `block in modify'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:15:in `synchronize'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:15:in `modify'\n # ./spec/support/spec_helper.rb:20:in `block (2 levels) in <top (required)>'\n # /Users/bob/.bundles/ruby/2.7.0/gems/webmock-3.19.1/lib/webmock/rspec.rb:39:in `block (2 levels) in <top (required)>'\n\n 9) Dalmatian::RdsTest#call changes back to the app root directory\n Failure/Error: \"rds\" => rds.to_params\n #<InstanceDouble(Dalmatian::Rds) (anonymous)> received unexpected message :to_params with (no args)\n # ./lib/dalmatian/rds_test.rb:29:in `env_config'\n # ./lib/dalmatian/testable.rb:25:in `terraform_validate'\n # ./lib/dalmatian/testable.rb:9:in `call'\n # ./spec/unit/rds_test_spec.rb:89:in `block (3 levels) in <module:Dalmatian>'\n # ./spec/support/spec_helper.rb:24:in `block (3 levels) in <top (required)>'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:24:in `block in modify'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:15:in `synchronize'\n # /Users/bob/.bundles/ruby/2.7.0/gems/climate_control-1.2.0/lib/climate_control.rb:15:in `modify'\n # ./spec/support/spec_helper.rb:20:in `block (2 levels) in <top (required)>'\n # /Users/bob/.bundles/ruby/2.7.0/gems/webmock-3.19.1/lib/webmock/rspec.rb:39:in `block (2 levels) in <top (required)>'\n\nFinished in 3.24 seconds (files took 0.75528 seconds to load)\n478 examples, 9 failures\n\nFailed examples:\n\nrspec ./spec/unit/rds_test_spec.rb:91 # Dalmatian::RdsTest#call changes to the ecs-services directory\nrspec ./spec/unit/rds_test_spec.rb:101 # Dalmatian::RdsTest#call logs our intention to run Terraform init\nrspec ./spec/unit/rds_test_spec.rb:107 # Dalmatian::RdsTest#call runs Terraform init, with upgrade option\nrspec ./spec/unit/rds_test_spec.rb:111 # Dalmatian::RdsTest#call ensures presence of workspace\nrspec ./spec/unit/rds_test_spec.rb:116 # Dalmatian::RdsTest#call logs our intention to run Terraform fmt\nrspec ./spec/unit/rds_test_spec.rb:122 # Dalmatian::RdsTest#call runs Terraform fmt with check and diff options\nrspec ./spec/unit/rds_test_spec.rb:126 # Dalmatian::RdsTest#call logs our intention to run Terraform validate\nrspec ./spec/unit/rds_test_spec.rb:132 # Dalmatian::RdsTest#call runs Terraform validate, with upgrade option\nrspec ./spec/unit/rds_test_spec.rb:190 # Dalmatian::RdsTest#call changes back to the app root directory\n\nCoverage report generated for RSpec to /Users/bob/git/dxw/dalmatian/coverage. 4299 / 4389 LOC (97.95%) covered.\nStopped processing SimpleCov as a previous error not related to SimpleCov has been detected\n/Users/bob/.rbenv/versions/2.7.1/bin/ruby -I/Users/bob/.bundles/ruby/2.7.0/gems/rspec-core-3.12.2/lib:/Users/bob/.bundles/ruby/2.7.0/gems/rspec-support-3.12.1/lib /Users/bob/.bundles/ruby/2.7.0/gems/rspec-core-3.12.2/exe/rspec --pattern spec/\\*\\*\\{,/\\*/\\*\\*\\}/\\*_spec.rb failed",
|
|
"displayName": "Shell",
|
|
"description": "This tool executes a given shell command as `bash -c <command>`. To run a command in the background, set the `is_background` parameter to true. Do NOT use `&` to background commands. Command is executed as a subprocess that leads its own process group. Command process group can be terminated as `kill -- -PGID` or signaled as `kill -s SIGNAL -- -PGID`.\n\n Efficiency Guidelines:\n - Quiet Flags: Always prefer silent or quiet flags (e.g., `npm install --silent`, `git --no-pager`) to reduce output volume while still capturing necessary information.\n - Pagination: Always disable terminal pagination to ensure commands terminate (e.g., use `git --no-pager`, `systemctl --no-pager`, or set `PAGER=cat`).\n\n The following information is returned:\n\n Output: Combined stdout/stderr. Can be `(empty)` or partial on error and for any unwaited background processes.\n Exit Code: Only included if non-zero (command failed).\n Error: Only included if a process-level error occurred (e.g., spawn failure).\n Signal: Only included if process was terminated by a signal.\n Background PIDs: Only included if background processes were started.\n Process Group PGID: Only included if available.",
|
|
"renderOutputAsMarkdown": false
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"id": "116ab4a8-4008-44c2-89b0-34704e996248",
|
|
"timestamp": "2026-02-20T17:16:21.865Z",
|
|
"type": "gemini",
|
|
"content": "Nine failures remain in `spec/unit/rds_test_spec.rb` because `RdsTest` now calls `to_params` on an unstubbed `instance_double`. I'll fix `spec/unit/rds_test_spec.rb` by stubbing `to_params`.",
|
|
"thoughts": [
|
|
{
|
|
"subject": "Troubleshooting RDS Tests",
|
|
"description": "I've identified the root cause of the remaining failures: the `RdsTest` unit tests. The tests are failing because they're not stubbing the `to_params` method on the `rds` object, which is now being called.",
|
|
"timestamp": "2026-02-20T17:16:21.560Z"
|
|
},
|
|
{
|
|
"subject": "Pinpointing Test Failures",
|
|
"description": "I'm now zeroing in on the `rds_test_spec.rb` file. The issue stems from the `RdsTest`'s recent call to `to_params` on the `rds` object. This call, however, isn't being stubbed out in the unit tests, causing the failures. My next step will be addressing this directly within that specific test file.",
|
|
"timestamp": "2026-02-20T17:16:21.597Z"
|
|
}
|
|
],
|
|
"tokens": {
|
|
"input": 87938,
|
|
"output": 88,
|
|
"cached": 73159,
|
|
"thoughts": 92,
|
|
"tool": 0,
|
|
"total": 88118
|
|
},
|
|
"model": "gemini-3-flash-preview",
|
|
"toolCalls": [
|
|
{
|
|
"id": "read_file_1771607781858_0",
|
|
"name": "read_file",
|
|
"args": {
|
|
"file_path": "spec/unit/rds_test_spec.rb"
|
|
},
|
|
"result": [
|
|
{
|
|
"functionResponse": {
|
|
"id": "read_file_1771607781858_0",
|
|
"name": "read_file",
|
|
"response": {
|
|
"output": "require_relative \"../support/spec_helper\"\n\nmodule Dalmatian\n RSpec.describe RdsTest do\n let(:helper) { class_double(Helper, change_to: true, run!: true, git_checkout: true) }\n let(:logger) { class_double(Logger, info: true) }\n\n let(:terraform) do\n class_double(\n Terraform,\n fmt: true,\n init: true,\n validate: true,\n ensure_presence_of_workspace: true\n )\n end\n\n let(:rds) do\n instance_double(\n Rds,\n identifier: \"testservice\",\n in_use_by: [\n \"test-service\"\n ],\n clusters_in_use: {\n \"production\" => [\n \"test\"\n ],\n \"staging\" => [\n \"test\"\n ]\n },\n instance_class: {\n \"production\" => \"db.t2.small\",\n \"staging\" => \"db.t2.micro\"\n },\n engine: \"postgres\",\n engine_version: \"11.4\",\n allocated_storage: 20,\n storage_encrypted: true,\n storage_type: \"gp3\",\n db_name: \"testapp\",\n port: 5432,\n maintenance_window: \"mon:19:00-mon:19:30\",\n backup_window: \"09:00-10:00\",\n backup_retention_period: 31,\n force_ssl: true,\n cluster_id: \"new-dedicated-cluster-id\",\n account_id: 123456789012,\n parameter_store_path_db_url_name: \"DATABASE_URL\",\n sql_backup_scheduled_task_environment_variables: [\n {\n \"name\" => \"foo\",\n \"value\" => \"bar\"\n }\n ],\n check_sql_backup_scheduled_task_environment_variables: [\n {\n \"name\" => \"foo\",\n \"value\" => \"bar\"\n }\n ],\n sync_sql_backup_to_azure: false,\n codebuild_access: [\n \"service-name\"\n ]\n )\n end\n\n let!(:rds_test) do\n RdsTest.new(\n rds: rds,\n env: {name: \"staging\", details: {\"min_servers\" => 2, \"max_servers\" => 4}},\n helper: helper,\n logger: logger,\n terraform: terraform\n )\n end\n\n describe \"#call\" do\n before do\n allow(Terraform).to receive(:init)\n allow(Terraform).to receive(:ensure_presence_of_workspace)\n allow(logger).to receive(:info)\n end\n\n let(:workspace_name) { \"new-dedicated-cluster-id-testservice-rds-staging\" }\n\n before { rds_test.call }\n\n it \"changes to the ecs-services directory\" do\n directory = File.join(\n Infrastructure::APP_ROOT,\n Infrastructure::PATH,\n \"rds\"\n )\n\n expect(helper).to have_received(:change_to).with(directory)\n end\n\n it \"logs our intention to run Terraform init\" do\n expect(logger).to have_received(:info).with(\n \"Running terraform init for #{workspace_name}\"\n )\n end\n\n it \"runs Terraform init, with upgrade option\" do\n expect(terraform).to have_received(:init).with(upgrade: true)\n end\n\n it \"ensures presence of workspace\" do\n expect(terraform).to have_received(:ensure_presence_of_workspace)\n .with(workspace_name)\n end\n\n it \"logs our intention to run Terraform fmt\" do\n expect(logger).to have_received(:info).with(\n \"Running terraform fmt for #{workspace_name}\"\n )\n end\n\n it \"runs Terraform fmt with check and diff options\" do\n expect(terraform).to have_received(:fmt).with(\"-check -diff\")\n end\n\n it \"logs our intention to run Terraform validate\" do\n expect(logger).to have_received(:info).with(\n \"Running terraform validate for #{workspace_name}\"\n )\n end\n\n it \"runs Terraform validate, with upgrade option\" do\n env_config = {\"min_servers\" => 2,\n \"max_servers\" => 4,\n \"rds\" => {\n \"identifier\" => \"testservice\",\n \"in_use_by\" => [\n \"test-service\"\n ],\n \"clusters_in_use\" => {\n \"production\" => [\n \"test\"\n ],\n \"staging\" => [\n \"test\"\n ]\n },\n \"instance_class\" => {\n \"production\" => \"db.t2.small\",\n \"staging\" => \"db.t2.micro\"\n },\n \"engine\" => \"postgres\",\n \"engine_version\" => \"11.4\",\n \"allocated_storage\" => 20,\n \"storage_encrypted\" => true,\n \"storage_type\" => \"gp3\",\n \"db_name\" => \"testapp\",\n \"port\" => 5432,\n \"maintenance_window\" => \"mon:19:00-mon:19:30\",\n \"backup_window\" => \"09:00-10:00\",\n \"backup_retention_period\" => 31,\n \"force_ssl\" => true,\n \"parameter_store_path_db_url_name\" => \"DATABASE_URL\",\n \"sql_backup_scheduled_task_environment_variables\" => [\n {\n \"name\" => \"foo\",\n \"value\" => \"bar\"\n }\n ],\n \"check_sql_backup_scheduled_task_environment_variables\" => [\n {\n \"name\" => \"foo\",\n \"value\" => \"bar\"\n }\n ],\n \"codebuild_access\" => [\n \"service-name\"\n ],\n \"sync_sql_backup_to_azure\" => false\n },\n \"account_id\" => 123456789012,\n \"infrastructure_name\" => \"new-dedicated-cluster-id\",\n \"environment\" => \"staging\",\n \"dalmatian_role\" => \"dalmatian-read\"}\n expect(terraform).to have_received(:validate).with(\n tfvars: env_config\n )\n end\n\n it \"changes back to the app root directory\" do\n expect(helper).to have_received(:change_to).with(Infrastructure::APP_ROOT)\n end\n end\n end\nend\n"
|
|
}
|
|
}
|
|
}
|
|
],
|
|
"status": "success",
|
|
"timestamp": "2026-02-20T17:16:21.898Z",
|
|
"resultDisplay": "",
|
|
"displayName": "ReadFile",
|
|
"description": "Reads and returns the content of a specified file. If the file is large, the content will be truncated. The tool's response will clearly indicate if truncation has occurred and will provide details on how to read more of the file using the 'offset' and 'limit' parameters. Handles text, images (PNG, JPG, GIF, WEBP, SVG, BMP), audio files (MP3, WAV, AIFF, AAC, OGG, FLAC), and PDF files. For text files, it can read specific line ranges.",
|
|
"renderOutputAsMarkdown": true
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"id": "d8f5102e-9868-40e8-a8bc-2cc36a4e2010",
|
|
"timestamp": "2026-02-20T17:16:28.700Z",
|
|
"type": "gemini",
|
|
"content": "I'll update `spec/unit/rds_test_spec.rb` by stubbing `to_params` on the `rds` mock and ensuring the `env_config` expectation matches its return value. I'll modify the `rds` mock to respond to `to_params` with a specific hash.",
|
|
"thoughts": [
|
|
{
|
|
"subject": "Revising Test Implementation",
|
|
"description": "I'm focused on refining the test spec, specifically `spec/unit/rds_test_spec.rb`. My current aim is to stub `to_params` on the `rds` mock. I also plan to update the `env_config` within the test expectations to align with the data generated by `to_params`. I believe this will provide better accuracy.",
|
|
"timestamp": "2026-02-20T17:16:24.287Z"
|
|
},
|
|
{
|
|
"subject": "Modifying Mock Behavior",
|
|
"description": "I'm now zeroing in on the mock behavior within `spec/unit/rds_test_spec.rb`. It's clear I need to ensure the `instance_double(Rds, ...)` responds to `to_params`. I will refactor the mock to have `to_params` return a specific hash. This approach allows me to control the test environment more precisely.",
|
|
"timestamp": "2026-02-20T17:16:25.129Z"
|
|
}
|
|
],
|
|
"tokens": {
|
|
"input": 89678,
|
|
"output": 754,
|
|
"cached": 76776,
|
|
"thoughts": 151,
|
|
"tool": 0,
|
|
"total": 90583
|
|
},
|
|
"model": "gemini-3-flash-preview",
|
|
"toolCalls": [
|
|
{
|
|
"id": "replace_1771607788693_0",
|
|
"name": "replace",
|
|
"args": {
|
|
"old_string": " sync_sql_backup_to_azure: false,\n codebuild_access: [\n \"service-name\"\n ]\n )\n end",
|
|
"file_path": "/Users/bob/git/dxw/dalmatian/spec/unit/rds_test_spec.rb",
|
|
"new_string": " sync_sql_backup_to_azure: false,\n replication_bucket_destination_arn: \"arn:aws:s3:::dest-bucket\",\n replication_kms_key_id: \"key-id\",\n codebuild_access: [\n \"service-name\"\n ],\n to_params: {\n \"identifier\" => \"testservice\",\n \"in_use_by\" => [\n \"test-service\"\n ],\n \"clusters_in_use\" => {\n \"production\" => [\n \"test\"\n ],\n \"staging\" => [\n \"test\"\n ]\n },\n \"instance_class\" => {\n \"production\" => \"db.t2.small\",\n \"staging\" => \"db.t2.micro\"\n },\n \"engine\" => \"postgres\",\n \"engine_version\" => \"11.4\",\n \"allocated_storage\" => 20,\n \"storage_encrypted\" => true,\n \"storage_type\" => \"gp3\",\n \"db_name\" => \"testapp\",\n \"port\" => 5432,\n \"maintenance_window\" => \"mon:19:00-mon:19:30\",\n \"backup_window\" => \"09:00-10:00\",\n \"backup_retention_period\" => 31,\n \"force_ssl\" => true,\n \"parameter_store_path_db_url_name\" => \"DATABASE_URL\",\n \"sql_backup_scheduled_task_environment_variables\" => [\n {\n \"name\" => \"foo\",\n \"value\" => \"bar\"\n }\n ],\n \"check_sql_backup_scheduled_task_environment_variables\" => [\n {\n \"name\" => \"foo\",\n \"value\" => \"bar\"\n }\n ],\n \"sync_sql_backup_to_azure\" => false,\n \"replication_bucket_destination_arn\" => \"arn:aws:s3:::dest-bucket\",\n \"replication_kms_key_id\" => \"key-id\",\n \"codebuild_access\" => [\n \"service-name\"\n ]\n }\n )\n end",
|
|
"instruction": "Update the rds mock and the test expectation in rds_test_spec.rb to account for RdsTest now using rds.to_params. This involves adding to_params to the rds mock and updating the expected rds configuration hash in the 'runs Terraform validate, with upgrade option' test to include the new fields."
|
|
},
|
|
"result": [
|
|
{
|
|
"functionResponse": {
|
|
"id": "replace_1771607788693_0",
|
|
"name": "replace",
|
|
"response": {
|
|
"output": "Successfully modified file: /Users/bob/git/dxw/dalmatian/spec/unit/rds_test_spec.rb (1 replacements)."
|
|
}
|
|
}
|
|
}
|
|
],
|
|
"status": "success",
|
|
"timestamp": "2026-02-20T17:16:28.729Z",
|
|
"resultDisplay": {
|
|
"fileDiff": "Index: rds_test_spec.rb\n===================================================================\n--- rds_test_spec.rb\tCurrent\n+++ rds_test_spec.rb\tProposed\n@@ -61,9 +61,59 @@\n }\n ],\n sync_sql_backup_to_azure: false,\n+ replication_bucket_destination_arn: \"arn:aws:s3:::dest-bucket\",\n+ replication_kms_key_id: \"key-id\",\n codebuild_access: [\n \"service-name\"\n- ]\n+ ],\n+ to_params: {\n+ \"identifier\" => \"testservice\",\n+ \"in_use_by\" => [\n+ \"test-service\"\n+ ],\n+ \"clusters_in_use\" => {\n+ \"production\" => [\n+ \"test\"\n+ ],\n+ \"staging\" => [\n+ \"test\"\n+ ]\n+ },\n+ \"instance_class\" => {\n+ \"production\" => \"db.t2.small\",\n+ \"staging\" => \"db.t2.micro\"\n+ },\n+ \"engine\" => \"postgres\",\n+ \"engine_version\" => \"11.4\",\n+ \"allocated_storage\" => 20,\n+ \"storage_encrypted\" => true,\n+ \"storage_type\" => \"gp3\",\n+ \"db_name\" => \"testapp\",\n+ \"port\" => 5432,\n+ \"maintenance_window\" => \"mon:19:00-mon:19:30\",\n+ \"backup_window\" => \"09:00-10:00\",\n+ \"backup_retention_period\" => 31,\n+ \"force_ssl\" => true,\n+ \"parameter_store_path_db_url_name\" => \"DATABASE_URL\",\n+ \"sql_backup_scheduled_task_environment_variables\" => [\n+ {\n+ \"name\" => \"foo\",\n+ \"value\" => \"bar\"\n+ }\n+ ],\n+ \"check_sql_backup_scheduled_task_environment_variables\" => [\n+ {\n+ \"name\" => \"foo\",\n+ \"value\" => \"bar\"\n+ }\n+ ],\n+ \"sync_sql_backup_to_azure\" => false,\n+ \"replication_bucket_destination_arn\" => \"arn:aws:s3:::dest-bucket\",\n+ \"replication_kms_key_id\" => \"key-id\",\n+ \"codebuild_access\" => [\n+ \"service-name\"\n+ ]\n+ }\n )\n end\n \n",
|
|
"fileName": "rds_test_spec.rb",
|
|
"filePath": "/Users/bob/git/dxw/dalmatian/spec/unit/rds_test_spec.rb",
|
|
"originalContent": "require_relative \"../support/spec_helper\"\n\nmodule Dalmatian\n RSpec.describe RdsTest do\n let(:helper) { class_double(Helper, change_to: true, run!: true, git_checkout: true) }\n let(:logger) { class_double(Logger, info: true) }\n\n let(:terraform) do\n class_double(\n Terraform,\n fmt: true,\n init: true,\n validate: true,\n ensure_presence_of_workspace: true\n )\n end\n\n let(:rds) do\n instance_double(\n Rds,\n identifier: \"testservice\",\n in_use_by: [\n \"test-service\"\n ],\n clusters_in_use: {\n \"production\" => [\n \"test\"\n ],\n \"staging\" => [\n \"test\"\n ]\n },\n instance_class: {\n \"production\" => \"db.t2.small\",\n \"staging\" => \"db.t2.micro\"\n },\n engine: \"postgres\",\n engine_version: \"11.4\",\n allocated_storage: 20,\n storage_encrypted: true,\n storage_type: \"gp3\",\n db_name: \"testapp\",\n port: 5432,\n maintenance_window: \"mon:19:00-mon:19:30\",\n backup_window: \"09:00-10:00\",\n backup_retention_period: 31,\n force_ssl: true,\n cluster_id: \"new-dedicated-cluster-id\",\n account_id: 123456789012,\n parameter_store_path_db_url_name: \"DATABASE_URL\",\n sql_backup_scheduled_task_environment_variables: [\n {\n \"name\" => \"foo\",\n \"value\" => \"bar\"\n }\n ],\n check_sql_backup_scheduled_task_environment_variables: [\n {\n \"name\" => \"foo\",\n \"value\" => \"bar\"\n }\n ],\n sync_sql_backup_to_azure: false,\n codebuild_access: [\n \"service-name\"\n ]\n )\n end\n\n let!(:rds_test) do\n RdsTest.new(\n rds: rds,\n env: {name: \"staging\", details: {\"min_servers\" => 2, \"max_servers\" => 4}},\n helper: helper,\n logger: logger,\n terraform: terraform\n )\n end\n\n describe \"#call\" do\n before do\n allow(Terraform).to receive(:init)\n allow(Terraform).to receive(:ensure_presence_of_workspace)\n allow(logger).to receive(:info)\n end\n\n let(:workspace_name) { \"new-dedicated-cluster-id-testservice-rds-staging\" }\n\n before { rds_test.call }\n\n it \"changes to the ecs-services directory\" do\n directory = File.join(\n Infrastructure::APP_ROOT,\n Infrastructure::PATH,\n \"rds\"\n )\n\n expect(helper).to have_received(:change_to).with(directory)\n end\n\n it \"logs our intention to run Terraform init\" do\n expect(logger).to have_received(:info).with(\n \"Running terraform init for #{workspace_name}\"\n )\n end\n\n it \"runs Terraform init, with upgrade option\" do\n expect(terraform).to have_received(:init).with(upgrade: true)\n end\n\n it \"ensures presence of workspace\" do\n expect(terraform).to have_received(:ensure_presence_of_workspace)\n .with(workspace_name)\n end\n\n it \"logs our intention to run Terraform fmt\" do\n expect(logger).to have_received(:info).with(\n \"Running terraform fmt for #{workspace_name}\"\n )\n end\n\n it \"runs Terraform fmt with check and diff options\" do\n expect(terraform).to have_received(:fmt).with(\"-check -diff\")\n end\n\n it \"logs our intention to run Terraform validate\" do\n expect(logger).to have_received(:info).with(\n \"Running terraform validate for #{workspace_name}\"\n )\n end\n\n it \"runs Terraform validate, with upgrade option\" do\n env_config = {\"min_servers\" => 2,\n \"max_servers\" => 4,\n \"rds\" => {\n \"identifier\" => \"testservice\",\n \"in_use_by\" => [\n \"test-service\"\n ],\n \"clusters_in_use\" => {\n \"production\" => [\n \"test\"\n ],\n \"staging\" => [\n \"test\"\n ]\n },\n \"instance_class\" => {\n \"production\" => \"db.t2.small\",\n \"staging\" => \"db.t2.micro\"\n },\n \"engine\" => \"postgres\",\n \"engine_version\" => \"11.4\",\n \"allocated_storage\" => 20,\n \"storage_encrypted\" => true,\n \"storage_type\" => \"gp3\",\n \"db_name\" => \"testapp\",\n \"port\" => 5432,\n \"maintenance_window\" => \"mon:19:00-mon:19:30\",\n \"backup_window\" => \"09:00-10:00\",\n \"backup_retention_period\" => 31,\n \"force_ssl\" => true,\n \"parameter_store_path_db_url_name\" => \"DATABASE_URL\",\n \"sql_backup_scheduled_task_environment_variables\" => [\n {\n \"name\" => \"foo\",\n \"value\" => \"bar\"\n }\n ],\n \"check_sql_backup_scheduled_task_environment_variables\" => [\n {\n \"name\" => \"foo\",\n \"value\" => \"bar\"\n }\n ],\n \"codebuild_access\" => [\n \"service-name\"\n ],\n \"sync_sql_backup_to_azure\" => false\n },\n \"account_id\" => 123456789012,\n \"infrastructure_name\" => \"new-dedicated-cluster-id\",\n \"environment\" => \"staging\",\n \"dalmatian_role\" => \"dalmatian-read\"}\n expect(terraform).to have_received(:validate).with(\n tfvars: env_config\n )\n end\n\n it \"changes back to the app root directory\" do\n expect(helper).to have_received(:change_to).with(Infrastructure::APP_ROOT)\n end\n end\n end\nend\n",
|
|
"newContent": "require_relative \"../support/spec_helper\"\n\nmodule Dalmatian\n RSpec.describe RdsTest do\n let(:helper) { class_double(Helper, change_to: true, run!: true, git_checkout: true) }\n let(:logger) { class_double(Logger, info: true) }\n\n let(:terraform) do\n class_double(\n Terraform,\n fmt: true,\n init: true,\n validate: true,\n ensure_presence_of_workspace: true\n )\n end\n\n let(:rds) do\n instance_double(\n Rds,\n identifier: \"testservice\",\n in_use_by: [\n \"test-service\"\n ],\n clusters_in_use: {\n \"production\" => [\n \"test\"\n ],\n \"staging\" => [\n \"test\"\n ]\n },\n instance_class: {\n \"production\" => \"db.t2.small\",\n \"staging\" => \"db.t2.micro\"\n },\n engine: \"postgres\",\n engine_version: \"11.4\",\n allocated_storage: 20,\n storage_encrypted: true,\n storage_type: \"gp3\",\n db_name: \"testapp\",\n port: 5432,\n maintenance_window: \"mon:19:00-mon:19:30\",\n backup_window: \"09:00-10:00\",\n backup_retention_period: 31,\n force_ssl: true,\n cluster_id: \"new-dedicated-cluster-id\",\n account_id: 123456789012,\n parameter_store_path_db_url_name: \"DATABASE_URL\",\n sql_backup_scheduled_task_environment_variables: [\n {\n \"name\" => \"foo\",\n \"value\" => \"bar\"\n }\n ],\n check_sql_backup_scheduled_task_environment_variables: [\n {\n \"name\" => \"foo\",\n \"value\" => \"bar\"\n }\n ],\n sync_sql_backup_to_azure: false,\n replication_bucket_destination_arn: \"arn:aws:s3:::dest-bucket\",\n replication_kms_key_id: \"key-id\",\n codebuild_access: [\n \"service-name\"\n ],\n to_params: {\n \"identifier\" => \"testservice\",\n \"in_use_by\" => [\n \"test-service\"\n ],\n \"clusters_in_use\" => {\n \"production\" => [\n \"test\"\n ],\n \"staging\" => [\n \"test\"\n ]\n },\n \"instance_class\" => {\n \"production\" => \"db.t2.small\",\n \"staging\" => \"db.t2.micro\"\n },\n \"engine\" => \"postgres\",\n \"engine_version\" => \"11.4\",\n \"allocated_storage\" => 20,\n \"storage_encrypted\" => true,\n \"storage_type\" => \"gp3\",\n \"db_name\" => \"testapp\",\n \"port\" => 5432,\n \"maintenance_window\" => \"mon:19:00-mon:19:30\",\n \"backup_window\" => \"09:00-10:00\",\n \"backup_retention_period\" => 31,\n \"force_ssl\" => true,\n \"parameter_store_path_db_url_name\" => \"DATABASE_URL\",\n \"sql_backup_scheduled_task_environment_variables\" => [\n {\n \"name\" => \"foo\",\n \"value\" => \"bar\"\n }\n ],\n \"check_sql_backup_scheduled_task_environment_variables\" => [\n {\n \"name\" => \"foo\",\n \"value\" => \"bar\"\n }\n ],\n \"sync_sql_backup_to_azure\" => false,\n \"replication_bucket_destination_arn\" => \"arn:aws:s3:::dest-bucket\",\n \"replication_kms_key_id\" => \"key-id\",\n \"codebuild_access\" => [\n \"service-name\"\n ]\n }\n )\n end\n\n let!(:rds_test) do\n RdsTest.new(\n rds: rds,\n env: {name: \"staging\", details: {\"min_servers\" => 2, \"max_servers\" => 4}},\n helper: helper,\n logger: logger,\n terraform: terraform\n )\n end\n\n describe \"#call\" do\n before do\n allow(Terraform).to receive(:init)\n allow(Terraform).to receive(:ensure_presence_of_workspace)\n allow(logger).to receive(:info)\n end\n\n let(:workspace_name) { \"new-dedicated-cluster-id-testservice-rds-staging\" }\n\n before { rds_test.call }\n\n it \"changes to the ecs-services directory\" do\n directory = File.join(\n Infrastructure::APP_ROOT,\n Infrastructure::PATH,\n \"rds\"\n )\n\n expect(helper).to have_received(:change_to).with(directory)\n end\n\n it \"logs our intention to run Terraform init\" do\n expect(logger).to have_received(:info).with(\n \"Running terraform init for #{workspace_name}\"\n )\n end\n\n it \"runs Terraform init, with upgrade option\" do\n expect(terraform).to have_received(:init).with(upgrade: true)\n end\n\n it \"ensures presence of workspace\" do\n expect(terraform).to have_received(:ensure_presence_of_workspace)\n .with(workspace_name)\n end\n\n it \"logs our intention to run Terraform fmt\" do\n expect(logger).to have_received(:info).with(\n \"Running terraform fmt for #{workspace_name}\"\n )\n end\n\n it \"runs Terraform fmt with check and diff options\" do\n expect(terraform).to have_received(:fmt).with(\"-check -diff\")\n end\n\n it \"logs our intention to run Terraform validate\" do\n expect(logger).to have_received(:info).with(\n \"Running terraform validate for #{workspace_name}\"\n )\n end\n\n it \"runs Terraform validate, with upgrade option\" do\n env_config = {\"min_servers\" => 2,\n \"max_servers\" => 4,\n \"rds\" => {\n \"identifier\" => \"testservice\",\n \"in_use_by\" => [\n \"test-service\"\n ],\n \"clusters_in_use\" => {\n \"production\" => [\n \"test\"\n ],\n \"staging\" => [\n \"test\"\n ]\n },\n \"instance_class\" => {\n \"production\" => \"db.t2.small\",\n \"staging\" => \"db.t2.micro\"\n },\n \"engine\" => \"postgres\",\n \"engine_version\" => \"11.4\",\n \"allocated_storage\" => 20,\n \"storage_encrypted\" => true,\n \"storage_type\" => \"gp3\",\n \"db_name\" => \"testapp\",\n \"port\" => 5432,\n \"maintenance_window\" => \"mon:19:00-mon:19:30\",\n \"backup_window\" => \"09:00-10:00\",\n \"backup_retention_period\" => 31,\n \"force_ssl\" => true,\n \"parameter_store_path_db_url_name\" => \"DATABASE_URL\",\n \"sql_backup_scheduled_task_environment_variables\" => [\n {\n \"name\" => \"foo\",\n \"value\" => \"bar\"\n }\n ],\n \"check_sql_backup_scheduled_task_environment_variables\" => [\n {\n \"name\" => \"foo\",\n \"value\" => \"bar\"\n }\n ],\n \"codebuild_access\" => [\n \"service-name\"\n ],\n \"sync_sql_backup_to_azure\" => false\n },\n \"account_id\" => 123456789012,\n \"infrastructure_name\" => \"new-dedicated-cluster-id\",\n \"environment\" => \"staging\",\n \"dalmatian_role\" => \"dalmatian-read\"}\n expect(terraform).to have_received(:validate).with(\n tfvars: env_config\n )\n end\n\n it \"changes back to the app root directory\" do\n expect(helper).to have_received(:change_to).with(Infrastructure::APP_ROOT)\n end\n end\n end\nend\n",
|
|
"diffStat": {
|
|
"model_added_lines": 51,
|
|
"model_removed_lines": 1,
|
|
"model_added_chars": 1584,
|
|
"model_removed_chars": 9,
|
|
"user_added_lines": 1,
|
|
"user_removed_lines": 190,
|
|
"user_added_chars": 7,
|
|
"user_removed_chars": 5948
|
|
},
|
|
"isNewFile": false
|
|
},
|
|
"displayName": "Edit",
|
|
"description": "Replaces text within a file. By default, replaces a single occurrence, but can replace multiple occurrences when `expected_replacements` is specified. This tool requires providing significant context around the change to ensure precise targeting. Always use the read_file tool to examine the file's current content before attempting a text replacement.\n \n The user has the ability to modify the `new_string` content. If modified, this will be stated in the response.\n \n Expectation for required parameters:\n 1. `old_string` MUST be the exact literal text to replace (including all whitespace, indentation, newlines, and surrounding code etc.).\n 2. `new_string` MUST be the exact literal text to replace `old_string` with (also including all whitespace, indentation, newlines, and surrounding code etc.). Ensure the resulting code is correct and idiomatic and that `old_string` and `new_string` are different.\n 3. `instruction` is the detailed instruction of what needs to be changed. It is important to Make it specific and detailed so developers or large language models can understand what needs to be changed and perform the changes on their own if necessary. \n 4. NEVER escape `old_string` or `new_string`, that would break the exact literal text requirement.\n **Important:** If ANY of the above are not satisfied, the tool will fail. CRITICAL for `old_string`: Must uniquely identify the single instance to change. Include at least 3 lines of context BEFORE and AFTER the target text, matching whitespace and indentation precisely. If this string matches multiple locations, or does not match exactly, the tool will fail.\n 5. Prefer to break down complex and long changes into multiple smaller atomic calls to this tool. Always check the content of the file after changes or not finding a string to match.\n **Multiple replacements:** Set `expected_replacements` to the number of occurrences you want to replace. The tool will replace ALL occurrences that match `old_string` exactly. Ensure the number of replacements matches your expectation.",
|
|
"renderOutputAsMarkdown": true
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"id": "1c0d81fa-a159-4844-930f-f58f71f4dc65",
|
|
"timestamp": "2026-02-20T17:16:32.764Z",
|
|
"type": "gemini",
|
|
"content": "Update expectation.",
|
|
"thoughts": [
|
|
{
|
|
"subject": "Revising the Document",
|
|
"description": "I'm now focused on updating the expectations within the same file. It's a crucial step to ensure everything aligns perfectly. I need to make sure the expectations are clear and up-to-date.",
|
|
"timestamp": "2026-02-20T17:16:31.671Z"
|
|
}
|
|
],
|
|
"tokens": {
|
|
"input": 90463,
|
|
"output": 336,
|
|
"cached": 87199,
|
|
"thoughts": 12,
|
|
"tool": 0,
|
|
"total": 90811
|
|
},
|
|
"model": "gemini-3-flash-preview",
|
|
"toolCalls": [
|
|
{
|
|
"id": "replace_1771607792756_0",
|
|
"name": "replace",
|
|
"args": {
|
|
"file_path": "/Users/bob/git/dxw/dalmatian/spec/unit/rds_test_spec.rb",
|
|
"old_string": " \"check_sql_backup_scheduled_task_environment_variables\" => [\n {\n \"name\" => \"foo\",\n \"value\" => \"bar\"\n }\n ],\n \"codebuild_access\" => [\n \"service-name\"\n ],\n \"sync_sql_backup_to_azure\" => false\n },\n \"account_id\" => 123456789012,",
|
|
"new_string": " \"check_sql_backup_scheduled_task_environment_variables\" => [\n {\n \"name\" => \"foo\",\n \"value\" => \"bar\"\n }\n ],\n \"sync_sql_backup_to_azure\" => false,\n \"replication_bucket_destination_arn\" => \"arn:aws:s3:::dest-bucket\",\n \"replication_kms_key_id\" => \"key-id\",\n \"codebuild_access\" => [\n \"service-name\"\n ]\n },\n \"account_id\" => 123456789012,",
|
|
"instruction": "Update the expected RDS configuration hash in the 'runs Terraform validate, with upgrade option' test to include the new replication fields and use the same structure as the rds.to_params return value."
|
|
},
|
|
"result": [
|
|
{
|
|
"functionResponse": {
|
|
"id": "replace_1771607792756_0",
|
|
"name": "replace",
|
|
"response": {
|
|
"output": "Successfully modified file: /Users/bob/git/dxw/dalmatian/spec/unit/rds_test_spec.rb (1 replacements)."
|
|
}
|
|
}
|
|
}
|
|
],
|
|
"status": "success",
|
|
"timestamp": "2026-02-20T17:16:32.794Z",
|
|
"resultDisplay": {
|
|
"fileDiff": "Index: rds_test_spec.rb\n===================================================================\n--- rds_test_spec.rb\tCurrent\n+++ rds_test_spec.rb\tProposed\n@@ -223,10 +223,12 @@\n \"value\" => \"bar\"\n }\n ],\n+ \"sync_sql_backup_to_azure\" => false,\n+ \"replication_bucket_destination_arn\" => \"arn:aws:s3:::dest-bucket\",\n+ \"replication_kms_key_id\" => \"key-id\",\n \"codebuild_access\" => [\n \"service-name\"\n- ],\n- \"sync_sql_backup_to_azure\" => false\n+ ]\n },\n \"account_id\" => 123456789012,\n \"infrastructure_name\" => \"new-dedicated-cluster-id\",\n",
|
|
"fileName": "rds_test_spec.rb",
|
|
"filePath": "/Users/bob/git/dxw/dalmatian/spec/unit/rds_test_spec.rb",
|
|
"originalContent": "require_relative \"../support/spec_helper\"\n\nmodule Dalmatian\n RSpec.describe RdsTest do\n let(:helper) { class_double(Helper, change_to: true, run!: true, git_checkout: true) }\n let(:logger) { class_double(Logger, info: true) }\n\n let(:terraform) do\n class_double(\n Terraform,\n fmt: true,\n init: true,\n validate: true,\n ensure_presence_of_workspace: true\n )\n end\n\n let(:rds) do\n instance_double(\n Rds,\n identifier: \"testservice\",\n in_use_by: [\n \"test-service\"\n ],\n clusters_in_use: {\n \"production\" => [\n \"test\"\n ],\n \"staging\" => [\n \"test\"\n ]\n },\n instance_class: {\n \"production\" => \"db.t2.small\",\n \"staging\" => \"db.t2.micro\"\n },\n engine: \"postgres\",\n engine_version: \"11.4\",\n allocated_storage: 20,\n storage_encrypted: true,\n storage_type: \"gp3\",\n db_name: \"testapp\",\n port: 5432,\n maintenance_window: \"mon:19:00-mon:19:30\",\n backup_window: \"09:00-10:00\",\n backup_retention_period: 31,\n force_ssl: true,\n cluster_id: \"new-dedicated-cluster-id\",\n account_id: 123456789012,\n parameter_store_path_db_url_name: \"DATABASE_URL\",\n sql_backup_scheduled_task_environment_variables: [\n {\n \"name\" => \"foo\",\n \"value\" => \"bar\"\n }\n ],\n check_sql_backup_scheduled_task_environment_variables: [\n {\n \"name\" => \"foo\",\n \"value\" => \"bar\"\n }\n ],\n sync_sql_backup_to_azure: false,\n replication_bucket_destination_arn: \"arn:aws:s3:::dest-bucket\",\n replication_kms_key_id: \"key-id\",\n codebuild_access: [\n \"service-name\"\n ],\n to_params: {\n \"identifier\" => \"testservice\",\n \"in_use_by\" => [\n \"test-service\"\n ],\n \"clusters_in_use\" => {\n \"production\" => [\n \"test\"\n ],\n \"staging\" => [\n \"test\"\n ]\n },\n \"instance_class\" => {\n \"production\" => \"db.t2.small\",\n \"staging\" => \"db.t2.micro\"\n },\n \"engine\" => \"postgres\",\n \"engine_version\" => \"11.4\",\n \"allocated_storage\" => 20,\n \"storage_encrypted\" => true,\n \"storage_type\" => \"gp3\",\n \"db_name\" => \"testapp\",\n \"port\" => 5432,\n \"maintenance_window\" => \"mon:19:00-mon:19:30\",\n \"backup_window\" => \"09:00-10:00\",\n \"backup_retention_period\" => 31,\n \"force_ssl\" => true,\n \"parameter_store_path_db_url_name\" => \"DATABASE_URL\",\n \"sql_backup_scheduled_task_environment_variables\" => [\n {\n \"name\" => \"foo\",\n \"value\" => \"bar\"\n }\n ],\n \"check_sql_backup_scheduled_task_environment_variables\" => [\n {\n \"name\" => \"foo\",\n \"value\" => \"bar\"\n }\n ],\n \"sync_sql_backup_to_azure\" => false,\n \"replication_bucket_destination_arn\" => \"arn:aws:s3:::dest-bucket\",\n \"replication_kms_key_id\" => \"key-id\",\n \"codebuild_access\" => [\n \"service-name\"\n ]\n }\n )\n end\n\n let!(:rds_test) do\n RdsTest.new(\n rds: rds,\n env: {name: \"staging\", details: {\"min_servers\" => 2, \"max_servers\" => 4}},\n helper: helper,\n logger: logger,\n terraform: terraform\n )\n end\n\n describe \"#call\" do\n before do\n allow(Terraform).to receive(:init)\n allow(Terraform).to receive(:ensure_presence_of_workspace)\n allow(logger).to receive(:info)\n end\n\n let(:workspace_name) { \"new-dedicated-cluster-id-testservice-rds-staging\" }\n\n before { rds_test.call }\n\n it \"changes to the ecs-services directory\" do\n directory = File.join(\n Infrastructure::APP_ROOT,\n Infrastructure::PATH,\n \"rds\"\n )\n\n expect(helper).to have_received(:change_to).with(directory)\n end\n\n it \"logs our intention to run Terraform init\" do\n expect(logger).to have_received(:info).with(\n \"Running terraform init for #{workspace_name}\"\n )\n end\n\n it \"runs Terraform init, with upgrade option\" do\n expect(terraform).to have_received(:init).with(upgrade: true)\n end\n\n it \"ensures presence of workspace\" do\n expect(terraform).to have_received(:ensure_presence_of_workspace)\n .with(workspace_name)\n end\n\n it \"logs our intention to run Terraform fmt\" do\n expect(logger).to have_received(:info).with(\n \"Running terraform fmt for #{workspace_name}\"\n )\n end\n\n it \"runs Terraform fmt with check and diff options\" do\n expect(terraform).to have_received(:fmt).with(\"-check -diff\")\n end\n\n it \"logs our intention to run Terraform validate\" do\n expect(logger).to have_received(:info).with(\n \"Running terraform validate for #{workspace_name}\"\n )\n end\n\n it \"runs Terraform validate, with upgrade option\" do\n env_config = {\"min_servers\" => 2,\n \"max_servers\" => 4,\n \"rds\" => {\n \"identifier\" => \"testservice\",\n \"in_use_by\" => [\n \"test-service\"\n ],\n \"clusters_in_use\" => {\n \"production\" => [\n \"test\"\n ],\n \"staging\" => [\n \"test\"\n ]\n },\n \"instance_class\" => {\n \"production\" => \"db.t2.small\",\n \"staging\" => \"db.t2.micro\"\n },\n \"engine\" => \"postgres\",\n \"engine_version\" => \"11.4\",\n \"allocated_storage\" => 20,\n \"storage_encrypted\" => true,\n \"storage_type\" => \"gp3\",\n \"db_name\" => \"testapp\",\n \"port\" => 5432,\n \"maintenance_window\" => \"mon:19:00-mon:19:30\",\n \"backup_window\" => \"09:00-10:00\",\n \"backup_retention_period\" => 31,\n \"force_ssl\" => true,\n \"parameter_store_path_db_url_name\" => \"DATABASE_URL\",\n \"sql_backup_scheduled_task_environment_variables\" => [\n {\n \"name\" => \"foo\",\n \"value\" => \"bar\"\n }\n ],\n \"check_sql_backup_scheduled_task_environment_variables\" => [\n {\n \"name\" => \"foo\",\n \"value\" => \"bar\"\n }\n ],\n \"codebuild_access\" => [\n \"service-name\"\n ],\n \"sync_sql_backup_to_azure\" => false\n },\n \"account_id\" => 123456789012,\n \"infrastructure_name\" => \"new-dedicated-cluster-id\",\n \"environment\" => \"staging\",\n \"dalmatian_role\" => \"dalmatian-read\"}\n expect(terraform).to have_received(:validate).with(\n tfvars: env_config\n )\n end\n\n it \"changes back to the app root directory\" do\n expect(helper).to have_received(:change_to).with(Infrastructure::APP_ROOT)\n end\n end\n end\nend\n",
|
|
"newContent": "require_relative \"../support/spec_helper\"\n\nmodule Dalmatian\n RSpec.describe RdsTest do\n let(:helper) { class_double(Helper, change_to: true, run!: true, git_checkout: true) }\n let(:logger) { class_double(Logger, info: true) }\n\n let(:terraform) do\n class_double(\n Terraform,\n fmt: true,\n init: true,\n validate: true,\n ensure_presence_of_workspace: true\n )\n end\n\n let(:rds) do\n instance_double(\n Rds,\n identifier: \"testservice\",\n in_use_by: [\n \"test-service\"\n ],\n clusters_in_use: {\n \"production\" => [\n \"test\"\n ],\n \"staging\" => [\n \"test\"\n ]\n },\n instance_class: {\n \"production\" => \"db.t2.small\",\n \"staging\" => \"db.t2.micro\"\n },\n engine: \"postgres\",\n engine_version: \"11.4\",\n allocated_storage: 20,\n storage_encrypted: true,\n storage_type: \"gp3\",\n db_name: \"testapp\",\n port: 5432,\n maintenance_window: \"mon:19:00-mon:19:30\",\n backup_window: \"09:00-10:00\",\n backup_retention_period: 31,\n force_ssl: true,\n cluster_id: \"new-dedicated-cluster-id\",\n account_id: 123456789012,\n parameter_store_path_db_url_name: \"DATABASE_URL\",\n sql_backup_scheduled_task_environment_variables: [\n {\n \"name\" => \"foo\",\n \"value\" => \"bar\"\n }\n ],\n check_sql_backup_scheduled_task_environment_variables: [\n {\n \"name\" => \"foo\",\n \"value\" => \"bar\"\n }\n ],\n sync_sql_backup_to_azure: false,\n replication_bucket_destination_arn: \"arn:aws:s3:::dest-bucket\",\n replication_kms_key_id: \"key-id\",\n codebuild_access: [\n \"service-name\"\n ],\n to_params: {\n \"identifier\" => \"testservice\",\n \"in_use_by\" => [\n \"test-service\"\n ],\n \"clusters_in_use\" => {\n \"production\" => [\n \"test\"\n ],\n \"staging\" => [\n \"test\"\n ]\n },\n \"instance_class\" => {\n \"production\" => \"db.t2.small\",\n \"staging\" => \"db.t2.micro\"\n },\n \"engine\" => \"postgres\",\n \"engine_version\" => \"11.4\",\n \"allocated_storage\" => 20,\n \"storage_encrypted\" => true,\n \"storage_type\" => \"gp3\",\n \"db_name\" => \"testapp\",\n \"port\" => 5432,\n \"maintenance_window\" => \"mon:19:00-mon:19:30\",\n \"backup_window\" => \"09:00-10:00\",\n \"backup_retention_period\" => 31,\n \"force_ssl\" => true,\n \"parameter_store_path_db_url_name\" => \"DATABASE_URL\",\n \"sql_backup_scheduled_task_environment_variables\" => [\n {\n \"name\" => \"foo\",\n \"value\" => \"bar\"\n }\n ],\n \"check_sql_backup_scheduled_task_environment_variables\" => [\n {\n \"name\" => \"foo\",\n \"value\" => \"bar\"\n }\n ],\n \"sync_sql_backup_to_azure\" => false,\n \"replication_bucket_destination_arn\" => \"arn:aws:s3:::dest-bucket\",\n \"replication_kms_key_id\" => \"key-id\",\n \"codebuild_access\" => [\n \"service-name\"\n ]\n }\n )\n end\n\n let!(:rds_test) do\n RdsTest.new(\n rds: rds,\n env: {name: \"staging\", details: {\"min_servers\" => 2, \"max_servers\" => 4}},\n helper: helper,\n logger: logger,\n terraform: terraform\n )\n end\n\n describe \"#call\" do\n before do\n allow(Terraform).to receive(:init)\n allow(Terraform).to receive(:ensure_presence_of_workspace)\n allow(logger).to receive(:info)\n end\n\n let(:workspace_name) { \"new-dedicated-cluster-id-testservice-rds-staging\" }\n\n before { rds_test.call }\n\n it \"changes to the ecs-services directory\" do\n directory = File.join(\n Infrastructure::APP_ROOT,\n Infrastructure::PATH,\n \"rds\"\n )\n\n expect(helper).to have_received(:change_to).with(directory)\n end\n\n it \"logs our intention to run Terraform init\" do\n expect(logger).to have_received(:info).with(\n \"Running terraform init for #{workspace_name}\"\n )\n end\n\n it \"runs Terraform init, with upgrade option\" do\n expect(terraform).to have_received(:init).with(upgrade: true)\n end\n\n it \"ensures presence of workspace\" do\n expect(terraform).to have_received(:ensure_presence_of_workspace)\n .with(workspace_name)\n end\n\n it \"logs our intention to run Terraform fmt\" do\n expect(logger).to have_received(:info).with(\n \"Running terraform fmt for #{workspace_name}\"\n )\n end\n\n it \"runs Terraform fmt with check and diff options\" do\n expect(terraform).to have_received(:fmt).with(\"-check -diff\")\n end\n\n it \"logs our intention to run Terraform validate\" do\n expect(logger).to have_received(:info).with(\n \"Running terraform validate for #{workspace_name}\"\n )\n end\n\n it \"runs Terraform validate, with upgrade option\" do\n env_config = {\"min_servers\" => 2,\n \"max_servers\" => 4,\n \"rds\" => {\n \"identifier\" => \"testservice\",\n \"in_use_by\" => [\n \"test-service\"\n ],\n \"clusters_in_use\" => {\n \"production\" => [\n \"test\"\n ],\n \"staging\" => [\n \"test\"\n ]\n },\n \"instance_class\" => {\n \"production\" => \"db.t2.small\",\n \"staging\" => \"db.t2.micro\"\n },\n \"engine\" => \"postgres\",\n \"engine_version\" => \"11.4\",\n \"allocated_storage\" => 20,\n \"storage_encrypted\" => true,\n \"storage_type\" => \"gp3\",\n \"db_name\" => \"testapp\",\n \"port\" => 5432,\n \"maintenance_window\" => \"mon:19:00-mon:19:30\",\n \"backup_window\" => \"09:00-10:00\",\n \"backup_retention_period\" => 31,\n \"force_ssl\" => true,\n \"parameter_store_path_db_url_name\" => \"DATABASE_URL\",\n \"sql_backup_scheduled_task_environment_variables\" => [\n {\n \"name\" => \"foo\",\n \"value\" => \"bar\"\n }\n ],\n \"check_sql_backup_scheduled_task_environment_variables\" => [\n {\n \"name\" => \"foo\",\n \"value\" => \"bar\"\n }\n ],\n \"sync_sql_backup_to_azure\" => false,\n \"replication_bucket_destination_arn\" => \"arn:aws:s3:::dest-bucket\",\n \"replication_kms_key_id\" => \"key-id\",\n \"codebuild_access\" => [\n \"service-name\"\n ]\n },\n \"account_id\" => 123456789012,\n \"infrastructure_name\" => \"new-dedicated-cluster-id\",\n \"environment\" => \"staging\",\n \"dalmatian_role\" => \"dalmatian-read\"}\n expect(terraform).to have_received(:validate).with(\n tfvars: env_config\n )\n end\n\n it \"changes back to the app root directory\" do\n expect(helper).to have_received(:change_to).with(Infrastructure::APP_ROOT)\n end\n end\n end\nend\n",
|
|
"diffStat": {
|
|
"model_added_lines": 4,
|
|
"model_removed_lines": 2,
|
|
"model_added_chars": 237,
|
|
"model_removed_chars": 85,
|
|
"user_added_lines": 1,
|
|
"user_removed_lines": 234,
|
|
"user_added_chars": 51,
|
|
"user_removed_chars": 7182
|
|
},
|
|
"isNewFile": false
|
|
},
|
|
"displayName": "Edit",
|
|
"description": "Replaces text within a file. By default, replaces a single occurrence, but can replace multiple occurrences when `expected_replacements` is specified. This tool requires providing significant context around the change to ensure precise targeting. Always use the read_file tool to examine the file's current content before attempting a text replacement.\n \n The user has the ability to modify the `new_string` content. If modified, this will be stated in the response.\n \n Expectation for required parameters:\n 1. `old_string` MUST be the exact literal text to replace (including all whitespace, indentation, newlines, and surrounding code etc.).\n 2. `new_string` MUST be the exact literal text to replace `old_string` with (also including all whitespace, indentation, newlines, and surrounding code etc.). Ensure the resulting code is correct and idiomatic and that `old_string` and `new_string` are different.\n 3. `instruction` is the detailed instruction of what needs to be changed. It is important to Make it specific and detailed so developers or large language models can understand what needs to be changed and perform the changes on their own if necessary. \n 4. NEVER escape `old_string` or `new_string`, that would break the exact literal text requirement.\n **Important:** If ANY of the above are not satisfied, the tool will fail. CRITICAL for `old_string`: Must uniquely identify the single instance to change. Include at least 3 lines of context BEFORE and AFTER the target text, matching whitespace and indentation precisely. If this string matches multiple locations, or does not match exactly, the tool will fail.\n 5. Prefer to break down complex and long changes into multiple smaller atomic calls to this tool. Always check the content of the file after changes or not finding a string to match.\n **Multiple replacements:** Set `expected_replacements` to the number of occurrences you want to replace. The tool will replace ALL occurrences that match `old_string` exactly. Ensure the number of replacements matches your expectation.",
|
|
"renderOutputAsMarkdown": true
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"id": "6dee1b0c-f22f-42b9-a407-0ce3cb594617",
|
|
"timestamp": "2026-02-20T17:16:34.875Z",
|
|
"type": "gemini",
|
|
"content": "Tests again.",
|
|
"thoughts": [
|
|
{
|
|
"subject": "Running the Tests Again",
|
|
"description": "Okay, I've re-run all the tests, just to be sure. It feels like a solid foundation, ready for the next layer of investigation. Everything seems consistent, but I'm eager to delve into the more nuanced aspects now.",
|
|
"timestamp": "2026-02-20T17:16:34.800Z"
|
|
}
|
|
],
|
|
"tokens": {
|
|
"input": 90830,
|
|
"output": 22,
|
|
"cached": 87207,
|
|
"thoughts": 10,
|
|
"tool": 0,
|
|
"total": 90862
|
|
},
|
|
"model": "gemini-3-flash-preview",
|
|
"toolCalls": [
|
|
{
|
|
"id": "run_shell_command_1771607794873_0",
|
|
"name": "run_shell_command",
|
|
"args": {
|
|
"command": "./scripts/bin/test -l"
|
|
},
|
|
"result": [
|
|
{
|
|
"functionResponse": {
|
|
"id": "run_shell_command_1771607794873_0",
|
|
"name": "run_shell_command",
|
|
"response": {
|
|
"output": "Output: ==> Linting YAML...\n\n==> Linting shell scripts...\n\n==> Checking Terraform for JSON errors...\n- Checking ./terraform/policies/iam-read.json... Passed\n- Checking ./terraform/policies/s3-rw-with-versioning.json... Passed\n- Checking ./terraform/policies/codestar-connection-use.json... Passed\n- Checking ./terraform/policies/iam-create-access-key.json... Passed\n- Checking ./terraform/policies/codebuild.json... Passed\n- Checking ./terraform/policies/kms-encrypt-decrypt.json... Passed\n- Checking ./terraform/policies/iam-change-password.json... Passed\n- Checking ./terraform/policies/administrator-access.json... Passed\n- Checking ./terraform/policies/assume_roles/aws-backup.json... Passed\n- Checking ./terraform/policies/assume_roles/autoscaling.json... Passed\n- Checking ./terraform/policies/assume_roles/events.json... Passed\n- Checking ./terraform/policies/assume_roles/ecs.json... Passed\n- Checking ./terraform/policies/assume_roles/codepipeline.json... Passed\n- Checking ./terraform/policies/iam-mfa.json... Passed\n- Checking ./terraform/policies/route53-read.json... Passed\n- Checking ./terraform/policies/s3-full-access.json... Passed\n- Checking ./terraform/policies/parameter-store-read-decrypt.json... Passed\n- Checking ./terraform/policies/s3-read.json... Passed\n- Checking ./terraform/policies/parameter-store-RW-encrypt-decrypt.json... Passed\n- Checking ./terraform/policies/all-read-with-billing.json... Passed\n- Checking ./terraform/policies/codebuild-start-build.json... Passed\n- Checking ./terraform/policies/all-read.json... Passed\n\n==> Linting Terraform...\n\n==> Running Ruby tests...\n/Users/bob/.rbenv/versions/2.7.1/bin/ruby -I/Users/bob/.bundles/ruby/2.7.0/gems/rspec-core-3.12.2/lib:/Users/bob/.bundles/ruby/2.7.0/gems/rspec-support-3.12.1/lib /Users/bob/.bundles/ruby/2.7.0/gems/rspec-core-3.12.2/exe/rspec --pattern spec/\\*\\*\\{,/\\*/\\*\\*\\}/\\*_spec.rb\n\ntests local configuration\n use of \"terraform apply\"\n passes the hosted zone config to \"terraform apply\"\n passes the s3 config to \"terraform apply\"\n passes the vpn customer gateway config to \"terraform apply\"\n passes the base config to \"terraform apply\"\n passes the waf config to \"terraform apply\"\n passes the rds config to \"terraform apply\"\n passes the elasticache config to \"terraform apply\"\n passes the opensearch config to \"terraform apply\"\n passes the service config to \"terraform apply\"\n passes the loadbalancer config to \"terraform apply\"\n passes the cluster 2 config to \"terraform apply\"\n passes the cluster 3 config to \"terraform apply\"\n passes the cluster 4 config to \"terraform apply\"\n\ntests remote configuration\n retrieves the remotely held full configuration\n proceeds with deploying the infrastructure as per the cached full configuration\n\ntests local configuration\n invokes \"terraform validate\" with the expected cluster options\n invokes \"terraform validate\" with the expected source options\n use of \"terraform plan\"\n passes the hosted zone config to \"terraform plan\"\n passes the s3 config to \"terraform plan\"\n passes the vpn customer gateway config to \"terraform plan\"\n passes the base config to \"terraform plan\"\n passes the waf config to \"terraform plan\"\n passes the rds config to \"terraform plan\"\n passes the elasticache config to \"terraform plan\"\n passes the opensearch config to \"terraform plan\"\n passes the services config to \"terraform plan\"\n passes the loadbalancer config to \"terraform plan\"\n passes the cluster 2 config to \"terraform plan\"\n passes the cluster 3 config to \"terraform plan\"\n passes the cluster 4 config to \"terraform plan\"\n\nDalmatian::Account\n initialisation\n gathering user input\n asks the user for AWS credentials\n asks the user for the AWS account id to use\n asks the user for an account alias\n #call\n changes to the bootstrapping directory\n runs terraform init with upgrade option\n creates the new workspace using the given aws account id and alias\n runs terraform apply with the user-supplied vars\n\nDalmatian::CacheHandlerSelector\n ::new_for(remote_reference)\n when the remote reference is for a git repo\n asks for an instance of GitCacheHandler\n when the remote reference is for an S3 bucket\n asks for an instance of S3CacheHandler\n when the remote reference is for a URL\n asks for an instance of UrlCacheHandler\n when the type is unknown\n raises an error\n\nCacheHandler\n when a subclass class does not implement #cache_remote_configuration\n raises a helpful error\n\nDalmatian::CI\n CI::PATH\n is a constant\n #deploy\n changes to the ci directory\n runs terraform init with upgrade option\n creates the new workspace using the given aws account id and alias\n runs terraform apply with the user-supplied vars\n #test\n runs terraform plan with the user-supplied vars\n\nDalmatian::ClusterDeployment\n #call\n changes to the ecs directory\n asks Terraform to ensure that the workspace is in place\n when the environment includes a git reference as \"track_revision\"\n does NOT attempt to check out that commit\n when in _plan_ mode\n invokes Terraform.plan using the _dalmatian-read_ role\n when NOT in _plan_ mode\n invokes Terraform.apply using the _dalmatian-admin_\n when in _auto_approve_ mode\n asks Terraform to use auto_approve mode\n\nDalmatian::Cluster\n on initialisation\n makes Hosted zones, S3, Sources, Services, Loadbalancers, WAF and Rds\n #target_directory\n is a standard _ecs_ path\n #id\n is the primary key of the cluster definition is used\n #name\n when the cluster has an explicitly provided _name_ property\n that property is used\n when the cluster does not have an explicitly provided _name_ property\n the primary key of the cluster definition is used\n #account_id\n is the aws account key for deployment\n #sources\n represents any links to remote sources\n #environments\n represents the attributes of each environment's cluster section\n #fetch\n when the source is remotely held\n logs the plan to clone the source into the infrastructure pth\n deletes any existing source at the infrastructure location\n clones each source into the infrastructure location\n changes to the infrastructure directory for each source\n runs rake terrafile\n changes back to the APP_ROOT\n when the source is a local file path\n does not re-clone the source\n does not run terrafile\n when the specified local directory exists\n logs the fact that the local source is in place\n when the specificed local directory does not exist\n logs an error that the local source is missing\n #deploy\n deploys source infrastructure for each source and each service in each environment\n when a cluster should be created\n deploys cluster infrastructure for each environment\n when the _plan_ option IS invoked\n creates Cluster Deployments with plan settings\n when the _auto_approve_ option IS invoked\n creates Cluster Deployments with auto_approve settings\n handling of tests\n when the _test_ option is NOT invoked\n does not run cluster tests\n does not run cluster tests\n does not run cluster tests\n does not run source tests\n does not run waf tests\n does not run rds tests\n does not run service tests\n does not run service tests\n when the test option IS invoked\n runs tests\n when a cluster should NOT be created\n does not deploy cluster infrastructure\n when test option is invoked\n tests sources and services for each environment\n\nDalmatian::ClusterTest\n #call\n changes to the ecs directory\n logs our intention to run Terraform init\n runs Terraform init, with upgrade option\n ensures presence of workspace\n logs our intention to run Terraform fmt\n runs Terraform fmt with check and diff options\n logs our intention to run Terraform validate\n runs Terraform validate, with upgrade option\n changes back to the app root directory\n when the environment includes a git reference as \"track_revision\"\n does NOT attempt to check out that commit\n\nDalmatian::ConfigurationReader\n when a full configuration is provided in a local file\n #call\n has no need to use a cache handler\n returns the loaded configuration\n when a reference to a remote configuration is provided\n and the reference is provided in a local file\n uses the CacheHandlerSelector to provide the appropriate retrieval mechanism\n calls on the selected cache handler\n returns the configuration returned by the cache_handler\n and the reference is provided using environment variables\n passes the provided remote reference to the CacheHandlerSelector\n and references are provided in both environment variables and config file\n prefers the environment variable references over the config file\n and no references are provided\n raises an error\n and the remote reference is missing its _type_\n raises an error\n #ci\n when a parameter path prefix is given\n overwrites the ci:variables config with those retrieved from the param store\n leaves other ci:variables in place\n when a parameter path prefix is NOT given\n does NOT overwrite any ci:variables from the param store\n\nDalmatian::ElasticacheCluster\n #identifier\n uses elasticache identifier\n #in_use_by\n uses elasticache_cluster in_use_by list\n #node_type\n uses elasticache_cluster node_type\n #node_count\n uses elasticache_cluster node_count\n #engine\n uses elasticache_cluster engine\n #engine_version\n uses the elasticache_cluster engine_version\n #parameters\n uses the elasticache_cluster parameters list\n #port\n uses the elasticache_cluster port\n #maintenance_window\n uses the elasticache_cluster maintenance_window\n #snapshot_window\n uses the elasticache_cluster snapshot_window\n #parameter_store_path_elasticache_cluster_url_name\n uses the elasticache_cluster parameter_store_path_elasticache_cluster_url_name\n #to_params\n provides a hash of attributes for use in deployment\n\nDalmatian::ElasticacheClusterTest\n #call\n changes to the elasticache-cluster directory\n logs our intention to run Terraform init\n runs Terraform init, with upgrade option\n ensures presence of workspace\n logs our intention to run Terraform fmt\n runs Terraform fmt with check and diff options\n logs our intention to run Terraform validate\n runs Terraform validate, with upgrade option\n changes back to the app root directory\n\nDalmatian::GitCacheHandler\n #call\n deletes any old cache\n uses git clone to save the remote config to a local cache\n logs the cloning action\n logs the path to the cached configuration\n returns the cached full configuration to the caller (configuration reader)\n reads the cached full configuration from the disk in order to return to caller\n when no special cache path is given\n uses the default cache path of ./.dalmatian_cache/remote_config\n\nDalmatian::Helper\n ::git_clone(source, destination)\n when source and destination args are not provided\n raises an error with usage info\n when given source and destination args\n passes the request to the git CLI\n ::git_checkout(revision)\n checks out the given revision using run!\n ::get(source, destination)\n when source and destination args are not provided\n raises an error with usage info\n when given source and destination args\n opens the source url\n opens a new file at the destination\n writes the source resource into that file\n reads the information from the fetched resource\n ::run!\n passes given cmd to Kernel.system\n when the call to Kernel.system returns _false_\n raise a helpful error\n ::run_with_output!(cmd)\n passes given cmd to Open3.capture3\n when the system call returns a zero exit status\n returns the systems output to STDOUT\n when the system call returns a non-zero exit status\n also returns STDOUT ignoring the exit code and STDERR\n when the system call raises an ENOENT error\n catches this and raises a helpful Error\n ::change_to(path)\n passes the given path to Dir.chdir\n ::to_bool(str)\n when given nil\n returns false\n when given an empty string\n returns false\n when given lower case string _true_\n returns true\n when given mixed case string _True_\n returns true\n when given the object true\n returns true\n when given the object false\n returns false\n ::tflint\n runs the tflint cmd\n ::terrafile\n runs rake terrafile\n ::ask\n delegates to HighLine#ask\n ::ask_in_confidence\n delegates to HighLine#ask\n passes a block to mask the answer\n\nDalmatian::HostedZoneDeployment\n #call\n changes to hosted-zone infrastructure directory\n asks Terraform to ensure that the workspace is in place\n when in _plan_ mode\n invokes Terraform.plan with the _dalmatian-read_ role\n when NOT in _plan_ mode\n invokes Terraform.apply with the _dalmatian-admin_ role\n when in _auto_approve_ mode\n asks Terraform to use auto_approve mode\n\nDalmatian::HostedZone\n #domain\n uses hosted_zone domain\n #ns_records\n uses hosted_zone ns_records\n #a_records\n uses hosted_zone a_records\n #alias_records\n uses hosted_zone alias_records\n #cname_records\n uses hosted_zone cname_records\n #mx_records\n uses hosted_zone mx_records\n #txt_records\n uses hosted_zone txt_records\n #srv_records\n uses hosted_zone srv_records\n #to_params\n provides a hash of attributes for use in deployment\n\nDalmatian::HostedZoneTest\n #call\n changes to the hosted-zone directory\n logs our intention to run Terraform init\n runs Terraform init, with upgrade option\n ensures presence of workspace\n logs our intention to run Terraform fmt\n runs Terraform fmt with check and diff options\n logs our intention to run Terraform validate\n runs Terraform validate, with upgrade option\n changes back to the app root directory\n\nDalmatian::Infrastructure\n Infrastructure::PATH\n is a constant\n Infrastructure::APP_ROOT\n is a constant\n initialisation\n when configuration is not provided\n builds one using the defaults\n #clusters\n creates one cluster for each cluster description provided\n key operations on clusters\n #fetch\n asks all clusters to #fetch\n #test\n asks all clusters to #deploy with _plan_ and _test_ options\n #deploy\n when no parameters given\n asks all clusters to #deploy with _plan_, _test_ and _auto-approve_ disabled\n when parameters are given\n asks all clusters to #deploy with the given options\n when a particular infrastructure is named for deployment\n asks only the named cluster to #deploy with the given options\n\nDalmatian::Logger\n ::error(msg)\n raises an error with a red message\n ::info(msg)\n puts the given given message in white\n ::success(msg)\n puts the given given message in green\n ::warn(msg)\n puts the given given message in yellow\n\nDalmatian::OpensearchCluster\n #identifier\n uses opensearch identifier\n #in_use_by\n uses opensearch_cluster in_use_by list\n #version\n uses opensearch_cluster version\n #master_enabled\n uses opensearch_cluster master_enabled bool\n #master_count\n uses opensearch_cluster master_count\n #master_type\n uses opensearch_cluster master_type\n #instance_count\n uses opensearch_cluster instance_count\n #instance_type\n uses opensearch_cluster instance_type\n #warm_enabled\n uses opensearch_cluster warm_enabled bool\n #warm_count\n uses opensearch_cluster warm_count\n #warm_type\n uses opensearch_cluster warm_type\n #parameter_store_path_opensearch_cluster_url_name\n uses opensearch_cluster parameter_store_path_opensearch_cluster_url_name\n #volume_size\n uses opensearch_cluster volume_size\n #to_params\n provides a hash of attributes for use in deployment\n\nDalmatian::OpensearchClusterTest\n #call\n changes to the opensearch-cluster directory\n logs our intention to run Terraform init\n runs Terraform init, with upgrade option\n ensures presence of workspace\n logs our intention to run Terraform fmt\n runs Terraform fmt with check and diff options\n logs our intention to run Terraform validate\n runs Terraform validate, with upgrade option\n changes back to the app root directory\n\nDalmatian::ParameterStore\n ::get_parameter(name: \"\", with_decryption: true)\n when getting a single parameter from Parameter Store\n runs aws ssm get-parameter\n ::get_parameters_by_path(path: \"\", with_decryption: true)\n when getting parameters by path from Parameter Store\n runs aws ssm get-parameter\n\nDalmatian::RdsDeployment\n #call\n changes to rds infrastructure directory\n asks Terraform to ensure that the workspace is in place\n when in _plan_ mode\n invokes Terraform.plan with the _dalmatian-read_ role\n when NOT in _plan_ mode\n invokes Terraform.apply with the _dalmatian-admin_ role\n when in _auto_approve_ mode\n asks Terraform to use auto_approve mode\n\nDalmatian::Rds\n #identifier\n uses rds identifier\n #in_use_by\n uses rds in_use_by list\n #clusters_in_use\n uses rds clusters_in_use list\n #instance_class\n uses rds instance_class\n #engine\n uses rds engine\n #engine_version\n uses the rds engine_version\n #allocated_storage\n uses the rds allocated_storage\n #storage_encrypted\n uses the rds storage_encrypted bool\n #storage_type\n uses the rds storage_type gp3\n #db_name\n uses the rds db_name\n #port\n uses the rds port\n #maintenance_window\n uses the rds maintenance_window\n #backup_window\n uses the rds backup_window\n #backup_retention_period\n uses the rds backup_retention_period\n #force_ssl\n uses the rds force_ssl bool\n #parameter_store_path_db_url_name\n uses the rds parameter_store_path_db_url_name\n #sql_backup_scheduled_task_environment_variables\n uses the rds sql_backup_scheduled_task_environment_variables\n #check_sql_backup_scheduled_task_environment_variables\n uses the rds check_sql_backup_scheduled_task_environment_variables\n #sync_sql_backup_to_azure\n will have offsite backups disabled by default\n #replication_bucket_destination_arn\n uses the rds replication_bucket_destination_arn\n #replication_kms_key_id\n uses the rds replication_kms_key_id\n #codebuild_access\n uses the rds codebuild_access\n #to_params\n provides a hash of attributes for use in deployment\n\nDalmatian::RdsTest\n #call\n changes to the ecs-services directory\n logs our intention to run Terraform init\n runs Terraform init, with upgrade option\n ensures presence of workspace\n logs our intention to run Terraform fmt\n runs Terraform fmt with check and diff options\n logs our intention to run Terraform validate\n runs Terraform validate, with upgrade option\n changes back to the app root directory\n\nDalmatian::RemoteReferenceValues\n when the reference is for a git repo\n returns a git shaped configuration\n if _filename_ is not present\n supplies the default of _dalmatian.yml_\n when the reference is for an S3 bucket\n returns an S3 shaped configuration\n if _key_ is not present\n supplies the default of _dalmatian.yml_\n when the reference is for a URL\n returns a git shaped configuration\n\nDalmatian::S3CacheHandler\n #call\n deletes any old cache\n uses the AWS S3 cmd to save the remote config to a local cache\n logs the cloning action\n logs the path to the cached configuration\n returns the cached full configuration to the caller (configuration reader)\n reads the cached full configuration from the disk in order to return to caller\n\nDalmatian::S3Deployment\n #call\n changes to s3 infrastructure directory\n asks Terraform to ensure that the workspace is in place\n when in _plan_ mode\n invokes Terraform.plan with the _dalmatian-read_ role\n when NOT in _plan_ mode\n invokes Terraform.apply with the _dalmatian-admin_ role\n when in _auto_approve_ mode\n asks Terraform to use auto_approve mode\n\nDalmatian::S3\n #name\n uses s3 name\n #enable_s3_versioning\n uses enable_s3_versioning bool\n #encrypted\n uses s3 encrypted bool\n #acl\n uses s3 acl\n #policy\n uses s3 policy\n #service_cloudfront_read_access\n uses s3 service_cloudfront_read_access\n #cloudfront\n uses s3 cloudfront\n #to_params\n provides a hash of attributes for use in deployment\n\nDalmatian::S3Test\n #call\n changes to the s3 directory\n logs our intention to run Terraform init\n runs Terraform init, with upgrade option\n ensures presence of workspace\n logs our intention to run Terraform fmt\n runs Terraform fmt with check and diff options\n logs our intention to run Terraform validate\n runs Terraform validate, with upgrade option\n changes back to the app root directory\n\nDalmatian::ServiceDeployment\n #call\n changes to ecs-services infrastructure directory\n asks Terraform to ensure that the workspace is in place\n when in _plan_ mode\n invokes Terraform.plan with the _dalmatian-read_ role\n when NOT in _plan_ mode\n invokes Terraform.apply with the _dalmatian-admin_ role\n when in _auto_approve_ mode\n asks Terraform to use auto_approve mode\n\nDalmatian::Service\n #name\n uses service name\n #blue_green\n uses the service blue_green map\n #parameter_store_path\n uses service parameter_store_path\n #parameter_store_key\n uses service parameter_store_key\n #daemon\n uses the service daemon bool\n #monitoring\n uses the service monitoring hash\n #cloudfront\n recasts the service config in environment groups\n includes the appropriate \"custom_origins\" values in each environment\n Uses an AWS cloudfront managed cache policy\n Uses an AWS cloudfront managed origin policy\n Uses an AWS cloudfront managed response headers policy\n mirroring of elements into each environment group\n includes the \"create\" value\n includes the \"tls_protocol_version\" value\n includes the \"origin_keepalive_timeout\" value\n includes the \"origin_read_timeout\" value\n includes the \"basic_auth\" value\n includes the \"basic_auth_users_extra\" value\n includes the \"viewer_request_functions\" values\n includes the \"offline_page_http_status\" value\n bypass_protection\n uses the \"bypass_protection\" configuration\n custom_behaviors\n converts list of \"path_patterns\" to a single \"path_pattern\"\n #shared_loadbalancer_name\n returns shared loadbalancer name if the service is in use by a shared loadbalancer\n returns empty string if the service is not in use by a shared loadbalancer\n #s3_policy\n uses the service s3_policy map\n #lb_ip_whitelistt\n uses the service lb_ip_whitelist list\n #lb_idle_timeout\n uses the service lb_idle_timeout\n #global_accelerator\n uses service global_accelerator value\n #health_check_path\n uses the service health_check_path\n #health_check_grace_period\n uses the service health_check_grace_period\n #deregistration_delay\n uses the service deregistration_delay\n #serve_from_subdirectory\n uses the service serve_from_subdirectory\n #domain_names\n groups the domain names from the service domain_list into environments\n #proxy_configuration\n groups the proxy configurations from the service proxy_configuration list into environments\n #home_directory\n uses the service home_directory\n #lb_ssl_certificate\n groups the certificate arns from the service lb_ssl_certificate list into environments\n #lb_ssl_policy\n sets the default ssl policy for each environment\n #cloudfront_ssl_certificate\n groups the certificate arns from the service cloudfront_ssl_certificate list into environments\n #image_source\n uses the service image source\n #launch_on\n uses the service 'launch_on' specification\n #launch_on_cluster\n uses the service 'launch_on_cluster' string\n #cluster_min_servers\n uses the service 'cluster_min_servers' string\n #image_location\n uses the service image location\n #track_revision\n uses the service track_revision string\n #custom_codestar_connection_arn\n uses the service custom_codestar_connection_arn\n #codepipeline_use_github_v1\n uses the service codepipeline_use_github_v1\n #codepipeline_codebuild_run_in_vpc\n uses the service codepipeline_codebuild_run_in_vpc\n #codepipeline_codebuild_use_service_env\n uses the service codepipeline_codebuild_use_service_env\n #buildspec\n uses the service buildspec\n #container_port\n uses the service container port\n #container_command\n uses the service container command\n #container_volumes\n uses the service container volumes\n #container_extra_hosts\n uses the service container extra hosts\n #container_count\n uses the service container_count\n #enable_max_one_container_per_instance\n uses the service enable_max_one_container_per_instance\n #scheduled_tasks\n uses the service scheduled tasks\n #workers\n uses the service workers\n #cluster_name\n delegates to the cluster\n #cluster_id\n delegates to the cluster\n #account_id\n delegates to the cluster\n #to_params\n provides a hash of attributes for use in deployment\n\nDalmatian::ServiceTest\n #call\n changes to the ecs-services directory\n logs our intention to run Terraform init\n runs Terraform init, with upgrade option\n ensures presence of workspace\n logs our intention to run Terraform fmt\n runs Terraform fmt with check and diff options\n logs our intention to run Terraform validate\n runs Terraform validate, with upgrade option\n changes back to the app root directory\n\nDalmatian::SharedLoadbalancerDeployment\n #call\n changes to shared-loadbalancer infrastructure directory\n asks Terraform to ensure that the workspace is in place\n when in _plan_ mode\n invokes Terraform.plan with the _dalmatian-read_ role\n when NOT in _plan_ mode\n invokes Terraform.apply with the _dalmatian-admin_ role\n when in _auto_approve_ mode\n asks Terraform to use auto_approve mode\n\nDalmatian::SharedLoadbalancer\n #name\n uses shared_loadbalancer name\n #in_use_by\n uses shared_loadbalancer in_use_by list\n #clusters_in_use\n uses shared_loadbalancer clusters_in_use list\n #subnets_name\n uses shared_loadbalancer subnets_name value\n #domain_names\n uses shared_loadbalancer domain_names list provided by Services\n #internal\n uses shared_loadbalancer internal value\n #ip_whitelist\n uses shared_loadbalancer ip_whitelist list\n #idle_timeout\n uses shared_loadbalancer idle_timeout value\n #global_accelerator\n uses shared_loadbalancer global_accelerator value\n #ssl_policy\n has the default ssl policy defined\n #to_params\n provides a hash of attributes for use in deployment\n\nDalmatian::SharedLoadbalancerTest\n #call\n changes to the shared-loadbalancer directory\n logs our intention to run Terraform init\n runs Terraform init, with upgrade option\n ensures presence of workspace\n logs our intention to run Terraform fmt\n runs Terraform fmt with check and diff options\n logs our intention to run Terraform validate\n runs Terraform validate, with upgrade option\n changes back to the app root directory\n\nDalmatian::SourceDeployment\n #call\n changes to infrastructure config directory\n asks Terraform to ensure that the workspace is in place\n when the environment includes a git reference as \"track_revision\"\n checks out that commit\n passes the \"track_revision\" reference along to Terraform\n when in _plan_ mode\n invokes Terraform.plan with the _dalmatian-read_ role\n when NOT in _plan_ mode\n invokes Terraform.apply with the _dalmatian-admin_ role\n when in _auto_approve_ mode\n asks Terraform to use auto_approve mode\n\nDalmatian::Source\n #name\n uses the cluster name and its own position in the cluster's list of sources\n #cluster_name\n delegates to the cluster\n #cluster_id\n delegates to the cluster\n #account_id\n delegates to the cluster\n\nDalmatian::SourceTest\n #call\n changes to the ecs directory\n logs our intention to run Terraform init\n runs Terraform init, with upgrade option\n ensures presence of workspace\n logs our intention to run Terraform fmt\n runs Terraform fmt with check and diff options\n logs our intention to run Terraform validate\n runs Terraform validate, with upgrade option\n changes back to the app root directory\n when the environment includes a git reference as \"track_revision\"\n checks out that commit\n passes the \"track_revision\" reference along to Terraform.validate\n\nDalmatian::Terraform\n ::init(upgrade: false)\n when asked to upgrade\n passes terraform init the upgrade flag\n when not asked to upgrade\n does not pass terraform init the upgrade flag\n ::fmt(args = nil)\n when passed some additional arguments\n passes terraform fmt the upgrade flag\n when passed NO additional arguments\n invokes terraform fmt with no arguments\n ::validate(tfvars)\n passes the given _var-file_ to terraform\n reformats the given tfvars and passes them to terraform as args\n ::ensure_presence_of_workspace(workspace_name)\n logs our intention to create the workspace\n asks Terraform to create the workspace\n when the workspace already exists (and an error is rescued)\n logs our intention to _select_ rather than _create_ the workspace\n asks Terraform to select the existing workspace\n ::plan(tfvars)\n passes the given _var-file_ to terraform\n reformats the given tfvars and passes them to terraform as args\n ::apply(tfvars, auto_approve=false)\n passes the given _var-file_ to terraform\n reformats the given tfvars and passes them to terraform as args\n when auto-approve is set to true\n passes the _auto-approve_ flag to terraform apply\n ::destroy(tfvars)\n passes the given _var-file_ to terraform\n reformats the given tfvars and passes them to terraform as args\n ::list_workspaces\n changes to the bootstrapping directory\n runs the terraform cmd to list workspaces\n\nDalmatian::UrlCacheHandler\n #call\n deletes any old cache\n uses the helper to GET a URI\n logs the cloning action\n logs the path to the cached configuration\n returns the cached full configuration to the caller (configuration reader)\n reads the cached full configuration from the disk in order to return to caller\n\nDalmatian::VpnCustomerGatewayDeployment\n #call\n changes to vpn-customer-gateway infrastructure directory\n asks Terraform to ensure that the workspace is in place\n when in _plan_ mode\n invokes Terraform.plan with the _dalmatian-read_ role\n when NOT in _plan_ mode\n invokes Terraform.apply with the _dalmatian-admin_ role\n when in _auto_approve_ mode\n asks Terraform to use auto_approve mode\n\nDalmatian::VpnCustomerGateway\n #name\n uses vpn_customer_gateway name\n #bgp_asn\n uses vpn_customer_gateway bgp_asn\n #ip_address\n uses vpn_customer_gateway ip_address\n #to_params\n provides a hash of attributes for use in deployment\n\nDalmatian::VpnCustomerGatewayTest\n #call\n changes to the vpn-customer-gateway directory\n logs our intention to run Terraform init\n runs Terraform init, with upgrade option\n ensures presence of workspace\n logs our intention to run Terraform fmt\n runs Terraform fmt with check and diff options\n logs our intention to run Terraform validate\n runs Terraform validate, with upgrade option\n changes back to the app root directory\n\nDalmatian::WAFDeployment\n #call\n changes to waf infrastructure directory\n asks Terraform to ensure that the workspace is in place\n when in _plan_ mode\n invokes Terraform.plan with the _dalmatian-read_ role\n when NOT in _plan_ mode\n invokes Terraform.apply with the _dalmatian-admin_ role\n when in _auto_approve_ mode\n asks Terraform to use auto_approve mode\n\nDalmatian::WAF\n #name\n uses waf name\n #action\n uses waf action\n #ip_deny_list\n has a list of IP addresses to block\n #aws_managed_rules\n uses waf aws_managed_rules list\n #associations\n uses waf associations list\n #to_params\n provides a hash of attributes for use in deployment\n\nDalmatian::WAFTest\n #call\n changes to the ecs-services directory\n logs our intention to run Terraform init\n runs Terraform init, with upgrade option\n ensures presence of workspace\n logs our intention to run Terraform fmt\n runs Terraform fmt with check and diff options\n logs our intention to run Terraform validate\n runs Terraform validate, with upgrade option\n changes back to the app root directory\n\nFinished in 3.27 seconds (files took 0.72402 seconds to load)\n478 examples, 0 failures\n\nCoverage report generated for RSpec to /Users/bob/git/dxw/dalmatian/coverage. 4310 / 4389 LOC (98.2%) covered.\n\n==> Linting markdown...\n./docs/database-backups.md:105: MD024 Multiple headers with the same content\n./docs/database-backups.md:109: MD024 Multiple headers with the same content\n./docs/database-backups.md:119: MD024 Multiple headers with the same content\n./docs/database-backups.md:123: MD024 Multiple headers with the same content\n./docs/database-backups.md:149: MD024 Multiple headers with the same content\n./docs/database-backups.md:169: MD024 Multiple headers with the same content\n./docs/database-backups.md:173: MD024 Multiple headers with the same content\n./docs/database-backups.md:183: MD024 Multiple headers with the same content\n./docs/database-backups.md:187: MD024 Multiple headers with the same content\n./docs/database-backups.md:213: MD024 Multiple headers with the same content\n./docs/database-backups.md:99: MD031 Fenced code blocks should be surrounded by blank lines\n./docs/database-backups.md:166: MD031 Fenced code blocks should be surrounded by blank lines\n./docs/database-backups.md:230: MD031 Fenced code blocks should be surrounded by blank lines\n./docs/database-backups.md:105: MD024 Multiple headers with the same content\n./docs/database-backups.md:109: MD024 Multiple headers with the same content\n./docs/database-backups.md:119: MD024 Multiple headers with the same content\n./docs/database-backups.md:123: MD024 Multiple headers with the same content\n./docs/database-backups.md:149: MD024 Multiple headers with the same content\n./docs/database-backups.md:169: MD024 Multiple headers with the same content\n./docs/database-backups.md:173: MD024 Multiple headers with the same content\n./docs/database-backups.md:183: MD024 Multiple headers with the same content\n./docs/database-backups.md:187: MD024 Multiple headers with the same content\n./docs/database-backups.md:213: MD024 Multiple headers with the same content\n./docs/database-backups.md:99: MD031 Fenced code blocks should be surrounded by blank lines\n./docs/database-backups.md:166: MD031 Fenced code blocks should be surrounded by blank lines\n./docs/database-backups.md:230: MD031 Fenced code blocks should be surrounded by blank lines\n./docs/database-backups.md:105: MD024 Multiple headers with the same content\n./docs/database-backups.md:109: MD024 Multiple headers with the same content\n./docs/database-backups.md:119: MD024 Multiple headers with the same content\n./docs/database-backups.md:123: MD024 Multiple headers with the same content\n./docs/database-backups.md:149: MD024 Multiple headers with the same content\n./docs/database-backups.md:169: MD024 Multiple headers with the same content\n./docs/database-backups.md:173: MD024 Multiple headers with the same content\n./docs/database-backups.md:183: MD024 Multiple headers with the same content\n./docs/database-backups.md:187: MD024 Multiple headers with the same content\n./docs/database-backups.md:213: MD024 Multiple headers with the same content\n./docs/database-backups.md:99: MD031 Fenced code blocks should be surrounded by blank lines\n./docs/database-backups.md:166: MD031 Fenced code blocks should be surrounded by blank lines\n./docs/database-backups.md:230: MD031 Fenced code blocks should be surrounded by blank lines\nExit Code: 1\nProcess Group PGID: 49015"
|
|
}
|
|
}
|
|
}
|
|
],
|
|
"status": "success",
|
|
"timestamp": "2026-02-20T17:16:47.134Z",
|
|
"resultDisplay": "==> Linting YAML...\n\n==> Linting shell scripts...\n\n==> Checking Terraform for JSON errors...\n- Checking ./terraform/policies/iam-read.json... Passed\n- Checking ./terraform/policies/s3-rw-with-versioning.json... Passed\n- Checking ./terraform/policies/codestar-connection-use.json... Passed\n- Checking ./terraform/policies/iam-create-access-key.json... Passed\n- Checking ./terraform/policies/codebuild.json... Passed\n- Checking ./terraform/policies/kms-encrypt-decrypt.json... Passed\n- Checking ./terraform/policies/iam-change-password.json... Passed\n- Checking ./terraform/policies/administrator-access.json... Passed\n- Checking ./terraform/policies/assume_roles/aws-backup.json... Passed\n- Checking ./terraform/policies/assume_roles/autoscaling.json... Passed\n- Checking ./terraform/policies/assume_roles/events.json... Passed\n- Checking ./terraform/policies/assume_roles/ecs.json... Passed\n- Checking ./terraform/policies/assume_roles/codepipeline.json... Passed\n- Checking ./terraform/policies/iam-mfa.json... Passed\n- Checking ./terraform/policies/route53-read.json... Passed\n- Checking ./terraform/policies/s3-full-access.json... Passed\n- Checking ./terraform/policies/parameter-store-read-decrypt.json... Passed\n- Checking ./terraform/policies/s3-read.json... Passed\n- Checking ./terraform/policies/parameter-store-RW-encrypt-decrypt.json... Passed\n- Checking ./terraform/policies/all-read-with-billing.json... Passed\n- Checking ./terraform/policies/codebuild-start-build.json... Passed\n- Checking ./terraform/policies/all-read.json... Passed\n\n==> Linting Terraform...\n\n==> Running Ruby tests...\n/Users/bob/.rbenv/versions/2.7.1/bin/ruby -I/Users/bob/.bundles/ruby/2.7.0/gems/rspec-core-3.12.2/lib:/Users/bob/.bundles/ruby/2.7.0/gems/rspec-support-3.12.1/lib /Users/bob/.bundles/ruby/2.7.0/gems/rspec-core-3.12.2/exe/rspec --pattern spec/\\*\\*\\{,/\\*/\\*\\*\\}/\\*_spec.rb\n\ntests local configuration\n use of \"terraform apply\"\n passes the hosted zone config to \"terraform apply\"\n passes the s3 config to \"terraform apply\"\n passes the vpn customer gateway config to \"terraform apply\"\n passes the base config to \"terraform apply\"\n passes the waf config to \"terraform apply\"\n passes the rds config to \"terraform apply\"\n passes the elasticache config to \"terraform apply\"\n passes the opensearch config to \"terraform apply\"\n passes the service config to \"terraform apply\"\n passes the loadbalancer config to \"terraform apply\"\n passes the cluster 2 config to \"terraform apply\"\n passes the cluster 3 config to \"terraform apply\"\n passes the cluster 4 config to \"terraform apply\"\n\ntests remote configuration\n retrieves the remotely held full configuration\n proceeds with deploying the infrastructure as per the cached full configuration\n\ntests local configuration\n invokes \"terraform validate\" with the expected cluster options\n invokes \"terraform validate\" with the expected source options\n use of \"terraform plan\"\n passes the hosted zone config to \"terraform plan\"\n passes the s3 config to \"terraform plan\"\n passes the vpn customer gateway config to \"terraform plan\"\n passes the base config to \"terraform plan\"\n passes the waf config to \"terraform plan\"\n passes the rds config to \"terraform plan\"\n passes the elasticache config to \"terraform plan\"\n passes the opensearch config to \"terraform plan\"\n passes the services config to \"terraform plan\"\n passes the loadbalancer config to \"terraform plan\"\n passes the cluster 2 config to \"terraform plan\"\n passes the cluster 3 config to \"terraform plan\"\n passes the cluster 4 config to \"terraform plan\"\n\nDalmatian::Account\n initialisation\n gathering user input\n asks the user for AWS credentials\n asks the user for the AWS account id to use\n asks the user for an account alias\n #call\n changes to the bootstrapping directory\n runs terraform init with upgrade option\n creates the new workspace using the given aws account id and alias\n runs terraform apply with the user-supplied vars\n\nDalmatian::CacheHandlerSelector\n ::new_for(remote_reference)\n when the remote reference is for a git repo\n asks for an instance of GitCacheHandler\n when the remote reference is for an S3 bucket\n asks for an instance of S3CacheHandler\n when the remote reference is for a URL\n asks for an instance of UrlCacheHandler\n when the type is unknown\n raises an error\n\nCacheHandler\n when a subclass class does not implement #cache_remote_configuration\n raises a helpful error\n\nDalmatian::CI\n CI::PATH\n is a constant\n #deploy\n changes to the ci directory\n runs terraform init with upgrade option\n creates the new workspace using the given aws account id and alias\n runs terraform apply with the user-supplied vars\n #test\n runs terraform plan with the user-supplied vars\n\nDalmatian::ClusterDeployment\n #call\n changes to the ecs directory\n asks Terraform to ensure that the workspace is in place\n when the environment includes a git reference as \"track_revision\"\n does NOT attempt to check out that commit\n when in _plan_ mode\n invokes Terraform.plan using the _dalmatian-read_ role\n when NOT in _plan_ mode\n invokes Terraform.apply using the _dalmatian-admin_\n when in _auto_approve_ mode\n asks Terraform to use auto_approve mode\n\nDalmatian::Cluster\n on initialisation\n makes Hosted zones, S3, Sources, Services, Loadbalancers, WAF and Rds\n #target_directory\n is a standard _ecs_ path\n #id\n is the primary key of the cluster definition is used\n #name\n when the cluster has an explicitly provided _name_ property\n that property is used\n when the cluster does not have an explicitly provided _name_ property\n the primary key of the cluster definition is used\n #account_id\n is the aws account key for deployment\n #sources\n represents any links to remote sources\n #environments\n represents the attributes of each environment's cluster section\n #fetch\n when the source is remotely held\n logs the plan to clone the source into the infrastructure pth\n deletes any existing source at the infrastructure location\n clones each source into the infrastructure location\n changes to the infrastructure directory for each source\n runs rake terrafile\n changes back to the APP_ROOT\n when the source is a local file path\n does not re-clone the source\n does not run terrafile\n when the specified local directory exists\n logs the fact that the local source is in place\n when the specificed local directory does not exist\n logs an error that the local source is missing\n #deploy\n deploys source infrastructure for each source and each service in each environment\n when a cluster should be created\n deploys cluster infrastructure for each environment\n when the _plan_ option IS invoked\n creates Cluster Deployments with plan settings\n when the _auto_approve_ option IS invoked\n creates Cluster Deployments with auto_approve settings\n handling of tests\n when the _test_ option is NOT invoked\n does not run cluster tests\n does not run cluster tests\n does not run cluster tests\n does not run source tests\n does not run waf tests\n does not run rds tests\n does not run service tests\n does not run service tests\n when the test option IS invoked\n runs tests\n when a cluster should NOT be created\n does not deploy cluster infrastructure\n when test option is invoked\n tests sources and services for each environment\n\nDalmatian::ClusterTest\n #call\n changes to the ecs directory\n logs our intention to run Terraform init\n runs Terraform init, with upgrade option\n ensures presence of workspace\n logs our intention to run Terraform fmt\n runs Terraform fmt with check and diff options\n logs our intention to run Terraform validate\n runs Terraform validate, with upgrade option\n changes back to the app root directory\n when the environment includes a git reference as \"track_revision\"\n does NOT attempt to check out that commit\n\nDalmatian::ConfigurationReader\n when a full configuration is provided in a local file\n #call\n has no need to use a cache handler\n returns the loaded configuration\n when a reference to a remote configuration is provided\n and the reference is provided in a local file\n uses the CacheHandlerSelector to provide the appropriate retrieval mechanism\n calls on the selected cache handler\n returns the configuration returned by the cache_handler\n and the reference is provided using environment variables\n passes the provided remote reference to the CacheHandlerSelector\n and references are provided in both environment variables and config file\n prefers the environment variable references over the config file\n and no references are provided\n raises an error\n and the remote reference is missing its _type_\n raises an error\n #ci\n when a parameter path prefix is given\n overwrites the ci:variables config with those retrieved from the param store\n leaves other ci:variables in place\n when a parameter path prefix is NOT given\n does NOT overwrite any ci:variables from the param store\n\nDalmatian::ElasticacheCluster\n #identifier\n uses elasticache identifier\n #in_use_by\n uses elasticache_cluster in_use_by list\n #node_type\n uses elasticache_cluster node_type\n #node_count\n uses elasticache_cluster node_count\n #engine\n uses elasticache_cluster engine\n #engine_version\n uses the elasticache_cluster engine_version\n #parameters\n uses the elasticache_cluster parameters list\n #port\n uses the elasticache_cluster port\n #maintenance_window\n uses the elasticache_cluster maintenance_window\n #snapshot_window\n uses the elasticache_cluster snapshot_window\n #parameter_store_path_elasticache_cluster_url_name\n uses the elasticache_cluster parameter_store_path_elasticache_cluster_url_name\n #to_params\n provides a hash of attributes for use in deployment\n\nDalmatian::ElasticacheClusterTest\n #call\n changes to the elasticache-cluster directory\n logs our intention to run Terraform init\n runs Terraform init, with upgrade option\n ensures presence of workspace\n logs our intention to run Terraform fmt\n runs Terraform fmt with check and diff options\n logs our intention to run Terraform validate\n runs Terraform validate, with upgrade option\n changes back to the app root directory\n\nDalmatian::GitCacheHandler\n #call\n deletes any old cache\n uses git clone to save the remote config to a local cache\n logs the cloning action\n logs the path to the cached configuration\n returns the cached full configuration to the caller (configuration reader)\n reads the cached full configuration from the disk in order to return to caller\n when no special cache path is given\n uses the default cache path of ./.dalmatian_cache/remote_config\n\nDalmatian::Helper\n ::git_clone(source, destination)\n when source and destination args are not provided\n raises an error with usage info\n when given source and destination args\n passes the request to the git CLI\n ::git_checkout(revision)\n checks out the given revision using run!\n ::get(source, destination)\n when source and destination args are not provided\n raises an error with usage info\n when given source and destination args\n opens the source url\n opens a new file at the destination\n writes the source resource into that file\n reads the information from the fetched resource\n ::run!\n passes given cmd to Kernel.system\n when the call to Kernel.system returns _false_\n raise a helpful error\n ::run_with_output!(cmd)\n passes given cmd to Open3.capture3\n when the system call returns a zero exit status\n returns the systems output to STDOUT\n when the system call returns a non-zero exit status\n also returns STDOUT ignoring the exit code and STDERR\n when the system call raises an ENOENT error\n catches this and raises a helpful Error\n ::change_to(path)\n passes the given path to Dir.chdir\n ::to_bool(str)\n when given nil\n returns false\n when given an empty string\n returns false\n when given lower case string _true_\n returns true\n when given mixed case string _True_\n returns true\n when given the object true\n returns true\n when given the object false\n returns false\n ::tflint\n runs the tflint cmd\n ::terrafile\n runs rake terrafile\n ::ask\n delegates to HighLine#ask\n ::ask_in_confidence\n delegates to HighLine#ask\n passes a block to mask the answer\n\nDalmatian::HostedZoneDeployment\n #call\n changes to hosted-zone infrastructure directory\n asks Terraform to ensure that the workspace is in place\n when in _plan_ mode\n invokes Terraform.plan with the _dalmatian-read_ role\n when NOT in _plan_ mode\n invokes Terraform.apply with the _dalmatian-admin_ role\n when in _auto_approve_ mode\n asks Terraform to use auto_approve mode\n\nDalmatian::HostedZone\n #domain\n uses hosted_zone domain\n #ns_records\n uses hosted_zone ns_records\n #a_records\n uses hosted_zone a_records\n #alias_records\n uses hosted_zone alias_records\n #cname_records\n uses hosted_zone cname_records\n #mx_records\n uses hosted_zone mx_records\n #txt_records\n uses hosted_zone txt_records\n #srv_records\n uses hosted_zone srv_records\n #to_params\n provides a hash of attributes for use in deployment\n\nDalmatian::HostedZoneTest\n #call\n changes to the hosted-zone directory\n logs our intention to run Terraform init\n runs Terraform init, with upgrade option\n ensures presence of workspace\n logs our intention to run Terraform fmt\n runs Terraform fmt with check and diff options\n logs our intention to run Terraform validate\n runs Terraform validate, with upgrade option\n changes back to the app root directory\n\nDalmatian::Infrastructure\n Infrastructure::PATH\n is a constant\n Infrastructure::APP_ROOT\n is a constant\n initialisation\n when configuration is not provided\n builds one using the defaults\n #clusters\n creates one cluster for each cluster description provided\n key operations on clusters\n #fetch\n asks all clusters to #fetch\n #test\n asks all clusters to #deploy with _plan_ and _test_ options\n #deploy\n when no parameters given\n asks all clusters to #deploy with _plan_, _test_ and _auto-approve_ disabled\n when parameters are given\n asks all clusters to #deploy with the given options\n when a particular infrastructure is named for deployment\n asks only the named cluster to #deploy with the given options\n\nDalmatian::Logger\n ::error(msg)\n raises an error with a red message\n ::info(msg)\n puts the given given message in white\n ::success(msg)\n puts the given given message in green\n ::warn(msg)\n puts the given given message in yellow\n\nDalmatian::OpensearchCluster\n #identifier\n uses opensearch identifier\n #in_use_by\n uses opensearch_cluster in_use_by list\n #version\n uses opensearch_cluster version\n #master_enabled\n uses opensearch_cluster master_enabled bool\n #master_count\n uses opensearch_cluster master_count\n #master_type\n uses opensearch_cluster master_type\n #instance_count\n uses opensearch_cluster instance_count\n #instance_type\n uses opensearch_cluster instance_type\n #warm_enabled\n uses opensearch_cluster warm_enabled bool\n #warm_count\n uses opensearch_cluster warm_count\n #warm_type\n uses opensearch_cluster warm_type\n #parameter_store_path_opensearch_cluster_url_name\n uses opensearch_cluster parameter_store_path_opensearch_cluster_url_name\n #volume_size\n uses opensearch_cluster volume_size\n #to_params\n provides a hash of attributes for use in deployment\n\nDalmatian::OpensearchClusterTest\n #call\n changes to the opensearch-cluster directory\n logs our intention to run Terraform init\n runs Terraform init, with upgrade option\n ensures presence of workspace\n logs our intention to run Terraform fmt\n runs Terraform fmt with check and diff options\n logs our intention to run Terraform validate\n runs Terraform validate, with upgrade option\n changes back to the app root directory\n\nDalmatian::ParameterStore\n ::get_parameter(name: \"\", with_decryption: true)\n when getting a single parameter from Parameter Store\n runs aws ssm get-parameter\n ::get_parameters_by_path(path: \"\", with_decryption: true)\n when getting parameters by path from Parameter Store\n runs aws ssm get-parameter\n\nDalmatian::RdsDeployment\n #call\n changes to rds infrastructure directory\n asks Terraform to ensure that the workspace is in place\n when in _plan_ mode\n invokes Terraform.plan with the _dalmatian-read_ role\n when NOT in _plan_ mode\n invokes Terraform.apply with the _dalmatian-admin_ role\n when in _auto_approve_ mode\n asks Terraform to use auto_approve mode\n\nDalmatian::Rds\n #identifier\n uses rds identifier\n #in_use_by\n uses rds in_use_by list\n #clusters_in_use\n uses rds clusters_in_use list\n #instance_class\n uses rds instance_class\n #engine\n uses rds engine\n #engine_version\n uses the rds engine_version\n #allocated_storage\n uses the rds allocated_storage\n #storage_encrypted\n uses the rds storage_encrypted bool\n #storage_type\n uses the rds storage_type gp3\n #db_name\n uses the rds db_name\n #port\n uses the rds port\n #maintenance_window\n uses the rds maintenance_window\n #backup_window\n uses the rds backup_window\n #backup_retention_period\n uses the rds backup_retention_period\n #force_ssl\n uses the rds force_ssl bool\n #parameter_store_path_db_url_name\n uses the rds parameter_store_path_db_url_name\n #sql_backup_scheduled_task_environment_variables\n uses the rds sql_backup_scheduled_task_environment_variables\n #check_sql_backup_scheduled_task_environment_variables\n uses the rds check_sql_backup_scheduled_task_environment_variables\n #sync_sql_backup_to_azure\n will have offsite backups disabled by default\n #replication_bucket_destination_arn\n uses the rds replication_bucket_destination_arn\n #replication_kms_key_id\n uses the rds replication_kms_key_id\n #codebuild_access\n uses the rds codebuild_access\n #to_params\n provides a hash of attributes for use in deployment\n\nDalmatian::RdsTest\n #call\n changes to the ecs-services directory\n logs our intention to run Terraform init\n runs Terraform init, with upgrade option\n ensures presence of workspace\n logs our intention to run Terraform fmt\n runs Terraform fmt with check and diff options\n logs our intention to run Terraform validate\n runs Terraform validate, with upgrade option\n changes back to the app root directory\n\nDalmatian::RemoteReferenceValues\n when the reference is for a git repo\n returns a git shaped configuration\n if _filename_ is not present\n supplies the default of _dalmatian.yml_\n when the reference is for an S3 bucket\n returns an S3 shaped configuration\n if _key_ is not present\n supplies the default of _dalmatian.yml_\n when the reference is for a URL\n returns a git shaped configuration\n\nDalmatian::S3CacheHandler\n #call\n deletes any old cache\n uses the AWS S3 cmd to save the remote config to a local cache\n logs the cloning action\n logs the path to the cached configuration\n returns the cached full configuration to the caller (configuration reader)\n reads the cached full configuration from the disk in order to return to caller\n\nDalmatian::S3Deployment\n #call\n changes to s3 infrastructure directory\n asks Terraform to ensure that the workspace is in place\n when in _plan_ mode\n invokes Terraform.plan with the _dalmatian-read_ role\n when NOT in _plan_ mode\n invokes Terraform.apply with the _dalmatian-admin_ role\n when in _auto_approve_ mode\n asks Terraform to use auto_approve mode\n\nDalmatian::S3\n #name\n uses s3 name\n #enable_s3_versioning\n uses enable_s3_versioning bool\n #encrypted\n uses s3 encrypted bool\n #acl\n uses s3 acl\n #policy\n uses s3 policy\n #service_cloudfront_read_access\n uses s3 service_cloudfront_read_access\n #cloudfront\n uses s3 cloudfront\n #to_params\n provides a hash of attributes for use in deployment\n\nDalmatian::S3Test\n #call\n changes to the s3 directory\n logs our intention to run Terraform init\n runs Terraform init, with upgrade option\n ensures presence of workspace\n logs our intention to run Terraform fmt\n runs Terraform fmt with check and diff options\n logs our intention to run Terraform validate\n runs Terraform validate, with upgrade option\n changes back to the app root directory\n\nDalmatian::ServiceDeployment\n #call\n changes to ecs-services infrastructure directory\n asks Terraform to ensure that the workspace is in place\n when in _plan_ mode\n invokes Terraform.plan with the _dalmatian-read_ role\n when NOT in _plan_ mode\n invokes Terraform.apply with the _dalmatian-admin_ role\n when in _auto_approve_ mode\n asks Terraform to use auto_approve mode\n\nDalmatian::Service\n #name\n uses service name\n #blue_green\n uses the service blue_green map\n #parameter_store_path\n uses service parameter_store_path\n #parameter_store_key\n uses service parameter_store_key\n #daemon\n uses the service daemon bool\n #monitoring\n uses the service monitoring hash\n #cloudfront\n recasts the service config in environment groups\n includes the appropriate \"custom_origins\" values in each environment\n Uses an AWS cloudfront managed cache policy\n Uses an AWS cloudfront managed origin policy\n Uses an AWS cloudfront managed response headers policy\n mirroring of elements into each environment group\n includes the \"create\" value\n includes the \"tls_protocol_version\" value\n includes the \"origin_keepalive_timeout\" value\n includes the \"origin_read_timeout\" value\n includes the \"basic_auth\" value\n includes the \"basic_auth_users_extra\" value\n includes the \"viewer_request_functions\" values\n includes the \"offline_page_http_status\" value\n bypass_protection\n uses the \"bypass_protection\" configuration\n custom_behaviors\n converts list of \"path_patterns\" to a single \"path_pattern\"\n #shared_loadbalancer_name\n returns shared loadbalancer name if the service is in use by a shared loadbalancer\n returns empty string if the service is not in use by a shared loadbalancer\n #s3_policy\n uses the service s3_policy map\n #lb_ip_whitelistt\n uses the service lb_ip_whitelist list\n #lb_idle_timeout\n uses the service lb_idle_timeout\n #global_accelerator\n uses service global_accelerator value\n #health_check_path\n uses the service health_check_path\n #health_check_grace_period\n uses the service health_check_grace_period\n #deregistration_delay\n uses the service deregistration_delay\n #serve_from_subdirectory\n uses the service serve_from_subdirectory\n #domain_names\n groups the domain names from the service domain_list into environments\n #proxy_configuration\n groups the proxy configurations from the service proxy_configuration list into environments\n #home_directory\n uses the service home_directory\n #lb_ssl_certificate\n groups the certificate arns from the service lb_ssl_certificate list into environments\n #lb_ssl_policy\n sets the default ssl policy for each environment\n #cloudfront_ssl_certificate\n groups the certificate arns from the service cloudfront_ssl_certificate list into environments\n #image_source\n uses the service image source\n #launch_on\n uses the service 'launch_on' specification\n #launch_on_cluster\n uses the service 'launch_on_cluster' string\n #cluster_min_servers\n uses the service 'cluster_min_servers' string\n #image_location\n uses the service image location\n #track_revision\n uses the service track_revision string\n #custom_codestar_connection_arn\n uses the service custom_codestar_connection_arn\n #codepipeline_use_github_v1\n uses the service codepipeline_use_github_v1\n #codepipeline_codebuild_run_in_vpc\n uses the service codepipeline_codebuild_run_in_vpc\n #codepipeline_codebuild_use_service_env\n uses the service codepipeline_codebuild_use_service_env\n #buildspec\n uses the service buildspec\n #container_port\n uses the service container port\n #container_command\n uses the service container command\n #container_volumes\n uses the service container volumes\n #container_extra_hosts\n uses the service container extra hosts\n #container_count\n uses the service container_count\n #enable_max_one_container_per_instance\n uses the service enable_max_one_container_per_instance\n #scheduled_tasks\n uses the service scheduled tasks\n #workers\n uses the service workers\n #cluster_name\n delegates to the cluster\n #cluster_id\n delegates to the cluster\n #account_id\n delegates to the cluster\n #to_params\n provides a hash of attributes for use in deployment\n\nDalmatian::ServiceTest\n #call\n changes to the ecs-services directory\n logs our intention to run Terraform init\n runs Terraform init, with upgrade option\n ensures presence of workspace\n logs our intention to run Terraform fmt\n runs Terraform fmt with check and diff options\n logs our intention to run Terraform validate\n runs Terraform validate, with upgrade option\n changes back to the app root directory\n\nDalmatian::SharedLoadbalancerDeployment\n #call\n changes to shared-loadbalancer infrastructure directory\n asks Terraform to ensure that the workspace is in place\n when in _plan_ mode\n invokes Terraform.plan with the _dalmatian-read_ role\n when NOT in _plan_ mode\n invokes Terraform.apply with the _dalmatian-admin_ role\n when in _auto_approve_ mode\n asks Terraform to use auto_approve mode\n\nDalmatian::SharedLoadbalancer\n #name\n uses shared_loadbalancer name\n #in_use_by\n uses shared_loadbalancer in_use_by list\n #clusters_in_use\n uses shared_loadbalancer clusters_in_use list\n #subnets_name\n uses shared_loadbalancer subnets_name value\n #domain_names\n uses shared_loadbalancer domain_names list provided by Services\n #internal\n uses shared_loadbalancer internal value\n #ip_whitelist\n uses shared_loadbalancer ip_whitelist list\n #idle_timeout\n uses shared_loadbalancer idle_timeout value\n #global_accelerator\n uses shared_loadbalancer global_accelerator value\n #ssl_policy\n has the default ssl policy defined\n #to_params\n provides a hash of attributes for use in deployment\n\nDalmatian::SharedLoadbalancerTest\n #call\n changes to the shared-loadbalancer directory\n logs our intention to run Terraform init\n runs Terraform init, with upgrade option\n ensures presence of workspace\n logs our intention to run Terraform fmt\n runs Terraform fmt with check and diff options\n logs our intention to run Terraform validate\n runs Terraform validate, with upgrade option\n changes back to the app root directory\n\nDalmatian::SourceDeployment\n #call\n changes to infrastructure config directory\n asks Terraform to ensure that the workspace is in place\n when the environment includes a git reference as \"track_revision\"\n checks out that commit\n passes the \"track_revision\" reference along to Terraform\n when in _plan_ mode\n invokes Terraform.plan with the _dalmatian-read_ role\n when NOT in _plan_ mode\n invokes Terraform.apply with the _dalmatian-admin_ role\n when in _auto_approve_ mode\n asks Terraform to use auto_approve mode\n\nDalmatian::Source\n #name\n uses the cluster name and its own position in the cluster's list of sources\n #cluster_name\n delegates to the cluster\n #cluster_id\n delegates to the cluster\n #account_id\n delegates to the cluster\n\nDalmatian::SourceTest\n #call\n changes to the ecs directory\n logs our intention to run Terraform init\n runs Terraform init, with upgrade option\n ensures presence of workspace\n logs our intention to run Terraform fmt\n runs Terraform fmt with check and diff options\n logs our intention to run Terraform validate\n runs Terraform validate, with upgrade option\n changes back to the app root directory\n when the environment includes a git reference as \"track_revision\"\n checks out that commit\n passes the \"track_revision\" reference along to Terraform.validate\n\nDalmatian::Terraform\n ::init(upgrade: false)\n when asked to upgrade\n passes terraform init the upgrade flag\n when not asked to upgrade\n does not pass terraform init the upgrade flag\n ::fmt(args = nil)\n when passed some additional arguments\n passes terraform fmt the upgrade flag\n when passed NO additional arguments\n invokes terraform fmt with no arguments\n ::validate(tfvars)\n passes the given _var-file_ to terraform\n reformats the given tfvars and passes them to terraform as args\n ::ensure_presence_of_workspace(workspace_name)\n logs our intention to create the workspace\n asks Terraform to create the workspace\n when the workspace already exists (and an error is rescued)\n logs our intention to _select_ rather than _create_ the workspace\n asks Terraform to select the existing workspace\n ::plan(tfvars)\n passes the given _var-file_ to terraform\n reformats the given tfvars and passes them to terraform as args\n ::apply(tfvars, auto_approve=false)\n passes the given _var-file_ to terraform\n reformats the given tfvars and passes them to terraform as args\n when auto-approve is set to true\n passes the _auto-approve_ flag to terraform apply\n ::destroy(tfvars)\n passes the given _var-file_ to terraform\n reformats the given tfvars and passes them to terraform as args\n ::list_workspaces\n changes to the bootstrapping directory\n runs the terraform cmd to list workspaces\n\nDalmatian::UrlCacheHandler\n #call\n deletes any old cache\n uses the helper to GET a URI\n logs the cloning action\n logs the path to the cached configuration\n returns the cached full configuration to the caller (configuration reader)\n reads the cached full configuration from the disk in order to return to caller\n\nDalmatian::VpnCustomerGatewayDeployment\n #call\n changes to vpn-customer-gateway infrastructure directory\n asks Terraform to ensure that the workspace is in place\n when in _plan_ mode\n invokes Terraform.plan with the _dalmatian-read_ role\n when NOT in _plan_ mode\n invokes Terraform.apply with the _dalmatian-admin_ role\n when in _auto_approve_ mode\n asks Terraform to use auto_approve mode\n\nDalmatian::VpnCustomerGateway\n #name\n uses vpn_customer_gateway name\n #bgp_asn\n uses vpn_customer_gateway bgp_asn\n #ip_address\n uses vpn_customer_gateway ip_address\n #to_params\n provides a hash of attributes for use in deployment\n\nDalmatian::VpnCustomerGatewayTest\n #call\n changes to the vpn-customer-gateway directory\n logs our intention to run Terraform init\n runs Terraform init, with upgrade option\n ensures presence of workspace\n logs our intention to run Terraform fmt\n runs Terraform fmt with check and diff options\n logs our intention to run Terraform validate\n runs Terraform validate, with upgrade option\n changes back to the app root directory\n\nDalmatian::WAFDeployment\n #call\n changes to waf infrastructure directory\n asks Terraform to ensure that the workspace is in place\n when in _plan_ mode\n invokes Terraform.plan with the _dalmatian-read_ role\n when NOT in _plan_ mode\n invokes Terraform.apply with the _dalmatian-admin_ role\n when in _auto_approve_ mode\n asks Terraform to use auto_approve mode\n\nDalmatian::WAF\n #name\n uses waf name\n #action\n uses waf action\n #ip_deny_list\n has a list of IP addresses to block\n #aws_managed_rules\n uses waf aws_managed_rules list\n #associations\n uses waf associations list\n #to_params\n provides a hash of attributes for use in deployment\n\nDalmatian::WAFTest\n #call\n changes to the ecs-services directory\n logs our intention to run Terraform init\n runs Terraform init, with upgrade option\n ensures presence of workspace\n logs our intention to run Terraform fmt\n runs Terraform fmt with check and diff options\n logs our intention to run Terraform validate\n runs Terraform validate, with upgrade option\n changes back to the app root directory\n\nFinished in 3.27 seconds (files took 0.72402 seconds to load)\n478 examples, 0 failures\n\nCoverage report generated for RSpec to /Users/bob/git/dxw/dalmatian/coverage. 4310 / 4389 LOC (98.2%) covered.\n\n==> Linting markdown...\n./docs/database-backups.md:105: MD024 Multiple headers with the same content\n./docs/database-backups.md:109: MD024 Multiple headers with the same content\n./docs/database-backups.md:119: MD024 Multiple headers with the same content\n./docs/database-backups.md:123: MD024 Multiple headers with the same content\n./docs/database-backups.md:149: MD024 Multiple headers with the same content\n./docs/database-backups.md:169: MD024 Multiple headers with the same content\n./docs/database-backups.md:173: MD024 Multiple headers with the same content\n./docs/database-backups.md:183: MD024 Multiple headers with the same content\n./docs/database-backups.md:187: MD024 Multiple headers with the same content\n./docs/database-backups.md:213: MD024 Multiple headers with the same content\n./docs/database-backups.md:99: MD031 Fenced code blocks should be surrounded by blank lines\n./docs/database-backups.md:166: MD031 Fenced code blocks should be surrounded by blank lines\n./docs/database-backups.md:230: MD031 Fenced code blocks should be surrounded by blank lines\n./docs/database-backups.md:105: MD024 Multiple headers with the same content\n./docs/database-backups.md:109: MD024 Multiple headers with the same content\n./docs/database-backups.md:119: MD024 Multiple headers with the same content\n./docs/database-backups.md:123: MD024 Multiple headers with the same content\n./docs/database-backups.md:149: MD024 Multiple headers with the same content\n./docs/database-backups.md:169: MD024 Multiple headers with the same content\n./docs/database-backups.md:173: MD024 Multiple headers with the same content\n./docs/database-backups.md:183: MD024 Multiple headers with the same content\n./docs/database-backups.md:187: MD024 Multiple headers with the same content\n./docs/database-backups.md:213: MD024 Multiple headers with the same content\n./docs/database-backups.md:99: MD031 Fenced code blocks should be surrounded by blank lines\n./docs/database-backups.md:166: MD031 Fenced code blocks should be surrounded by blank lines\n./docs/database-backups.md:230: MD031 Fenced code blocks should be surrounded by blank lines\n./docs/database-backups.md:105: MD024 Multiple headers with the same content\n./docs/database-backups.md:109: MD024 Multiple headers with the same content\n./docs/database-backups.md:119: MD024 Multiple headers with the same content\n./docs/database-backups.md:123: MD024 Multiple headers with the same content\n./docs/database-backups.md:149: MD024 Multiple headers with the same content\n./docs/database-backups.md:169: MD024 Multiple headers with the same content\n./docs/database-backups.md:173: MD024 Multiple headers with the same content\n./docs/database-backups.md:183: MD024 Multiple headers with the same content\n./docs/database-backups.md:187: MD024 Multiple headers with the same content\n./docs/database-backups.md:213: MD024 Multiple headers with the same content\n./docs/database-backups.md:99: MD031 Fenced code blocks should be surrounded by blank lines\n./docs/database-backups.md:166: MD031 Fenced code blocks should be surrounded by blank lines\n./docs/database-backups.md:230: MD031 Fenced code blocks should be surrounded by blank lines",
|
|
"displayName": "Shell",
|
|
"description": "This tool executes a given shell command as `bash -c <command>`. To run a command in the background, set the `is_background` parameter to true. Do NOT use `&` to background commands. Command is executed as a subprocess that leads its own process group. Command process group can be terminated as `kill -- -PGID` or signaled as `kill -s SIGNAL -- -PGID`.\n\n Efficiency Guidelines:\n - Quiet Flags: Always prefer silent or quiet flags (e.g., `npm install --silent`, `git --no-pager`) to reduce output volume while still capturing necessary information.\n - Pagination: Always disable terminal pagination to ensure commands terminate (e.g., use `git --no-pager`, `systemctl --no-pager`, or set `PAGER=cat`).\n\n The following information is returned:\n\n Output: Combined stdout/stderr. Can be `(empty)` or partial on error and for any unwaited background processes.\n Exit Code: Only included if non-zero (command failed).\n Error: Only included if a process-level error occurred (e.g., spawn failure).\n Signal: Only included if process was terminated by a signal.\n Background PIDs: Only included if background processes were started.\n Process Group PGID: Only included if available.",
|
|
"renderOutputAsMarkdown": false
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"id": "9b5d84ab-a0b2-4ef8-b385-62d34e6c62ca",
|
|
"timestamp": "2026-02-20T17:17:38.613Z",
|
|
"type": "gemini",
|
|
"content": "Ruby tests passed, but markdown linting errors in `docs/database-backups.md` caused `scripts/bin/test` to exit with code 1. While potentially pre-existing, I'll take a quick look to see if they're easily fixable, though my primary task of resolving RDS parameter-related test failures is complete.",
|
|
"thoughts": [
|
|
{
|
|
"subject": "Refining Test Results",
|
|
"description": "I'm examining the test results more closely. While the Ruby tests look clean, the script's exit code is flagging an issue. It appears markdown linting errors are the culprit, specifically in the `docs/database-backups.md` file. I'll need to separate the code issues from these documentation concerns.",
|
|
"timestamp": "2026-02-20T17:17:23.977Z"
|
|
},
|
|
{
|
|
"subject": "Assessing Linting Fixes",
|
|
"description": "I'm now contemplating whether to address the markdown linting issues. The errors, particularly the duplicate headers and lack of blank lines around code blocks, appear independent of the recent code modifications. My initial inclination is to stay focused on the RDS parameter-related changes. However, I'm quickly assessing the ease of resolving these linting problems to potentially prevent future confusion.",
|
|
"timestamp": "2026-02-20T17:17:38.379Z"
|
|
}
|
|
],
|
|
"tokens": {
|
|
"input": 100108,
|
|
"output": 97,
|
|
"cached": 56571,
|
|
"thoughts": 239,
|
|
"tool": 0,
|
|
"total": 100444
|
|
},
|
|
"model": "gemini-3-flash-preview",
|
|
"toolCalls": [
|
|
{
|
|
"id": "read_file_1771607858605_0",
|
|
"name": "read_file",
|
|
"args": {
|
|
"offset": 90,
|
|
"limit": 100,
|
|
"file_path": "docs/database-backups.md"
|
|
},
|
|
"result": [
|
|
{
|
|
"functionResponse": {
|
|
"id": "read_file_1771607858605_0",
|
|
"name": "read_file",
|
|
"response": {
|
|
"output": "\nIMPORTANT: The file content has been truncated.\nStatus: Showing lines 91-190 of 233 total lines.\nAction: To read more of the file, you can use the 'offset' and 'limit' parameters in a subsequent 'read_file' call. For example, to read the next section of the file, use offset: 190.\n\n--- FILE CONTENT (truncated) ---\n \"AWS\": \"arn:aws:iam::<SOURCE_ACCOUNT_ID>:role/<INFRASTRUCTURE_NAME>-<RDS_ID>-sql-backup-replication\"\n },\n \"Action\": [\n \"kms:Encrypt\",\n \"kms:GenerateDataKey\"\n ],\n \"Resource\": \"*\"\n}\n```\n||||||| Stash base\n=======\n<<<<<<< Updated upstream\n||||||| Stash base\n\n## Cross-account S3 replication for SQL backups\n\nSQL backups can be replicated to an S3 bucket in another AWS account for offsite storage or disaster recovery.\n\n### Source Account Configuration\n\nIn your `dalmatian.yml`, specify the destination bucket ARN and (optionally) the KMS key ID for the destination bucket:\n\n```yaml\nrds:\n replication_bucket_destination_arn: \"arn:aws:s3:::your-destination-bucket-name\"\n replication_kms_key_id: \"your-destination-kms-key-id\"\n```\n\n### Destination Account Configuration\n\nThe destination account must permit the source account's replication role to write to the bucket and use the KMS key.\n\n#### 1. Destination Bucket Policy\n\nAdd a policy to the destination bucket to allow the replication role from the source account:\n\n```json\n{\n \"Version\": \"2012-10-17\",\n \"Statement\": [\n {\n \"Sid\": \"AllowReplicationFromDalmatianSource\",\n \"Effect\": \"Allow\",\n \"Principal\": {\n \"AWS\": \"arn:aws:iam::<SOURCE_ACCOUNT_ID>:role/<INFRASTRUCTURE_NAME>-<RDS_ID>-sql-backup-replication\"\n },\n \"Action\": [\n \"s3:ReplicateObject\",\n \"s3:ReplicateDelete\",\n \"s3:ReplicateTags\",\n \"s3:ObjectOwnerOverrideToBucketOwner\"\n ],\n \"Resource\": \"arn:aws:s3:::<DESTINATION_BUCKET_NAME>/*\"\n }\n ]\n}\n```\n\n#### 2. Destination KMS Key Policy (Optional)\n\nIf the destination bucket uses a Customer Managed Key (CMK) for encryption, the key policy must allow the source replication role to use it:\n\n```json\n{\n \"Sid\": \"AllowUsageByDalmatianSourceReplicationRole\",\n \"Effect\": \"Allow\",\n \"Principal\": {\n \"AWS\": \"arn:aws:iam::<SOURCE_ACCOUNT_ID>:role/<INFRASTRUCTURE_NAME>-<RDS_ID>-sql-backup-replication\"\n },\n \"Action\": [\n \"kms:Encrypt\",\n \"kms:GenerateDataKey\"\n ],\n \"Resource\": \"*\"\n}\n```\n=======\n\n## Cross-account S3 replication for SQL backups\n\nSQL backups can be replicated to an S3 bucket in another AWS account for offsite storage or disaster recovery.\n\n### Source Account Configuration\n\nIn your `dalmatian.yml`, specify the destination bucket ARN and (optionally) the KMS key ID for the destination bucket:\n\n```yaml\nrds:\n replication_bucket_destination_arn: \"arn:aws:s3:::your-destination-bucket-name\"\n replication_kms_key_id: \"your-destination-kms-key-id\"\n```\n\n### Destination Account Configuration\n\nThe destination account must permit the source account's replication role to write to the bucket and use the KMS key.\n\n#### 1. Destination Bucket Policy\n\nAdd a policy to the destination bucket to allow the replication role from the source account:\n"
|
|
}
|
|
}
|
|
}
|
|
],
|
|
"status": "success",
|
|
"timestamp": "2026-02-20T17:17:38.640Z",
|
|
"resultDisplay": "Read lines 91-190 of 233 from docs/database-backups.md",
|
|
"displayName": "ReadFile",
|
|
"description": "Reads and returns the content of a specified file. If the file is large, the content will be truncated. The tool's response will clearly indicate if truncation has occurred and will provide details on how to read more of the file using the 'offset' and 'limit' parameters. Handles text, images (PNG, JPG, GIF, WEBP, SVG, BMP), audio files (MP3, WAV, AIFF, AAC, OGG, FLAC), and PDF files. For text files, it can read specific line ranges.",
|
|
"renderOutputAsMarkdown": true
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"id": "f15fdd8a-137f-4315-91c1-fc5a5df4a65a",
|
|
"timestamp": "2026-02-20T17:18:37.739Z",
|
|
"type": "gemini",
|
|
"content": "`docs/database-backups.md` contains git conflict markers and duplicated content, causing markdown linter failures. I'll resolve this by removing the markers and redundant sections.",
|
|
"thoughts": [
|
|
{
|
|
"subject": "Diagnosing a Conflict",
|
|
"description": "I've identified a file, `docs/database-backups.md`, marred by Git conflict markers. It's clear that these markers, specifically those like \"<<<<<<< Updated upstream\" and \"=======,\" are the root cause of the markdown linter failure. I'm now certain this is not good.",
|
|
"timestamp": "2026-02-20T17:18:33.270Z"
|
|
},
|
|
{
|
|
"subject": "Refining the Resolution",
|
|
"description": "I've examined the conflicting content, and it appears to be entirely redundant, particularly the \"Cross-account S3 replication\" section. My immediate plan is to simply eliminate the conflict markers and the duplicates in `docs/database-backups.md`, which should resolve the linter errors swiftly. I'll make the changes and move on.",
|
|
"timestamp": "2026-02-20T17:18:37.500Z"
|
|
}
|
|
],
|
|
"tokens": {
|
|
"input": 101090,
|
|
"output": 56,
|
|
"cached": 3532,
|
|
"thoughts": 194,
|
|
"tool": 0,
|
|
"total": 101340
|
|
},
|
|
"model": "gemini-3-flash-preview",
|
|
"toolCalls": [
|
|
{
|
|
"id": "read_file_1771607917726_0",
|
|
"name": "read_file",
|
|
"args": {
|
|
"file_path": "docs/database-backups.md"
|
|
},
|
|
"result": [
|
|
{
|
|
"functionResponse": {
|
|
"id": "read_file_1771607917726_0",
|
|
"name": "read_file",
|
|
"response": {
|
|
"output": "# Database backups\n\nAutomated RDS backups are taken daily within AWS. The time and retention periods vary depending on the configuration.\n\nManual backups are also possible when required.\n\nAs the RDS instances are not publicly available, manual backups must be done via the ECS instances.\n\nFollow the [Shell access to ECS instances](shell-access-to-ecs-instances.md) guide to access one of the ECS instances.\n\n## Manual backup of PostgreSQL databases\n\nThe postgres container is available in the ECR, so as long as you have https access to the VPC endpoints, you will be able to access it.\n\nThe URI of the postgres container is `<aws-account-number>.dkr.ecr.<aws-region>.amazonaws.com/<infrastructure-environment-name>-postgres`. This can also be found via the [ECR UI](https://console.aws.amazon.com/ecr/repositories).\n\nYou will need to run login to ECR's docker to pull the container\n\n```\n$(aws ecr get-login --no-include-email --region <aws-region>)\n```\n\nCreate a directory on the instance to store the database dump:\n\n```\nmkdir -p /db-backup\n```\n\nTo create a postgresql sql dump, run:\n\n```\ndocker run -i -v /db-backup:/db-backup <postgres-container-uri> /bin/bash -c \"pg_dump postgres://<username>:<password>@<rds-endpoint>:5432/<database-name> > /db-backup/<backup-name>.sql\"\n```\n\nTo transfer the backup, follow the [Transferring files to the ECS instances](transferring-files-to-the-ecs-instances.md) guide\n<<<<<<< Updated upstream\n\n## Cross-account S3 replication for SQL backups\n\nSQL backups can be replicated to an S3 bucket in another AWS account for offsite storage or disaster recovery.\n\n### Source Account Configuration\n\nIn your `dalmatian.yml`, specify the destination bucket ARN and (optionally) the KMS key ID for the destination bucket:\n\n```yaml\nrds:\n replication_bucket_destination_arn: \"arn:aws:s3:::your-destination-bucket-name\"\n replication_kms_key_id: \"your-destination-kms-key-id\"\n```\n\n### Destination Account Configuration\n\nThe destination account must permit the source account's replication role to write to the bucket and use the KMS key.\n\n#### 1. Destination Bucket Policy\n\nAdd a policy to the destination bucket to allow the replication role from the source account:\n\n```json\n{\n \"Version\": \"2012-10-17\",\n \"Statement\": [\n {\n \"Sid\": \"AllowReplicationFromDalmatianSource\",\n \"Effect\": \"Allow\",\n \"Principal\": {\n \"AWS\": \"arn:aws:iam::<SOURCE_ACCOUNT_ID>:role/<INFRASTRUCTURE_NAME>-<RDS_ID>-sql-backup-replication\"\n },\n \"Action\": [\n \"s3:ReplicateObject\",\n \"s3:ReplicateDelete\",\n \"s3:ReplicateTags\",\n \"s3:ObjectOwnerOverrideToBucketOwner\"\n ],\n \"Resource\": \"arn:aws:s3:::<DESTINATION_BUCKET_NAME>/*\"\n }\n ]\n}\n```\n\n#### 2. Destination KMS Key Policy (Optional)\n\nIf the destination bucket uses a Customer Managed Key (CMK) for encryption, the key policy must allow the source replication role to use it:\n\n```json\n{\n \"Sid\": \"AllowUsageByDalmatianSourceReplicationRole\",\n \"Effect\": \"Allow\",\n \"Principal\": {\n \"AWS\": \"arn:aws:iam::<SOURCE_ACCOUNT_ID>:role/<INFRASTRUCTURE_NAME>-<RDS_ID>-sql-backup-replication\"\n },\n \"Action\": [\n \"kms:Encrypt\",\n \"kms:GenerateDataKey\"\n ],\n \"Resource\": \"*\"\n}\n```\n||||||| Stash base\n=======\n<<<<<<< Updated upstream\n||||||| Stash base\n\n## Cross-account S3 replication for SQL backups\n\nSQL backups can be replicated to an S3 bucket in another AWS account for offsite storage or disaster recovery.\n\n### Source Account Configuration\n\nIn your `dalmatian.yml`, specify the destination bucket ARN and (optionally) the KMS key ID for the destination bucket:\n\n```yaml\nrds:\n replication_bucket_destination_arn: \"arn:aws:s3:::your-destination-bucket-name\"\n replication_kms_key_id: \"your-destination-kms-key-id\"\n```\n\n### Destination Account Configuration\n\nThe destination account must permit the source account's replication role to write to the bucket and use the KMS key.\n\n#### 1. Destination Bucket Policy\n\nAdd a policy to the destination bucket to allow the replication role from the source account:\n\n```json\n{\n \"Version\": \"2012-10-17\",\n \"Statement\": [\n {\n \"Sid\": \"AllowReplicationFromDalmatianSource\",\n \"Effect\": \"Allow\",\n \"Principal\": {\n \"AWS\": \"arn:aws:iam::<SOURCE_ACCOUNT_ID>:role/<INFRASTRUCTURE_NAME>-<RDS_ID>-sql-backup-replication\"\n },\n \"Action\": [\n \"s3:ReplicateObject\",\n \"s3:ReplicateDelete\",\n \"s3:ReplicateTags\",\n \"s3:ObjectOwnerOverrideToBucketOwner\"\n ],\n \"Resource\": \"arn:aws:s3:::<DESTINATION_BUCKET_NAME>/*\"\n }\n ]\n}\n```\n\n#### 2. Destination KMS Key Policy (Optional)\n\nIf the destination bucket uses a Customer Managed Key (CMK) for encryption, the key policy must allow the source replication role to use it:\n\n```json\n{\n \"Sid\": \"AllowUsageByDalmatianSourceReplicationRole\",\n \"Effect\": \"Allow\",\n \"Principal\": {\n \"AWS\": \"arn:aws:iam::<SOURCE_ACCOUNT_ID>:role/<INFRASTRUCTURE_NAME>-<RDS_ID>-sql-backup-replication\"\n },\n \"Action\": [\n \"kms:Encrypt\",\n \"kms:GenerateDataKey\"\n ],\n \"Resource\": \"*\"\n}\n```\n=======\n\n## Cross-account S3 replication for SQL backups\n\nSQL backups can be replicated to an S3 bucket in another AWS account for offsite storage or disaster recovery.\n\n### Source Account Configuration\n\nIn your `dalmatian.yml`, specify the destination bucket ARN and (optionally) the KMS key ID for the destination bucket:\n\n```yaml\nrds:\n replication_bucket_destination_arn: \"arn:aws:s3:::your-destination-bucket-name\"\n replication_kms_key_id: \"your-destination-kms-key-id\"\n```\n\n### Destination Account Configuration\n\nThe destination account must permit the source account's replication role to write to the bucket and use the KMS key.\n\n#### 1. Destination Bucket Policy\n\nAdd a policy to the destination bucket to allow the replication role from the source account:\n\n```json\n{\n \"Version\": \"2012-10-17\",\n \"Statement\": [\n {\n \"Sid\": \"AllowReplicationFromDalmatianSource\",\n \"Effect\": \"Allow\",\n \"Principal\": {\n \"AWS\": \"arn:aws:iam::<SOURCE_ACCOUNT_ID>:role/<INFRASTRUCTURE_NAME>-<RDS_ID>-sql-backup-replication\"\n },\n \"Action\": [\n \"s3:ReplicateObject\",\n \"s3:ReplicateDelete\",\n \"s3:ReplicateTags\",\n \"s3:ObjectOwnerOverrideToBucketOwner\"\n ],\n \"Resource\": \"arn:aws:s3:::<DESTINATION_BUCKET_NAME>/*\"\n }\n ]\n}\n```\n\n#### 2. Destination KMS Key Policy (Optional)\n\nIf the destination bucket uses a Customer Managed Key (CMK) for encryption, the key policy must allow the source replication role to use it:\n\n```json\n{\n \"Sid\": \"AllowUsageByDalmatianSourceReplicationRole\",\n \"Effect\": \"Allow\",\n \"Principal\": {\n \"AWS\": \"arn:aws:iam::<SOURCE_ACCOUNT_ID>:role/<INFRASTRUCTURE_NAME>-<RDS_ID>-sql-backup-replication\"\n },\n \"Action\": [\n \"kms:Encrypt\",\n \"kms:GenerateDataKey\"\n ],\n \"Resource\": \"*\"\n}\n```\n>>>>>>> Stashed changes\n>>>>>>> Stashed changes\n"
|
|
}
|
|
}
|
|
}
|
|
],
|
|
"status": "success",
|
|
"timestamp": "2026-02-20T17:18:37.787Z",
|
|
"resultDisplay": "",
|
|
"displayName": "ReadFile",
|
|
"description": "Reads and returns the content of a specified file. If the file is large, the content will be truncated. The tool's response will clearly indicate if truncation has occurred and will provide details on how to read more of the file using the 'offset' and 'limit' parameters. Handles text, images (PNG, JPG, GIF, WEBP, SVG, BMP), audio files (MP3, WAV, AIFF, AAC, OGG, FLAC), and PDF files. For text files, it can read specific line ranges.",
|
|
"renderOutputAsMarkdown": true
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"id": "aad16e4a-5d18-4c1a-b0d8-eb1b9130423e",
|
|
"timestamp": "2026-02-20T17:18:57.039Z",
|
|
"type": "gemini",
|
|
"content": "Way too many conflict markers. Rewriting with clean content.",
|
|
"thoughts": [
|
|
{
|
|
"subject": "Addressing the Conflicts",
|
|
"description": "I've been staring at this mess of stashed changes and conflict markers. It's quite the headache. My plan is to rewrite the entire file, but now I must make sure that it's clean and doesn't contain any unwanted additions.",
|
|
"timestamp": "2026-02-20T17:18:53.034Z"
|
|
}
|
|
],
|
|
"tokens": {
|
|
"input": 103110,
|
|
"output": 920,
|
|
"cached": 91910,
|
|
"thoughts": 27,
|
|
"tool": 0,
|
|
"total": 104057
|
|
},
|
|
"model": "gemini-3-flash-preview",
|
|
"toolCalls": [
|
|
{
|
|
"id": "write_file_1771607937027_0",
|
|
"name": "write_file",
|
|
"args": {
|
|
"content": "# Database backups\n\nAutomated RDS backups are taken daily within AWS. The time and retention periods vary depending on the configuration.\n\nManual backups are also possible when required.\n\nAs the RDS instances are not publicly available, manual backups must be done via the ECS instances.\n\nFollow the [Shell access to ECS instances](shell-access-to-ecs-instances.md) guide to access one of the ECS instances.\n\n## Manual backup of PostgreSQL databases\n\nThe postgres container is available in the ECR, so as long as you have https access to the VPC endpoints, you will be able to access it.\n\nThe URI of the postgres container is `<aws-account-number>.dkr.ecr.<aws-region>.amazonaws.com/<infrastructure-environment-name>-postgres`. This can also be found via the [ECR UI](https://console.aws.amazon.com/ecr/repositories).\n\nYou will need to run login to ECR's docker to pull the container\n\n```\n$(aws ecr get-login --no-include-email --region <aws-region>)\n```\n\nCreate a directory on the instance to store the database dump:\n\n```\nmkdir -p /db-backup\n```\n\nTo create a postgresql sql dump, run:\n\n```\ndocker run -i -v /db-backup:/db-backup <postgres-container-uri> /bin/bash -c \"pg_dump postgres://<username>:<password>@<rds-endpoint>:5432/<database-name> > /db-backup/<backup-name>.sql\"\n```\n\nTo transfer the backup, follow the [Transferring files to the ECS instances](transferring-files-to-the-ecs-instances.md) guide\n\n## Cross-account S3 replication for SQL backups\n\nSQL backups can be replicated to an S3 bucket in another AWS account for offsite storage or disaster recovery.\n\n### Source Account Configuration\n\nIn your `dalmatian.yml`, specify the destination bucket ARN and (optionally) the KMS key ID for the destination bucket:\n\n```yaml\nrds:\n replication_bucket_destination_arn: \"arn:aws:s3:::your-destination-bucket-name\"\n replication_kms_key_id: \"your-destination-kms-key-id\"\n```\n\n### Destination Account Configuration\n\nThe destination account must permit the source account's replication role to write to the bucket and use the KMS key.\n\n#### 1. Destination Bucket Policy\n\nAdd a policy to the destination bucket to allow the replication role from the source account:\n\n```json\n{\n \"Version\": \"2012-10-17\",\n \"Statement\": [\n {\n \"Sid\": \"AllowReplicationFromDalmatianSource\",\n \"Effect\": \"Allow\",\n \"Principal\": {\n \"AWS\": \"arn:aws:iam::<SOURCE_ACCOUNT_ID>:role/<INFRASTRUCTURE_NAME>-<RDS_ID>-sql-backup-replication\"\n },\n \"Action\": [\n \"s3:ReplicateObject\",\n \"s3:ReplicateDelete\",\n \"s3:ReplicateTags\",\n \"s3:ObjectOwnerOverrideToBucketOwner\"\n ],\n \"Resource\": \"arn:aws:s3:::<DESTINATION_BUCKET_NAME>/*\"\n }\n ]\n}\n```\n\n#### 2. Destination KMS Key Policy (Optional)\n\nIf the destination bucket uses a Customer Managed Key (CMK) for encryption, the key policy must allow the source replication role to use it:\n\n```json\n{\n \"Sid\": \"AllowUsageByDalmatianSourceReplicationRole\",\n \"Effect\": \"Allow\",\n \"Principal\": {\n \"AWS\": \"arn:aws:iam::<SOURCE_ACCOUNT_ID>:role/<INFRASTRUCTURE_NAME>-<RDS_ID>-sql-backup-replication\"\n },\n \"Action\": [\n \"kms:Encrypt\",\n \"kms:GenerateDataKey\"\n ],\n \"Resource\": \"*\"\n}\n```\n",
|
|
"file_path": "docs/database-backups.md"
|
|
},
|
|
"result": [
|
|
{
|
|
"functionResponse": {
|
|
"id": "write_file_1771607937027_0",
|
|
"name": "write_file",
|
|
"response": {
|
|
"output": "Successfully overwrote file: /Users/bob/git/dxw/dalmatian/docs/database-backups.md."
|
|
}
|
|
}
|
|
}
|
|
],
|
|
"status": "success",
|
|
"timestamp": "2026-02-20T17:18:57.071Z",
|
|
"resultDisplay": {
|
|
"fileDiff": "Index: database-backups.md\n===================================================================\n--- database-backups.md\tOriginal\n+++ database-backups.md\tWritten\n@@ -33,7 +33,6 @@\n ```\n \n To transfer the backup, follow the [Transferring files to the ECS instances](transferring-files-to-the-ecs-instances.md) guide\n-<<<<<<< Updated upstream\n \n ## Cross-account S3 replication for SQL backups\n \n@@ -97,136 +96,3 @@\n \"Resource\": \"*\"\n }\n ```\n-||||||| Stash base\n-=======\n-<<<<<<< Updated upstream\n-||||||| Stash base\n-\n-## Cross-account S3 replication for SQL backups\n-\n-SQL backups can be replicated to an S3 bucket in another AWS account for offsite storage or disaster recovery.\n-\n-### Source Account Configuration\n-\n-In your `dalmatian.yml`, specify the destination bucket ARN and (optionally) the KMS key ID for the destination bucket:\n-\n-```yaml\n-rds:\n- replication_bucket_destination_arn: \"arn:aws:s3:::your-destination-bucket-name\"\n- replication_kms_key_id: \"your-destination-kms-key-id\"\n-```\n-\n-### Destination Account Configuration\n-\n-The destination account must permit the source account's replication role to write to the bucket and use the KMS key.\n-\n-#### 1. Destination Bucket Policy\n-\n-Add a policy to the destination bucket to allow the replication role from the source account:\n-\n-```json\n-{\n- \"Version\": \"2012-10-17\",\n- \"Statement\": [\n- {\n- \"Sid\": \"AllowReplicationFromDalmatianSource\",\n- \"Effect\": \"Allow\",\n- \"Principal\": {\n- \"AWS\": \"arn:aws:iam::<SOURCE_ACCOUNT_ID>:role/<INFRASTRUCTURE_NAME>-<RDS_ID>-sql-backup-replication\"\n- },\n- \"Action\": [\n- \"s3:ReplicateObject\",\n- \"s3:ReplicateDelete\",\n- \"s3:ReplicateTags\",\n- \"s3:ObjectOwnerOverrideToBucketOwner\"\n- ],\n- \"Resource\": \"arn:aws:s3:::<DESTINATION_BUCKET_NAME>/*\"\n- }\n- ]\n-}\n-```\n-\n-#### 2. Destination KMS Key Policy (Optional)\n-\n-If the destination bucket uses a Customer Managed Key (CMK) for encryption, the key policy must allow the source replication role to use it:\n-\n-```json\n-{\n- \"Sid\": \"AllowUsageByDalmatianSourceReplicationRole\",\n- \"Effect\": \"Allow\",\n- \"Principal\": {\n- \"AWS\": \"arn:aws:iam::<SOURCE_ACCOUNT_ID>:role/<INFRASTRUCTURE_NAME>-<RDS_ID>-sql-backup-replication\"\n- },\n- \"Action\": [\n- \"kms:Encrypt\",\n- \"kms:GenerateDataKey\"\n- ],\n- \"Resource\": \"*\"\n-}\n-```\n-=======\n-\n-## Cross-account S3 replication for SQL backups\n-\n-SQL backups can be replicated to an S3 bucket in another AWS account for offsite storage or disaster recovery.\n-\n-### Source Account Configuration\n-\n-In your `dalmatian.yml`, specify the destination bucket ARN and (optionally) the KMS key ID for the destination bucket:\n-\n-```yaml\n-rds:\n- replication_bucket_destination_arn: \"arn:aws:s3:::your-destination-bucket-name\"\n- replication_kms_key_id: \"your-destination-kms-key-id\"\n-```\n-\n-### Destination Account Configuration\n-\n-The destination account must permit the source account's replication role to write to the bucket and use the KMS key.\n-\n-#### 1. Destination Bucket Policy\n-\n-Add a policy to the destination bucket to allow the replication role from the source account:\n-\n-```json\n-{\n- \"Version\": \"2012-10-17\",\n- \"Statement\": [\n- {\n- \"Sid\": \"AllowReplicationFromDalmatianSource\",\n- \"Effect\": \"Allow\",\n- \"Principal\": {\n- \"AWS\": \"arn:aws:iam::<SOURCE_ACCOUNT_ID>:role/<INFRASTRUCTURE_NAME>-<RDS_ID>-sql-backup-replication\"\n- },\n- \"Action\": [\n- \"s3:ReplicateObject\",\n- \"s3:ReplicateDelete\",\n- \"s3:ReplicateTags\",\n- \"s3:ObjectOwnerOverrideToBucketOwner\"\n- ],\n- \"Resource\": \"arn:aws:s3:::<DESTINATION_BUCKET_NAME>/*\"\n- }\n- ]\n-}\n-```\n-\n-#### 2. Destination KMS Key Policy (Optional)\n-\n-If the destination bucket uses a Customer Managed Key (CMK) for encryption, the key policy must allow the source replication role to use it:\n-\n-```json\n-{\n- \"Sid\": \"AllowUsageByDalmatianSourceReplicationRole\",\n- \"Effect\": \"Allow\",\n- \"Principal\": {\n- \"AWS\": \"arn:aws:iam::<SOURCE_ACCOUNT_ID>:role/<INFRASTRUCTURE_NAME>-<RDS_ID>-sql-backup-replication\"\n- },\n- \"Action\": [\n- \"kms:Encrypt\",\n- \"kms:GenerateDataKey\"\n- ],\n- \"Resource\": \"*\"\n-}\n-```\n->>>>>>> Stashed changes\n->>>>>>> Stashed changes\n",
|
|
"fileName": "database-backups.md",
|
|
"filePath": "/Users/bob/git/dxw/dalmatian/docs/database-backups.md",
|
|
"originalContent": "# Database backups\n\nAutomated RDS backups are taken daily within AWS. The time and retention periods vary depending on the configuration.\n\nManual backups are also possible when required.\n\nAs the RDS instances are not publicly available, manual backups must be done via the ECS instances.\n\nFollow the [Shell access to ECS instances](shell-access-to-ecs-instances.md) guide to access one of the ECS instances.\n\n## Manual backup of PostgreSQL databases\n\nThe postgres container is available in the ECR, so as long as you have https access to the VPC endpoints, you will be able to access it.\n\nThe URI of the postgres container is `<aws-account-number>.dkr.ecr.<aws-region>.amazonaws.com/<infrastructure-environment-name>-postgres`. This can also be found via the [ECR UI](https://console.aws.amazon.com/ecr/repositories).\n\nYou will need to run login to ECR's docker to pull the container\n\n```\n$(aws ecr get-login --no-include-email --region <aws-region>)\n```\n\nCreate a directory on the instance to store the database dump:\n\n```\nmkdir -p /db-backup\n```\n\nTo create a postgresql sql dump, run:\n\n```\ndocker run -i -v /db-backup:/db-backup <postgres-container-uri> /bin/bash -c \"pg_dump postgres://<username>:<password>@<rds-endpoint>:5432/<database-name> > /db-backup/<backup-name>.sql\"\n```\n\nTo transfer the backup, follow the [Transferring files to the ECS instances](transferring-files-to-the-ecs-instances.md) guide\n<<<<<<< Updated upstream\n\n## Cross-account S3 replication for SQL backups\n\nSQL backups can be replicated to an S3 bucket in another AWS account for offsite storage or disaster recovery.\n\n### Source Account Configuration\n\nIn your `dalmatian.yml`, specify the destination bucket ARN and (optionally) the KMS key ID for the destination bucket:\n\n```yaml\nrds:\n replication_bucket_destination_arn: \"arn:aws:s3:::your-destination-bucket-name\"\n replication_kms_key_id: \"your-destination-kms-key-id\"\n```\n\n### Destination Account Configuration\n\nThe destination account must permit the source account's replication role to write to the bucket and use the KMS key.\n\n#### 1. Destination Bucket Policy\n\nAdd a policy to the destination bucket to allow the replication role from the source account:\n\n```json\n{\n \"Version\": \"2012-10-17\",\n \"Statement\": [\n {\n \"Sid\": \"AllowReplicationFromDalmatianSource\",\n \"Effect\": \"Allow\",\n \"Principal\": {\n \"AWS\": \"arn:aws:iam::<SOURCE_ACCOUNT_ID>:role/<INFRASTRUCTURE_NAME>-<RDS_ID>-sql-backup-replication\"\n },\n \"Action\": [\n \"s3:ReplicateObject\",\n \"s3:ReplicateDelete\",\n \"s3:ReplicateTags\",\n \"s3:ObjectOwnerOverrideToBucketOwner\"\n ],\n \"Resource\": \"arn:aws:s3:::<DESTINATION_BUCKET_NAME>/*\"\n }\n ]\n}\n```\n\n#### 2. Destination KMS Key Policy (Optional)\n\nIf the destination bucket uses a Customer Managed Key (CMK) for encryption, the key policy must allow the source replication role to use it:\n\n```json\n{\n \"Sid\": \"AllowUsageByDalmatianSourceReplicationRole\",\n \"Effect\": \"Allow\",\n \"Principal\": {\n \"AWS\": \"arn:aws:iam::<SOURCE_ACCOUNT_ID>:role/<INFRASTRUCTURE_NAME>-<RDS_ID>-sql-backup-replication\"\n },\n \"Action\": [\n \"kms:Encrypt\",\n \"kms:GenerateDataKey\"\n ],\n \"Resource\": \"*\"\n}\n```\n||||||| Stash base\n=======\n<<<<<<< Updated upstream\n||||||| Stash base\n\n## Cross-account S3 replication for SQL backups\n\nSQL backups can be replicated to an S3 bucket in another AWS account for offsite storage or disaster recovery.\n\n### Source Account Configuration\n\nIn your `dalmatian.yml`, specify the destination bucket ARN and (optionally) the KMS key ID for the destination bucket:\n\n```yaml\nrds:\n replication_bucket_destination_arn: \"arn:aws:s3:::your-destination-bucket-name\"\n replication_kms_key_id: \"your-destination-kms-key-id\"\n```\n\n### Destination Account Configuration\n\nThe destination account must permit the source account's replication role to write to the bucket and use the KMS key.\n\n#### 1. Destination Bucket Policy\n\nAdd a policy to the destination bucket to allow the replication role from the source account:\n\n```json\n{\n \"Version\": \"2012-10-17\",\n \"Statement\": [\n {\n \"Sid\": \"AllowReplicationFromDalmatianSource\",\n \"Effect\": \"Allow\",\n \"Principal\": {\n \"AWS\": \"arn:aws:iam::<SOURCE_ACCOUNT_ID>:role/<INFRASTRUCTURE_NAME>-<RDS_ID>-sql-backup-replication\"\n },\n \"Action\": [\n \"s3:ReplicateObject\",\n \"s3:ReplicateDelete\",\n \"s3:ReplicateTags\",\n \"s3:ObjectOwnerOverrideToBucketOwner\"\n ],\n \"Resource\": \"arn:aws:s3:::<DESTINATION_BUCKET_NAME>/*\"\n }\n ]\n}\n```\n\n#### 2. Destination KMS Key Policy (Optional)\n\nIf the destination bucket uses a Customer Managed Key (CMK) for encryption, the key policy must allow the source replication role to use it:\n\n```json\n{\n \"Sid\": \"AllowUsageByDalmatianSourceReplicationRole\",\n \"Effect\": \"Allow\",\n \"Principal\": {\n \"AWS\": \"arn:aws:iam::<SOURCE_ACCOUNT_ID>:role/<INFRASTRUCTURE_NAME>-<RDS_ID>-sql-backup-replication\"\n },\n \"Action\": [\n \"kms:Encrypt\",\n \"kms:GenerateDataKey\"\n ],\n \"Resource\": \"*\"\n}\n```\n=======\n\n## Cross-account S3 replication for SQL backups\n\nSQL backups can be replicated to an S3 bucket in another AWS account for offsite storage or disaster recovery.\n\n### Source Account Configuration\n\nIn your `dalmatian.yml`, specify the destination bucket ARN and (optionally) the KMS key ID for the destination bucket:\n\n```yaml\nrds:\n replication_bucket_destination_arn: \"arn:aws:s3:::your-destination-bucket-name\"\n replication_kms_key_id: \"your-destination-kms-key-id\"\n```\n\n### Destination Account Configuration\n\nThe destination account must permit the source account's replication role to write to the bucket and use the KMS key.\n\n#### 1. Destination Bucket Policy\n\nAdd a policy to the destination bucket to allow the replication role from the source account:\n\n```json\n{\n \"Version\": \"2012-10-17\",\n \"Statement\": [\n {\n \"Sid\": \"AllowReplicationFromDalmatianSource\",\n \"Effect\": \"Allow\",\n \"Principal\": {\n \"AWS\": \"arn:aws:iam::<SOURCE_ACCOUNT_ID>:role/<INFRASTRUCTURE_NAME>-<RDS_ID>-sql-backup-replication\"\n },\n \"Action\": [\n \"s3:ReplicateObject\",\n \"s3:ReplicateDelete\",\n \"s3:ReplicateTags\",\n \"s3:ObjectOwnerOverrideToBucketOwner\"\n ],\n \"Resource\": \"arn:aws:s3:::<DESTINATION_BUCKET_NAME>/*\"\n }\n ]\n}\n```\n\n#### 2. Destination KMS Key Policy (Optional)\n\nIf the destination bucket uses a Customer Managed Key (CMK) for encryption, the key policy must allow the source replication role to use it:\n\n```json\n{\n \"Sid\": \"AllowUsageByDalmatianSourceReplicationRole\",\n \"Effect\": \"Allow\",\n \"Principal\": {\n \"AWS\": \"arn:aws:iam::<SOURCE_ACCOUNT_ID>:role/<INFRASTRUCTURE_NAME>-<RDS_ID>-sql-backup-replication\"\n },\n \"Action\": [\n \"kms:Encrypt\",\n \"kms:GenerateDataKey\"\n ],\n \"Resource\": \"*\"\n}\n```\n>>>>>>> Stashed changes\n>>>>>>> Stashed changes\n",
|
|
"newContent": "# Database backups\n\nAutomated RDS backups are taken daily within AWS. The time and retention periods vary depending on the configuration.\n\nManual backups are also possible when required.\n\nAs the RDS instances are not publicly available, manual backups must be done via the ECS instances.\n\nFollow the [Shell access to ECS instances](shell-access-to-ecs-instances.md) guide to access one of the ECS instances.\n\n## Manual backup of PostgreSQL databases\n\nThe postgres container is available in the ECR, so as long as you have https access to the VPC endpoints, you will be able to access it.\n\nThe URI of the postgres container is `<aws-account-number>.dkr.ecr.<aws-region>.amazonaws.com/<infrastructure-environment-name>-postgres`. This can also be found via the [ECR UI](https://console.aws.amazon.com/ecr/repositories).\n\nYou will need to run login to ECR's docker to pull the container\n\n```\n$(aws ecr get-login --no-include-email --region <aws-region>)\n```\n\nCreate a directory on the instance to store the database dump:\n\n```\nmkdir -p /db-backup\n```\n\nTo create a postgresql sql dump, run:\n\n```\ndocker run -i -v /db-backup:/db-backup <postgres-container-uri> /bin/bash -c \"pg_dump postgres://<username>:<password>@<rds-endpoint>:5432/<database-name> > /db-backup/<backup-name>.sql\"\n```\n\nTo transfer the backup, follow the [Transferring files to the ECS instances](transferring-files-to-the-ecs-instances.md) guide\n\n## Cross-account S3 replication for SQL backups\n\nSQL backups can be replicated to an S3 bucket in another AWS account for offsite storage or disaster recovery.\n\n### Source Account Configuration\n\nIn your `dalmatian.yml`, specify the destination bucket ARN and (optionally) the KMS key ID for the destination bucket:\n\n```yaml\nrds:\n replication_bucket_destination_arn: \"arn:aws:s3:::your-destination-bucket-name\"\n replication_kms_key_id: \"your-destination-kms-key-id\"\n```\n\n### Destination Account Configuration\n\nThe destination account must permit the source account's replication role to write to the bucket and use the KMS key.\n\n#### 1. Destination Bucket Policy\n\nAdd a policy to the destination bucket to allow the replication role from the source account:\n\n```json\n{\n \"Version\": \"2012-10-17\",\n \"Statement\": [\n {\n \"Sid\": \"AllowReplicationFromDalmatianSource\",\n \"Effect\": \"Allow\",\n \"Principal\": {\n \"AWS\": \"arn:aws:iam::<SOURCE_ACCOUNT_ID>:role/<INFRASTRUCTURE_NAME>-<RDS_ID>-sql-backup-replication\"\n },\n \"Action\": [\n \"s3:ReplicateObject\",\n \"s3:ReplicateDelete\",\n \"s3:ReplicateTags\",\n \"s3:ObjectOwnerOverrideToBucketOwner\"\n ],\n \"Resource\": \"arn:aws:s3:::<DESTINATION_BUCKET_NAME>/*\"\n }\n ]\n}\n```\n\n#### 2. Destination KMS Key Policy (Optional)\n\nIf the destination bucket uses a Customer Managed Key (CMK) for encryption, the key policy must allow the source replication role to use it:\n\n```json\n{\n \"Sid\": \"AllowUsageByDalmatianSourceReplicationRole\",\n \"Effect\": \"Allow\",\n \"Principal\": {\n \"AWS\": \"arn:aws:iam::<SOURCE_ACCOUNT_ID>:role/<INFRASTRUCTURE_NAME>-<RDS_ID>-sql-backup-replication\"\n },\n \"Action\": [\n \"kms:Encrypt\",\n \"kms:GenerateDataKey\"\n ],\n \"Resource\": \"*\"\n}\n```\n",
|
|
"diffStat": {
|
|
"model_added_lines": 0,
|
|
"model_removed_lines": 134,
|
|
"model_added_chars": 0,
|
|
"model_removed_chars": 3794,
|
|
"user_added_lines": 0,
|
|
"user_removed_lines": 0,
|
|
"user_added_chars": 0,
|
|
"user_removed_chars": 0
|
|
},
|
|
"isNewFile": false
|
|
},
|
|
"displayName": "WriteFile",
|
|
"description": "Writes content to a specified file in the local filesystem.\n\n The user has the ability to modify `content`. If modified, this will be stated in the response.",
|
|
"renderOutputAsMarkdown": true
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"id": "23a71d0f-d64b-4484-a4c5-bd7607df6713",
|
|
"timestamp": "2026-02-20T17:19:17.611Z",
|
|
"type": "gemini",
|
|
"content": "Tests, one last time.",
|
|
"thoughts": [
|
|
{
|
|
"subject": "Re-evaluating the Testing",
|
|
"description": "I'm just running the tests again, a final sweep, to make sure everything's still shipshape. This is crucial before I can even think about moving forward. Fingers crossed, this goes smoothly.",
|
|
"timestamp": "2026-02-20T17:19:17.425Z"
|
|
}
|
|
],
|
|
"tokens": {
|
|
"input": 104058,
|
|
"output": 25,
|
|
"cached": 99053,
|
|
"thoughts": 11,
|
|
"tool": 0,
|
|
"total": 104094
|
|
},
|
|
"model": "gemini-3-flash-preview",
|
|
"toolCalls": [
|
|
{
|
|
"id": "run_shell_command_1771607957604_0",
|
|
"name": "run_shell_command",
|
|
"args": {
|
|
"command": "./scripts/bin/test -l"
|
|
},
|
|
"result": [
|
|
{
|
|
"functionResponse": {
|
|
"id": "run_shell_command_1771607957604_0",
|
|
"name": "run_shell_command",
|
|
"response": {
|
|
"output": "Output: ==> Linting YAML...\n\n==> Linting shell scripts...\n\n==> Checking Terraform for JSON errors...\n- Checking ./terraform/policies/iam-read.json... Passed\n- Checking ./terraform/policies/s3-rw-with-versioning.json... Passed\n- Checking ./terraform/policies/codestar-connection-use.json... Passed\n- Checking ./terraform/policies/iam-create-access-key.json... Passed\n- Checking ./terraform/policies/codebuild.json... Passed\n- Checking ./terraform/policies/kms-encrypt-decrypt.json... Passed\n- Checking ./terraform/policies/iam-change-password.json... Passed\n- Checking ./terraform/policies/administrator-access.json... Passed\n- Checking ./terraform/policies/assume_roles/aws-backup.json... Passed\n- Checking ./terraform/policies/assume_roles/autoscaling.json... Passed\n- Checking ./terraform/policies/assume_roles/events.json... Passed\n- Checking ./terraform/policies/assume_roles/ecs.json... Passed\n- Checking ./terraform/policies/assume_roles/codepipeline.json... Passed\n- Checking ./terraform/policies/iam-mfa.json... Passed\n- Checking ./terraform/policies/route53-read.json... Passed\n- Checking ./terraform/policies/s3-full-access.json... Passed\n- Checking ./terraform/policies/parameter-store-read-decrypt.json... Passed\n- Checking ./terraform/policies/s3-read.json... Passed\n- Checking ./terraform/policies/parameter-store-RW-encrypt-decrypt.json... Passed\n- Checking ./terraform/policies/all-read-with-billing.json... Passed\n- Checking ./terraform/policies/codebuild-start-build.json... Passed\n- Checking ./terraform/policies/all-read.json... Passed\n\n==> Linting Terraform...\n\n==> Running Ruby tests...\n/Users/bob/.rbenv/versions/2.7.1/bin/ruby -I/Users/bob/.bundles/ruby/2.7.0/gems/rspec-core-3.12.2/lib:/Users/bob/.bundles/ruby/2.7.0/gems/rspec-support-3.12.1/lib /Users/bob/.bundles/ruby/2.7.0/gems/rspec-core-3.12.2/exe/rspec --pattern spec/\\*\\*\\{,/\\*/\\*\\*\\}/\\*_spec.rb\n\ntests local configuration\n use of \"terraform apply\"\n passes the hosted zone config to \"terraform apply\"\n passes the s3 config to \"terraform apply\"\n passes the vpn customer gateway config to \"terraform apply\"\n passes the base config to \"terraform apply\"\n passes the waf config to \"terraform apply\"\n passes the rds config to \"terraform apply\"\n passes the elasticache config to \"terraform apply\"\n passes the opensearch config to \"terraform apply\"\n passes the service config to \"terraform apply\"\n passes the loadbalancer config to \"terraform apply\"\n passes the cluster 2 config to \"terraform apply\"\n passes the cluster 3 config to \"terraform apply\"\n passes the cluster 4 config to \"terraform apply\"\n\ntests remote configuration\n retrieves the remotely held full configuration\n proceeds with deploying the infrastructure as per the cached full configuration\n\ntests local configuration\n invokes \"terraform validate\" with the expected cluster options\n invokes \"terraform validate\" with the expected source options\n use of \"terraform plan\"\n passes the hosted zone config to \"terraform plan\"\n passes the s3 config to \"terraform plan\"\n passes the vpn customer gateway config to \"terraform plan\"\n passes the base config to \"terraform plan\"\n passes the waf config to \"terraform plan\"\n passes the rds config to \"terraform plan\"\n passes the elasticache config to \"terraform plan\"\n passes the opensearch config to \"terraform plan\"\n passes the services config to \"terraform plan\"\n passes the loadbalancer config to \"terraform plan\"\n passes the cluster 2 config to \"terraform plan\"\n passes the cluster 3 config to \"terraform plan\"\n passes the cluster 4 config to \"terraform plan\"\n\nDalmatian::Account\n initialisation\n gathering user input\n asks the user for AWS credentials\n asks the user for the AWS account id to use\n asks the user for an account alias\n #call\n changes to the bootstrapping directory\n runs terraform init with upgrade option\n creates the new workspace using the given aws account id and alias\n runs terraform apply with the user-supplied vars\n\nDalmatian::CacheHandlerSelector\n ::new_for(remote_reference)\n when the remote reference is for a git repo\n asks for an instance of GitCacheHandler\n when the remote reference is for an S3 bucket\n asks for an instance of S3CacheHandler\n when the remote reference is for a URL\n asks for an instance of UrlCacheHandler\n when the type is unknown\n raises an error\n\nCacheHandler\n when a subclass class does not implement #cache_remote_configuration\n raises a helpful error\n\nDalmatian::CI\n CI::PATH\n is a constant\n #deploy\n changes to the ci directory\n runs terraform init with upgrade option\n creates the new workspace using the given aws account id and alias\n runs terraform apply with the user-supplied vars\n #test\n runs terraform plan with the user-supplied vars\n\nDalmatian::ClusterDeployment\n #call\n changes to the ecs directory\n asks Terraform to ensure that the workspace is in place\n when the environment includes a git reference as \"track_revision\"\n does NOT attempt to check out that commit\n when in _plan_ mode\n invokes Terraform.plan using the _dalmatian-read_ role\n when NOT in _plan_ mode\n invokes Terraform.apply using the _dalmatian-admin_\n when in _auto_approve_ mode\n asks Terraform to use auto_approve mode\n\nDalmatian::Cluster\n on initialisation\n makes Hosted zones, S3, Sources, Services, Loadbalancers, WAF and Rds\n #target_directory\n is a standard _ecs_ path\n #id\n is the primary key of the cluster definition is used\n #name\n when the cluster has an explicitly provided _name_ property\n that property is used\n when the cluster does not have an explicitly provided _name_ property\n the primary key of the cluster definition is used\n #account_id\n is the aws account key for deployment\n #sources\n represents any links to remote sources\n #environments\n represents the attributes of each environment's cluster section\n #fetch\n when the source is remotely held\n logs the plan to clone the source into the infrastructure pth\n deletes any existing source at the infrastructure location\n clones each source into the infrastructure location\n changes to the infrastructure directory for each source\n runs rake terrafile\n changes back to the APP_ROOT\n when the source is a local file path\n does not re-clone the source\n does not run terrafile\n when the specified local directory exists\n logs the fact that the local source is in place\n when the specificed local directory does not exist\n logs an error that the local source is missing\n #deploy\n deploys source infrastructure for each source and each service in each environment\n when a cluster should be created\n deploys cluster infrastructure for each environment\n when the _plan_ option IS invoked\n creates Cluster Deployments with plan settings\n when the _auto_approve_ option IS invoked\n creates Cluster Deployments with auto_approve settings\n handling of tests\n when the _test_ option is NOT invoked\n does not run cluster tests\n does not run cluster tests\n does not run cluster tests\n does not run source tests\n does not run waf tests\n does not run rds tests\n does not run service tests\n does not run service tests\n when the test option IS invoked\n runs tests\n when a cluster should NOT be created\n does not deploy cluster infrastructure\n when test option is invoked\n tests sources and services for each environment\n\nDalmatian::ClusterTest\n #call\n changes to the ecs directory\n logs our intention to run Terraform init\n runs Terraform init, with upgrade option\n ensures presence of workspace\n logs our intention to run Terraform fmt\n runs Terraform fmt with check and diff options\n logs our intention to run Terraform validate\n runs Terraform validate, with upgrade option\n changes back to the app root directory\n when the environment includes a git reference as \"track_revision\"\n does NOT attempt to check out that commit\n\nDalmatian::ConfigurationReader\n when a full configuration is provided in a local file\n #call\n has no need to use a cache handler\n returns the loaded configuration\n when a reference to a remote configuration is provided\n and the reference is provided in a local file\n uses the CacheHandlerSelector to provide the appropriate retrieval mechanism\n calls on the selected cache handler\n returns the configuration returned by the cache_handler\n and the reference is provided using environment variables\n passes the provided remote reference to the CacheHandlerSelector\n and references are provided in both environment variables and config file\n prefers the environment variable references over the config file\n and no references are provided\n raises an error\n and the remote reference is missing its _type_\n raises an error\n #ci\n when a parameter path prefix is given\n overwrites the ci:variables config with those retrieved from the param store\n leaves other ci:variables in place\n when a parameter path prefix is NOT given\n does NOT overwrite any ci:variables from the param store\n\nDalmatian::ElasticacheCluster\n #identifier\n uses elasticache identifier\n #in_use_by\n uses elasticache_cluster in_use_by list\n #node_type\n uses elasticache_cluster node_type\n #node_count\n uses elasticache_cluster node_count\n #engine\n uses elasticache_cluster engine\n #engine_version\n uses the elasticache_cluster engine_version\n #parameters\n uses the elasticache_cluster parameters list\n #port\n uses the elasticache_cluster port\n #maintenance_window\n uses the elasticache_cluster maintenance_window\n #snapshot_window\n uses the elasticache_cluster snapshot_window\n #parameter_store_path_elasticache_cluster_url_name\n uses the elasticache_cluster parameter_store_path_elasticache_cluster_url_name\n #to_params\n provides a hash of attributes for use in deployment\n\nDalmatian::ElasticacheClusterTest\n #call\n changes to the elasticache-cluster directory\n logs our intention to run Terraform init\n runs Terraform init, with upgrade option\n ensures presence of workspace\n logs our intention to run Terraform fmt\n runs Terraform fmt with check and diff options\n logs our intention to run Terraform validate\n runs Terraform validate, with upgrade option\n changes back to the app root directory\n\nDalmatian::GitCacheHandler\n #call\n deletes any old cache\n uses git clone to save the remote config to a local cache\n logs the cloning action\n logs the path to the cached configuration\n returns the cached full configuration to the caller (configuration reader)\n reads the cached full configuration from the disk in order to return to caller\n when no special cache path is given\n uses the default cache path of ./.dalmatian_cache/remote_config\n\nDalmatian::Helper\n ::git_clone(source, destination)\n when source and destination args are not provided\n raises an error with usage info\n when given source and destination args\n passes the request to the git CLI\n ::git_checkout(revision)\n checks out the given revision using run!\n ::get(source, destination)\n when source and destination args are not provided\n raises an error with usage info\n when given source and destination args\n opens the source url\n opens a new file at the destination\n writes the source resource into that file\n reads the information from the fetched resource\n ::run!\n passes given cmd to Kernel.system\n when the call to Kernel.system returns _false_\n raise a helpful error\n ::run_with_output!(cmd)\n passes given cmd to Open3.capture3\n when the system call returns a zero exit status\n returns the systems output to STDOUT\n when the system call returns a non-zero exit status\n also returns STDOUT ignoring the exit code and STDERR\n when the system call raises an ENOENT error\n catches this and raises a helpful Error\n ::change_to(path)\n passes the given path to Dir.chdir\n ::to_bool(str)\n when given nil\n returns false\n when given an empty string\n returns false\n when given lower case string _true_\n returns true\n when given mixed case string _True_\n returns true\n when given the object true\n returns true\n when given the object false\n returns false\n ::tflint\n runs the tflint cmd\n ::terrafile\n runs rake terrafile\n ::ask\n delegates to HighLine#ask\n ::ask_in_confidence\n delegates to HighLine#ask\n passes a block to mask the answer\n\nDalmatian::HostedZoneDeployment\n #call\n changes to hosted-zone infrastructure directory\n asks Terraform to ensure that the workspace is in place\n when in _plan_ mode\n invokes Terraform.plan with the _dalmatian-read_ role\n when NOT in _plan_ mode\n invokes Terraform.apply with the _dalmatian-admin_ role\n when in _auto_approve_ mode\n asks Terraform to use auto_approve mode\n\nDalmatian::HostedZone\n #domain\n uses hosted_zone domain\n #ns_records\n uses hosted_zone ns_records\n #a_records\n uses hosted_zone a_records\n #alias_records\n uses hosted_zone alias_records\n #cname_records\n uses hosted_zone cname_records\n #mx_records\n uses hosted_zone mx_records\n #txt_records\n uses hosted_zone txt_records\n #srv_records\n uses hosted_zone srv_records\n #to_params\n provides a hash of attributes for use in deployment\n\nDalmatian::HostedZoneTest\n #call\n changes to the hosted-zone directory\n logs our intention to run Terraform init\n runs Terraform init, with upgrade option\n ensures presence of workspace\n logs our intention to run Terraform fmt\n runs Terraform fmt with check and diff options\n logs our intention to run Terraform validate\n runs Terraform validate, with upgrade option\n changes back to the app root directory\n\nDalmatian::Infrastructure\n Infrastructure::PATH\n is a constant\n Infrastructure::APP_ROOT\n is a constant\n initialisation\n when configuration is not provided\n builds one using the defaults\n #clusters\n creates one cluster for each cluster description provided\n key operations on clusters\n #fetch\n asks all clusters to #fetch\n #test\n asks all clusters to #deploy with _plan_ and _test_ options\n #deploy\n when no parameters given\n asks all clusters to #deploy with _plan_, _test_ and _auto-approve_ disabled\n when parameters are given\n asks all clusters to #deploy with the given options\n when a particular infrastructure is named for deployment\n asks only the named cluster to #deploy with the given options\n\nDalmatian::Logger\n ::error(msg)\n raises an error with a red message\n ::info(msg)\n puts the given given message in white\n ::success(msg)\n puts the given given message in green\n ::warn(msg)\n puts the given given message in yellow\n\nDalmatian::OpensearchCluster\n #identifier\n uses opensearch identifier\n #in_use_by\n uses opensearch_cluster in_use_by list\n #version\n uses opensearch_cluster version\n #master_enabled\n uses opensearch_cluster master_enabled bool\n #master_count\n uses opensearch_cluster master_count\n #master_type\n uses opensearch_cluster master_type\n #instance_count\n uses opensearch_cluster instance_count\n #instance_type\n uses opensearch_cluster instance_type\n #warm_enabled\n uses opensearch_cluster warm_enabled bool\n #warm_count\n uses opensearch_cluster warm_count\n #warm_type\n uses opensearch_cluster warm_type\n #parameter_store_path_opensearch_cluster_url_name\n uses opensearch_cluster parameter_store_path_opensearch_cluster_url_name\n #volume_size\n uses opensearch_cluster volume_size\n #to_params\n provides a hash of attributes for use in deployment\n\nDalmatian::OpensearchClusterTest\n #call\n changes to the opensearch-cluster directory\n logs our intention to run Terraform init\n runs Terraform init, with upgrade option\n ensures presence of workspace\n logs our intention to run Terraform fmt\n runs Terraform fmt with check and diff options\n logs our intention to run Terraform validate\n runs Terraform validate, with upgrade option\n changes back to the app root directory\n\nDalmatian::ParameterStore\n ::get_parameter(name: \"\", with_decryption: true)\n when getting a single parameter from Parameter Store\n runs aws ssm get-parameter\n ::get_parameters_by_path(path: \"\", with_decryption: true)\n when getting parameters by path from Parameter Store\n runs aws ssm get-parameter\n\nDalmatian::RdsDeployment\n #call\n changes to rds infrastructure directory\n asks Terraform to ensure that the workspace is in place\n when in _plan_ mode\n invokes Terraform.plan with the _dalmatian-read_ role\n when NOT in _plan_ mode\n invokes Terraform.apply with the _dalmatian-admin_ role\n when in _auto_approve_ mode\n asks Terraform to use auto_approve mode\n\nDalmatian::Rds\n #identifier\n uses rds identifier\n #in_use_by\n uses rds in_use_by list\n #clusters_in_use\n uses rds clusters_in_use list\n #instance_class\n uses rds instance_class\n #engine\n uses rds engine\n #engine_version\n uses the rds engine_version\n #allocated_storage\n uses the rds allocated_storage\n #storage_encrypted\n uses the rds storage_encrypted bool\n #storage_type\n uses the rds storage_type gp3\n #db_name\n uses the rds db_name\n #port\n uses the rds port\n #maintenance_window\n uses the rds maintenance_window\n #backup_window\n uses the rds backup_window\n #backup_retention_period\n uses the rds backup_retention_period\n #force_ssl\n uses the rds force_ssl bool\n #parameter_store_path_db_url_name\n uses the rds parameter_store_path_db_url_name\n #sql_backup_scheduled_task_environment_variables\n uses the rds sql_backup_scheduled_task_environment_variables\n #check_sql_backup_scheduled_task_environment_variables\n uses the rds check_sql_backup_scheduled_task_environment_variables\n #sync_sql_backup_to_azure\n will have offsite backups disabled by default\n #replication_bucket_destination_arn\n uses the rds replication_bucket_destination_arn\n #replication_kms_key_id\n uses the rds replication_kms_key_id\n #codebuild_access\n uses the rds codebuild_access\n #to_params\n provides a hash of attributes for use in deployment\n\nDalmatian::RdsTest\n #call\n changes to the ecs-services directory\n logs our intention to run Terraform init\n runs Terraform init, with upgrade option\n ensures presence of workspace\n logs our intention to run Terraform fmt\n runs Terraform fmt with check and diff options\n logs our intention to run Terraform validate\n runs Terraform validate, with upgrade option\n changes back to the app root directory\n\nDalmatian::RemoteReferenceValues\n when the reference is for a git repo\n returns a git shaped configuration\n if _filename_ is not present\n supplies the default of _dalmatian.yml_\n when the reference is for an S3 bucket\n returns an S3 shaped configuration\n if _key_ is not present\n supplies the default of _dalmatian.yml_\n when the reference is for a URL\n returns a git shaped configuration\n\nDalmatian::S3CacheHandler\n #call\n deletes any old cache\n uses the AWS S3 cmd to save the remote config to a local cache\n logs the cloning action\n logs the path to the cached configuration\n returns the cached full configuration to the caller (configuration reader)\n reads the cached full configuration from the disk in order to return to caller\n\nDalmatian::S3Deployment\n #call\n changes to s3 infrastructure directory\n asks Terraform to ensure that the workspace is in place\n when in _plan_ mode\n invokes Terraform.plan with the _dalmatian-read_ role\n when NOT in _plan_ mode\n invokes Terraform.apply with the _dalmatian-admin_ role\n when in _auto_approve_ mode\n asks Terraform to use auto_approve mode\n\nDalmatian::S3\n #name\n uses s3 name\n #enable_s3_versioning\n uses enable_s3_versioning bool\n #encrypted\n uses s3 encrypted bool\n #acl\n uses s3 acl\n #policy\n uses s3 policy\n #service_cloudfront_read_access\n uses s3 service_cloudfront_read_access\n #cloudfront\n uses s3 cloudfront\n #to_params\n provides a hash of attributes for use in deployment\n\nDalmatian::S3Test\n #call\n changes to the s3 directory\n logs our intention to run Terraform init\n runs Terraform init, with upgrade option\n ensures presence of workspace\n logs our intention to run Terraform fmt\n runs Terraform fmt with check and diff options\n logs our intention to run Terraform validate\n runs Terraform validate, with upgrade option\n changes back to the app root directory\n\nDalmatian::ServiceDeployment\n #call\n changes to ecs-services infrastructure directory\n asks Terraform to ensure that the workspace is in place\n when in _plan_ mode\n invokes Terraform.plan with the _dalmatian-read_ role\n when NOT in _plan_ mode\n invokes Terraform.apply with the _dalmatian-admin_ role\n when in _auto_approve_ mode\n asks Terraform to use auto_approve mode\n\nDalmatian::Service\n #name\n uses service name\n #blue_green\n uses the service blue_green map\n #parameter_store_path\n uses service parameter_store_path\n #parameter_store_key\n uses service parameter_store_key\n #daemon\n uses the service daemon bool\n #monitoring\n uses the service monitoring hash\n #cloudfront\n recasts the service config in environment groups\n includes the appropriate \"custom_origins\" values in each environment\n Uses an AWS cloudfront managed cache policy\n Uses an AWS cloudfront managed origin policy\n Uses an AWS cloudfront managed response headers policy\n mirroring of elements into each environment group\n includes the \"create\" value\n includes the \"tls_protocol_version\" value\n includes the \"origin_keepalive_timeout\" value\n includes the \"origin_read_timeout\" value\n includes the \"basic_auth\" value\n includes the \"basic_auth_users_extra\" value\n includes the \"viewer_request_functions\" values\n includes the \"offline_page_http_status\" value\n bypass_protection\n uses the \"bypass_protection\" configuration\n custom_behaviors\n converts list of \"path_patterns\" to a single \"path_pattern\"\n #shared_loadbalancer_name\n returns shared loadbalancer name if the service is in use by a shared loadbalancer\n returns empty string if the service is not in use by a shared loadbalancer\n #s3_policy\n uses the service s3_policy map\n #lb_ip_whitelistt\n uses the service lb_ip_whitelist list\n #lb_idle_timeout\n uses the service lb_idle_timeout\n #global_accelerator\n uses service global_accelerator value\n #health_check_path\n uses the service health_check_path\n #health_check_grace_period\n uses the service health_check_grace_period\n #deregistration_delay\n uses the service deregistration_delay\n #serve_from_subdirectory\n uses the service serve_from_subdirectory\n #domain_names\n groups the domain names from the service domain_list into environments\n #proxy_configuration\n groups the proxy configurations from the service proxy_configuration list into environments\n #home_directory\n uses the service home_directory\n #lb_ssl_certificate\n groups the certificate arns from the service lb_ssl_certificate list into environments\n #lb_ssl_policy\n sets the default ssl policy for each environment\n #cloudfront_ssl_certificate\n groups the certificate arns from the service cloudfront_ssl_certificate list into environments\n #image_source\n uses the service image source\n #launch_on\n uses the service 'launch_on' specification\n #launch_on_cluster\n uses the service 'launch_on_cluster' string\n #cluster_min_servers\n uses the service 'cluster_min_servers' string\n #image_location\n uses the service image location\n #track_revision\n uses the service track_revision string\n #custom_codestar_connection_arn\n uses the service custom_codestar_connection_arn\n #codepipeline_use_github_v1\n uses the service codepipeline_use_github_v1\n #codepipeline_codebuild_run_in_vpc\n uses the service codepipeline_codebuild_run_in_vpc\n #codepipeline_codebuild_use_service_env\n uses the service codepipeline_codebuild_use_service_env\n #buildspec\n uses the service buildspec\n #container_port\n uses the service container port\n #container_command\n uses the service container command\n #container_volumes\n uses the service container volumes\n #container_extra_hosts\n uses the service container extra hosts\n #container_count\n uses the service container_count\n #enable_max_one_container_per_instance\n uses the service enable_max_one_container_per_instance\n #scheduled_tasks\n uses the service scheduled tasks\n #workers\n uses the service workers\n #cluster_name\n delegates to the cluster\n #cluster_id\n delegates to the cluster\n #account_id\n delegates to the cluster\n #to_params\n provides a hash of attributes for use in deployment\n\nDalmatian::ServiceTest\n #call\n changes to the ecs-services directory\n logs our intention to run Terraform init\n runs Terraform init, with upgrade option\n ensures presence of workspace\n logs our intention to run Terraform fmt\n runs Terraform fmt with check and diff options\n logs our intention to run Terraform validate\n runs Terraform validate, with upgrade option\n changes back to the app root directory\n\nDalmatian::SharedLoadbalancerDeployment\n #call\n changes to shared-loadbalancer infrastructure directory\n asks Terraform to ensure that the workspace is in place\n when in _plan_ mode\n invokes Terraform.plan with the _dalmatian-read_ role\n when NOT in _plan_ mode\n invokes Terraform.apply with the _dalmatian-admin_ role\n when in _auto_approve_ mode\n asks Terraform to use auto_approve mode\n\nDalmatian::SharedLoadbalancer\n #name\n uses shared_loadbalancer name\n #in_use_by\n uses shared_loadbalancer in_use_by list\n #clusters_in_use\n uses shared_loadbalancer clusters_in_use list\n #subnets_name\n uses shared_loadbalancer subnets_name value\n #domain_names\n uses shared_loadbalancer domain_names list provided by Services\n #internal\n uses shared_loadbalancer internal value\n #ip_whitelist\n uses shared_loadbalancer ip_whitelist list\n #idle_timeout\n uses shared_loadbalancer idle_timeout value\n #global_accelerator\n uses shared_loadbalancer global_accelerator value\n #ssl_policy\n has the default ssl policy defined\n #to_params\n provides a hash of attributes for use in deployment\n\nDalmatian::SharedLoadbalancerTest\n #call\n changes to the shared-loadbalancer directory\n logs our intention to run Terraform init\n runs Terraform init, with upgrade option\n ensures presence of workspace\n logs our intention to run Terraform fmt\n runs Terraform fmt with check and diff options\n logs our intention to run Terraform validate\n runs Terraform validate, with upgrade option\n changes back to the app root directory\n\nDalmatian::SourceDeployment\n #call\n changes to infrastructure config directory\n asks Terraform to ensure that the workspace is in place\n when the environment includes a git reference as \"track_revision\"\n checks out that commit\n passes the \"track_revision\" reference along to Terraform\n when in _plan_ mode\n invokes Terraform.plan with the _dalmatian-read_ role\n when NOT in _plan_ mode\n invokes Terraform.apply with the _dalmatian-admin_ role\n when in _auto_approve_ mode\n asks Terraform to use auto_approve mode\n\nDalmatian::Source\n #name\n uses the cluster name and its own position in the cluster's list of sources\n #cluster_name\n delegates to the cluster\n #cluster_id\n delegates to the cluster\n #account_id\n delegates to the cluster\n\nDalmatian::SourceTest\n #call\n changes to the ecs directory\n logs our intention to run Terraform init\n runs Terraform init, with upgrade option\n ensures presence of workspace\n logs our intention to run Terraform fmt\n runs Terraform fmt with check and diff options\n logs our intention to run Terraform validate\n runs Terraform validate, with upgrade option\n changes back to the app root directory\n when the environment includes a git reference as \"track_revision\"\n checks out that commit\n passes the \"track_revision\" reference along to Terraform.validate\n\nDalmatian::Terraform\n ::init(upgrade: false)\n when asked to upgrade\n passes terraform init the upgrade flag\n when not asked to upgrade\n does not pass terraform init the upgrade flag\n ::fmt(args = nil)\n when passed some additional arguments\n passes terraform fmt the upgrade flag\n when passed NO additional arguments\n invokes terraform fmt with no arguments\n ::validate(tfvars)\n passes the given _var-file_ to terraform\n reformats the given tfvars and passes them to terraform as args\n ::ensure_presence_of_workspace(workspace_name)\n logs our intention to create the workspace\n asks Terraform to create the workspace\n when the workspace already exists (and an error is rescued)\n logs our intention to _select_ rather than _create_ the workspace\n asks Terraform to select the existing workspace\n ::plan(tfvars)\n passes the given _var-file_ to terraform\n reformats the given tfvars and passes them to terraform as args\n ::apply(tfvars, auto_approve=false)\n passes the given _var-file_ to terraform\n reformats the given tfvars and passes them to terraform as args\n when auto-approve is set to true\n passes the _auto-approve_ flag to terraform apply\n ::destroy(tfvars)\n passes the given _var-file_ to terraform\n reformats the given tfvars and passes them to terraform as args\n ::list_workspaces\n changes to the bootstrapping directory\n runs the terraform cmd to list workspaces\n\nDalmatian::UrlCacheHandler\n #call\n deletes any old cache\n uses the helper to GET a URI\n logs the cloning action\n logs the path to the cached configuration\n returns the cached full configuration to the caller (configuration reader)\n reads the cached full configuration from the disk in order to return to caller\n\nDalmatian::VpnCustomerGatewayDeployment\n #call\n changes to vpn-customer-gateway infrastructure directory\n asks Terraform to ensure that the workspace is in place\n when in _plan_ mode\n invokes Terraform.plan with the _dalmatian-read_ role\n when NOT in _plan_ mode\n invokes Terraform.apply with the _dalmatian-admin_ role\n when in _auto_approve_ mode\n asks Terraform to use auto_approve mode\n\nDalmatian::VpnCustomerGateway\n #name\n uses vpn_customer_gateway name\n #bgp_asn\n uses vpn_customer_gateway bgp_asn\n #ip_address\n uses vpn_customer_gateway ip_address\n #to_params\n provides a hash of attributes for use in deployment\n\nDalmatian::VpnCustomerGatewayTest\n #call\n changes to the vpn-customer-gateway directory\n logs our intention to run Terraform init\n runs Terraform init, with upgrade option\n ensures presence of workspace\n logs our intention to run Terraform fmt\n runs Terraform fmt with check and diff options\n logs our intention to run Terraform validate\n runs Terraform validate, with upgrade option\n changes back to the app root directory\n\nDalmatian::WAFDeployment\n #call\n changes to waf infrastructure directory\n asks Terraform to ensure that the workspace is in place\n when in _plan_ mode\n invokes Terraform.plan with the _dalmatian-read_ role\n when NOT in _plan_ mode\n invokes Terraform.apply with the _dalmatian-admin_ role\n when in _auto_approve_ mode\n asks Terraform to use auto_approve mode\n\nDalmatian::WAF\n #name\n uses waf name\n #action\n uses waf action\n #ip_deny_list\n has a list of IP addresses to block\n #aws_managed_rules\n uses waf aws_managed_rules list\n #associations\n uses waf associations list\n #to_params\n provides a hash of attributes for use in deployment\n\nDalmatian::WAFTest\n #call\n changes to the ecs-services directory\n logs our intention to run Terraform init\n runs Terraform init, with upgrade option\n ensures presence of workspace\n logs our intention to run Terraform fmt\n runs Terraform fmt with check and diff options\n logs our intention to run Terraform validate\n runs Terraform validate, with upgrade option\n changes back to the app root directory\n\nFinished in 3.32 seconds (files took 0.75242 seconds to load)\n478 examples, 0 failures\n\nCoverage report generated for RSpec to /Users/bob/git/dxw/dalmatian/coverage. 4310 / 4389 LOC (98.2%) covered.\n\n==> Linting markdown...\nProcess Group PGID: 49455"
|
|
}
|
|
}
|
|
}
|
|
],
|
|
"status": "success",
|
|
"timestamp": "2026-02-20T17:19:29.772Z",
|
|
"resultDisplay": "==> Linting YAML...\n\n==> Linting shell scripts...\n\n==> Checking Terraform for JSON errors...\n- Checking ./terraform/policies/iam-read.json... Passed\n- Checking ./terraform/policies/s3-rw-with-versioning.json... Passed\n- Checking ./terraform/policies/codestar-connection-use.json... Passed\n- Checking ./terraform/policies/iam-create-access-key.json... Passed\n- Checking ./terraform/policies/codebuild.json... Passed\n- Checking ./terraform/policies/kms-encrypt-decrypt.json... Passed\n- Checking ./terraform/policies/iam-change-password.json... Passed\n- Checking ./terraform/policies/administrator-access.json... Passed\n- Checking ./terraform/policies/assume_roles/aws-backup.json... Passed\n- Checking ./terraform/policies/assume_roles/autoscaling.json... Passed\n- Checking ./terraform/policies/assume_roles/events.json... Passed\n- Checking ./terraform/policies/assume_roles/ecs.json... Passed\n- Checking ./terraform/policies/assume_roles/codepipeline.json... Passed\n- Checking ./terraform/policies/iam-mfa.json... Passed\n- Checking ./terraform/policies/route53-read.json... Passed\n- Checking ./terraform/policies/s3-full-access.json... Passed\n- Checking ./terraform/policies/parameter-store-read-decrypt.json... Passed\n- Checking ./terraform/policies/s3-read.json... Passed\n- Checking ./terraform/policies/parameter-store-RW-encrypt-decrypt.json... Passed\n- Checking ./terraform/policies/all-read-with-billing.json... Passed\n- Checking ./terraform/policies/codebuild-start-build.json... Passed\n- Checking ./terraform/policies/all-read.json... Passed\n\n==> Linting Terraform...\n\n==> Running Ruby tests...\n/Users/bob/.rbenv/versions/2.7.1/bin/ruby -I/Users/bob/.bundles/ruby/2.7.0/gems/rspec-core-3.12.2/lib:/Users/bob/.bundles/ruby/2.7.0/gems/rspec-support-3.12.1/lib /Users/bob/.bundles/ruby/2.7.0/gems/rspec-core-3.12.2/exe/rspec --pattern spec/\\*\\*\\{,/\\*/\\*\\*\\}/\\*_spec.rb\n\ntests local configuration\n use of \"terraform apply\"\n passes the hosted zone config to \"terraform apply\"\n passes the s3 config to \"terraform apply\"\n passes the vpn customer gateway config to \"terraform apply\"\n passes the base config to \"terraform apply\"\n passes the waf config to \"terraform apply\"\n passes the rds config to \"terraform apply\"\n passes the elasticache config to \"terraform apply\"\n passes the opensearch config to \"terraform apply\"\n passes the service config to \"terraform apply\"\n passes the loadbalancer config to \"terraform apply\"\n passes the cluster 2 config to \"terraform apply\"\n passes the cluster 3 config to \"terraform apply\"\n passes the cluster 4 config to \"terraform apply\"\n\ntests remote configuration\n retrieves the remotely held full configuration\n proceeds with deploying the infrastructure as per the cached full configuration\n\ntests local configuration\n invokes \"terraform validate\" with the expected cluster options\n invokes \"terraform validate\" with the expected source options\n use of \"terraform plan\"\n passes the hosted zone config to \"terraform plan\"\n passes the s3 config to \"terraform plan\"\n passes the vpn customer gateway config to \"terraform plan\"\n passes the base config to \"terraform plan\"\n passes the waf config to \"terraform plan\"\n passes the rds config to \"terraform plan\"\n passes the elasticache config to \"terraform plan\"\n passes the opensearch config to \"terraform plan\"\n passes the services config to \"terraform plan\"\n passes the loadbalancer config to \"terraform plan\"\n passes the cluster 2 config to \"terraform plan\"\n passes the cluster 3 config to \"terraform plan\"\n passes the cluster 4 config to \"terraform plan\"\n\nDalmatian::Account\n initialisation\n gathering user input\n asks the user for AWS credentials\n asks the user for the AWS account id to use\n asks the user for an account alias\n #call\n changes to the bootstrapping directory\n runs terraform init with upgrade option\n creates the new workspace using the given aws account id and alias\n runs terraform apply with the user-supplied vars\n\nDalmatian::CacheHandlerSelector\n ::new_for(remote_reference)\n when the remote reference is for a git repo\n asks for an instance of GitCacheHandler\n when the remote reference is for an S3 bucket\n asks for an instance of S3CacheHandler\n when the remote reference is for a URL\n asks for an instance of UrlCacheHandler\n when the type is unknown\n raises an error\n\nCacheHandler\n when a subclass class does not implement #cache_remote_configuration\n raises a helpful error\n\nDalmatian::CI\n CI::PATH\n is a constant\n #deploy\n changes to the ci directory\n runs terraform init with upgrade option\n creates the new workspace using the given aws account id and alias\n runs terraform apply with the user-supplied vars\n #test\n runs terraform plan with the user-supplied vars\n\nDalmatian::ClusterDeployment\n #call\n changes to the ecs directory\n asks Terraform to ensure that the workspace is in place\n when the environment includes a git reference as \"track_revision\"\n does NOT attempt to check out that commit\n when in _plan_ mode\n invokes Terraform.plan using the _dalmatian-read_ role\n when NOT in _plan_ mode\n invokes Terraform.apply using the _dalmatian-admin_\n when in _auto_approve_ mode\n asks Terraform to use auto_approve mode\n\nDalmatian::Cluster\n on initialisation\n makes Hosted zones, S3, Sources, Services, Loadbalancers, WAF and Rds\n #target_directory\n is a standard _ecs_ path\n #id\n is the primary key of the cluster definition is used\n #name\n when the cluster has an explicitly provided _name_ property\n that property is used\n when the cluster does not have an explicitly provided _name_ property\n the primary key of the cluster definition is used\n #account_id\n is the aws account key for deployment\n #sources\n represents any links to remote sources\n #environments\n represents the attributes of each environment's cluster section\n #fetch\n when the source is remotely held\n logs the plan to clone the source into the infrastructure pth\n deletes any existing source at the infrastructure location\n clones each source into the infrastructure location\n changes to the infrastructure directory for each source\n runs rake terrafile\n changes back to the APP_ROOT\n when the source is a local file path\n does not re-clone the source\n does not run terrafile\n when the specified local directory exists\n logs the fact that the local source is in place\n when the specificed local directory does not exist\n logs an error that the local source is missing\n #deploy\n deploys source infrastructure for each source and each service in each environment\n when a cluster should be created\n deploys cluster infrastructure for each environment\n when the _plan_ option IS invoked\n creates Cluster Deployments with plan settings\n when the _auto_approve_ option IS invoked\n creates Cluster Deployments with auto_approve settings\n handling of tests\n when the _test_ option is NOT invoked\n does not run cluster tests\n does not run cluster tests\n does not run cluster tests\n does not run source tests\n does not run waf tests\n does not run rds tests\n does not run service tests\n does not run service tests\n when the test option IS invoked\n runs tests\n when a cluster should NOT be created\n does not deploy cluster infrastructure\n when test option is invoked\n tests sources and services for each environment\n\nDalmatian::ClusterTest\n #call\n changes to the ecs directory\n logs our intention to run Terraform init\n runs Terraform init, with upgrade option\n ensures presence of workspace\n logs our intention to run Terraform fmt\n runs Terraform fmt with check and diff options\n logs our intention to run Terraform validate\n runs Terraform validate, with upgrade option\n changes back to the app root directory\n when the environment includes a git reference as \"track_revision\"\n does NOT attempt to check out that commit\n\nDalmatian::ConfigurationReader\n when a full configuration is provided in a local file\n #call\n has no need to use a cache handler\n returns the loaded configuration\n when a reference to a remote configuration is provided\n and the reference is provided in a local file\n uses the CacheHandlerSelector to provide the appropriate retrieval mechanism\n calls on the selected cache handler\n returns the configuration returned by the cache_handler\n and the reference is provided using environment variables\n passes the provided remote reference to the CacheHandlerSelector\n and references are provided in both environment variables and config file\n prefers the environment variable references over the config file\n and no references are provided\n raises an error\n and the remote reference is missing its _type_\n raises an error\n #ci\n when a parameter path prefix is given\n overwrites the ci:variables config with those retrieved from the param store\n leaves other ci:variables in place\n when a parameter path prefix is NOT given\n does NOT overwrite any ci:variables from the param store\n\nDalmatian::ElasticacheCluster\n #identifier\n uses elasticache identifier\n #in_use_by\n uses elasticache_cluster in_use_by list\n #node_type\n uses elasticache_cluster node_type\n #node_count\n uses elasticache_cluster node_count\n #engine\n uses elasticache_cluster engine\n #engine_version\n uses the elasticache_cluster engine_version\n #parameters\n uses the elasticache_cluster parameters list\n #port\n uses the elasticache_cluster port\n #maintenance_window\n uses the elasticache_cluster maintenance_window\n #snapshot_window\n uses the elasticache_cluster snapshot_window\n #parameter_store_path_elasticache_cluster_url_name\n uses the elasticache_cluster parameter_store_path_elasticache_cluster_url_name\n #to_params\n provides a hash of attributes for use in deployment\n\nDalmatian::ElasticacheClusterTest\n #call\n changes to the elasticache-cluster directory\n logs our intention to run Terraform init\n runs Terraform init, with upgrade option\n ensures presence of workspace\n logs our intention to run Terraform fmt\n runs Terraform fmt with check and diff options\n logs our intention to run Terraform validate\n runs Terraform validate, with upgrade option\n changes back to the app root directory\n\nDalmatian::GitCacheHandler\n #call\n deletes any old cache\n uses git clone to save the remote config to a local cache\n logs the cloning action\n logs the path to the cached configuration\n returns the cached full configuration to the caller (configuration reader)\n reads the cached full configuration from the disk in order to return to caller\n when no special cache path is given\n uses the default cache path of ./.dalmatian_cache/remote_config\n\nDalmatian::Helper\n ::git_clone(source, destination)\n when source and destination args are not provided\n raises an error with usage info\n when given source and destination args\n passes the request to the git CLI\n ::git_checkout(revision)\n checks out the given revision using run!\n ::get(source, destination)\n when source and destination args are not provided\n raises an error with usage info\n when given source and destination args\n opens the source url\n opens a new file at the destination\n writes the source resource into that file\n reads the information from the fetched resource\n ::run!\n passes given cmd to Kernel.system\n when the call to Kernel.system returns _false_\n raise a helpful error\n ::run_with_output!(cmd)\n passes given cmd to Open3.capture3\n when the system call returns a zero exit status\n returns the systems output to STDOUT\n when the system call returns a non-zero exit status\n also returns STDOUT ignoring the exit code and STDERR\n when the system call raises an ENOENT error\n catches this and raises a helpful Error\n ::change_to(path)\n passes the given path to Dir.chdir\n ::to_bool(str)\n when given nil\n returns false\n when given an empty string\n returns false\n when given lower case string _true_\n returns true\n when given mixed case string _True_\n returns true\n when given the object true\n returns true\n when given the object false\n returns false\n ::tflint\n runs the tflint cmd\n ::terrafile\n runs rake terrafile\n ::ask\n delegates to HighLine#ask\n ::ask_in_confidence\n delegates to HighLine#ask\n passes a block to mask the answer\n\nDalmatian::HostedZoneDeployment\n #call\n changes to hosted-zone infrastructure directory\n asks Terraform to ensure that the workspace is in place\n when in _plan_ mode\n invokes Terraform.plan with the _dalmatian-read_ role\n when NOT in _plan_ mode\n invokes Terraform.apply with the _dalmatian-admin_ role\n when in _auto_approve_ mode\n asks Terraform to use auto_approve mode\n\nDalmatian::HostedZone\n #domain\n uses hosted_zone domain\n #ns_records\n uses hosted_zone ns_records\n #a_records\n uses hosted_zone a_records\n #alias_records\n uses hosted_zone alias_records\n #cname_records\n uses hosted_zone cname_records\n #mx_records\n uses hosted_zone mx_records\n #txt_records\n uses hosted_zone txt_records\n #srv_records\n uses hosted_zone srv_records\n #to_params\n provides a hash of attributes for use in deployment\n\nDalmatian::HostedZoneTest\n #call\n changes to the hosted-zone directory\n logs our intention to run Terraform init\n runs Terraform init, with upgrade option\n ensures presence of workspace\n logs our intention to run Terraform fmt\n runs Terraform fmt with check and diff options\n logs our intention to run Terraform validate\n runs Terraform validate, with upgrade option\n changes back to the app root directory\n\nDalmatian::Infrastructure\n Infrastructure::PATH\n is a constant\n Infrastructure::APP_ROOT\n is a constant\n initialisation\n when configuration is not provided\n builds one using the defaults\n #clusters\n creates one cluster for each cluster description provided\n key operations on clusters\n #fetch\n asks all clusters to #fetch\n #test\n asks all clusters to #deploy with _plan_ and _test_ options\n #deploy\n when no parameters given\n asks all clusters to #deploy with _plan_, _test_ and _auto-approve_ disabled\n when parameters are given\n asks all clusters to #deploy with the given options\n when a particular infrastructure is named for deployment\n asks only the named cluster to #deploy with the given options\n\nDalmatian::Logger\n ::error(msg)\n raises an error with a red message\n ::info(msg)\n puts the given given message in white\n ::success(msg)\n puts the given given message in green\n ::warn(msg)\n puts the given given message in yellow\n\nDalmatian::OpensearchCluster\n #identifier\n uses opensearch identifier\n #in_use_by\n uses opensearch_cluster in_use_by list\n #version\n uses opensearch_cluster version\n #master_enabled\n uses opensearch_cluster master_enabled bool\n #master_count\n uses opensearch_cluster master_count\n #master_type\n uses opensearch_cluster master_type\n #instance_count\n uses opensearch_cluster instance_count\n #instance_type\n uses opensearch_cluster instance_type\n #warm_enabled\n uses opensearch_cluster warm_enabled bool\n #warm_count\n uses opensearch_cluster warm_count\n #warm_type\n uses opensearch_cluster warm_type\n #parameter_store_path_opensearch_cluster_url_name\n uses opensearch_cluster parameter_store_path_opensearch_cluster_url_name\n #volume_size\n uses opensearch_cluster volume_size\n #to_params\n provides a hash of attributes for use in deployment\n\nDalmatian::OpensearchClusterTest\n #call\n changes to the opensearch-cluster directory\n logs our intention to run Terraform init\n runs Terraform init, with upgrade option\n ensures presence of workspace\n logs our intention to run Terraform fmt\n runs Terraform fmt with check and diff options\n logs our intention to run Terraform validate\n runs Terraform validate, with upgrade option\n changes back to the app root directory\n\nDalmatian::ParameterStore\n ::get_parameter(name: \"\", with_decryption: true)\n when getting a single parameter from Parameter Store\n runs aws ssm get-parameter\n ::get_parameters_by_path(path: \"\", with_decryption: true)\n when getting parameters by path from Parameter Store\n runs aws ssm get-parameter\n\nDalmatian::RdsDeployment\n #call\n changes to rds infrastructure directory\n asks Terraform to ensure that the workspace is in place\n when in _plan_ mode\n invokes Terraform.plan with the _dalmatian-read_ role\n when NOT in _plan_ mode\n invokes Terraform.apply with the _dalmatian-admin_ role\n when in _auto_approve_ mode\n asks Terraform to use auto_approve mode\n\nDalmatian::Rds\n #identifier\n uses rds identifier\n #in_use_by\n uses rds in_use_by list\n #clusters_in_use\n uses rds clusters_in_use list\n #instance_class\n uses rds instance_class\n #engine\n uses rds engine\n #engine_version\n uses the rds engine_version\n #allocated_storage\n uses the rds allocated_storage\n #storage_encrypted\n uses the rds storage_encrypted bool\n #storage_type\n uses the rds storage_type gp3\n #db_name\n uses the rds db_name\n #port\n uses the rds port\n #maintenance_window\n uses the rds maintenance_window\n #backup_window\n uses the rds backup_window\n #backup_retention_period\n uses the rds backup_retention_period\n #force_ssl\n uses the rds force_ssl bool\n #parameter_store_path_db_url_name\n uses the rds parameter_store_path_db_url_name\n #sql_backup_scheduled_task_environment_variables\n uses the rds sql_backup_scheduled_task_environment_variables\n #check_sql_backup_scheduled_task_environment_variables\n uses the rds check_sql_backup_scheduled_task_environment_variables\n #sync_sql_backup_to_azure\n will have offsite backups disabled by default\n #replication_bucket_destination_arn\n uses the rds replication_bucket_destination_arn\n #replication_kms_key_id\n uses the rds replication_kms_key_id\n #codebuild_access\n uses the rds codebuild_access\n #to_params\n provides a hash of attributes for use in deployment\n\nDalmatian::RdsTest\n #call\n changes to the ecs-services directory\n logs our intention to run Terraform init\n runs Terraform init, with upgrade option\n ensures presence of workspace\n logs our intention to run Terraform fmt\n runs Terraform fmt with check and diff options\n logs our intention to run Terraform validate\n runs Terraform validate, with upgrade option\n changes back to the app root directory\n\nDalmatian::RemoteReferenceValues\n when the reference is for a git repo\n returns a git shaped configuration\n if _filename_ is not present\n supplies the default of _dalmatian.yml_\n when the reference is for an S3 bucket\n returns an S3 shaped configuration\n if _key_ is not present\n supplies the default of _dalmatian.yml_\n when the reference is for a URL\n returns a git shaped configuration\n\nDalmatian::S3CacheHandler\n #call\n deletes any old cache\n uses the AWS S3 cmd to save the remote config to a local cache\n logs the cloning action\n logs the path to the cached configuration\n returns the cached full configuration to the caller (configuration reader)\n reads the cached full configuration from the disk in order to return to caller\n\nDalmatian::S3Deployment\n #call\n changes to s3 infrastructure directory\n asks Terraform to ensure that the workspace is in place\n when in _plan_ mode\n invokes Terraform.plan with the _dalmatian-read_ role\n when NOT in _plan_ mode\n invokes Terraform.apply with the _dalmatian-admin_ role\n when in _auto_approve_ mode\n asks Terraform to use auto_approve mode\n\nDalmatian::S3\n #name\n uses s3 name\n #enable_s3_versioning\n uses enable_s3_versioning bool\n #encrypted\n uses s3 encrypted bool\n #acl\n uses s3 acl\n #policy\n uses s3 policy\n #service_cloudfront_read_access\n uses s3 service_cloudfront_read_access\n #cloudfront\n uses s3 cloudfront\n #to_params\n provides a hash of attributes for use in deployment\n\nDalmatian::S3Test\n #call\n changes to the s3 directory\n logs our intention to run Terraform init\n runs Terraform init, with upgrade option\n ensures presence of workspace\n logs our intention to run Terraform fmt\n runs Terraform fmt with check and diff options\n logs our intention to run Terraform validate\n runs Terraform validate, with upgrade option\n changes back to the app root directory\n\nDalmatian::ServiceDeployment\n #call\n changes to ecs-services infrastructure directory\n asks Terraform to ensure that the workspace is in place\n when in _plan_ mode\n invokes Terraform.plan with the _dalmatian-read_ role\n when NOT in _plan_ mode\n invokes Terraform.apply with the _dalmatian-admin_ role\n when in _auto_approve_ mode\n asks Terraform to use auto_approve mode\n\nDalmatian::Service\n #name\n uses service name\n #blue_green\n uses the service blue_green map\n #parameter_store_path\n uses service parameter_store_path\n #parameter_store_key\n uses service parameter_store_key\n #daemon\n uses the service daemon bool\n #monitoring\n uses the service monitoring hash\n #cloudfront\n recasts the service config in environment groups\n includes the appropriate \"custom_origins\" values in each environment\n Uses an AWS cloudfront managed cache policy\n Uses an AWS cloudfront managed origin policy\n Uses an AWS cloudfront managed response headers policy\n mirroring of elements into each environment group\n includes the \"create\" value\n includes the \"tls_protocol_version\" value\n includes the \"origin_keepalive_timeout\" value\n includes the \"origin_read_timeout\" value\n includes the \"basic_auth\" value\n includes the \"basic_auth_users_extra\" value\n includes the \"viewer_request_functions\" values\n includes the \"offline_page_http_status\" value\n bypass_protection\n uses the \"bypass_protection\" configuration\n custom_behaviors\n converts list of \"path_patterns\" to a single \"path_pattern\"\n #shared_loadbalancer_name\n returns shared loadbalancer name if the service is in use by a shared loadbalancer\n returns empty string if the service is not in use by a shared loadbalancer\n #s3_policy\n uses the service s3_policy map\n #lb_ip_whitelistt\n uses the service lb_ip_whitelist list\n #lb_idle_timeout\n uses the service lb_idle_timeout\n #global_accelerator\n uses service global_accelerator value\n #health_check_path\n uses the service health_check_path\n #health_check_grace_period\n uses the service health_check_grace_period\n #deregistration_delay\n uses the service deregistration_delay\n #serve_from_subdirectory\n uses the service serve_from_subdirectory\n #domain_names\n groups the domain names from the service domain_list into environments\n #proxy_configuration\n groups the proxy configurations from the service proxy_configuration list into environments\n #home_directory\n uses the service home_directory\n #lb_ssl_certificate\n groups the certificate arns from the service lb_ssl_certificate list into environments\n #lb_ssl_policy\n sets the default ssl policy for each environment\n #cloudfront_ssl_certificate\n groups the certificate arns from the service cloudfront_ssl_certificate list into environments\n #image_source\n uses the service image source\n #launch_on\n uses the service 'launch_on' specification\n #launch_on_cluster\n uses the service 'launch_on_cluster' string\n #cluster_min_servers\n uses the service 'cluster_min_servers' string\n #image_location\n uses the service image location\n #track_revision\n uses the service track_revision string\n #custom_codestar_connection_arn\n uses the service custom_codestar_connection_arn\n #codepipeline_use_github_v1\n uses the service codepipeline_use_github_v1\n #codepipeline_codebuild_run_in_vpc\n uses the service codepipeline_codebuild_run_in_vpc\n #codepipeline_codebuild_use_service_env\n uses the service codepipeline_codebuild_use_service_env\n #buildspec\n uses the service buildspec\n #container_port\n uses the service container port\n #container_command\n uses the service container command\n #container_volumes\n uses the service container volumes\n #container_extra_hosts\n uses the service container extra hosts\n #container_count\n uses the service container_count\n #enable_max_one_container_per_instance\n uses the service enable_max_one_container_per_instance\n #scheduled_tasks\n uses the service scheduled tasks\n #workers\n uses the service workers\n #cluster_name\n delegates to the cluster\n #cluster_id\n delegates to the cluster\n #account_id\n delegates to the cluster\n #to_params\n provides a hash of attributes for use in deployment\n\nDalmatian::ServiceTest\n #call\n changes to the ecs-services directory\n logs our intention to run Terraform init\n runs Terraform init, with upgrade option\n ensures presence of workspace\n logs our intention to run Terraform fmt\n runs Terraform fmt with check and diff options\n logs our intention to run Terraform validate\n runs Terraform validate, with upgrade option\n changes back to the app root directory\n\nDalmatian::SharedLoadbalancerDeployment\n #call\n changes to shared-loadbalancer infrastructure directory\n asks Terraform to ensure that the workspace is in place\n when in _plan_ mode\n invokes Terraform.plan with the _dalmatian-read_ role\n when NOT in _plan_ mode\n invokes Terraform.apply with the _dalmatian-admin_ role\n when in _auto_approve_ mode\n asks Terraform to use auto_approve mode\n\nDalmatian::SharedLoadbalancer\n #name\n uses shared_loadbalancer name\n #in_use_by\n uses shared_loadbalancer in_use_by list\n #clusters_in_use\n uses shared_loadbalancer clusters_in_use list\n #subnets_name\n uses shared_loadbalancer subnets_name value\n #domain_names\n uses shared_loadbalancer domain_names list provided by Services\n #internal\n uses shared_loadbalancer internal value\n #ip_whitelist\n uses shared_loadbalancer ip_whitelist list\n #idle_timeout\n uses shared_loadbalancer idle_timeout value\n #global_accelerator\n uses shared_loadbalancer global_accelerator value\n #ssl_policy\n has the default ssl policy defined\n #to_params\n provides a hash of attributes for use in deployment\n\nDalmatian::SharedLoadbalancerTest\n #call\n changes to the shared-loadbalancer directory\n logs our intention to run Terraform init\n runs Terraform init, with upgrade option\n ensures presence of workspace\n logs our intention to run Terraform fmt\n runs Terraform fmt with check and diff options\n logs our intention to run Terraform validate\n runs Terraform validate, with upgrade option\n changes back to the app root directory\n\nDalmatian::SourceDeployment\n #call\n changes to infrastructure config directory\n asks Terraform to ensure that the workspace is in place\n when the environment includes a git reference as \"track_revision\"\n checks out that commit\n passes the \"track_revision\" reference along to Terraform\n when in _plan_ mode\n invokes Terraform.plan with the _dalmatian-read_ role\n when NOT in _plan_ mode\n invokes Terraform.apply with the _dalmatian-admin_ role\n when in _auto_approve_ mode\n asks Terraform to use auto_approve mode\n\nDalmatian::Source\n #name\n uses the cluster name and its own position in the cluster's list of sources\n #cluster_name\n delegates to the cluster\n #cluster_id\n delegates to the cluster\n #account_id\n delegates to the cluster\n\nDalmatian::SourceTest\n #call\n changes to the ecs directory\n logs our intention to run Terraform init\n runs Terraform init, with upgrade option\n ensures presence of workspace\n logs our intention to run Terraform fmt\n runs Terraform fmt with check and diff options\n logs our intention to run Terraform validate\n runs Terraform validate, with upgrade option\n changes back to the app root directory\n when the environment includes a git reference as \"track_revision\"\n checks out that commit\n passes the \"track_revision\" reference along to Terraform.validate\n\nDalmatian::Terraform\n ::init(upgrade: false)\n when asked to upgrade\n passes terraform init the upgrade flag\n when not asked to upgrade\n does not pass terraform init the upgrade flag\n ::fmt(args = nil)\n when passed some additional arguments\n passes terraform fmt the upgrade flag\n when passed NO additional arguments\n invokes terraform fmt with no arguments\n ::validate(tfvars)\n passes the given _var-file_ to terraform\n reformats the given tfvars and passes them to terraform as args\n ::ensure_presence_of_workspace(workspace_name)\n logs our intention to create the workspace\n asks Terraform to create the workspace\n when the workspace already exists (and an error is rescued)\n logs our intention to _select_ rather than _create_ the workspace\n asks Terraform to select the existing workspace\n ::plan(tfvars)\n passes the given _var-file_ to terraform\n reformats the given tfvars and passes them to terraform as args\n ::apply(tfvars, auto_approve=false)\n passes the given _var-file_ to terraform\n reformats the given tfvars and passes them to terraform as args\n when auto-approve is set to true\n passes the _auto-approve_ flag to terraform apply\n ::destroy(tfvars)\n passes the given _var-file_ to terraform\n reformats the given tfvars and passes them to terraform as args\n ::list_workspaces\n changes to the bootstrapping directory\n runs the terraform cmd to list workspaces\n\nDalmatian::UrlCacheHandler\n #call\n deletes any old cache\n uses the helper to GET a URI\n logs the cloning action\n logs the path to the cached configuration\n returns the cached full configuration to the caller (configuration reader)\n reads the cached full configuration from the disk in order to return to caller\n\nDalmatian::VpnCustomerGatewayDeployment\n #call\n changes to vpn-customer-gateway infrastructure directory\n asks Terraform to ensure that the workspace is in place\n when in _plan_ mode\n invokes Terraform.plan with the _dalmatian-read_ role\n when NOT in _plan_ mode\n invokes Terraform.apply with the _dalmatian-admin_ role\n when in _auto_approve_ mode\n asks Terraform to use auto_approve mode\n\nDalmatian::VpnCustomerGateway\n #name\n uses vpn_customer_gateway name\n #bgp_asn\n uses vpn_customer_gateway bgp_asn\n #ip_address\n uses vpn_customer_gateway ip_address\n #to_params\n provides a hash of attributes for use in deployment\n\nDalmatian::VpnCustomerGatewayTest\n #call\n changes to the vpn-customer-gateway directory\n logs our intention to run Terraform init\n runs Terraform init, with upgrade option\n ensures presence of workspace\n logs our intention to run Terraform fmt\n runs Terraform fmt with check and diff options\n logs our intention to run Terraform validate\n runs Terraform validate, with upgrade option\n changes back to the app root directory\n\nDalmatian::WAFDeployment\n #call\n changes to waf infrastructure directory\n asks Terraform to ensure that the workspace is in place\n when in _plan_ mode\n invokes Terraform.plan with the _dalmatian-read_ role\n when NOT in _plan_ mode\n invokes Terraform.apply with the _dalmatian-admin_ role\n when in _auto_approve_ mode\n asks Terraform to use auto_approve mode\n\nDalmatian::WAF\n #name\n uses waf name\n #action\n uses waf action\n #ip_deny_list\n has a list of IP addresses to block\n #aws_managed_rules\n uses waf aws_managed_rules list\n #associations\n uses waf associations list\n #to_params\n provides a hash of attributes for use in deployment\n\nDalmatian::WAFTest\n #call\n changes to the ecs-services directory\n logs our intention to run Terraform init\n runs Terraform init, with upgrade option\n ensures presence of workspace\n logs our intention to run Terraform fmt\n runs Terraform fmt with check and diff options\n logs our intention to run Terraform validate\n runs Terraform validate, with upgrade option\n changes back to the app root directory\n\nFinished in 3.32 seconds (files took 0.75242 seconds to load)\n478 examples, 0 failures\n\nCoverage report generated for RSpec to /Users/bob/git/dxw/dalmatian/coverage. 4310 / 4389 LOC (98.2%) covered.\n\n==> Linting markdown...",
|
|
"displayName": "Shell",
|
|
"description": "This tool executes a given shell command as `bash -c <command>`. To run a command in the background, set the `is_background` parameter to true. Do NOT use `&` to background commands. Command is executed as a subprocess that leads its own process group. Command process group can be terminated as `kill -- -PGID` or signaled as `kill -s SIGNAL -- -PGID`.\n\n Efficiency Guidelines:\n - Quiet Flags: Always prefer silent or quiet flags (e.g., `npm install --silent`, `git --no-pager`) to reduce output volume while still capturing necessary information.\n - Pagination: Always disable terminal pagination to ensure commands terminate (e.g., use `git --no-pager`, `systemctl --no-pager`, or set `PAGER=cat`).\n\n The following information is returned:\n\n Output: Combined stdout/stderr. Can be `(empty)` or partial on error and for any unwaited background processes.\n Exit Code: Only included if non-zero (command failed).\n Error: Only included if a process-level error occurred (e.g., spawn failure).\n Signal: Only included if process was terminated by a signal.\n Background PIDs: Only included if background processes were started.\n Process Group PGID: Only included if available.",
|
|
"renderOutputAsMarkdown": false
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"id": "54af8b8a-bb5a-4aa4-9cf3-28c2a0fc0be2",
|
|
"timestamp": "2026-02-20T17:19:34.048Z",
|
|
"type": "gemini",
|
|
"content": "Tests and linters passed. I'm done.\n\nI have fixed the test failures in the Dalmatian project. The failures were primarily caused by missing RDS parameters (`replication_bucket_destination_arn` and `replication_kms_key_id`) in several integration and unit tests after recent code changes. I also identified and resolved a separate issue where `Dalmatian::RdsTest` was manually building its configuration hash instead of using the `to_params` method, which led to inconsistencies.\n\nSummary of changes:\n1. **Updated `lib/dalmatian/rds_test.rb`**: Refactored `RdsTest#env_config` to use `rds.to_params` for building the RDS configuration hash, ensuring consistency with `RdsDeployment`.\n2. **Updated `spec/unit/rds_test_spec.rb`**: Stubbed `to_params` on the `rds` mock and updated test expectations to include the new replication fields.\n3. **Updated `spec/integration/tests_local_configuration_spec.rb`**: Added the missing RDS parameters to all relevant `let` definitions for terraform validate and plan commands.\n4. **Updated `spec/integration/deploys_local_configuration_spec.rb`**: Added the missing RDS parameters to the `let` definitions for terraform apply commands.\n5. **Fixed `docs/database-backups.md`**: Removed git conflict markers and duplicated content that were causing markdown linting failures.\n\nAll 478 Ruby tests now pass, and all linters (YAML, shell, Terraform, and Markdown) are successful.",
|
|
"thoughts": [
|
|
{
|
|
"subject": "Wrapping Up Analysis",
|
|
"description": "I've completed all tests, and the linters have given a clean bill of health. The markdown linter's silence confirms all's well. I can confidently say that my work on this is finished.",
|
|
"timestamp": "2026-02-20T17:19:32.546Z"
|
|
}
|
|
],
|
|
"tokens": {
|
|
"input": 112325,
|
|
"output": 352,
|
|
"cached": 103598,
|
|
"thoughts": 29,
|
|
"tool": 0,
|
|
"total": 112706
|
|
},
|
|
"model": "gemini-3-flash-preview"
|
|
}
|
|
]
|
|
} |