cloud-mu 1.9.0.pre.beta → 2.0.0.pre.alpha

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (114) hide show
  1. checksums.yaml +4 -4
  2. data/Berksfile +16 -54
  3. data/Berksfile.lock +14 -62
  4. data/bin/mu-aws-setup +131 -108
  5. data/bin/mu-configure +311 -74
  6. data/bin/mu-gcp-setup +84 -62
  7. data/bin/mu-load-config.rb +46 -2
  8. data/bin/mu-self-update +11 -9
  9. data/bin/mu-upload-chef-artifacts +4 -4
  10. data/{mu.gemspec → cloud-mu.gemspec} +2 -2
  11. data/cookbooks/awscli/Berksfile +8 -0
  12. data/cookbooks/mu-activedirectory/Berksfile +11 -0
  13. data/cookbooks/mu-firewall/Berksfile +9 -0
  14. data/cookbooks/mu-firewall/metadata.rb +1 -1
  15. data/cookbooks/mu-glusterfs/Berksfile +10 -0
  16. data/cookbooks/mu-jenkins/Berksfile +14 -0
  17. data/cookbooks/mu-master/Berksfile +23 -0
  18. data/cookbooks/mu-master/attributes/default.rb +1 -1
  19. data/cookbooks/mu-master/metadata.rb +2 -2
  20. data/cookbooks/mu-master/recipes/default.rb +1 -1
  21. data/cookbooks/mu-master/recipes/init.rb +7 -3
  22. data/cookbooks/mu-master/recipes/ssl-certs.rb +1 -0
  23. data/cookbooks/mu-mongo/Berksfile +10 -0
  24. data/cookbooks/mu-openvpn/Berksfile +11 -0
  25. data/cookbooks/mu-php54/Berksfile +13 -0
  26. data/cookbooks/mu-splunk/Berksfile +10 -0
  27. data/cookbooks/mu-tools/Berksfile +21 -0
  28. data/cookbooks/mu-tools/files/default/Mu_CA.pem +15 -15
  29. data/cookbooks/mu-utility/Berksfile +9 -0
  30. data/cookbooks/mu-utility/metadata.rb +2 -1
  31. data/cookbooks/nagios/Berksfile +7 -4
  32. data/cookbooks/s3fs/Berksfile +9 -0
  33. data/environments/dev.json +6 -6
  34. data/environments/prod.json +6 -6
  35. data/modules/mu.rb +20 -42
  36. data/modules/mu/cleanup.rb +102 -100
  37. data/modules/mu/cloud.rb +90 -28
  38. data/modules/mu/clouds/aws.rb +449 -218
  39. data/modules/mu/clouds/aws/alarm.rb +29 -17
  40. data/modules/mu/clouds/aws/cache_cluster.rb +78 -64
  41. data/modules/mu/clouds/aws/collection.rb +25 -18
  42. data/modules/mu/clouds/aws/container_cluster.rb +73 -66
  43. data/modules/mu/clouds/aws/database.rb +124 -116
  44. data/modules/mu/clouds/aws/dnszone.rb +27 -20
  45. data/modules/mu/clouds/aws/firewall_rule.rb +30 -22
  46. data/modules/mu/clouds/aws/folder.rb +18 -3
  47. data/modules/mu/clouds/aws/function.rb +77 -23
  48. data/modules/mu/clouds/aws/group.rb +19 -12
  49. data/modules/mu/clouds/aws/habitat.rb +153 -0
  50. data/modules/mu/clouds/aws/loadbalancer.rb +59 -52
  51. data/modules/mu/clouds/aws/log.rb +30 -23
  52. data/modules/mu/clouds/aws/msg_queue.rb +29 -20
  53. data/modules/mu/clouds/aws/notifier.rb +222 -0
  54. data/modules/mu/clouds/aws/role.rb +178 -90
  55. data/modules/mu/clouds/aws/search_domain.rb +40 -24
  56. data/modules/mu/clouds/aws/server.rb +169 -137
  57. data/modules/mu/clouds/aws/server_pool.rb +60 -83
  58. data/modules/mu/clouds/aws/storage_pool.rb +59 -31
  59. data/modules/mu/clouds/aws/user.rb +36 -27
  60. data/modules/mu/clouds/aws/userdata/linux.erb +101 -93
  61. data/modules/mu/clouds/aws/vpc.rb +250 -189
  62. data/modules/mu/clouds/azure.rb +132 -0
  63. data/modules/mu/clouds/cloudformation.rb +65 -1
  64. data/modules/mu/clouds/cloudformation/alarm.rb +8 -0
  65. data/modules/mu/clouds/cloudformation/cache_cluster.rb +7 -0
  66. data/modules/mu/clouds/cloudformation/collection.rb +7 -0
  67. data/modules/mu/clouds/cloudformation/database.rb +7 -0
  68. data/modules/mu/clouds/cloudformation/dnszone.rb +7 -0
  69. data/modules/mu/clouds/cloudformation/firewall_rule.rb +9 -2
  70. data/modules/mu/clouds/cloudformation/loadbalancer.rb +7 -0
  71. data/modules/mu/clouds/cloudformation/log.rb +7 -0
  72. data/modules/mu/clouds/cloudformation/server.rb +7 -0
  73. data/modules/mu/clouds/cloudformation/server_pool.rb +7 -0
  74. data/modules/mu/clouds/cloudformation/vpc.rb +7 -0
  75. data/modules/mu/clouds/google.rb +214 -110
  76. data/modules/mu/clouds/google/container_cluster.rb +42 -24
  77. data/modules/mu/clouds/google/database.rb +15 -6
  78. data/modules/mu/clouds/google/firewall_rule.rb +17 -25
  79. data/modules/mu/clouds/google/group.rb +13 -5
  80. data/modules/mu/clouds/google/habitat.rb +105 -0
  81. data/modules/mu/clouds/google/loadbalancer.rb +28 -20
  82. data/modules/mu/clouds/google/server.rb +93 -354
  83. data/modules/mu/clouds/google/server_pool.rb +18 -10
  84. data/modules/mu/clouds/google/user.rb +22 -14
  85. data/modules/mu/clouds/google/vpc.rb +97 -69
  86. data/modules/mu/config.rb +133 -38
  87. data/modules/mu/config/alarm.rb +25 -0
  88. data/modules/mu/config/cache_cluster.rb +5 -3
  89. data/modules/mu/config/cache_cluster.yml +23 -0
  90. data/modules/mu/config/database.rb +25 -16
  91. data/modules/mu/config/database.yml +3 -3
  92. data/modules/mu/config/function.rb +1 -2
  93. data/modules/mu/config/{project.rb → habitat.rb} +10 -10
  94. data/modules/mu/config/notifier.rb +85 -0
  95. data/modules/mu/config/notifier.yml +9 -0
  96. data/modules/mu/config/role.rb +1 -1
  97. data/modules/mu/config/search_domain.yml +2 -2
  98. data/modules/mu/config/server.rb +13 -1
  99. data/modules/mu/config/server.yml +3 -3
  100. data/modules/mu/config/server_pool.rb +3 -1
  101. data/modules/mu/config/storage_pool.rb +3 -1
  102. data/modules/mu/config/storage_pool.yml +19 -0
  103. data/modules/mu/config/vpc.rb +70 -8
  104. data/modules/mu/groomers/chef.rb +2 -3
  105. data/modules/mu/kittens.rb +500 -122
  106. data/modules/mu/master.rb +5 -5
  107. data/modules/mu/mommacat.rb +151 -91
  108. data/modules/tests/super_complex_bok.yml +12 -0
  109. data/modules/tests/super_simple_bok.yml +12 -0
  110. data/spec/mu/clouds/azure_spec.rb +82 -0
  111. data/spec/spec_helper.rb +105 -0
  112. metadata +26 -5
  113. data/modules/mu/clouds/aws/notification.rb +0 -139
  114. data/modules/mu/config/notification.rb +0 -44
@@ -58,12 +58,16 @@ module MU
58
58
  @config["dimensions"] = dimensions
59
59
  end
60
60
 
61
+ @config["alarm_actions"] = [] if @config["alarm_actions"].nil?
62
+ @config["ok_actions"] = [] if @config["ok_actions"].nil?
61
63
  if @config["enable_notifications"]
62
- @config["alarm_actions"] = [] if @config["alarm_actions"].nil?
63
- @config["ok_actions"] = [] if @config["ok_actions"].nil?
64
64
 
65
- topic_arn = MU::Cloud::AWS::Notification.createTopic(@config["notification_group"], region: @config["region"])
66
- MU::Cloud::AWS::Notification.subscribe(arn: topic_arn, protocol: @config["notification_type"], endpoint: @config["notification_endpoint"], region: @config["region"])
65
+ topic_arn = if @config["notification_group"].match(/^arn:/)
66
+ @config["notification_group"]
67
+ else
68
+ topic = @deploy.findLitterMate(name: @config["notification_group"], type: "notifiers")
69
+ topic.cloudobj.arn
70
+ end
67
71
 
68
72
  @config["alarm_actions"] << topic_arn
69
73
  @config["ok_actions"] << topic_arn
@@ -85,7 +89,8 @@ module MU
85
89
  evaluation_periods: @config["evaluation_periods"],
86
90
  threshold: @config["threshold"],
87
91
  comparison_operator: @config["comparison_operator"],
88
- region: @config["region"]
92
+ region: @config["region"],
93
+ credentials: @config['credentials']
89
94
  )
90
95
 
91
96
  @cloud_id = @mu_name
@@ -117,23 +122,30 @@ module MU
117
122
  return deploy_struct
118
123
  end
119
124
 
125
+ # Does this resource type exist as a global (cloud-wide) artifact, or
126
+ # is it localized to a region/zone?
127
+ # @return [Boolean]
128
+ def self.isGlobal?
129
+ false
130
+ end
131
+
120
132
  # Remove all alarms associated with the currently loaded deployment.
121
133
  # @param noop [Boolean]: If true, will only print what would be done
122
134
  # @param ignoremaster [Boolean]: If true, will remove resources not flagged as originating from this Mu server
123
135
  # @param region [String]: The cloud provider region
124
136
  # @return [void]
125
- def self.cleanup(noop: false, ignoremaster: false, region: MU.curRegion, flags: {})
137
+ def self.cleanup(noop: false, ignoremaster: false, region: MU.curRegion, credentials: nil, flags: {})
126
138
  alarms = []
127
139
  # We don't have a way to tag alarms, so we try to delete them by the deploy ID.
128
140
  # This can miss alarms in some cases (eg. cache_cluster) so we might want to delete alarms from each API as well.
129
- MU::Cloud::AWS.cloudwatch(region).describe_alarms.each { |page|
141
+ MU::Cloud::AWS.cloudwatch(credentials: credentials, region: region).describe_alarms.each { |page|
130
142
  page.metric_alarms.map(&:alarm_name).each { |alarm_name|
131
143
  alarms << alarm_name if alarm_name.match(MU.deploy_id)
132
144
  }
133
145
  }
134
146
 
135
147
  if !alarms.empty?
136
- MU::Cloud::AWS.cloudwatch(region).delete_alarms(alarm_names: alarms) unless noop
148
+ MU::Cloud::AWS.cloudwatch(credentials: credentials, region: region).delete_alarms(alarm_names: alarms) unless noop
137
149
  MU.log "Deleted alarms #{alarms.join(', ')}"
138
150
  end
139
151
  end
@@ -143,19 +155,19 @@ module MU
143
155
  # @param region [String]: The cloud provider region.
144
156
  # @param flags [Hash]: Optional flags
145
157
  # @return [OpenStruct]: The cloud provider's complete descriptions of matching alarm.
146
- def self.find(cloud_id: nil, region: MU.curRegion, flags: {})
147
- MU::Cloud::AWS::Alarm.getAlarmByName(cloud_id, region: region)
158
+ def self.find(cloud_id: nil, region: MU.curRegion, credentials: nil, flags: {})
159
+ MU::Cloud::AWS::Alarm.getAlarmByName(cloud_id, region: region, credentials: credentials)
148
160
  end
149
161
 
150
162
  # Create an alarm.
151
163
  def self.setAlarm(
152
164
  name: nil, ok_actions: [], alarm_actions: [], insufficient_data_actions: [], metric_name: nil, namespace: nil, statistic: nil,
153
- dimensions: [], period: nil, unit: nil, evaluation_periods: nil, threshold: nil, comparison_operator: nil, region: MU.curRegion
165
+ dimensions: [], period: nil, unit: nil, evaluation_periods: nil, threshold: nil, comparison_operator: nil, region: MU.curRegion, credentials: nil
154
166
  )
155
167
 
156
168
  # If the alarm already exists, then assume we're updating it and
157
169
  # munge in potentially new arguments.
158
- ext_alarm = getAlarmByName(name, region: region)
170
+ ext_alarm = getAlarmByName(name, region: region, credentials: credentials)
159
171
  if ext_alarm
160
172
  if !ext_alarm.dimensions.empty?
161
173
  ext_alarm.dimensions.each { |dim|
@@ -181,7 +193,7 @@ module MU
181
193
  end
182
194
 
183
195
  begin
184
- MU::Cloud::AWS.cloudwatch(region).put_metric_alarm(
196
+ MU::Cloud::AWS.cloudwatch(region: region, credentials: credentials).put_metric_alarm(
185
197
  alarm_name: name,
186
198
  alarm_description: name,
187
199
  actions_enabled: true,
@@ -215,8 +227,8 @@ module MU
215
227
  # @param name [String]: The cloud provider's identifier for this alarm.
216
228
  # @param region [String]: The cloud provider region
217
229
  # @return [OpenStruct]
218
- def self.getAlarmByName(name, region: MU.curRegion)
219
- MU::Cloud::AWS.cloudwatch(region).describe_alarms(alarm_names: [name]).metric_alarms.first
230
+ def self.getAlarmByName(name, region: MU.curRegion, credentials: nil)
231
+ MU::Cloud::AWS.cloudwatch(region: region, credentials: credentials).describe_alarms(alarm_names: [name]).metric_alarms.first
220
232
  end
221
233
 
222
234
  # Publish logging data, or create a new custom container/group for your logging data
@@ -224,14 +236,14 @@ module MU
224
236
  # @param metric_data [Array]: The data points describing your new metric.
225
237
  # @param region [String]: The cloud provider region.
226
238
  def self.createMetric(namespace: nil, metric_data: [], region: MU.curRegion)
227
- MU::Cloud::AWS.cloudwatch(region).put_metric_data(namespace: namespace, metric_data: metric_data, region: region)
239
+ MU::Cloud::AWS.cloudwatch(region: region).put_metric_data(namespace: namespace, metric_data: metric_data, region: region)
228
240
  end
229
241
 
230
242
  # Enable the state of the alarm
231
243
  # @param name [String]: The cloud provider's identifier for this alarm.
232
244
  # @param region [String]: The cloud provider region.
233
245
  def self.enableAlarmAction(name, region: MU.curRegion)
234
- MU::Cloud::AWS.cloudwatch(region).enable_alarm_actions(alarm_names: [name])
246
+ MU::Cloud::AWS.cloudwatch(region: region).enable_alarm_actions(alarm_names: [name])
235
247
  end
236
248
 
237
249
  # Cloud-specific configuration properties.
@@ -47,7 +47,7 @@ module MU
47
47
  # Canonical Amazon Resource Number for this resource
48
48
  # @return [String]
49
49
  def arn
50
- "arn:"+(MU::Cloud::AWS.isGovCloud?(@config["region"]) ? "aws-us-gov" : "aws")+":elasticache:"+@config['region']+":"+MU.account_number+":cluster/"+@cloud_id
50
+ "arn:"+(MU::Cloud::AWS.isGovCloud?(@config["region"]) ? "aws-us-gov" : "aws")+":elasticache:"+@config['region']+":"+MU::Cloud::AWS.credToAcct(@config['credentials'])+":cluster/"+@cloud_id
51
51
  end
52
52
 
53
53
  # Locate an existing Cache Cluster or Cache Clusters and return an array containing matching AWS resource descriptors for those that match.
@@ -57,7 +57,7 @@ module MU
57
57
  # @param tag_value [String]: The value of the tag specified by tag_key to match when searching by tag.
58
58
  # @param flags [Hash]: Optional flags
59
59
  # @return [Array<Hash<String,OpenStruct>>]: The cloud provider's complete descriptions of matching Cache Clusters.
60
- def self.find(cloud_id: nil, region: MU.curRegion, tag_key: "Name", tag_value: nil, flags: {})
60
+ def self.find(cloud_id: nil, region: MU.curRegion, tag_key: "Name", tag_value: nil, credentials: nil, flags: {})
61
61
  map = {}
62
62
  if cloud_id
63
63
  cache_cluster = MU::Cloud::AWS::CacheCluster.getCacheClusterById(cloud_id, region: region)
@@ -65,9 +65,9 @@ module MU
65
65
  end
66
66
 
67
67
  if tag_value
68
- MU::Cloud::AWS.elasticache(region).describe_cache_clusters.cache_clusters.each { |cc|
69
- resp = MU::Cloud::AWS.elasticache(region).list_tags_for_resource(
70
- resource_name: MU::Cloud::AWS::CacheCluster.getARN(cc.cache_cluster_id, "cluster", "elasticache", region: region)
68
+ MU::Cloud::AWS.elasticache(region: region, credentials: credentials).describe_cache_clusters.cache_clusters.each { |cc|
69
+ resp = MU::Cloud::AWS.elasticache(region: region, credentials: credentials).list_tags_for_resource(
70
+ resource_name: MU::Cloud::AWS::CacheCluster.getARN(cc.cache_cluster_id, "cluster", "elasticache", region: region, credentials: credentials)
71
71
  )
72
72
  if resp && resp.tag_list && !resp.tag_list.empty?
73
73
  resp.tag_list.each { |tag|
@@ -86,11 +86,11 @@ module MU
86
86
  # @param client_type [String]: The name of the client (eg. elasticache, rds, ec2, s3)
87
87
  # @param resource_type [String]: The type of the resource
88
88
  # @param region [String]: The region in which the resource resides.
89
- # @param account_number [String]: The account in which the resource resides.
89
+ # @param credentials [String]: The account in which the resource resides.
90
90
  # @return [String]
91
- def self.getARN(resource, resource_type, client_type, region: MU.curRegion, account_number: MU.account_number)
91
+ def self.getARN(resource, resource_type, client_type, region: MU.curRegion, credentials: nil)
92
92
  aws_str = MU::Cloud::AWS.isGovCloud?(region) ? "aws-us-gov" : "aws"
93
- "arn:#{aws_str}:#{client_type}:#{region}:#{account_number}:#{resource_type}:#{resource}"
93
+ "arn:#{aws_str}:#{client_type}:#{region}:#{MU::Cloud::AWS.credToAcct(credentials)}:#{resource_type}:#{resource}"
94
94
  end
95
95
 
96
96
  # Construct all our tags.
@@ -122,8 +122,8 @@ module MU
122
122
  # @param region [String]: The cloud provider region
123
123
  def addStandardTags(resource, resource_type, region: MU.curRegion)
124
124
  MU.log "Adding tags to ElasticCache resource #{resource}"
125
- MU::Cloud::AWS.elasticache(region).add_tags_to_resource(
126
- resource_name: MU::Cloud::AWS::CacheCluster.getARN(resource, resource_type, "elasticache", region: region),
125
+ MU::Cloud::AWS.elasticache(region: region).add_tags_to_resource(
126
+ resource_name: MU::Cloud::AWS::CacheCluster.getARN(resource, resource_type, "elasticache", region: @config['region'], credentials: @config['credentials']),
127
127
  tags: allTags
128
128
  )
129
129
  end
@@ -184,12 +184,12 @@ module MU
184
184
  # config_struct[:preferred_cache_cluster_a_zs] = @config["preferred_cache_cluster_azs"]
185
185
 
186
186
  MU.log "Creating cache replication group #{@config['identifier']}"
187
- resp = MU::Cloud::AWS.elasticache(@config['region']).create_replication_group(config_struct).replication_group
187
+ resp = MU::Cloud::AWS.elasticache(region: @config['region'], credentials: @config['credentials']).create_replication_group(config_struct).replication_group
188
188
 
189
189
  wait_start_time = Time.now
190
190
  retries = 0
191
191
  begin
192
- MU::Cloud::AWS.elasticache(@config['region']).wait_until(:replication_group_available, replication_group_id: @config['identifier']) do |waiter|
192
+ MU::Cloud::AWS.elasticache(region: @config['region'], credentials: @config['credentials']).wait_until(:replication_group_available, replication_group_id: @config['identifier']) do |waiter|
193
193
  waiter.max_attempts = nil
194
194
  waiter.before_attempt do |attempts|
195
195
  MU.log "Waiting for cache replication group #{@config['identifier']} to become available", MU::NOTICE if attempts % 5 == 0
@@ -241,12 +241,12 @@ module MU
241
241
  # config_struct[:preferred_availability_zones] = @config["preferred_availability_zones"] if @config["preferred_availability_zones"] && @config["az_mode"] == "cross-az"
242
242
 
243
243
  MU.log "Creating cache cluster #{@config['identifier']}"
244
- resp = MU::Cloud::AWS.elasticache(@config['region']).create_cache_cluster(config_struct).cache_cluster
244
+ resp = MU::Cloud::AWS.elasticache(region: @config['region'], credentials: @config['credentials']).create_cache_cluster(config_struct).cache_cluster
245
245
 
246
246
  wait_start_time = Time.now
247
247
  retries = 0
248
248
  begin
249
- MU::Cloud::AWS.elasticache(@config['region']).wait_until(:cache_cluster_available, cache_cluster_id: @config['identifier']) do |waiter|
249
+ MU::Cloud::AWS.elasticache(region: @config['region'], credentials: @config['credentials']).wait_until(:cache_cluster_available, cache_cluster_id: @config['identifier']) do |waiter|
250
250
  waiter.max_attempts = nil
251
251
  waiter.before_attempt do |attempts|
252
252
  MU.log "Waiting for cache cluster #{@config['identifier']} to become available", MU::NOTICE if attempts % 5 == 0
@@ -263,7 +263,7 @@ module MU
263
263
  retry
264
264
  end
265
265
 
266
- resp = MU::Cloud::AWS::CacheCluster.getCacheClusterById(@config['identifier'], region: @config['region'])
266
+ resp = MU::Cloud::AWS::CacheCluster.getCacheClusterById(@config['identifier'], region: @config['region'], credentials: @config['credentials'])
267
267
  MU.log "Cache Cluster #{@config['identifier']} is ready to use"
268
268
  @cloud_id = resp.cache_cluster_id
269
269
  end
@@ -295,10 +295,10 @@ module MU
295
295
  # If we didn't specify a VPC try to figure out if the account has a default VPC
296
296
  vpc_id = nil
297
297
  subnets = []
298
- MU::Cloud::AWS.ec2(@config['region']).describe_vpcs.vpcs.each { |vpc|
298
+ MU::Cloud::AWS.ec2(region: @config['region'], credentials: @config['credentials']).describe_vpcs.vpcs.each { |vpc|
299
299
  if vpc.is_default
300
300
  vpc_id = vpc.vpc_id
301
- subnets = MU::Cloud::AWS.ec2(@config['region']).describe_subnets(
301
+ subnets = MU::Cloud::AWS.ec2(region: @config['region'], credentials: @config['credentials']).describe_subnets(
302
302
  filters: [
303
303
  {
304
304
  name: "vpc-id",
@@ -331,7 +331,7 @@ module MU
331
331
  else
332
332
  MU.log "Creating subnet group #{@config["subnet_group_name"]} for cache cluster #{@config['identifier']}"
333
333
 
334
- resp = MU::Cloud::AWS.elasticache(@config['region']).create_cache_subnet_group(
334
+ resp = MU::Cloud::AWS.elasticache(region: @config['region'], credentials: @config['credentials']).create_cache_subnet_group(
335
335
  cache_subnet_group_name: @config["subnet_group_name"],
336
336
  cache_subnet_group_description: @config["subnet_group_name"],
337
337
  subnet_ids: subnet_ids
@@ -368,7 +368,7 @@ module MU
368
368
  # Create a Cache Cluster parameter group.
369
369
  def createParameterGroup
370
370
  MU.log "Creating a cache cluster parameter group #{@config["parameter_group_name"]}"
371
- resp = MU::Cloud::AWS.elasticache(@config['region']).create_cache_parameter_group(
371
+ resp = MU::Cloud::AWS.elasticache(region: @config['region'], credentials: @config['credentials']).create_cache_parameter_group(
372
372
  cache_parameter_group_name: @config["parameter_group_name"],
373
373
  cache_parameter_group_family: @config["parameter_group_family"],
374
374
  description: "Parameter group for #{@config["parameter_group_family"]}"
@@ -381,7 +381,7 @@ module MU
381
381
  }
382
382
 
383
383
  MU.log "Modifiying cache cluster parameter group #{@config["parameter_group_name"]}"
384
- MU::Cloud::AWS.elasticache(@config['region']).modify_cache_parameter_group(
384
+ MU::Cloud::AWS.elasticache(region: @config['region'], credentials: @config['credentials']).modify_cache_parameter_group(
385
385
  cache_parameter_group_name: @config["parameter_group_name"],
386
386
  parameter_name_values: params
387
387
  )
@@ -391,7 +391,7 @@ module MU
391
391
  # Retrieve a Cache Cluster parameter group name of on existing parameter group.
392
392
  # @return [String]: Cache Cluster parameter group name.
393
393
  def getParameterGroup
394
- MU::Cloud::AWS.elasticache(@config['region']).describe_cache_parameter_groups(
394
+ MU::Cloud::AWS.elasticache(region: @config['region'], credentials: @config['credentials']).describe_cache_parameter_groups(
395
395
  cache_parameter_group_name: @config["parameter_group_name"]
396
396
  ).cache_parameter_groups.first.cache_parameter_group_name
397
397
  end
@@ -405,23 +405,27 @@ module MU
405
405
  # @param cc_id [String]: The cloud provider's identifier for this cache cluster.
406
406
  # @param region [String]: The cloud provider's region.
407
407
  # @return [OpenStruct]
408
- def self.getCacheClusterById(cc_id, region: MU.curRegion)
409
- MU::Cloud::AWS.elasticache(region).describe_cache_clusters(cache_cluster_id: cc_id).cache_clusters.first
408
+ def self.getCacheClusterById(cc_id, region: MU.curRegion, credentials: nil)
409
+ begin
410
+ MU::Cloud::AWS.elasticache(region: region, credentials: credentials).describe_cache_clusters(cache_cluster_id: cc_id).cache_clusters.first
411
+ rescue Aws::ElastiCache::Errors::CacheClusterNotFound => e
412
+ nil
413
+ end
410
414
  end
411
415
 
412
416
  # Retrieve the complete cloud provider description of a cache replication group.
413
417
  # @param repl_group_id [String]: The cloud provider's identifier for this cache replication group.
414
418
  # @param region [String]: The cloud provider's region.
415
419
  # @return [OpenStruct]
416
- def self.getCacheReplicationGroupById(repl_group_id, region: MU.curRegion)
417
- MU::Cloud::AWS.elasticache(region).describe_replication_groups(replication_group_id: repl_group_id).replication_groups.first
420
+ def self.getCacheReplicationGroupById(repl_group_id, region: MU.curRegion, credentials: nil)
421
+ MU::Cloud::AWS.elasticache(region: region, credentials: credentials).describe_replication_groups(replication_group_id: repl_group_id).replication_groups.first
418
422
  end
419
423
 
420
424
  # Register a description of this cache cluster / cache replication group with this deployment's metadata.
421
425
  def notify
422
426
  ### TO DO: Flatten the replication group deployment metadata structure. It is probably waaaaaaay too nested.
423
427
  if @config["create_replication_group"]
424
- repl_group = MU::Cloud::AWS::CacheCluster.getCacheReplicationGroupById(@config['identifier'], region: @config['region'])
428
+ repl_group = MU::Cloud::AWS::CacheCluster.getCacheReplicationGroupById(@config['identifier'], region: @config['region'], credentials: @config['credentials'])
425
429
  # DNS records for the "real" zone should always be registered as late as possible so override_existing only overwrites the records after the resource is ready to use.
426
430
  if @config['dns_records']
427
431
  @config['dns_records'].each { |dnsrec|
@@ -485,7 +489,8 @@ module MU
485
489
  deploy_struct[member.cache_cluster_id]["current_role"] = member.current_role
486
490
  }
487
491
  else
488
- cluster = MU::Cloud::AWS::CacheCluster.getCacheClusterById(@config['identifier'], region: @config['region'])
492
+ cluster = MU::Cloud::AWS::CacheCluster.getCacheClusterById(@config['identifier'], region: @config['region'], credentials: @config['credentials'])
493
+
489
494
  vpc_sg_ids = []
490
495
  cluster.security_groups.each { |vpc_sg|
491
496
  vpc_sg_ids << vpc_sg.security_group_id
@@ -531,7 +536,7 @@ module MU
531
536
 
532
537
  attempts = 0
533
538
  begin
534
- snapshot = MU::Cloud::AWS.elasticache(@config['region']).create_snapshot(
539
+ snapshot = MU::Cloud::AWS.elasticache(region: @config['region'], credentials: @config['credentials']).create_snapshot(
535
540
  cache_cluster_id: @config["identifier"],
536
541
  snapshot_name: snap_id
537
542
  )
@@ -551,7 +556,7 @@ module MU
551
556
  MU.log "Waiting for snapshot of cache cluster #{@config["identifier"]} to be ready...", MU::NOTICE if attempts % 20 == 0
552
557
  MU.log "Waiting for snapshot of cache cluster #{@config["identifier"]} to be ready...", MU::DEBUG
553
558
 
554
- snapshot_resp = MU::Cloud::AWS.elasticache(@config['region']).describe_snapshots(snapshot_name: snap_id)
559
+ snapshot_resp = MU::Cloud::AWS.elasticache(region: @config['region'], credentials: @config['credentials']).describe_snapshots(snapshot_name: snap_id)
555
560
  attempts += 1
556
561
  break unless snapshot_resp.snapshots.first.snapshot_status != "available"
557
562
  sleep 15
@@ -562,18 +567,26 @@ module MU
562
567
 
563
568
  # @return [String]: The cloud provider's identifier for the snapshot.
564
569
  def getExistingSnapshot
565
- MU::Cloud::AWS.elasticache(@config['region']).describe_snapshots(snapshot_name: @config["identifier"]).snapshots.first.snapshot_name
570
+ MU::Cloud::AWS.elasticache(region: @config['region'], credentials: @config['credentials']).describe_snapshots(snapshot_name: @config["identifier"]).snapshots.first.snapshot_name
566
571
  rescue NoMethodError
567
572
  raise MuError, "Snapshot #{@config["identifier"]} doesn't exist, make sure you provided a valid snapshot ID/Name"
568
573
  end
569
574
 
575
+ # Does this resource type exist as a global (cloud-wide) artifact, or
576
+ # is it localized to a region/zone?
577
+ # @return [Boolean]
578
+ def self.isGlobal?
579
+ false
580
+ end
581
+
570
582
  # Called by {MU::Cleanup}. Locates resources that were created by the currently-loaded deployment and purges them.
571
583
  # @param noop [Boolean]: If true, will only print what would be done.
572
584
  # @param ignoremaster [Boolean]: If true, will remove resources not flagged as originating from this Mu server.
573
585
  # @param region [String]: The cloud provider's region in which to operate.
574
586
  # @return [void]
575
- def self.cleanup(skipsnapshots: false, noop: false, ignoremaster: false, region: MU.curRegion, flags: {})
576
- all_clusters = MU::Cloud::AWS.elasticache(region).describe_cache_clusters
587
+ def self.cleanup(noop: false, ignoremaster: false, credentials: nil, region: MU.curRegion, flags: {})
588
+ skipsnapshots = flags["skipsnapshots"]
589
+ all_clusters = MU::Cloud::AWS.elasticache(credentials: credentials, region: region).describe_cache_clusters
577
590
  our_clusters = []
578
591
  our_replication_group_ids = []
579
592
 
@@ -597,19 +610,20 @@ module MU
597
610
  loop do
598
611
  MU.log "Waiting for #{cluster_id} to be in a removable state", MU::NOTICE
599
612
  cluster = MU::Cloud::AWS::CacheCluster.getCacheClusterById(cluster_id, region: region)
613
+ break if !cluster
600
614
  break unless %w{creating modifying backing-up}.include?(cluster.cache_cluster_status)
601
615
  sleep 60
602
616
  end
603
617
  end
604
618
  end
605
619
 
606
- arn = MU::Cloud::AWS::CacheCluster.getARN(cluster_id, "cluster", "elasticache", region: region)
620
+ arn = MU::Cloud::AWS::CacheCluster.getARN(cluster_id, "cluster", "elasticache", region: region, credentials: credentials)
607
621
  attempts = 0
608
622
 
609
623
  begin
610
- tags = MU::Cloud::AWS.elasticache(region).list_tags_for_resource(resource_name: arn).tag_list
624
+ tags = MU::Cloud::AWS.elasticache(credentials: credentials, region: region).list_tags_for_resource(resource_name: arn).tag_list
611
625
  rescue Aws::ElastiCache::Errors::CacheClusterNotFound => e
612
- if attempts < 10
626
+ if attempts < 5
613
627
  MU.log "Can't get tags for #{cluster_id}, retrying a few times in case of a lagging resource", MU::WARN
614
628
  MU.log "arn #{arn}", MU::WARN
615
629
  attempts += 1
@@ -653,7 +667,7 @@ module MU
653
667
  threads << Thread.new(replication_group) { |myrepl_group|
654
668
  MU.dupGlobals(parent_thread_id)
655
669
  Thread.abort_on_exception = true
656
- MU::Cloud::AWS::CacheCluster.terminate_replication_group(myrepl_group, noop: noop, skipsnapshots: skipsnapshots, region: region, deploy_id: MU.deploy_id, cloud_id: myrepl_group.replication_group_id)
670
+ MU::Cloud::AWS::CacheCluster.terminate_replication_group(myrepl_group, noop: noop, skipsnapshots: skipsnapshots, region: region, deploy_id: MU.deploy_id, cloud_id: myrepl_group.replication_group_id, credentials: credentials)
657
671
  }
658
672
  }
659
673
  end
@@ -665,7 +679,7 @@ module MU
665
679
  threads << Thread.new(cluster) { |mycluster|
666
680
  MU.dupGlobals(parent_thread_id)
667
681
  Thread.abort_on_exception = true
668
- MU::Cloud::AWS::CacheCluster.terminate_cache_cluster(mycluster, noop: noop, skipsnapshots: skipsnapshots, region: region, deploy_id: MU.deploy_id, cloud_id: mycluster.cache_cluster_id)
682
+ MU::Cloud::AWS::CacheCluster.terminate_cache_cluster(mycluster, noop: noop, skipsnapshots: skipsnapshots, region: region, deploy_id: MU.deploy_id, cloud_id: mycluster.cache_cluster_id, credentials: credentials)
669
683
  }
670
684
  }
671
685
  end
@@ -714,7 +728,7 @@ module MU
714
728
  def self.validateConfig(cache, configurator)
715
729
  ok = true
716
730
 
717
- if cluster.has_key?("parameter_group_parameters") && cache["parameter_group_family"].nil?
731
+ if cache.has_key?("parameter_group_parameters") && cache["parameter_group_family"].nil?
718
732
  MU.log "parameter_group_family must be set when setting parameter_group_parameters", MU::ERR
719
733
  ok = false
720
734
  end
@@ -728,7 +742,7 @@ module MU
728
742
 
729
743
  # Some instance types don't support snapshotting
730
744
  if %w{cache.t2.micro cache.t2.small cache.t2.medium}.include?(cache["size"])
731
- if cluster.has_key?("snapshot_retention_limit") || cluster.has_key?("snapshot_window")
745
+ if cache.has_key?("snapshot_retention_limit") || cache.has_key?("snapshot_window")
732
746
  MU.log "Can't set snapshot_retention_limit or snapshot_window on #{cache["size"]}", MU::ERR
733
747
  ok = false
734
748
  end
@@ -743,7 +757,7 @@ module MU
743
757
  end
744
758
 
745
759
  # memcached doesn't support snapshots
746
- if cluster.has_key?("snapshot_retention_limit") || cluster.has_key?("snapshot_window")
760
+ if cache.has_key?("snapshot_retention_limit") || cache.has_key?("snapshot_window")
747
761
  MU.log "Can't set snapshot_retention_limit or snapshot_window on #{cache["engine"]}", MU::ERR
748
762
  ok = false
749
763
  end
@@ -761,7 +775,7 @@ module MU
761
775
  # @param region [String]: The cloud provider's region in which to operate.
762
776
  # @param cloud_id [String]: The cloud provider's identifier for this resource.
763
777
  # @return [void]
764
- def self.terminate_cache_cluster(cluster, noop: false, skipsnapshots: false, region: MU.curRegion, deploy_id: MU.deploy_id, mu_name: nil, cloud_id: nil)
778
+ def self.terminate_cache_cluster(cluster, noop: false, skipsnapshots: false, region: MU.curRegion, deploy_id: MU.deploy_id, mu_name: nil, cloud_id: nil, credentials: nil)
765
779
  raise MuError, "terminate_cache_cluster requires a non-nil cache cluster descriptor" if cluster.nil? || cluster.empty?
766
780
 
767
781
  cluster_id = cluster.cache_cluster_id
@@ -772,7 +786,7 @@ module MU
772
786
  unless cluster.cache_cluster_status == "available"
773
787
  loop do
774
788
  MU.log "Waiting for #{cluster_id} to be in a removable state...", MU::NOTICE
775
- cluster = MU::Cloud::AWS::CacheCluster.getCacheClusterById(cluster_id, region: region)
789
+ cluster = MU::Cloud::AWS::CacheCluster.getCacheClusterById(cluster_id, region: region, credentials: credentials)
776
790
  break unless %w{creating modifying backing-up}.include?(cluster.cache_cluster_status)
777
791
  sleep 60
778
792
  end
@@ -785,23 +799,23 @@ module MU
785
799
  MU.log "#{cluster_id} has already been terminated", MU::WARN
786
800
  else
787
801
  unless noop
788
- def self.clusterSkipSnap(cluster_id, region)
802
+ def self.clusterSkipSnap(cluster_id, region, credentials)
789
803
  # We're calling this several times so lets declare it once
790
804
  MU.log "Terminating #{cluster_id}. Not saving final snapshot"
791
- MU::Cloud::AWS.elasticache(region).delete_cache_cluster(cache_cluster_id: cluster_id)
805
+ MU::Cloud::AWS.elasticache(region: region, credentials: credentials).delete_cache_cluster(cache_cluster_id: cluster_id)
792
806
  end
793
807
 
794
- def self.clusterCreateSnap(cluster_id, region)
808
+ def self.clusterCreateSnap(cluster_id, region, credentials)
795
809
  MU.log "Terminating #{cluster_id}. Final snapshot name: #{cluster_id}-mufinal"
796
- MU::Cloud::AWS.elasticache(region).delete_cache_cluster(cache_cluster_id: cluster_id, final_snapshot_identifier: "#{cluster_id}-MUfinal")
810
+ MU::Cloud::AWS.elasticache(region: region, credentials: credentials).delete_cache_cluster(cache_cluster_id: cluster_id, final_snapshot_identifier: "#{cluster_id}-MUfinal")
797
811
  end
798
812
 
799
813
  retries = 0
800
814
  begin
801
815
  if cluster.engine == "memcached"
802
- clusterSkipSnap(cluster_id, region)
816
+ clusterSkipSnap(cluster_id, region, credentials)
803
817
  else
804
- skipsnapshots ? clusterSkipSnap(cluster_id, region) : clusterCreateSnap(cluster_id, region)
818
+ skipsnapshots ? clusterSkipSnap(cluster_id, region, credentials) : clusterCreateSnap(cluster_id, region, credentials)
805
819
  end
806
820
  rescue Aws::ElastiCache::Errors::InvalidCacheClusterState => e
807
821
  if retries < 5
@@ -815,16 +829,16 @@ module MU
815
829
  end
816
830
  rescue Aws::ElastiCache::Errors::SnapshotAlreadyExistsFault
817
831
  MU.log "Snapshot #{cluster_id}-MUfinal already exists", MU::WARN
818
- clusterSkipSnap(cluster_id, region)
832
+ clusterSkipSnap(cluster_id, region, credentials)
819
833
  rescue Aws::ElastiCache::Errors::SnapshotQuotaExceededFault
820
834
  MU.log "Snapshot quota exceeded while deleting #{cluster_id}", MU::ERR
821
- clusterSkipSnap(cluster_id, region)
835
+ clusterSkipSnap(cluster_id, region, credentials)
822
836
  end
823
837
 
824
838
  wait_start_time = Time.now
825
839
  retries = 0
826
840
  begin
827
- MU::Cloud::AWS.elasticache(region).wait_until(:cache_cluster_deleted, cache_cluster_id: cluster_id) do |waiter|
841
+ MU::Cloud::AWS.elasticache(region: region, credentials: credentials).wait_until(:cache_cluster_deleted, cache_cluster_id: cluster_id) do |waiter|
828
842
  waiter.max_attempts = nil
829
843
  waiter.before_attempt do |attempts|
830
844
  MU.log "Waiting for cache cluster #{cluster_id} to delete..", MU::NOTICE if attempts % 10 == 0
@@ -848,8 +862,8 @@ module MU
848
862
  MU.log "#{cluster_id} has been terminated"
849
863
 
850
864
  unless noop
851
- MU::Cloud::AWS::CacheCluster.delete_subnet_group(subnet_group, region: region) if subnet_group
852
- MU::Cloud::AWS::CacheCluster.delete_parameter_group(parameter_group, region: region) if parameter_group && !parameter_group.start_with?("default")
865
+ MU::Cloud::AWS::CacheCluster.delete_subnet_group(subnet_group, region: region, credentials: credentials) if subnet_group
866
+ MU::Cloud::AWS::CacheCluster.delete_parameter_group(parameter_group, region: region, credentials: credentials) if parameter_group && !parameter_group.start_with?("default")
853
867
  end
854
868
  end
855
869
 
@@ -891,10 +905,10 @@ module MU
891
905
  MU.log "#{repl_group_id} has already been terminated", MU::WARN
892
906
  else
893
907
  unless noop
894
- def self.skipSnap(repl_group_id, region)
908
+ def self.skipSnap(repl_group_id, region, credentials)
895
909
  # We're calling this several times so lets declare it once
896
910
  MU.log "Terminating #{repl_group_id}. Not saving final snapshot"
897
- MU::Cloud::AWS.elasticache(region).delete_replication_group(
911
+ MU::Cloud::AWS.elasticache(region: region, credentials: credentials).delete_replication_group(
898
912
  replication_group_id: repl_group_id,
899
913
  retain_primary_cluster: false
900
914
  )
@@ -902,7 +916,7 @@ module MU
902
916
 
903
917
  def self.createSnap(repl_group_id, region)
904
918
  MU.log "Terminating #{repl_group_id}. Final snapshot name: #{repl_group_id}-mufinal"
905
- MU::Cloud::AWS.elasticache(region).delete_replication_group(
919
+ MU::Cloud::AWS.elasticache(region: region).delete_replication_group(
906
920
  replication_group_id: repl_group_id,
907
921
  retain_primary_cluster: false,
908
922
  final_snapshot_identifier: "#{repl_group_id}-mufinal"
@@ -911,7 +925,7 @@ module MU
911
925
 
912
926
  retries = 0
913
927
  begin
914
- skipsnapshots ? skipSnap(repl_group_id, region) : createSnap(repl_group_id, region)
928
+ skipsnapshots ? skipSnap(repl_group_id, region, credentials) : createSnap(repl_group_id, region, credentials)
915
929
  rescue Aws::ElastiCache::Errors::InvalidReplicationGroupState => e
916
930
  if retries < 5
917
931
  MU.log "#{repl_group_id} is not in a removable state, retrying several times", MU::WARN
@@ -924,16 +938,16 @@ module MU
924
938
  end
925
939
  rescue Aws::ElastiCache::Errors::SnapshotAlreadyExistsFault
926
940
  MU.log "Snapshot #{repl_group_id}-MUfinal already exists", MU::WARN
927
- skipSnap(repl_group_id, region)
941
+ skipSnap(repl_group_id, region, credentials)
928
942
  rescue Aws::ElastiCache::Errors::SnapshotQuotaExceededFault
929
943
  MU.log "Snapshot quota exceeded while deleting #{repl_group_id}", MU::ERR
930
- skipSnap(repl_group_id, region)
944
+ skipSnap(repl_group_id, region, credentials)
931
945
  end
932
946
 
933
947
  wait_start_time = Time.now
934
948
  retries = 0
935
949
  begin
936
- MU::Cloud::AWS.elasticache(region).wait_until(:replication_group_deleted, replication_group_id: repl_group_id) do |waiter|
950
+ MU::Cloud::AWS.elasticache(region: region).wait_until(:replication_group_deleted, replication_group_id: repl_group_id) do |waiter|
937
951
  waiter.max_attempts = nil
938
952
  waiter.before_attempt do |attempts|
939
953
  MU.log "Waiting for #{repl_group_id} to delete..", MU::NOTICE if attempts % 10 == 0
@@ -965,10 +979,10 @@ module MU
965
979
  # @param subnet_group_id [string]: The cloud provider's ID of the cache cluster subnet group.
966
980
  # @param region [String]: The cloud provider's region in which to operate.
967
981
  # @return [void]
968
- def self.delete_subnet_group(subnet_group_id, region: MU.curRegion)
982
+ def self.delete_subnet_group(subnet_group_id, region: MU.curRegion, credentials: nil)
969
983
  retries ||= 0
970
984
  MU.log "Deleting Subnet group #{subnet_group_id}"
971
- MU::Cloud::AWS.elasticache(region).delete_cache_subnet_group(cache_subnet_group_name: subnet_group_id)
985
+ MU::Cloud::AWS.elasticache(region: region, credentials: credentials).delete_cache_subnet_group(cache_subnet_group_name: subnet_group_id)
972
986
  rescue Aws::ElastiCache::Errors::CacheSubnetGroupNotFoundFault
973
987
  MU.log "Subnet group #{subnet_group_id} disappeared before we could remove it", MU::WARN
974
988
  rescue Aws::ElastiCache::Errors::CacheSubnetGroupInUse => e
@@ -986,10 +1000,10 @@ module MU
986
1000
  # @param parameter_group_id [string]: The cloud provider's ID of the cache cluster parameter group.
987
1001
  # @param region [String]: The cloud provider's region in which to operate.
988
1002
  # @return [void]
989
- def self.delete_parameter_group(parameter_group_id, region: MU.curRegion)
1003
+ def self.delete_parameter_group(parameter_group_id, region: MU.curRegion, credentials: nil)
990
1004
  retries ||= 0
991
1005
  MU.log "Deleting parameter group #{parameter_group_id}"
992
- MU::Cloud::AWS.elasticache(region).delete_cache_parameter_group(
1006
+ MU::Cloud::AWS.elasticache(region: region, credentials: credentials).delete_cache_parameter_group(
993
1007
  cache_parameter_group_name: parameter_group_id
994
1008
  )
995
1009
  rescue Aws::ElastiCache::Errors::CacheParameterGroupNotFound