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
@@ -190,14 +190,14 @@ module MU
190
190
 
191
191
  if !File.open("/etc/mtab").read.match(/ #{path} /)
192
192
  realdevice = device.dup
193
- if MU::Cloud::Google.hosted
193
+ if MU::Cloud::Google.hosted?
194
194
  realdevice = "/dev/disk/by-id/google-"+device.gsub(/.*?\/([^\/]+)$/, '\1')
195
195
  end
196
196
  alias_device = cryptfile ? "/dev/mapper/"+path.gsub(/[^0-9a-z_\-]/i, "_") : realdevice
197
197
 
198
198
  if !File.exists?(realdevice)
199
199
  MU.log "Creating #{path} volume"
200
- if MU::Cloud::AWS.hosted
200
+ if MU::Cloud::AWS.hosted?
201
201
  dummy_svr = MU::Cloud::AWS::Server.new(
202
202
  mu_name: "MU-MASTER",
203
203
  cloud_id: MU.myInstanceId,
@@ -210,7 +210,7 @@ module MU
210
210
  tag_name: "Name",
211
211
  tag_value: "#{$MU_CFG['hostname']} #{path}"
212
212
  )
213
- elsif MU::Cloud::Google.hosted
213
+ elsif MU::Cloud::Google.hosted?
214
214
  dummy_svr = MU::Cloud::Google::Server.new(
215
215
  mu_name: "MU-MASTER",
216
216
  cloud_id: MU.myInstanceId,
@@ -224,7 +224,7 @@ module MU
224
224
 
225
225
  if cryptfile
226
226
  body = nil
227
- if MU::Cloud::AWS.hosted
227
+ if MU::Cloud::AWS.hosted?
228
228
  begin
229
229
  resp = MU::Cloud::AWS.s3.get_object(bucket: MU.adminBucketName, key: cryptfile)
230
230
  body = resp.body
@@ -233,7 +233,7 @@ module MU
233
233
  %x{/bin/dd if=/dev/urandom of=#{temp_dev} bs=1M count=1 > /dev/null 2>&1}
234
234
  raise e
235
235
  end
236
- elsif MU::Cloud::Google.hosted
236
+ elsif MU::Cloud::Google.hosted?
237
237
  begin
238
238
  body = MU::Cloud::Google.storage.get_object(MU.adminBucketName, cryptfile)
239
239
  rescue Exception => e
@@ -217,10 +217,13 @@ module MU
217
217
  if @original_config.nil? or !@original_config.is_a?(Hash)
218
218
  raise DeployInitializeError, "New MommaCat repository requires config hash"
219
219
  end
220
+ credsets = {}
220
221
  @appname = @original_config['name']
221
222
  MU::Cloud.resource_types.each { |cloudclass, data|
222
223
  if !@original_config[data[:cfg_plural]].nil? and @original_config[data[:cfg_plural]].size > 0
223
224
  @original_config[data[:cfg_plural]].each { |resource|
225
+ credsets[resource['cloud']] ||= []
226
+ credsets[resource['cloud']] << resource['credentials']
224
227
  @clouds[resource['cloud']] = 0 if !@clouds.has_key?(resource['cloud'])
225
228
  @clouds[resource['cloud']] = @clouds[resource['cloud']] + 1
226
229
  }
@@ -233,13 +236,13 @@ module MU
233
236
  MU.log "Creating deploy secret for #{MU.deploy_id}"
234
237
  @deploy_secret = Password.random(256)
235
238
  if !@original_config['scrub_mu_isms']
236
- # TODO there's a nicer way to do this than hardcoding strings
237
- if @clouds["AWS"] and @clouds["AWS"] > 0
238
- MU::Cloud::AWS.writeDeploySecret(@deploy_id, @deploy_secret)
239
- end
240
- if @clouds["Google"] and @clouds["Google"] > 0
241
- MU::Cloud::Google.writeDeploySecret(@deploy_id, @deploy_secret)
242
- end
239
+ credsets.each_pair { |cloud, creds|
240
+ creds.uniq!
241
+ cloudclass = Object.const_get("MU").const_get("Cloud").const_get(cloud)
242
+ creds.each { |credentials|
243
+ cloudclass.writeDeploySecret(@deploy_id, @deploy_secret, credentials: credentials)
244
+ }
245
+ }
243
246
  end
244
247
  if set_context_to_me
245
248
  MU::MommaCat.setThreadContext(self)
@@ -807,8 +810,23 @@ module MU
807
810
  @ssh_private_key = File.read("#{ssh_dir}/#{@ssh_key_name}")
808
811
  @ssh_private_key.chomp!
809
812
 
810
- if numKittens(clouds: ["AWS"], types: ["Server", "ServerPool"]) > 0
811
- MU::Cloud::AWS.createEc2SSHKey(@ssh_key_name, @ssh_public_key)
813
+ if numKittens(clouds: ["AWS"], types: ["Server", "ServerPool", "ContainerCluster"]) > 0
814
+ creds_used = []
815
+ ["servers", "server_pools", "container_clusters"].each { |type|
816
+ next if @original_config[type].nil?
817
+ @original_config[type].each { |descriptor|
818
+ if descriptor['credentials']
819
+ creds_used << descriptor['credentials']
820
+ else
821
+ creds_used << MU::Cloud::AWS.credConfig(name_only: true)
822
+ end
823
+ }
824
+ }
825
+ creds_used << nil if creds_used.empty?
826
+
827
+ creds_used.uniq.each { |credset|
828
+ MU::Cloud::AWS.createEc2SSHKey(@ssh_key_name, @ssh_public_key, credentials: credset)
829
+ }
812
830
  end
813
831
 
814
832
  return [@ssh_key_name, @ssh_private_key, @ssh_public_key]
@@ -1037,6 +1055,7 @@ module MU
1037
1055
  name: nil,
1038
1056
  mu_name: nil,
1039
1057
  cloud_id: nil,
1058
+ credentials: nil,
1040
1059
  region: nil,
1041
1060
  tag_key: nil,
1042
1061
  tag_value: nil,
@@ -1056,6 +1075,13 @@ module MU
1056
1075
  shortclass, cfg_name, cfg_plural, classname, attrs = MU::Cloud.getResourceNames(type)
1057
1076
  resourceclass = MU::Cloud.loadCloudType(cloud, shortclass)
1058
1077
  cloudclass = Object.const_get("MU").const_get("Cloud").const_get(cloud)
1078
+
1079
+ credlist = if credentials
1080
+ [credentials]
1081
+ else
1082
+ cloudclass.listCredentials
1083
+ end
1084
+
1059
1085
  if (tag_key and !tag_value) or (!tag_key and tag_value)
1060
1086
  raise MuError, "Can't call findStray with only one of tag_key and tag_value set, must be both or neither"
1061
1087
  end
@@ -1072,13 +1098,13 @@ module MU
1072
1098
  deploy_id = mu_name.sub(/^(\w+-\w+-\d{10}-[A-Z]{2})-/, '\1')
1073
1099
  end
1074
1100
  end
1075
- MU.log "Called findStray with cloud: #{cloud}, type: #{type}, deploy_id: #{deploy_id}, calling_deploy: #{calling_deploy.deploy_id if !calling_deploy.nil?}, name: #{name}, cloud_id: #{cloud_id}, tag_key: #{tag_key}, tag_value: #{tag_value}", MU::DEBUG, details: flags
1101
+ MU.log "Called findStray with cloud: #{cloud}, type: #{type}, deploy_id: #{deploy_id}, calling_deploy: #{calling_deploy.deploy_id if !calling_deploy.nil?}, name: #{name}, cloud_id: #{cloud_id}, tag_key: #{tag_key}, tag_value: #{tag_value}, credentials: #{credentials}", MU::DEBUG, details: flags
1076
1102
 
1077
1103
  # See if the thing we're looking for is a member of the deploy that's
1078
1104
  # asking after it.
1079
1105
  if !deploy_id.nil? and !calling_deploy.nil? and flags.empty? and
1080
1106
  calling_deploy.deploy_id == deploy_id and (!name.nil? or !mu_name.nil?)
1081
- handle = calling_deploy.findLitterMate(type: type, name: name, mu_name: mu_name, cloud_id: cloud_id)
1107
+ handle = calling_deploy.findLitterMate(type: type, name: name, mu_name: mu_name, cloud_id: cloud_id, credentials: credentials)
1082
1108
  return [handle] if !handle.nil?
1083
1109
  end
1084
1110
 
@@ -1091,13 +1117,14 @@ module MU
1091
1117
  next if matches.nil? or matches.size == 0
1092
1118
  momma = MU::MommaCat.getLitter(deploy_id)
1093
1119
  straykitten = nil
1120
+
1094
1121
  # If we found exactly one match in this deploy, use its metadata to
1095
1122
  # guess at resource names we weren't told.
1096
1123
  if matches.size == 1 and name.nil? and mu_name.nil?
1097
1124
  if cloud_id.nil?
1098
- straykitten = momma.findLitterMate(type: type, name: matches.first["name"], cloud_id: matches.first["cloud_id"])
1125
+ straykitten = momma.findLitterMate(type: type, name: matches.first["name"], cloud_id: matches.first["cloud_id"], credentials: credentials)
1099
1126
  else
1100
- straykitten = momma.findLitterMate(type: type, name: matches.first["name"], cloud_id: cloud_id)
1127
+ straykitten = momma.findLitterMate(type: type, name: matches.first["name"], cloud_id: cloud_id, credentials: credentials)
1101
1128
  end
1102
1129
  # elsif !flags.nil? and !flags.empty? # XXX eh, maybe later
1103
1130
  # # see if we can narrow it down further with some flags
@@ -1111,17 +1138,23 @@ module MU
1111
1138
  # straykitten = momma.findLitterMate(type: type, name: matches.first["name"], cloud_id: filtered.first['cloud_id'])
1112
1139
  # end
1113
1140
  else
1114
- straykitten = momma.findLitterMate(type: type, name: name, mu_name: mu_name, cloud_id: cloud_id)
1141
+ # There's more than one of this type of resource in the target
1142
+ # deploy, so see if findLitterMate can narrow it down for us
1143
+ straykitten = momma.findLitterMate(type: type, name: name, mu_name: mu_name, cloud_id: cloud_id, credentials: credentials)
1115
1144
  end
1116
1145
 
1117
1146
  next if straykitten.nil?
1118
1147
 
1119
1148
  kittens[straykitten.cloud_id] = straykitten
1149
+
1120
1150
  # Peace out if we found the exact resource we want
1121
1151
  if cloud_id and straykitten.cloud_id == cloud_id
1122
1152
  return [straykitten]
1153
+ # ...or if we've validated our one possible match
1123
1154
  elsif !cloud_id and mu_descs.size == 1 and matches.size == 1
1124
1155
  return [straykitten]
1156
+ elsif credentials and credlist.size == 1 and straykitten.credentials == credentials
1157
+ return [straykitten]
1125
1158
  end
1126
1159
  }
1127
1160
 
@@ -1142,77 +1175,84 @@ module MU
1142
1175
 
1143
1176
  matches = []
1144
1177
 
1145
- if cloud_id or (tag_key and tag_value) or !flags.empty?
1146
- regions = []
1147
- begin
1148
- if region
1149
- regions << region
1150
- else
1151
- regions = cloudclass.listRegions
1178
+ credlist.each { |creds|
1179
+ if cloud_id or (tag_key and tag_value) or !flags.empty?
1180
+ regions = []
1181
+ begin
1182
+ if region
1183
+ regions << region
1184
+ else
1185
+ regions = cloudclass.listRegions(credentials: creds)
1186
+ end
1187
+ rescue NoMethodError # Not all cloud providers have regions
1188
+ regions = [""]
1152
1189
  end
1153
- rescue NoMethodError # Not all cloud providers have regions
1154
- regions = [""]
1155
- end
1156
-
1157
- if cloud == "Google" and ["vpcs", "firewall_rules"].include?(cfg_plural)
1158
- regions = [nil]
1159
- end
1160
1190
 
1161
- cloud_descs = {}
1162
- regions.each { |r|
1163
- cloud_descs[r] = resourceclass.find(cloud_id: cloud_id, region: r, tag_key: tag_key, tag_value: tag_value, flags: flags)
1164
- # Stop if you found the thing
1165
- if cloud_id and cloud_descs[r] and !cloud_descs[r].empty?
1166
- break
1191
+ if cloud == "Google" and ["vpcs", "firewall_rules"].include?(cfg_plural)
1192
+ regions = [nil]
1167
1193
  end
1168
- }
1169
- regions.each { |r|
1170
- next if cloud_descs[r].nil?
1171
- cloud_descs[r].each_pair { |kitten_cloud_id, descriptor|
1172
- # We already have a MU::Cloud object for this guy, use it
1173
- if kittens.has_key?(kitten_cloud_id)
1174
- matches << kittens[kitten_cloud_id]
1175
- elsif kittens.size == 0
1176
- if !dummy_ok
1177
- next
1178
- end
1179
- # If we don't have a MU::Cloud object, manufacture a dummy one.
1180
- # Give it a fake name if we have to and have decided that's ok.
1181
- if (name.nil? or name.empty?)
1194
+
1195
+ cloud_descs = {}
1196
+ regions.each { |r|
1197
+ cloud_descs[r] = resourceclass.find(cloud_id: cloud_id, region: r, tag_key: tag_key, tag_value: tag_value, flags: flags, credentials: creds)
1198
+ # Stop if you found the thing
1199
+ if cloud_id and cloud_descs[r] and !cloud_descs[r].empty?
1200
+ break
1201
+ end
1202
+ }
1203
+ regions.each { |r|
1204
+ next if cloud_descs[r].nil?
1205
+ cloud_descs[r].each_pair { |kitten_cloud_id, descriptor|
1206
+ # We already have a MU::Cloud object for this guy, use it
1207
+ if kittens.has_key?(kitten_cloud_id)
1208
+ matches << kittens[kitten_cloud_id]
1209
+ elsif kittens.size == 0
1182
1210
  if !dummy_ok
1183
- MU.log "Found cloud provider data for #{cloud} #{type} #{kitten_cloud_id}, but without a name I can't manufacture a proper #{type} object to return", MU::DEBUG, details: caller
1184
1211
  next
1185
- else
1186
- if !mu_name.nil?
1187
- name = mu_name
1188
- elsif !tag_value.nil?
1189
- name = tag_value
1212
+ end
1213
+ # If we don't have a MU::Cloud object, manufacture a dummy one.
1214
+ # Give it a fake name if we have to and have decided that's ok.
1215
+ if (name.nil? or name.empty?)
1216
+ if !dummy_ok
1217
+ MU.log "Found cloud provider data for #{cloud} #{type} #{kitten_cloud_id}, but without a name I can't manufacture a proper #{type} object to return", MU::DEBUG, details: caller
1218
+ next
1190
1219
  else
1191
- name = kitten_cloud_id
1220
+ if !mu_name.nil?
1221
+ name = mu_name
1222
+ elsif !tag_value.nil?
1223
+ name = tag_value
1224
+ else
1225
+ name = kitten_cloud_id
1226
+ end
1192
1227
  end
1193
1228
  end
1194
- end
1195
- cfg = {"name" => name, "cloud" => cloud, "region" => r}
1196
- # If we can at least find the config from the deploy this will
1197
- # belong with, use that, even if it's an ungroomed resource.
1198
- if !calling_deploy.nil? and
1199
- !calling_deploy.original_config.nil? and
1200
- !calling_deploy.original_config[type+"s"].nil?
1201
- calling_deploy.original_config[type+"s"].each { |s|
1202
- if s["name"] == name
1203
- cfg = s.dup
1204
- break
1205
- end
1229
+ cfg = {
1230
+ "name" => name,
1231
+ "cloud" => cloud,
1232
+ "region" => r,
1233
+ "credentials" => creds
1206
1234
  }
1235
+ # If we can at least find the config from the deploy this will
1236
+ # belong with, use that, even if it's an ungroomed resource.
1237
+ if !calling_deploy.nil? and
1238
+ !calling_deploy.original_config.nil? and
1239
+ !calling_deploy.original_config[type+"s"].nil?
1240
+ calling_deploy.original_config[type+"s"].each { |s|
1241
+ if s["name"] == name
1242
+ cfg = s.dup
1243
+ break
1244
+ end
1245
+ }
1207
1246
 
1208
- matches << resourceclass.new(mommacat: calling_deploy, kitten_cfg: cfg, cloud_id: kitten_cloud_id)
1209
- else
1210
- matches << resourceclass.new(mu_name: name, kitten_cfg: cfg, cloud_id: kitten_cloud_id.to_s)
1247
+ matches << resourceclass.new(mommacat: calling_deploy, kitten_cfg: cfg, cloud_id: kitten_cloud_id)
1248
+ else
1249
+ matches << resourceclass.new(mu_name: name, kitten_cfg: cfg, cloud_id: kitten_cloud_id.to_s)
1250
+ end
1211
1251
  end
1212
- end
1252
+ }
1213
1253
  }
1214
- }
1215
- end
1254
+ end
1255
+ }
1216
1256
  rescue Exception => e
1217
1257
  MU.log e.inspect, MU::ERR, details: e.backtrace
1218
1258
  end
@@ -1227,7 +1267,7 @@ module MU
1227
1267
  # @param created_only [Boolean]: Only return the littermate if its cloud_id method returns a value
1228
1268
  # @param return_all [Boolean]: Return a Hash of matching objects indexed by their mu_name, instead of a single match. Only valid for resource types where has_multiples is true.
1229
1269
  # @return [MU::Cloud]
1230
- def findLitterMate(type: nil, name: nil, mu_name: nil, cloud_id: nil, created_only: false, return_all: false)
1270
+ def findLitterMate(type: nil, name: nil, mu_name: nil, cloud_id: nil, created_only: false, return_all: false, credentials: nil)
1231
1271
  shortclass, cfg_name, cfg_plural, classname, attrs = MU::Cloud.getResourceNames(type)
1232
1272
  type = cfg_plural
1233
1273
  has_multiples = attrs[:has_multiples]
@@ -1236,9 +1276,17 @@ module MU
1236
1276
  if !@kittens.has_key?(type)
1237
1277
  return nil
1238
1278
  end
1239
- MU.log "findLitterMate(type: #{type}, name: #{name}, mu_name: #{mu_name}, cloud_id: #{cloud_id}, created_only: #{created_only}). Caller: #{caller[2]}", MU::DEBUG, details: @kittens.keys.map { |k| k.to_s+": "+@kittens[k].keys.join(", ") }
1279
+ MU.log "findLitterMate(type: #{type}, name: #{name}, mu_name: #{mu_name}, cloud_id: #{cloud_id}, created_only: #{created_only}, credentials: #{credentials}). has_multiples is #{attrs[:has_multiples].to_s}. Caller: #{caller[2]}", MU::DEBUG, details: @kittens.keys.map { |k| k.to_s+": "+@kittens[k].keys.join(", ") }
1280
+ matches = []
1281
+
1240
1282
  @kittens[type].each { |sib_class, data|
1241
- next if !name.nil? and name != sib_class
1283
+ virtual_name = nil
1284
+
1285
+ if !has_multiples and data and !data.is_a?(Hash) and data.config and data.config.is_a?(Hash) and data.config['virtual_name'] and name == data.config['virtual_name']
1286
+ virtual_name = data.config['virtual_name']
1287
+ elsif !name.nil? and name != sib_class
1288
+ next
1289
+ end
1242
1290
  if has_multiples
1243
1291
  if !name.nil?
1244
1292
  if return_all
@@ -1255,7 +1303,8 @@ module MU
1255
1303
  end
1256
1304
  data.each_pair { |sib_mu_name, obj|
1257
1305
  if (!mu_name.nil? and mu_name == sib_mu_name) or
1258
- (!cloud_id.nil? and cloud_id == obj.cloud_id)
1306
+ (!cloud_id.nil? and cloud_id == obj.cloud_id) or
1307
+ (!credentials.nil? and credentials == obj.credentials)
1259
1308
  if !created_only or !obj.cloud_id.nil?
1260
1309
  if return_all
1261
1310
  return data.dup
@@ -1266,13 +1315,21 @@ module MU
1266
1315
  end
1267
1316
  }
1268
1317
  else
1269
- if (name.nil? or sib_class == name) and
1270
- (cloud_id.nil? or cloud_id == data.cloud_id)
1271
- return data if !created_only or !data.cloud_id.nil?
1318
+ if (name.nil? or sib_class == name or virtual_name == name) and
1319
+ (cloud_id.nil? or cloud_id == data.cloud_id) and
1320
+ (credentials.nil? or data.credentials.nil? or credentials == data.credentials)
1321
+ matches << data if !created_only or !data.cloud_id.nil?
1272
1322
  end
1273
1323
  end
1274
1324
  }
1325
+
1326
+ return matches.first if matches.size == 1
1327
+ if return_all and matches.size > 1
1328
+ return matches
1329
+ end
1275
1330
  }
1331
+
1332
+
1276
1333
  return nil
1277
1334
  end
1278
1335
 
@@ -1373,12 +1430,13 @@ module MU
1373
1430
  def self.createTag(resource = nil,
1374
1431
  tag_name="MU-ID",
1375
1432
  tag_value=MU.deploy_id,
1376
- region: MU.curRegion)
1433
+ region: MU.curRegion,
1434
+ credentials: nil)
1377
1435
  attempts = 0
1378
1436
 
1379
1437
  if !MU::Cloud::CloudFormation.emitCloudFormation
1380
1438
  begin
1381
- MU::Cloud::AWS.ec2(region).create_tags(
1439
+ MU::Cloud::AWS.ec2(credentials: credentials, region: region).create_tags(
1382
1440
  resources: [resource],
1383
1441
  tags: [
1384
1442
  {
@@ -1412,7 +1470,7 @@ module MU
1412
1470
  # @param resource [String]: The cloud provider identifier of the resource to tag
1413
1471
  # @param region [String]: The cloud provider region
1414
1472
  # @return [void]
1415
- def self.createStandardTags(resource = nil, region: MU.curRegion)
1473
+ def self.createStandardTags(resource = nil, region: MU.curRegion, credentials: nil)
1416
1474
  tags = []
1417
1475
  listStandardTags.each_pair { |name, value|
1418
1476
  if !value.nil?
@@ -1425,7 +1483,7 @@ module MU
1425
1483
 
1426
1484
  attempts = 0
1427
1485
  begin
1428
- MU::Cloud::AWS.ec2(region).create_tags(
1486
+ MU::Cloud::AWS.ec2(region: region, credentials: credentials).create_tags(
1429
1487
  resources: [resource],
1430
1488
  tags: tags
1431
1489
  )
@@ -1508,7 +1566,7 @@ module MU
1508
1566
 
1509
1567
  mu_zone = nil
1510
1568
  # XXX GCP!
1511
- if MU::Cloud::AWS.hosted and !MU::Cloud::AWS.isGovCloud?
1569
+ if MU::Cloud::AWS.hosted? and !MU::Cloud::AWS.isGovCloud?
1512
1570
  zones = MU::Cloud::DNSZone.find(cloud_id: "platform-mu")
1513
1571
  mu_zone = zones.values.first if !zones.nil?
1514
1572
  end
@@ -2168,8 +2226,10 @@ MESSAGE_END
2168
2226
  Thread.current.thread_variable_set("name", "sync-"+sibling.mu_name.downcase)
2169
2227
  MU.setVar("syncLitterThread", true)
2170
2228
  begin
2171
- sibling.groomer.saveDeployData
2172
- sibling.groomer.run(purpose: "Synchronizing sibling kittens") if !save_all_only
2229
+ if sibling.config['groom'].nil? or sibling.config['groom']
2230
+ sibling.groomer.saveDeployData
2231
+ sibling.groomer.run(purpose: "Synchronizing sibling kittens") if !save_all_only
2232
+ end
2173
2233
  rescue MU::Groomer::RunError => e
2174
2234
  MU.log "Sync of #{sibling.mu_name} failed: #{e.inspect}", MU::WARN
2175
2235
  end
@@ -2192,9 +2252,9 @@ MESSAGE_END
2192
2252
  # @param poolname [Boolean]: If true, generate certificates for the base name of the server pool of which this node is a member, rather than for the individual node
2193
2253
  # @param keysize [Integer]: The size of the private key to use when generating this certificate
2194
2254
  def nodeSSLCerts(resource, poolname = false, keysize = 4096)
2195
- nat_ssh_key, nat_ssh_user, nat_ssh_host, canonical_ip, ssh_user, ssh_key_name = resource.getSSHConfig
2255
+ nat_ssh_key, nat_ssh_user, nat_ssh_host, canonical_ip, ssh_user, ssh_key_name = resource.getSSHConfig if resource.respond_to?(:getSSHConfig)
2196
2256
 
2197
- deploy_id = resource.deploy_id || resource.deploy.deploy_id
2257
+ deploy_id = resource.deploy_id || @deploy_id || resource.deploy.deploy_id
2198
2258
 
2199
2259
  cert_cn = poolname ? deploy_id + "-" + resource.config['name'].upcase : resource.mu_name
2200
2260
 
@@ -2222,7 +2282,7 @@ MESSAGE_END
2222
2282
 
2223
2283
  if results.size == 0
2224
2284
  certs[cert_cn] = {
2225
- "sans" => ["IP:#{canonical_ip}"],
2285
+ # "sans" => ["IP:#{canonical_ip}"],
2226
2286
  "cn" => cert_cn
2227
2287
  }
2228
2288
  if canonical_ip
@@ -2243,7 +2303,7 @@ MESSAGE_END
2243
2303
  end
2244
2304
 
2245
2305
  certs.each { |certname, data|
2246
- MU.log "Generating SSL certificate #{certname} for #{resource}"
2306
+ MU.log "Generating SSL certificate #{certname} for #{resource} with key size #{keysize.to_s}"
2247
2307
 
2248
2308
  # Create and save a key
2249
2309
  key = OpenSSL::PKey::RSA.new keysize