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

Sign up to get free protection for your applications and to get access to all the features.
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