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
@@ -51,7 +51,7 @@ module MU
51
51
 
52
52
  zones_to_try = @config["zones"]
53
53
  begin
54
- asg = MU::Cloud::AWS.autoscale(@config['region']).create_auto_scaling_group(asg_options)
54
+ asg = MU::Cloud::AWS.autoscale(region: @config['region'], credentials: @config['credentials']).create_auto_scaling_group(asg_options)
55
55
  rescue Aws::AutoScaling::Errors::ValidationError => e
56
56
  if zones_to_try != nil and zones_to_try.size > 0
57
57
  MU.log "#{e.message}, retrying with individual AZs", MU::WARN
@@ -66,7 +66,7 @@ module MU
66
66
  if zones_to_try != nil and zones_to_try.size < @config["zones"].size
67
67
  zones_to_try.each { |zone|
68
68
  begin
69
- MU::Cloud::AWS.autoscale(@config['region']).update_auto_scaling_group(
69
+ MU::Cloud::AWS.autoscale(region: @config['region'], credentials: @config['credentials']).update_auto_scaling_group(
70
70
  auto_scaling_group_name: @mu_name,
71
71
  availability_zones: [zone]
72
72
  )
@@ -84,11 +84,11 @@ module MU
84
84
  attempts = 0
85
85
  begin
86
86
  sleep 5
87
- desc = MU::Cloud::AWS.autoscale(@config['region']).describe_auto_scaling_groups(auto_scaling_group_names: [@mu_name]).auto_scaling_groups.first
87
+ desc = MU::Cloud::AWS.autoscale(region: @config['region'], credentials: @config['credentials']).describe_auto_scaling_groups(auto_scaling_group_names: [@mu_name]).auto_scaling_groups.first
88
88
  MU.log "Looking for #{desc.min_size} instances in #{@mu_name}, found #{desc.instances.size}", MU::DEBUG
89
89
  attempts = attempts + 1
90
90
  if attempts > 25 and desc.instances.size == 0
91
- MU.log "No instances spun up after #{5*attempts} seconds, something's wrong with Autoscale group #{@mu_name}", MU::ERR, details: MU::Cloud::AWS.autoscale(@config['region']).describe_scaling_activities(auto_scaling_group_name: @mu_name).activities
91
+ MU.log "No instances spun up after #{5*attempts} seconds, something's wrong with Autoscale group #{@mu_name}", MU::ERR, details: MU::Cloud::AWS.autoscale(region: @config['region'], credentials: @config['credentials']).describe_scaling_activities(auto_scaling_group_name: @mu_name).activities
92
92
  raise MuError, "No instances spun up after #{5*attempts} seconds, something's wrong with Autoscale group #{@mu_name}"
93
93
  end
94
94
  end while desc.instances.size < desc.min_size
@@ -136,7 +136,7 @@ module MU
136
136
  t.join
137
137
  }
138
138
  MU.log "Setting min_size to #{@config['min_size']} and max_size to #{@config['max_size']}"
139
- MU::Cloud::AWS.autoscale(@config['region']).update_auto_scaling_group(
139
+ MU::Cloud::AWS.autoscale(region: @config['region'], credentials: @config['credentials']).update_auto_scaling_group(
140
140
  auto_scaling_group_name: @mu_name,
141
141
  min_size: @config['min_size'],
142
142
  max_size: @config['max_size']
@@ -158,7 +158,7 @@ module MU
158
158
  def setScaleInProtection(need_instances = @config['min_size'])
159
159
  live_instances = []
160
160
  begin
161
- desc = MU::Cloud::AWS.autoscale(@config['region']).describe_auto_scaling_groups(auto_scaling_group_names: [@mu_name]).auto_scaling_groups.first
161
+ desc = MU::Cloud::AWS.autoscale(region: @config['region'], credentials: @config['credentials']).describe_auto_scaling_groups(auto_scaling_group_names: [@mu_name]).auto_scaling_groups.first
162
162
 
163
163
  live_instances = desc.instances.map { |i| i.instance_id }
164
164
  already_set = 0
@@ -170,7 +170,7 @@ module MU
170
170
  elsif already_set > need_instances
171
171
  unset_me = live_instances.sample(already_set - need_instances)
172
172
  MU.log "Disabling scale-in protection for #{unset_me.size.to_s} instances in #{@mu_name}", MU::NOTICE, details: unset_me
173
- MU::Cloud::AWS.autoscale(@config['region']).set_instance_protection(
173
+ MU::Cloud::AWS.autoscale(region: @config['region'], credentials: @config['credentials']).set_instance_protection(
174
174
  auto_scaling_group_name: @mu_name,
175
175
  instance_ids: unset_me,
176
176
  protected_from_scale_in: false
@@ -179,7 +179,7 @@ module MU
179
179
  live_instances = live_instances.sample(need_instances)
180
180
  MU.log "Enabling scale-in protection for #{@config['scale_in_protection']} instances in #{@mu_name}", details: live_instances
181
181
  begin
182
- MU::Cloud::AWS.autoscale(@config['region']).set_instance_protection(
182
+ MU::Cloud::AWS.autoscale(region: @config['region'], credentials: @config['credentials']).set_instance_protection(
183
183
  auto_scaling_group_name: @mu_name,
184
184
  instance_ids: live_instances,
185
185
  protected_from_scale_in: true
@@ -213,7 +213,7 @@ module MU
213
213
  # Called automatically by {MU::Deploy#createResources}
214
214
  def groom
215
215
  if @config['schedule']
216
- ext_actions = MU::Cloud::AWS.autoscale(@config['region']).describe_scheduled_actions(
216
+ ext_actions = MU::Cloud::AWS.autoscale(region: @config['region'], credentials: @config['credentials']).describe_scheduled_actions(
217
217
  auto_scaling_group_name: @mu_name
218
218
  ).scheduled_update_group_actions
219
219
 
@@ -234,7 +234,7 @@ module MU
234
234
  if s['action_name'] == ext.scheduled_action_name
235
235
  if !MU.hashCmp(MU.structToHash(ext), sched_config, missing_is_default: true)
236
236
  MU.log "Removing scheduled action #{s['action_name']} from AutoScale group #{@mu_name}"
237
- MU::Cloud::AWS.autoscale(@config['region']).delete_scheduled_action(
237
+ MU::Cloud::AWS.autoscale(region: @config['region'], credentials: @config['credentials']).delete_scheduled_action(
238
238
  auto_scaling_group_name: @mu_name,
239
239
  scheduled_action_name: s['action_name']
240
240
  )
@@ -246,7 +246,7 @@ module MU
246
246
  }
247
247
  if !action_already_correct
248
248
  MU.log "Adding scheduled action to AutoScale group #{@mu_name}", MU::NOTICE, details: sched_config
249
- MU::Cloud::AWS.autoscale(@config['region']).put_scheduled_update_group_action(
249
+ MU::Cloud::AWS.autoscale(region: @config['region'], credentials: @config['credentials']).put_scheduled_update_group_action(
250
250
  sched_config
251
251
  )
252
252
  end
@@ -274,10 +274,10 @@ module MU
274
274
  if need_tag_update
275
275
  MU.log "Updating ServerPool #{@mu_name} with new tags", MU::NOTICE, details: tag_conf[:tags]
276
276
 
277
- MU::Cloud::AWS.autoscale(@config['region']).create_or_update_tags(tag_conf)
277
+ MU::Cloud::AWS.autoscale(region: @config['region'], credentials: @config['credentials']).create_or_update_tags(tag_conf)
278
278
  current.instances.each { |instance|
279
279
  tag_conf[:tags].each { |t|
280
- MU::MommaCat.createTag(instance.instance_id, t[:key], t[:value], region: @config['region'])
280
+ MU::MommaCat.createTag(instance.instance_id, t[:key], t[:value], region: @config['region'], credentials: @config['credentials'])
281
281
  }
282
282
  }
283
283
  end
@@ -291,7 +291,7 @@ module MU
291
291
  asg_options[:new_instances_protected_from_scale_in] = (@config['scale_in_protection'] == "all")
292
292
  tg_arns = []
293
293
  if asg_options[:target_group_arns]
294
- MU::Cloud::AWS.autoscale(@config['region']).attach_load_balancer_target_groups(
294
+ MU::Cloud::AWS.autoscale(region: @config['region'], credentials: @config['credentials']).attach_load_balancer_target_groups(
295
295
  auto_scaling_group_name: @mu_name,
296
296
  target_group_arns: asg_options[:target_group_arns]
297
297
  )
@@ -299,7 +299,7 @@ module MU
299
299
  asg_options.delete(:target_group_arns)
300
300
  end
301
301
 
302
- MU::Cloud::AWS.autoscale(@config['region']).update_auto_scaling_group(asg_options)
302
+ MU::Cloud::AWS.autoscale(region: @config['region'], credentials: @config['credentials']).update_auto_scaling_group(asg_options)
303
303
 
304
304
  if @config['scale_in_protection']
305
305
  if @config['scale_in_protection'] == "all"
@@ -313,7 +313,7 @@ module MU
313
313
  setScaleInProtection(0)
314
314
  end
315
315
 
316
- ext_pols = MU::Cloud::AWS.autoscale(@config['region']).describe_policies(
316
+ ext_pols = MU::Cloud::AWS.autoscale(region: @config['region'], credentials: @config['credentials']).describe_policies(
317
317
  auto_scaling_group_name: @mu_name
318
318
  ).scaling_policies
319
319
  if @config["scaling_policies"] and @config["scaling_policies"].size > 0
@@ -325,7 +325,7 @@ module MU
325
325
  ext_pols.each { |ext|
326
326
  if !legit_policies.include?(ext.policy_name)
327
327
  MU.log "Scaling policy #{ext.policy_name} is not named in scaling_policies, removing from #{@mu_name}", MU::NOTICE, details: ext
328
- MU::Cloud::AWS.autoscale(@config['region']).delete_policy(
328
+ MU::Cloud::AWS.autoscale(region: @config['region'], credentials: @config['credentials']).delete_policy(
329
329
  auto_scaling_group_name: @mu_name,
330
330
  policy_name: ext.policy_name
331
331
  )
@@ -389,7 +389,7 @@ module MU
389
389
  ext_pols.each { |ext|
390
390
  if ext.policy_name == policy_name
391
391
  if !MU.hashCmp(MU.structToHash(ext), policy_params, missing_is_default: true)
392
- MU::Cloud::AWS.autoscale(@config['region']).delete_policy(
392
+ MU::Cloud::AWS.autoscale(region: @config['region'], credentials: @config['credentials']).delete_policy(
393
393
  auto_scaling_group_name: @mu_name,
394
394
  policy_name: policy_name
395
395
  )
@@ -401,44 +401,9 @@ module MU
401
401
  }
402
402
  if !policy_already_correct
403
403
  MU.log "Putting scaling policy #{policy_name} for #{@mu_name}", MU::NOTICE, details: policy_params
404
- resp = MU::Cloud::AWS.autoscale(@config['region']).put_scaling_policy(policy_params)
404
+ resp = MU::Cloud::AWS.autoscale(region: @config['region'], credentials: @config['credentials']).put_scaling_policy(policy_params)
405
405
  end
406
406
 
407
-
408
- # If we are creating alarms for scaling policies we need to have the autoscaling policy ARN
409
- # To make life easier we're creating the alarms here
410
- if policy.has_key?("alarms") && !policy["alarms"].empty?
411
- policy["alarms"].each { |alarm|
412
- alarm["alarm_actions"] = [] if !alarm.has_key?("alarm_actions")
413
- alarm["ok_actions"] = [] if !alarm.has_key?("ok_actions")
414
- alarm["alarm_actions"] << resp.policy_arn
415
- alarm["dimensions"] = [{name: "AutoScalingGroupName", value: asg_options[:auto_scaling_group_name]}]
416
-
417
- if alarm["enable_notifications"]
418
- topic_arn = MU::Cloud::AWS::Notification.createTopic(alarm["notification_group"], region: @config["region"])
419
- MU::Cloud::AWS::Notification.subscribe(arn: topic_arn, protocol: alarm["notification_type"], endpoint: alarm["notification_endpoint"], region: @config["region"])
420
- alarm["alarm_actions"] << topic_arn
421
- alarm["ok_actions"] << topic_arn
422
- end
423
-
424
- MU::Cloud::AWS::Alarm.setAlarm(
425
- name: "#{MU.deploy_id}-#{alarm["name"]}".upcase,
426
- ok_actions: alarm["ok_actions"],
427
- alarm_actions: alarm["alarm_actions"],
428
- insufficient_data_actions: alarm["no_data_actions"],
429
- metric_name: alarm["metric_name"],
430
- namespace: alarm["namespace"],
431
- statistic: alarm["statistic"],
432
- dimensions: alarm["dimensions"],
433
- period: alarm["period"],
434
- unit: alarm["unit"],
435
- evaluation_periods: alarm["evaluation_periods"],
436
- threshold: alarm["threshold"],
437
- comparison_operator: alarm["comparison_operator"],
438
- region: @config["region"]
439
- )
440
- }
441
- end
442
407
  }
443
408
  end
444
409
 
@@ -447,7 +412,7 @@ module MU
447
412
  # Retrieve the AWS descriptor for this Autoscale group
448
413
  # @return [OpenStruct]
449
414
  def cloud_desc
450
- MU::Cloud::AWS.autoscale(@config['region']).describe_auto_scaling_groups(
415
+ MU::Cloud::AWS.autoscale(region: @config['region'], credentials: @config['credentials']).describe_auto_scaling_groups(
451
416
  auto_scaling_group_names: [@mu_name]
452
417
  ).auto_scaling_groups.first
453
418
  end
@@ -471,10 +436,10 @@ module MU
471
436
  # @param tag_value [String]: The value of the tag specified by tag_key to match when searching by tag.
472
437
  # @param flags [Hash]: Optional flags
473
438
  # @return [Array<Hash<String,OpenStruct>>]: The cloud provider's complete descriptions of matching ServerPools
474
- def self.find(cloud_id: nil, region: MU.curRegion, tag_key: "Name", tag_value: nil, flags: {})
439
+ def self.find(cloud_id: nil, region: MU.curRegion, tag_key: "Name", tag_value: nil, credentials: nil, flags: {})
475
440
  found = []
476
441
  if cloud_id
477
- resp = MU::Cloud::AWS.autoscale(region).describe_auto_scaling_groups({
442
+ resp = MU::Cloud::AWS.autoscale(region: region, credentials: credentials).describe_auto_scaling_groups({
478
443
  auto_scaling_group_names: [
479
444
  cloud_id
480
445
  ],
@@ -751,7 +716,7 @@ module MU
751
716
  ok = true
752
717
 
753
718
  if pool["termination_policy"]
754
- valid_policies = MU::Cloud::AWS.autoscale(pool['region']).describe_termination_policy_types.termination_policy_types
719
+ valid_policies = MU::Cloud::AWS.autoscale(region: pool['region']).describe_termination_policy_types.termination_policy_types
755
720
  if !valid_policies.include?(pool["termination_policy"])
756
721
  ok = false
757
722
  MU.log "Termination policy #{pool["termination_policy"]} is not valid in region #{pool['region']}", MU::ERR, details: valid_policies
@@ -853,6 +818,7 @@ module MU
853
818
  # XXX maybe break this down into policies and add those?
854
819
  end
855
820
 
821
+ role['credentials'] = pool['credentials'] if pool['credentials']
856
822
  configurator.insertKitten(role, "roles")
857
823
  pool["dependencies"] ||= []
858
824
  pool["dependencies"] << {
@@ -949,7 +915,9 @@ module MU
949
915
  alarm['dimensions'] << { "name" => pool["name"], "cloud_class" => "AutoScalingGroupName" }
950
916
  alarm["namespace"] = "AWS/EC2" if alarm["namespace"].nil?
951
917
  alarm['cloud'] = pool['cloud']
952
- # ok = false if !insertKitten(alarm, "alarms")
918
+ alarm['credentials'] = pool['credentials']
919
+ alarm['region'] = pool['region']
920
+ ok = false if !configurator.insertKitten(alarm, "alarms")
953
921
  }
954
922
  end
955
923
  }
@@ -957,17 +925,24 @@ module MU
957
925
  ok
958
926
  end
959
927
 
928
+ # Does this resource type exist as a global (cloud-wide) artifact, or
929
+ # is it localized to a region/zone?
930
+ # @return [Boolean]
931
+ def self.isGlobal?
932
+ false
933
+ end
934
+
960
935
  # Remove all autoscale groups associated with the currently loaded deployment.
961
936
  # @param noop [Boolean]: If true, will only print what would be done
962
937
  # @param ignoremaster [Boolean]: If true, will remove resources not flagged as originating from this Mu server
963
938
  # @param region [String]: The cloud provider region
964
939
  # @return [void]
965
- def self.cleanup(noop: false, ignoremaster: false, region: MU.curRegion, flags: {})
940
+ def self.cleanup(noop: false, ignoremaster: false, region: MU.curRegion, credentials: nil, flags: {})
966
941
  filters = [{name: "key", values: ["MU-ID"]}]
967
942
  if !ignoremaster
968
943
  filters << {name: "key", values: ["MU-MASTER-IP"]}
969
944
  end
970
- resp = MU::Cloud::AWS.autoscale(region).describe_tags(
945
+ resp = MU::Cloud::AWS.autoscale(credentials: credentials, region: region).describe_tags(
971
946
  filters: filters,
972
947
  max_records: 100
973
948
  )
@@ -995,7 +970,7 @@ module MU
995
970
  next if noop
996
971
  retries = 0
997
972
  begin
998
- MU::Cloud::AWS.autoscale(region).delete_auto_scaling_group(
973
+ MU::Cloud::AWS.autoscale(credentials: credentials, region: region).delete_auto_scaling_group(
999
974
  auto_scaling_group_name: resource_id,
1000
975
  # XXX this should obey @force
1001
976
  force_delete: true
@@ -1017,7 +992,7 @@ module MU
1017
992
  retries = 0
1018
993
  begin
1019
994
  MU.log "Removing AutoScale Launch Configuration #{resource_id}"
1020
- MU::Cloud::AWS.autoscale(region).delete_launch_configuration(
995
+ MU::Cloud::AWS.autoscale(credentials: credentials, region: region).delete_launch_configuration(
1021
996
  launch_configuration_name: resource_id
1022
997
  )
1023
998
  rescue Aws::AutoScaling::Errors::ValidationError => e
@@ -1054,12 +1029,13 @@ module MU
1054
1029
  elsif !@config['basis']['launch_config']["instance_id"].nil?
1055
1030
  @config['basis']['launch_config']["ami_id"] = MU::Cloud::AWS::Server.createImage(
1056
1031
  name: @mu_name,
1057
- instance_id: @config['basis']['launch_config']["instance_id"]
1032
+ instance_id: @config['basis']['launch_config']["instance_id"],
1033
+ credentials: @config['credentials']
1058
1034
  )
1059
1035
  end
1060
- MU::Cloud::AWS::Server.waitForAMI(@config['basis']['launch_config']["ami_id"])
1036
+ MU::Cloud::AWS::Server.waitForAMI(@config['basis']['launch_config']["ami_id"], credentials: @config['credentials'])
1061
1037
 
1062
- oldlaunch = MU::Cloud::AWS.autoscale(@config['region']).describe_launch_configurations(
1038
+ oldlaunch = MU::Cloud::AWS.autoscale(region: @config['region'], credentials: @config['credentials']).describe_launch_configurations(
1063
1039
  launch_configuration_names: [@mu_name]
1064
1040
  ).launch_configurations.first
1065
1041
 
@@ -1131,7 +1107,7 @@ module MU
1131
1107
  # Put our Autoscale group onto a temporary launch config
1132
1108
  begin
1133
1109
 
1134
- MU::Cloud::AWS.autoscale(@config['region']).create_launch_configuration(
1110
+ MU::Cloud::AWS.autoscale(region: @config['region'], credentials: @config['credentials']).create_launch_configuration(
1135
1111
  launch_configuration_name: @mu_name+"-TMP",
1136
1112
  user_data: Base64.encode64(olduserdata),
1137
1113
  image_id: oldlaunch.image_id,
@@ -1154,12 +1130,12 @@ module MU
1154
1130
  end
1155
1131
 
1156
1132
 
1157
- MU::Cloud::AWS.autoscale(@config['region']).update_auto_scaling_group(
1133
+ MU::Cloud::AWS.autoscale(region: @config['region'], credentials: @config['credentials']).update_auto_scaling_group(
1158
1134
  auto_scaling_group_name: @mu_name,
1159
1135
  launch_configuration_name: @mu_name+"-TMP"
1160
1136
  )
1161
1137
  # ...now back to an identical one with the "real" name
1162
- MU::Cloud::AWS.autoscale(@config['region']).delete_launch_configuration(
1138
+ MU::Cloud::AWS.autoscale(region: @config['region'], credentials: @config['credentials']).delete_launch_configuration(
1163
1139
  launch_configuration_name: @mu_name
1164
1140
  )
1165
1141
  end
@@ -1197,9 +1173,16 @@ module MU
1197
1173
  }
1198
1174
 
1199
1175
  if @config['basis']['launch_config']['generate_iam_role']
1200
- # Using ARN instead of IAM instance profile name to hopefully get around some random AWS failures
1201
- rolename, cfm_role_name, cfm_prof_name, arn = MU::Cloud::AWS::Server.createIAMProfile(@mu_name, base_profile: @config['basis']['launch_config']['iam_role'], extra_policies: @config['basis']['launch_config']['iam_policies'], canned_policies: @config['basis']['launch_config']['canned_iam_policies'])
1202
- launch_options[:iam_instance_profile] = rolename
1176
+ role = @deploy.findLitterMate(name: @config['name'], type: "roles")
1177
+ # XXX are these the right patterns for a pool, or did we need wildcards?
1178
+ s3_objs = ["#{@deploy.deploy_id}-secret", "#{role.mu_name}.pfx", "#{role.mu_name}.crt", "#{role.mu_name}.key", "#{role.mu_name}-winrm.crt", "#{role.mu_name}-winrm.key"].map { |file|
1179
+ 'arn:'+(MU::Cloud::AWS.isGovCloud?(@config['region']) ? "aws-us-gov" : "aws")+':s3:::'+MU.adminBucketName+'/'+file
1180
+ }
1181
+ role.cloudobj.injectPolicyTargets("MuSecrets", s3_objs)
1182
+
1183
+ @config['iam_role'] = role.mu_name
1184
+
1185
+ launch_options[:iam_instance_profile] = role.cloudobj.createInstanceProfile
1203
1186
  elsif @config['basis']['launch_config']['iam_role'].nil?
1204
1187
  raise MuError, "#{@mu_name} has generate_iam_role set to false, but no iam_role assigned."
1205
1188
  else
@@ -1208,18 +1191,12 @@ module MU
1208
1191
 
1209
1192
  @config['iam_role'] = rolename ? rolename : launch_options[:iam_instance_profile]
1210
1193
 
1211
- if rolename
1212
- MU::Cloud::AWS::Server.addStdPoliciesToIAMProfile(rolename, region: @config['region'])
1213
- else
1214
- MU::Cloud::AWS::Server.addStdPoliciesToIAMProfile(@config['iam_role'], region: @config['region'])
1215
- end
1216
-
1217
1194
  lc_attempts = 0
1218
1195
  begin
1219
- MU::Cloud::AWS.autoscale(@config['region']).create_launch_configuration(launch_options)
1196
+ MU::Cloud::AWS.autoscale(region: @config['region'], credentials: @config['credentials']).create_launch_configuration(launch_options)
1220
1197
  rescue Aws::AutoScaling::Errors::ValidationError => e
1221
1198
  if lc_attempts > 3
1222
- MU.log "Got error while creating #{@mu_name} Launch Config: #{e.message}, retrying in 10s", MU::WARN
1199
+ MU.log "Got error while creating #{@mu_name} Launch Config#{@config['credentials'] ? " with credentials #{@config['credentials']}" : ""}: #{e.message}, retrying in 10s", MU::WARN, details: launch_options.reject { |k,v | k == :user_data }
1223
1200
  end
1224
1201
  sleep 5
1225
1202
  lc_attempts += 1
@@ -1228,11 +1205,11 @@ module MU
1228
1205
 
1229
1206
  if !oldlaunch.nil?
1230
1207
  # Tell the ASG to use the new one, and nuke the old one
1231
- MU::Cloud::AWS.autoscale(@config['region']).update_auto_scaling_group(
1208
+ MU::Cloud::AWS.autoscale(region: @config['region'], credentials: @config['credentials']).update_auto_scaling_group(
1232
1209
  auto_scaling_group_name: @mu_name,
1233
1210
  launch_configuration_name: @mu_name
1234
1211
  )
1235
- MU::Cloud::AWS.autoscale(@config['region']).delete_launch_configuration(
1212
+ MU::Cloud::AWS.autoscale(region: @config['region'], credentials: @config['credentials']).delete_launch_configuration(
1236
1213
  launch_configuration_name: @mu_name+"-TMP"
1237
1214
  )
1238
1215
  MU.log "Launch Configuration #{@mu_name} replaced"
@@ -1375,7 +1352,7 @@ module MU
1375
1352
  # Do the dance of specifying individual zones if we haven't asked to
1376
1353
  # use particular VPC subnets.
1377
1354
  if @config['zones'].nil? and asg_options[:vpc_zone_identifier].nil?
1378
- @config["zones"] = MU::Cloud::AWS.listAZs(@config['region'])
1355
+ @config["zones"] = MU::Cloud::AWS.listAZs(region: @config['region'])
1379
1356
  MU.log "Using zones from #{@config['region']}", MU::DEBUG, details: @config['zones']
1380
1357
  end
1381
1358
  asg_options[:availability_zones] = @config["zones"] if @config["zones"] != nil
@@ -36,7 +36,7 @@ module MU
36
36
  # @return [String]: The cloud provider's identifier for this storage pool.
37
37
  def create
38
38
  MU.log "Creating storage pool #{@mu_name}"
39
- resp = MU::Cloud::AWS.efs(@config['region']).create_file_system(
39
+ resp = MU::Cloud::AWS.efs(region: @config['region'], credentials: @config['credentials']).create_file_system(
40
40
  creation_token: @mu_name,
41
41
  performance_mode: @config['storage_type']
42
42
  )
@@ -44,7 +44,7 @@ module MU
44
44
  attempts = 0
45
45
  loop do
46
46
  MU.log "Waiting for #{@mu_name}: #{resp.file_system_id} to become available" if attempts % 5 == 0
47
- storage_pool = MU::Cloud::AWS.efs(@config['region']).describe_file_systems(
47
+ storage_pool = MU::Cloud::AWS.efs(region: @config['region'], credentials: @config['credentials']).describe_file_systems(
48
48
  creation_token: @mu_name
49
49
  ).file_systems.first
50
50
  break if storage_pool.life_cycle_state == "available"
@@ -54,7 +54,7 @@ module MU
54
54
  raise MuError, "timed out waiting for #{resp.mount_target_id }" if attempts >= 20
55
55
  end
56
56
 
57
- addStandardTags(cloud_id: resp.file_system_id, region: @config['region'])
57
+ addStandardTags(cloud_id: resp.file_system_id, region: @config['region'], credentials: @config['credentials'])
58
58
  @cloud_id = resp.file_system_id
59
59
 
60
60
  if @config['mount_points'] && !@config['mount_points'].empty?
@@ -89,6 +89,7 @@ module MU
89
89
  ip_address: target['ip_address'],
90
90
  subnet_id: target['vpc']['subnet_id'],
91
91
  security_groups: sgs,
92
+ credentials: @config['credentials'],
92
93
  region: @config['region']
93
94
  )
94
95
  target['cloud_id'] = mount_target.mount_target_id
@@ -106,7 +107,7 @@ module MU
106
107
  # Canonical Amazon Resource Number for this resource
107
108
  # @return [String]
108
109
  def arn
109
- "arn:"+(MU::Cloud::AWS.isGovCloud?(@config["region"]) ? "aws-us-gov" : "aws")+":elasticfilesystem:"+@config['region']+":"+MU.account_number+":file-system/"+@cloud_id
110
+ "arn:"+(MU::Cloud::AWS.isGovCloud?(@config["region"]) ? "aws-us-gov" : "aws")+":elasticfilesystem:"+@config['region']+":"+MU::Cloud::AWS.credToAcct(@config['credentials'])+":file-system/"+@cloud_id
110
111
  end
111
112
 
112
113
  # Locate an existing storage pool and return an array containing matching AWS resource descriptors for those that match.
@@ -116,10 +117,10 @@ module MU
116
117
  # @param tag_value [String]: The value of the tag specified by tag_key to match when searching by tag.
117
118
  # @param flags [Hash]: Optional flags
118
119
  # @return [Array<Hash<String,OpenStruct>>]: The cloud provider's complete descriptions of matching storage pool
119
- def self.find(cloud_id: nil, region: MU.curRegion, tag_key: "Name", tag_value: nil, flags: {})
120
+ def self.find(cloud_id: nil, region: MU.curRegion, tag_key: "Name", tag_value: nil, credentials: nil, flags: {})
120
121
  map = {}
121
122
  if cloud_id
122
- storge_pool = MU::Cloud::AWS.efs(region).describe_file_systems(
123
+ storge_pool = MU::Cloud::AWS.efs(region: region, credentials: credentials).describe_file_systems(
123
124
  file_system_id: cloud_id
124
125
  ).file_systems.first
125
126
 
@@ -127,11 +128,11 @@ module MU
127
128
  end
128
129
 
129
130
  if tag_value
130
- storage_pools = MU::Cloud::AWS.efs(region).describe_file_systems.file_systems
131
+ storage_pools = MU::Cloud::AWS.efs(region: region, credentials: credentials).describe_file_systems.file_systems
131
132
 
132
133
  if !storage_pools.empty?
133
134
  storage_pools.each{ |pool|
134
- tags = MU::Cloud::AWS.efs(region).describe_tags(
135
+ tags = MU::Cloud::AWS.efs(region: region, credentials: credentials).describe_tags(
135
136
  file_system_id: pool.file_system_id
136
137
  ).tags
137
138
 
@@ -157,7 +158,7 @@ module MU
157
158
  # Add our standard tag set to an Amazon EFS File System.
158
159
  # @param cloud_id [String]: The cloud provider's identifier for this resource.
159
160
  # @param region [String]: The cloud provider region
160
- def addStandardTags(cloud_id: nil, region: MU.curRegion)
161
+ def addStandardTags(cloud_id: nil, region: MU.curRegion, credentials: nil)
161
162
  if cloud_id
162
163
  tags = []
163
164
  MU::MommaCat.listStandardTags.each_pair { |name, value|
@@ -180,7 +181,7 @@ module MU
180
181
 
181
182
  tags << {key: "Name", value: @mu_name} unless name_tag
182
183
 
183
- MU::Cloud::AWS.efs(region).create_tags(
184
+ MU::Cloud::AWS.efs(region: region, credentials: credentials).create_tags(
184
185
  file_system_id: cloud_id,
185
186
  tags: tags
186
187
  )
@@ -200,10 +201,10 @@ module MU
200
201
  # @param subnet_id [String]: The subnet_id to associate the mount point with
201
202
  # @param security_groups [Array]: A list of security groups to associate with the mount point.
202
203
  # @param region [String]: The cloud provider region
203
- def self.create_mount_target(cloud_id: nil, ip_address: nil, subnet_id: nil, security_groups: [], region: MU.curRegion)
204
+ def self.create_mount_target(cloud_id: nil, ip_address: nil, subnet_id: nil, security_groups: [], region: MU.curRegion, credentials: nil)
204
205
  MU.log "Creating mount target for filesystem #{cloud_id}"
205
206
 
206
- resp = MU::Cloud::AWS.efs(region).create_mount_target(
207
+ resp = MU::Cloud::AWS.efs(region: region, credentials: credentials).create_mount_target(
207
208
  file_system_id: cloud_id,
208
209
  subnet_id: subnet_id,
209
210
  ip_address: ip_address,
@@ -215,12 +216,12 @@ module MU
215
216
  loop do
216
217
  MU.log "Waiting for #{resp.mount_target_id} to become available", MU::NOTICE if attempts % 10 == 0
217
218
  begin
218
- mount_target = MU::Cloud::AWS.efs(region).describe_mount_targets(
219
+ mount_target = MU::Cloud::AWS.efs(region: region, credentials: credentials).describe_mount_targets(
219
220
  mount_target_id: resp.mount_target_id
220
221
  ).mount_targets.first
221
222
  rescue Aws::EFS::Errors::MountTargetNotFound
222
223
  if retries <= 3
223
- sleep 5
224
+ sleep 10
224
225
  retry
225
226
  else
226
227
  return nil
@@ -244,7 +245,7 @@ module MU
244
245
  # @param region [String]: The cloud provider region
245
246
  def self.modify_security_groups(cloud_id: nil, replace: false , security_groups: [], region: MU.curRegion)
246
247
  unless replace
247
- extisting_sgs = MU::Cloud::AWS.efs(region).describe_mount_target_security_groups(
248
+ extisting_sgs = MU::Cloud::AWS.efs(region: region).describe_mount_target_security_groups(
248
249
  mount_target_id: cloud_id
249
250
  ).security_groups
250
251
 
@@ -252,7 +253,7 @@ module MU
252
253
  end
253
254
 
254
255
  security_groups.uniq!
255
- resp = MU::Cloud::AWS.efs(region).modify_mount_target_security_groups(
256
+ resp = MU::Cloud::AWS.efs(region: region).modify_mount_target_security_groups(
256
257
  mount_target_id: cloud_id,
257
258
  security_groups: security_groups
258
259
  )
@@ -261,7 +262,7 @@ module MU
261
262
  # Register a description of this storage pool with this deployment's metadata.
262
263
  def notify
263
264
  deploy_struct = {}
264
- storage_pool = MU::Cloud::AWS.efs(@config['region']).describe_file_systems(
265
+ storage_pool = MU::Cloud::AWS.efs(region: @config['region'], credentials: @config['credentials']).describe_file_systems(
265
266
  creation_token: @mu_name
266
267
  ).file_systems.first
267
268
 
@@ -272,19 +273,33 @@ module MU
272
273
  subnet = nil
273
274
  dependencies
274
275
  mp_vpc = if mp['vpc'] and mp['vpc']['vpc_name']
275
- @deploy.findLitterMate(type: "vpc", name: mp['vpc']['vpc_name'])
276
+ @deploy.findLitterMate(type: "vpc", name: mp['vpc']['vpc_name'], credentials: @config['credentials'])
277
+ elsif mp['vpc']
278
+ MU::MommaCat.findStray(
279
+ @config['cloud'],
280
+ "vpcs",
281
+ deploy_id: mp['vpc']["deploy_id"],
282
+ credentials: @config['credentials'],
283
+ mu_name: mp['vpc']["mu_name"],
284
+ cloud_id: mp['vpc']['vpc_id'],
285
+ region: @config['region'],
286
+ dummy_ok: false
287
+ ).first
276
288
  # XXX non-sibling, findStray version
277
289
  end
278
290
 
279
- mount_targets = MU::Cloud::AWS.efs(@config['region']).describe_mount_targets(
291
+ mount_targets = MU::Cloud::AWS.efs(region: @config['region'], credentials: @config['credentials']).describe_mount_targets(
280
292
  file_system_id: storage_pool.file_system_id
281
293
  ).mount_targets
282
294
 
295
+ # subnet_obj = mp_vpc.subnets.select { |s|
296
+ # s.name == mp["vpc"]["subnet_name"] or s.cloud_id == mp["vpc"]["subnet_id"]
297
+ # }.first
283
298
  mount_target = nil
284
- subnet_cidr_obj = NetAddr::IPv4Net.parse(subnet_obj.ip_block)
285
299
  mp_vpc.subnets.each { |subnet_obj|
286
300
  mount_targets.map { |t|
287
- if subnet_cidr_obj.contains(t.ip_address)
301
+ subnet_cidr_obj = NetAddr::IPv4Net.parse(subnet_obj.ip_block)
302
+ if subnet_cidr_obj.contains(NetAddr::IPv4.parse(t.ip_address))
288
303
  mount_target = t
289
304
  subnet = subnet_obj.cloud_desc
290
305
  end
@@ -292,7 +307,7 @@ module MU
292
307
  break if mount_target
293
308
  }
294
309
 
295
- # mount_target = MU::Cloud::AWS.efs(@config['region']).describe_mount_targets(
310
+ # mount_target = MU::Cloud::AWS.efs(region: @config['region'], credentials: @config['credentials']).describe_mount_targets(
296
311
  # mount_target_id: mp["cloud_id"]
297
312
  # ).mount_targets.first
298
313
 
@@ -303,7 +318,7 @@ module MU
303
318
  "file_system_id" => mount_target.file_system_id,
304
319
  "mount_directory" => mp["directory"],
305
320
  "subnet_id" => mount_target.subnet_id,
306
- "vpc_id" => subnet.vpc_id,
321
+ "vpc_id" => mp_vpc.cloud_id,
307
322
  "availability_zone" => subnet.availability_zone,
308
323
  "state" => mount_target.life_cycle_state,
309
324
  "ip_address" => mount_target.ip_address,
@@ -327,17 +342,24 @@ module MU
327
342
  return deploy_struct
328
343
  end
329
344
 
345
+ # Does this resource type exist as a global (cloud-wide) artifact, or
346
+ # is it localized to a region/zone?
347
+ # @return [Boolean]
348
+ def self.isGlobal?
349
+ false
350
+ end
351
+
330
352
  # Called by {MU::Cleanup}. Locates resources that were created by the
331
353
  # currently-loaded deployment, and purges them.
332
354
  # @param noop [Boolean]: If true, will only print what would be done
333
355
  # @param ignoremaster [Boolean]: If true, will remove resources not flagged as originating from this Mu server
334
356
  # @param region [String]: The cloud provider region in which to operate
335
357
  # @return [void]
336
- def self.cleanup(noop: false, ignoremaster: false, region: MU.curRegion, flags: {})
358
+ def self.cleanup(noop: false, ignoremaster: false, region: MU.curRegion, credentials: nil, flags: {})
337
359
  supported_regions = %w{us-west-2 us-east-1 eu-west-1}
338
360
  if supported_regions.include?(region)
339
361
  begin
340
- resp = MU::Cloud::AWS.efs(region).describe_file_systems
362
+ resp = MU::Cloud::AWS.efs(credentials: credentials, region: region).describe_file_systems
341
363
  return if resp.nil? or resp.file_systems.nil?
342
364
  storage_pools = resp.file_systems
343
365
  rescue Aws::EFS::Errors::AccessDeniedException
@@ -350,7 +372,7 @@ module MU
350
372
 
351
373
  if !storage_pools.empty?
352
374
  storage_pools.each{ |pool|
353
- tags = MU::Cloud::AWS.efs(region).describe_tags(
375
+ tags = MU::Cloud::AWS.efs(credentials: credentials, region: region).describe_tags(
354
376
  file_system_id: pool.file_system_id
355
377
  ).tags
356
378
 
@@ -372,7 +394,7 @@ module MU
372
394
 
373
395
  # How to identify mount points in a reliable way? Mount points are not tagged, which means we can only reliably identify mount points based on a filesystem ID. We can you our deployment metadata, but it isn’t necessarily reliable
374
396
  # begin
375
- # resp = MU::Cloud::AWS.efs(region).delete_mount_target(
397
+ # resp = MU::Cloud::AWS.efs(credentials: credentials, region: region).delete_mount_target(
376
398
  # mount_target_id: "MountTargetId"
377
399
  # )
378
400
  # MU.log "Deleted mount target"
@@ -382,7 +404,7 @@ module MU
382
404
 
383
405
  if !our_pools.empty?
384
406
  our_pools.each{ |pool|
385
- mount_targets = MU::Cloud::AWS.efs(region).describe_mount_targets(
407
+ mount_targets = MU::Cloud::AWS.efs(credentials: credentials, region: region).describe_mount_targets(
386
408
  file_system_id: pool.file_system_id
387
409
  ).mount_targets
388
410
 
@@ -391,7 +413,7 @@ module MU
391
413
  MU.log "Deleting mount target #{mp.mount_target_id} for filesystem #{pool.name}: #{pool.file_system_id}"
392
414
  unless noop
393
415
  begin
394
- resp = MU::Cloud::AWS.efs(region).delete_mount_target(
416
+ resp = MU::Cloud::AWS.efs(credentials: credentials, region: region).delete_mount_target(
395
417
  mount_target_id: mp.mount_target_id
396
418
  )
397
419
  rescue Aws::EFS::Errors::BadRequest => e
@@ -405,7 +427,7 @@ module MU
405
427
  unless noop
406
428
  attempts = 0
407
429
  begin
408
- resp = MU::Cloud::AWS.efs(region).delete_file_system(
430
+ resp = MU::Cloud::AWS.efs(credentials: credentials, region: region).delete_file_system(
409
431
  file_system_id: pool.file_system_id
410
432
  )
411
433
  rescue Aws::EFS::Errors::BadRequest => e
@@ -474,7 +496,13 @@ module MU
474
496
  pool['mount_points'].each{ |mp|
475
497
  if mp['ingress_rules']
476
498
  fwname = "storage-#{mp['name']}"
477
- acl = {"name" => fwname, "rules" => mp['ingress_rules'], "region" => pool['region'], "optional_tags" => pool['optional_tags']}
499
+ acl = {
500
+ "name" => fwname,
501
+ "rules" => mp['ingress_rules'],
502
+ "region" => pool['region'],
503
+ "credentials" => pool['credentials'],
504
+ "optional_tags" => pool['optional_tags']
505
+ }
478
506
  acl["tags"] = pool['tags'] if pool['tags'] && !pool['tags'].empty?
479
507
  acl["vpc"] = mp['vpc'].dup if mp['vpc']
480
508
  ok = false if !configurator.insertKitten(acl, "firewall_rules")