cloud-mu 3.1.2 → 3.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Dockerfile +15 -3
- data/ansible/roles/mu-windows/README.md +33 -0
- data/ansible/roles/mu-windows/defaults/main.yml +2 -0
- data/ansible/roles/mu-windows/files/LaunchConfig.json +9 -0
- data/ansible/roles/mu-windows/files/config.xml +76 -0
- data/ansible/roles/mu-windows/handlers/main.yml +2 -0
- data/ansible/roles/mu-windows/meta/main.yml +53 -0
- data/ansible/roles/mu-windows/tasks/main.yml +36 -0
- data/ansible/roles/mu-windows/tests/inventory +2 -0
- data/ansible/roles/mu-windows/tests/test.yml +5 -0
- data/ansible/roles/mu-windows/vars/main.yml +2 -0
- data/bin/mu-adopt +10 -13
- data/bin/mu-azure-tests +57 -0
- data/bin/mu-cleanup +2 -4
- data/bin/mu-configure +52 -0
- data/bin/mu-deploy +3 -3
- data/bin/mu-findstray-tests +25 -0
- data/bin/mu-gen-docs +2 -4
- data/bin/mu-load-config.rb +2 -3
- data/bin/mu-node-manage +15 -16
- data/bin/mu-run-tests +135 -37
- data/cloud-mu.gemspec +22 -20
- data/cookbooks/mu-activedirectory/resources/domain.rb +4 -4
- data/cookbooks/mu-activedirectory/resources/domain_controller.rb +4 -4
- data/cookbooks/mu-tools/libraries/helper.rb +3 -2
- data/cookbooks/mu-tools/libraries/monkey.rb +35 -0
- data/cookbooks/mu-tools/recipes/apply_security.rb +14 -14
- data/cookbooks/mu-tools/recipes/aws_api.rb +9 -0
- data/cookbooks/mu-tools/recipes/eks.rb +2 -2
- data/cookbooks/mu-tools/recipes/google_api.rb +2 -2
- data/cookbooks/mu-tools/recipes/selinux.rb +2 -1
- data/cookbooks/mu-tools/recipes/windows-client.rb +163 -164
- data/cookbooks/mu-tools/resources/disk.rb +1 -1
- data/cookbooks/mu-tools/resources/windows_users.rb +44 -43
- data/extras/clean-stock-amis +25 -19
- data/extras/generate-stock-images +1 -0
- data/extras/image-generators/AWS/win2k12.yaml +18 -13
- data/extras/image-generators/AWS/win2k16.yaml +18 -13
- data/extras/image-generators/AWS/win2k19.yaml +21 -0
- data/extras/image-generators/Google/centos6.yaml +1 -0
- data/extras/image-generators/Google/centos7.yaml +1 -1
- data/modules/mommacat.ru +6 -16
- data/modules/mu.rb +165 -111
- data/modules/mu/adoption.rb +401 -68
- data/modules/mu/cleanup.rb +199 -306
- data/modules/mu/cloud.rb +100 -1632
- data/modules/mu/cloud/database.rb +49 -0
- data/modules/mu/cloud/dnszone.rb +46 -0
- data/modules/mu/cloud/machine_images.rb +212 -0
- data/modules/mu/cloud/providers.rb +81 -0
- data/modules/mu/cloud/resource_base.rb +920 -0
- data/modules/mu/cloud/server.rb +40 -0
- data/modules/mu/cloud/server_pool.rb +1 -0
- data/modules/mu/cloud/ssh_sessions.rb +228 -0
- data/modules/mu/cloud/winrm_sessions.rb +237 -0
- data/modules/mu/cloud/wrappers.rb +165 -0
- data/modules/mu/config.rb +171 -1767
- data/modules/mu/config/alarm.rb +2 -6
- data/modules/mu/config/bucket.rb +4 -4
- data/modules/mu/config/cache_cluster.rb +1 -1
- data/modules/mu/config/collection.rb +4 -4
- data/modules/mu/config/container_cluster.rb +9 -4
- data/modules/mu/config/database.rb +83 -104
- data/modules/mu/config/database.yml +1 -2
- data/modules/mu/config/dnszone.rb +6 -6
- data/modules/mu/config/doc_helpers.rb +516 -0
- data/modules/mu/config/endpoint.rb +4 -4
- data/modules/mu/config/firewall_rule.rb +103 -4
- data/modules/mu/config/folder.rb +4 -4
- data/modules/mu/config/function.rb +3 -3
- data/modules/mu/config/group.rb +4 -4
- data/modules/mu/config/habitat.rb +4 -4
- data/modules/mu/config/loadbalancer.rb +60 -14
- data/modules/mu/config/log.rb +4 -4
- data/modules/mu/config/msg_queue.rb +4 -4
- data/modules/mu/config/nosqldb.rb +4 -4
- data/modules/mu/config/notifier.rb +3 -3
- data/modules/mu/config/ref.rb +365 -0
- data/modules/mu/config/role.rb +4 -4
- data/modules/mu/config/schema_helpers.rb +509 -0
- data/modules/mu/config/search_domain.rb +4 -4
- data/modules/mu/config/server.rb +97 -70
- data/modules/mu/config/server.yml +1 -0
- data/modules/mu/config/server_pool.rb +5 -9
- data/modules/mu/config/storage_pool.rb +1 -1
- data/modules/mu/config/tail.rb +200 -0
- data/modules/mu/config/user.rb +4 -4
- data/modules/mu/config/vpc.rb +70 -27
- data/modules/mu/config/vpc.yml +0 -1
- data/modules/mu/defaults/AWS.yaml +83 -60
- data/modules/mu/defaults/Azure.yaml +1 -0
- data/modules/mu/defaults/Google.yaml +3 -2
- data/modules/mu/deploy.rb +30 -26
- data/modules/mu/groomer.rb +17 -2
- data/modules/mu/groomers/ansible.rb +188 -41
- data/modules/mu/groomers/chef.rb +116 -55
- data/modules/mu/logger.rb +127 -148
- data/modules/mu/master.rb +389 -2
- data/modules/mu/master/chef.rb +3 -4
- data/modules/mu/master/ldap.rb +3 -3
- data/modules/mu/master/ssl.rb +12 -3
- data/modules/mu/mommacat.rb +217 -2612
- data/modules/mu/mommacat/daemon.rb +397 -0
- data/modules/mu/mommacat/naming.rb +473 -0
- data/modules/mu/mommacat/search.rb +495 -0
- data/modules/mu/mommacat/storage.rb +722 -0
- data/modules/mu/{clouds → providers}/README.md +1 -1
- data/modules/mu/{clouds → providers}/aws.rb +271 -112
- data/modules/mu/{clouds → providers}/aws/alarm.rb +5 -3
- data/modules/mu/{clouds → providers}/aws/bucket.rb +26 -22
- data/modules/mu/{clouds → providers}/aws/cache_cluster.rb +33 -67
- data/modules/mu/{clouds → providers}/aws/collection.rb +24 -23
- data/modules/mu/{clouds → providers}/aws/container_cluster.rb +681 -721
- data/modules/mu/providers/aws/database.rb +1744 -0
- data/modules/mu/{clouds → providers}/aws/dnszone.rb +64 -63
- data/modules/mu/{clouds → providers}/aws/endpoint.rb +22 -27
- data/modules/mu/{clouds → providers}/aws/firewall_rule.rb +214 -244
- data/modules/mu/{clouds → providers}/aws/folder.rb +7 -7
- data/modules/mu/{clouds → providers}/aws/function.rb +17 -22
- data/modules/mu/{clouds → providers}/aws/group.rb +23 -23
- data/modules/mu/{clouds → providers}/aws/habitat.rb +17 -14
- data/modules/mu/{clouds → providers}/aws/loadbalancer.rb +57 -48
- data/modules/mu/{clouds → providers}/aws/log.rb +15 -12
- data/modules/mu/{clouds → providers}/aws/msg_queue.rb +17 -16
- data/modules/mu/{clouds → providers}/aws/nosqldb.rb +18 -11
- data/modules/mu/{clouds → providers}/aws/notifier.rb +11 -6
- data/modules/mu/{clouds → providers}/aws/role.rb +112 -86
- data/modules/mu/{clouds → providers}/aws/search_domain.rb +39 -33
- data/modules/mu/{clouds → providers}/aws/server.rb +835 -1133
- data/modules/mu/{clouds → providers}/aws/server_pool.rb +56 -60
- data/modules/mu/{clouds → providers}/aws/storage_pool.rb +24 -42
- data/modules/mu/{clouds → providers}/aws/user.rb +21 -22
- data/modules/mu/{clouds → providers}/aws/userdata/README.md +0 -0
- data/modules/mu/{clouds → providers}/aws/userdata/linux.erb +0 -0
- data/modules/mu/{clouds → providers}/aws/userdata/windows.erb +2 -1
- data/modules/mu/{clouds → providers}/aws/vpc.rb +523 -929
- data/modules/mu/providers/aws/vpc_subnet.rb +286 -0
- data/modules/mu/{clouds → providers}/azure.rb +29 -9
- data/modules/mu/{clouds → providers}/azure/container_cluster.rb +3 -8
- data/modules/mu/{clouds → providers}/azure/firewall_rule.rb +18 -11
- data/modules/mu/{clouds → providers}/azure/habitat.rb +8 -6
- data/modules/mu/{clouds → providers}/azure/loadbalancer.rb +5 -5
- data/modules/mu/{clouds → providers}/azure/role.rb +8 -10
- data/modules/mu/{clouds → providers}/azure/server.rb +95 -48
- data/modules/mu/{clouds → providers}/azure/user.rb +6 -8
- data/modules/mu/{clouds → providers}/azure/userdata/README.md +0 -0
- data/modules/mu/{clouds → providers}/azure/userdata/linux.erb +0 -0
- data/modules/mu/{clouds → providers}/azure/userdata/windows.erb +0 -0
- data/modules/mu/{clouds → providers}/azure/vpc.rb +16 -21
- data/modules/mu/{clouds → providers}/cloudformation.rb +18 -7
- data/modules/mu/{clouds → providers}/cloudformation/alarm.rb +3 -3
- data/modules/mu/{clouds → providers}/cloudformation/cache_cluster.rb +3 -3
- data/modules/mu/{clouds → providers}/cloudformation/collection.rb +3 -3
- data/modules/mu/{clouds → providers}/cloudformation/database.rb +6 -17
- data/modules/mu/{clouds → providers}/cloudformation/dnszone.rb +3 -3
- data/modules/mu/{clouds → providers}/cloudformation/firewall_rule.rb +3 -3
- data/modules/mu/{clouds → providers}/cloudformation/loadbalancer.rb +3 -3
- data/modules/mu/{clouds → providers}/cloudformation/log.rb +3 -3
- data/modules/mu/{clouds → providers}/cloudformation/server.rb +7 -7
- data/modules/mu/{clouds → providers}/cloudformation/server_pool.rb +5 -5
- data/modules/mu/{clouds → providers}/cloudformation/vpc.rb +5 -7
- data/modules/mu/{clouds → providers}/docker.rb +0 -0
- data/modules/mu/{clouds → providers}/google.rb +67 -30
- data/modules/mu/{clouds → providers}/google/bucket.rb +13 -15
- data/modules/mu/{clouds → providers}/google/container_cluster.rb +84 -77
- data/modules/mu/{clouds → providers}/google/database.rb +10 -20
- data/modules/mu/{clouds → providers}/google/firewall_rule.rb +15 -14
- data/modules/mu/{clouds → providers}/google/folder.rb +20 -17
- data/modules/mu/{clouds → providers}/google/function.rb +139 -167
- data/modules/mu/{clouds → providers}/google/group.rb +29 -34
- data/modules/mu/{clouds → providers}/google/habitat.rb +21 -22
- data/modules/mu/{clouds → providers}/google/loadbalancer.rb +18 -20
- data/modules/mu/{clouds → providers}/google/role.rb +92 -58
- data/modules/mu/{clouds → providers}/google/server.rb +242 -155
- data/modules/mu/{clouds → providers}/google/server_pool.rb +25 -44
- data/modules/mu/{clouds → providers}/google/user.rb +95 -31
- data/modules/mu/{clouds → providers}/google/userdata/README.md +0 -0
- data/modules/mu/{clouds → providers}/google/userdata/linux.erb +0 -0
- data/modules/mu/{clouds → providers}/google/userdata/windows.erb +0 -0
- data/modules/mu/{clouds → providers}/google/vpc.rb +103 -79
- data/modules/tests/bucket.yml +4 -0
- data/modules/tests/centos6.yaml +11 -0
- data/modules/tests/centos7.yaml +11 -0
- data/modules/tests/centos8.yaml +12 -0
- data/modules/tests/ecs.yaml +23 -0
- data/modules/tests/includes-and-params.yaml +2 -1
- data/modules/tests/rds.yaml +108 -0
- data/modules/tests/regrooms/aws-iam.yaml +201 -0
- data/modules/tests/regrooms/bucket.yml +19 -0
- data/modules/tests/regrooms/rds.yaml +123 -0
- data/modules/tests/server-with-scrub-muisms.yaml +1 -0
- data/modules/tests/super_simple_bok.yml +1 -3
- data/modules/tests/win2k12.yaml +17 -5
- data/modules/tests/win2k16.yaml +25 -0
- data/modules/tests/win2k19.yaml +25 -0
- data/requirements.txt +1 -0
- data/spec/mu/clouds/azure_spec.rb +2 -2
- metadata +232 -154
- data/extras/image-generators/AWS/windows.yaml +0 -18
- data/modules/mu/clouds/aws/database.rb +0 -1985
data/modules/mu/adoption.rb
CHANGED
@@ -30,7 +30,8 @@ module MU
|
|
30
30
|
:omnibus => "Jam everything into one monolothic configuration"
|
31
31
|
}
|
32
32
|
|
33
|
-
|
33
|
+
|
34
|
+
def initialize(clouds: MU::Cloud.supportedClouds, types: MU::Cloud.resource_types.keys, parent: nil, billing: nil, sources: nil, credentials: nil, group_by: :logical, savedeploys: false, diff: false, habitats: [], scrub_mu_isms: false, regions: [], merge: false)
|
34
35
|
@scraped = {}
|
35
36
|
@clouds = clouds
|
36
37
|
@types = types
|
@@ -44,7 +45,10 @@ module MU
|
|
44
45
|
@savedeploys = savedeploys
|
45
46
|
@diff = diff
|
46
47
|
@habitats = habitats
|
48
|
+
@regions = regions
|
47
49
|
@habitats ||= []
|
50
|
+
@scrub_mu_isms = scrub_mu_isms
|
51
|
+
@merge = merge
|
48
52
|
end
|
49
53
|
|
50
54
|
# Walk cloud providers with available credentials to discover resources
|
@@ -52,7 +56,7 @@ module MU
|
|
52
56
|
@default_parent = nil
|
53
57
|
|
54
58
|
@clouds.each { |cloud|
|
55
|
-
cloudclass =
|
59
|
+
cloudclass = MU::Cloud.cloudClass(cloud)
|
56
60
|
next if cloudclass.listCredentials.nil?
|
57
61
|
|
58
62
|
if cloud == "Google" and !@parent and @target_creds
|
@@ -64,6 +68,10 @@ module MU
|
|
64
68
|
|
65
69
|
cloudclass.listCredentials.each { |credset|
|
66
70
|
next if @sources and !@sources.include?(credset)
|
71
|
+
cfg = cloudclass.credConfig(credset)
|
72
|
+
if cfg and cfg['restrict_to_habitats']
|
73
|
+
cfg['restrict_to_habitats'] << cfg['project'] if cfg['project']
|
74
|
+
end
|
67
75
|
|
68
76
|
if @parent
|
69
77
|
# TODO handle different inputs (cloud_id, etc)
|
@@ -84,7 +92,7 @@ module MU
|
|
84
92
|
|
85
93
|
@types.each { |type|
|
86
94
|
begin
|
87
|
-
resclass =
|
95
|
+
resclass = MU::Cloud.resourceClass(cloud, type)
|
88
96
|
rescue ::MU::Cloud::MuCloudResourceNotImplemented
|
89
97
|
next
|
90
98
|
end
|
@@ -100,17 +108,30 @@ module MU
|
|
100
108
|
credentials: credset,
|
101
109
|
allow_multi: true,
|
102
110
|
habitats: @habitats.dup,
|
111
|
+
region: @regions,
|
103
112
|
dummy_ok: true,
|
104
|
-
|
105
|
-
|
113
|
+
skip_provider_owned: true,
|
114
|
+
# debug: false#,
|
106
115
|
)
|
107
116
|
|
108
117
|
|
109
118
|
if found and found.size > 0
|
119
|
+
if resclass.cfg_plural == "habitats"
|
120
|
+
found.reject! { |h|
|
121
|
+
!cloudclass.listHabitats(credset).include?(h.cloud_id)
|
122
|
+
}
|
123
|
+
end
|
110
124
|
MU.log "Found #{found.size.to_s} raw #{resclass.cfg_plural} in #{cloud}"
|
111
125
|
@scraped[type] ||= {}
|
112
126
|
found.each { |obj|
|
127
|
+
if obj.habitat and !cloudclass.listHabitats(credset).include?(obj.habitat)
|
128
|
+
next
|
129
|
+
end
|
113
130
|
# XXX apply any filters (e.g. MU-ID tags)
|
131
|
+
if obj.cloud_id.nil?
|
132
|
+
MU.log "This damn thing gave me no cloud id, what do I even do with that", MU::ERR, details: obj
|
133
|
+
exit
|
134
|
+
end
|
114
135
|
@scraped[type][obj.cloud_id] = obj
|
115
136
|
}
|
116
137
|
end
|
@@ -123,6 +144,8 @@ module MU
|
|
123
144
|
MU.log "Failed to locate a folder that resembles #{@parent}", MU::ERR
|
124
145
|
end
|
125
146
|
MU.log "Scraping complete"
|
147
|
+
|
148
|
+
@scraped
|
126
149
|
end
|
127
150
|
|
128
151
|
# Given a list of BoK style tags, try to reverse-engineer the correct
|
@@ -130,8 +153,9 @@ module MU
|
|
130
153
|
# this infers from Mu-style tagging, but we'll add a couple cases for
|
131
154
|
# special cloud provider cases.
|
132
155
|
# @param tags [Array<Hash>]
|
156
|
+
# @param basename [String]
|
133
157
|
# return [String]
|
134
|
-
def self.tagsToName(tags = [])
|
158
|
+
def self.tagsToName(tags = [], basename: nil)
|
135
159
|
tags.each { |tag|
|
136
160
|
if tag['key'] == "aws:cloudformation:logical-id"
|
137
161
|
return tag['value']
|
@@ -144,6 +168,7 @@ module MU
|
|
144
168
|
break
|
145
169
|
end
|
146
170
|
}
|
171
|
+
|
147
172
|
tags.each { |tag|
|
148
173
|
if tag['key'] == "Name"
|
149
174
|
if muid and tag['value'].match(/^#{Regexp.quote(muid)}-(.*)/)
|
@@ -153,6 +178,11 @@ module MU
|
|
153
178
|
end
|
154
179
|
end
|
155
180
|
}
|
181
|
+
|
182
|
+
if basename and muid and basename.match(/^#{Regexp.quote(muid)}-(.*)/)
|
183
|
+
return Regexp.last_match[1].downcase
|
184
|
+
end
|
185
|
+
|
156
186
|
nil
|
157
187
|
end
|
158
188
|
|
@@ -179,53 +209,98 @@ module MU
|
|
179
209
|
prefix = "mu" if prefix.empty? # so that appnames aren't ever empty
|
180
210
|
end
|
181
211
|
|
212
|
+
# Find any previous deploys with this particular profile, which we'll use
|
213
|
+
# later for --diff.
|
214
|
+
@existing_deploys = {}
|
215
|
+
@existing_deploys_by_id = {}
|
216
|
+
@origins = {}
|
217
|
+
@types_found_in = {}
|
182
218
|
groupings.each_pair { |appname, types|
|
183
|
-
bok = { "appname" => prefix+appname }
|
184
|
-
if @target_creds
|
185
|
-
bok["credentials"] = @target_creds
|
186
|
-
end
|
187
|
-
|
188
|
-
count = 0
|
189
219
|
allowed_types = @types.map { |t| MU::Cloud.resource_types[t][:cfg_plural] }
|
190
220
|
next if (types & allowed_types).size == 0
|
191
221
|
origin = {
|
192
|
-
"appname" =>
|
222
|
+
"appname" => prefix+appname,
|
193
223
|
"types" => (types & allowed_types).sort,
|
194
224
|
"habitats" => @habitats.sort,
|
195
225
|
"group_by" => @group_by.to_s
|
196
226
|
}
|
197
227
|
|
198
|
-
|
199
|
-
if @
|
200
|
-
|
201
|
-
|
228
|
+
@existing_deploys[appname] = MU::MommaCat.findMatchingDeploy(origin)
|
229
|
+
if @existing_deploys[appname]
|
230
|
+
@existing_deploys_by_id[@existing_deploys[appname].deploy_id] = @existing_deploys[appname]
|
231
|
+
@origins[appname] = origin
|
232
|
+
origin['types'].each { |t|
|
233
|
+
@types_found_in[t] = @existing_deploys[appname]
|
234
|
+
}
|
235
|
+
end
|
236
|
+
}
|
237
|
+
|
238
|
+
groupings.each_pair { |appname, types|
|
239
|
+
allowed_types = @types.map { |t| MU::Cloud.resource_types[t][:cfg_plural] }
|
240
|
+
next if (types & allowed_types).size == 0
|
241
|
+
|
242
|
+
bok = { "appname" => prefix+appname }
|
243
|
+
if @scrub_mu_isms
|
244
|
+
bok["scrub_mu_isms"] = true
|
245
|
+
end
|
246
|
+
if @target_creds
|
247
|
+
bok["credentials"] = @target_creds
|
248
|
+
end
|
249
|
+
|
250
|
+
count = 0
|
251
|
+
if @diff
|
252
|
+
if !@existing_deploys[appname]
|
253
|
+
MU.log "--diff was set but I failed to find a deploy like '#{appname}' to compare to (have #{@existing_deploys.keys.join(", ")})", MU::ERR, details: @origins[appname]
|
254
|
+
exit 1
|
255
|
+
else
|
256
|
+
MU.log "Will diff current live resources against #{@existing_deploys[appname].deploy_id}", MU::NOTICE, details: @origins[appname]
|
257
|
+
end
|
202
258
|
end
|
203
259
|
|
204
260
|
threads = []
|
261
|
+
timers = {}
|
262
|
+
walltimers = {}
|
205
263
|
@clouds.each { |cloud|
|
206
264
|
@scraped.each_pair { |type, resources|
|
265
|
+
typestart = Time.now
|
207
266
|
res_class = begin
|
208
|
-
MU::Cloud.
|
209
|
-
rescue MU::Cloud::MuCloudResourceNotImplemented
|
267
|
+
MU::Cloud.resourceClass(cloud, type)
|
268
|
+
rescue MU::Cloud::MuCloudResourceNotImplemented
|
210
269
|
# XXX I don't think this can actually happen
|
211
270
|
next
|
212
271
|
end
|
213
272
|
next if !types.include?(res_class.cfg_plural)
|
214
273
|
|
215
274
|
bok[res_class.cfg_plural] ||= []
|
275
|
+
timers[type] ||= {}
|
216
276
|
|
217
277
|
class_semaphore = Mutex.new
|
218
278
|
|
219
279
|
Thread.abort_on_exception = true
|
220
|
-
resources.
|
221
|
-
|
280
|
+
resources.values.each { |obj_thr|
|
281
|
+
obj_desc = nil
|
282
|
+
begin
|
283
|
+
obj_desc = obj_thr.cloud_desc
|
284
|
+
rescue StandardError
|
285
|
+
ensure
|
286
|
+
if !obj_desc
|
287
|
+
MU.log cloud+" "+type.to_s+" "+obj_thr.cloud_id+" did not return a cloud descriptor, skipping", MU::WARN
|
288
|
+
next
|
289
|
+
end
|
290
|
+
end
|
291
|
+
threads << Thread.new(obj_thr) { |obj|
|
292
|
+
start = Time.now
|
222
293
|
|
223
|
-
kitten_cfg = obj.toKitten(rootparent: @default_parent, billing: @billing, habitats: @habitats)
|
294
|
+
kitten_cfg = obj.toKitten(rootparent: @default_parent, billing: @billing, habitats: @habitats, types: @types)
|
224
295
|
if kitten_cfg
|
225
296
|
print "."
|
226
297
|
kitten_cfg.delete("credentials") if @target_creds
|
227
298
|
class_semaphore.synchronize {
|
228
299
|
bok[res_class.cfg_plural] << kitten_cfg
|
300
|
+
if !kitten_cfg['cloud_id']
|
301
|
+
MU.log "No cloud id in this #{res_class.cfg_name} kitten!", MU::ERR, details: kitten_cfg
|
302
|
+
end
|
303
|
+
timers[type][kitten_cfg['cloud_id']] = (Time.now - start)
|
229
304
|
}
|
230
305
|
count += 1
|
231
306
|
end
|
@@ -236,6 +311,7 @@ module MU
|
|
236
311
|
threads.each { |t|
|
237
312
|
t.join
|
238
313
|
}
|
314
|
+
|
239
315
|
puts ""
|
240
316
|
bok[res_class.cfg_plural].sort! { |a, b|
|
241
317
|
strs = [a, b].map { |x|
|
@@ -257,49 +333,68 @@ module MU
|
|
257
333
|
bok[res_class.cfg_plural].each { |sibling|
|
258
334
|
next if kitten_cfg == sibling
|
259
335
|
if sibling['name'] == kitten_cfg['name']
|
260
|
-
MU.
|
261
|
-
if kitten_cfg['parent'] and kitten_cfg['parent'].respond_to?(:id) and kitten_cfg['parent'].id
|
262
|
-
kitten_cfg['name'] = kitten_cfg['name']+kitten_cfg['parent'].id
|
263
|
-
elsif kitten_cfg['project']
|
264
|
-
kitten_cfg['name'] = kitten_cfg['name']+kitten_cfg['project']
|
265
|
-
elsif kitten_cfg['region']
|
266
|
-
kitten_cfg['name'] = kitten_cfg['name']+kitten_cfg['region']
|
267
|
-
elsif kitten_cfg['cloud_id']
|
268
|
-
kitten_cfg['name'] = kitten_cfg['name']+kitten_cfg['cloud_id'].gsub(/[^a-z0-9]/i, "-")
|
269
|
-
else
|
270
|
-
raise MU::Config::DuplicateNameError, "Saw duplicate #{res_class.cfg_name} name #{sibling['name']} and couldn't come up with a good way to differentiate them"
|
271
|
-
end
|
336
|
+
MU::Adoption.deDuplicateName(kitten_cfg, res_class)
|
272
337
|
MU.log "De-duplication: Renamed #{res_class.cfg_name} name '#{sibling['name']}' => '#{kitten_cfg['name']}'", MU::NOTICE
|
273
338
|
break
|
274
339
|
end
|
275
340
|
}
|
276
341
|
}
|
342
|
+
walltimers[type] ||= 0
|
343
|
+
walltimers[type] += (Time.now - typestart)
|
277
344
|
}
|
278
345
|
}
|
279
346
|
|
347
|
+
timers.each_pair { |type, resources|
|
348
|
+
next if resources.empty?
|
349
|
+
total = resources.values.sum
|
350
|
+
top_5 = resources.keys.sort { |a, b|
|
351
|
+
resources[b] <=> resources[a]
|
352
|
+
}.slice(0, 5).map { |k|
|
353
|
+
k.to_s+": "+sprintf("%.2fs", resources[k])
|
354
|
+
}
|
355
|
+
if walltimers[type] < 45
|
356
|
+
MU.log "Kittened #{resources.size.to_s} eligible #{type}s in #{sprintf("%.2fs", walltimers[type])}"
|
357
|
+
else
|
358
|
+
MU.log "Kittened #{resources.size.to_s} eligible #{type}s in #{sprintf("%.2fs", walltimers[type])} (CPU time #{sprintf("%.2fs", total)}, avg #{sprintf("%.2fs", total/resources.size)}). Top 5:", MU::NOTICE, details: top_5
|
359
|
+
end
|
360
|
+
}
|
361
|
+
|
280
362
|
# No matching resources isn't necessarily an error
|
281
363
|
next if count == 0 or bok.nil?
|
282
364
|
|
283
365
|
# Now walk through all of the Refs in these objects, resolve them, and minimize
|
284
366
|
# their config footprint
|
285
367
|
MU.log "Minimizing footprint of #{count.to_s} found resources", MU::DEBUG
|
286
|
-
@boks[bok['appname']] = vacuum(bok, origin: origin, save: @savedeploys)
|
287
368
|
|
288
|
-
|
369
|
+
generated_deploy = generateStubDeploy(bok)
|
370
|
+
@boks[bok['appname']] = vacuum(bok, origin: @origins[appname], deploy: generated_deploy, save: @savedeploys)
|
371
|
+
|
372
|
+
if @diff and !@existing_deploys[appname]
|
289
373
|
MU.log "diff flag set, but no comparable deploy provided for #{bok['appname']}", MU::ERR
|
290
374
|
exit 1
|
291
375
|
end
|
292
376
|
|
293
|
-
if
|
294
|
-
|
377
|
+
if @diff
|
378
|
+
prev_vacuumed = vacuum(@existing_deploys[appname].original_config, deploy: @existing_deploys[appname], keep_missing: true, copy_from: generated_deploy)
|
379
|
+
prevcfg = MU::Config.manxify(prev_vacuumed)
|
295
380
|
if !prevcfg
|
296
|
-
MU.log "#{
|
381
|
+
MU.log "#{@existing_deploys[appname].deploy_id} didn't have a working original config for me to compare", MU::ERR
|
297
382
|
exit 1
|
298
383
|
end
|
299
384
|
newcfg = MU::Config.manxify(@boks[bok['appname']])
|
385
|
+
report = prevcfg.diff(newcfg)
|
386
|
+
|
387
|
+
if report
|
388
|
+
|
389
|
+
if MU.muCfg['adopt_change_notify']
|
390
|
+
notifyChanges(@existing_deploys[appname], report.freeze)
|
391
|
+
end
|
392
|
+
if @merge
|
393
|
+
MU.log "Saving changes to #{@existing_deploys[appname].deploy_id}"
|
394
|
+
@existing_deploys[appname].updateBasketofKittens(newcfg, save_now: true)
|
395
|
+
end
|
396
|
+
end
|
300
397
|
|
301
|
-
prevcfg.diff(newcfg)
|
302
|
-
exit
|
303
398
|
end
|
304
399
|
}
|
305
400
|
@boks
|
@@ -307,14 +402,191 @@ module MU
|
|
307
402
|
|
308
403
|
private
|
309
404
|
|
310
|
-
|
405
|
+
# @param tier [Hash]
|
406
|
+
# @param parent_key [String]
|
407
|
+
def crawlChangeReport(tier, parent_key = nil, indent: "")
|
408
|
+
report = []
|
409
|
+
if tier.is_a?(Array)
|
410
|
+
tier.each { |a|
|
411
|
+
sub_report = crawlChangeReport(a, parent_key)
|
412
|
+
report.concat(sub_report) if sub_report and !sub_report.empty?
|
413
|
+
}
|
414
|
+
elsif tier.is_a?(Hash)
|
415
|
+
if tier[:action]
|
416
|
+
preposition = if tier[:action] == :added
|
417
|
+
"to"
|
418
|
+
elsif tier[:action] == :removed
|
419
|
+
"from"
|
420
|
+
else
|
421
|
+
"in"
|
422
|
+
end
|
423
|
+
|
424
|
+
name = ""
|
425
|
+
type_of = parent_key.sub(/s$|\[.*/, '') if parent_key
|
426
|
+
loc = tier[:habitat]
|
427
|
+
|
428
|
+
if tier[:value] and tier[:value].is_a?(Hash)
|
429
|
+
name, loc = MU::MommaCat.getChunkName(tier[:value], type_of)
|
430
|
+
elsif parent_key
|
431
|
+
name = parent_key
|
432
|
+
end
|
433
|
+
|
434
|
+
path_str = []
|
435
|
+
slack_path_str = ""
|
436
|
+
if tier[:parents] and tier[:parents].size > 2
|
437
|
+
path = tier[:parents].clone
|
438
|
+
slack_path_str += "#{preposition} \*"+path.join(" ⇨ ")+"\*" if path.size > 0
|
439
|
+
path.shift
|
440
|
+
path.shift
|
441
|
+
path.pop if path.last == name
|
442
|
+
for c in (0..(path.size-1)) do
|
443
|
+
path_str << (" " * (c+2)) + (path[c] || "<nil>")
|
444
|
+
end
|
445
|
+
end
|
446
|
+
path_str << "" if !path_str.empty?
|
447
|
+
|
448
|
+
plain = (name ? name : type_of) if name or type_of
|
449
|
+
plain ||= "" # XXX but this is a problem
|
450
|
+
slack = "`"+plain+"`"
|
451
|
+
|
452
|
+
plain += " ("+loc+")" if loc and !loc.empty?
|
453
|
+
color = plain
|
454
|
+
|
455
|
+
if tier[:action] == :added
|
456
|
+
color = "+ ".green + plain
|
457
|
+
plain = "+ " + plain
|
458
|
+
slack += " added"
|
459
|
+
elsif tier[:action] == :removed
|
460
|
+
color = "- ".red + plain
|
461
|
+
plain = "- " + plain
|
462
|
+
slack += " removed"
|
463
|
+
end
|
464
|
+
|
465
|
+
slack += " #{tier[:action]} #{preposition} \*#{loc}\*" if loc and !loc.empty? and [Array, Hash].include?(tier[:value].class)
|
466
|
+
|
467
|
+
plain = path_str.join(" => \n") + indent + plain
|
468
|
+
color = path_str.join(" => \n") + indent + color
|
469
|
+
|
470
|
+
slack += " "+slack_path_str if !slack_path_str.empty?
|
471
|
+
myreport = {
|
472
|
+
"slack" => slack,
|
473
|
+
"plain" => plain,
|
474
|
+
"color" => color
|
475
|
+
}
|
476
|
+
|
477
|
+
append = ""
|
478
|
+
if tier[:value] and (tier[:value].is_a?(Array) or tier[:value].is_a?(Hash))
|
479
|
+
if tier[:value].is_a?(Hash)
|
480
|
+
if name
|
481
|
+
tier[:value].delete("entity")
|
482
|
+
tier[:value].delete(name.sub(/\[.*/, '')) if name
|
483
|
+
end
|
484
|
+
if (tier[:value].keys - ["id", "name", "type"]).size > 0
|
485
|
+
myreport["details"] = tier[:value].clone
|
486
|
+
append = PP.pp(tier[:value], '').gsub(/(^|\n)/, '\1'+indent)
|
487
|
+
end
|
488
|
+
else
|
489
|
+
append = indent+"["+tier[:value].map { |v| MU::MommaCat.getChunkName(v, type_of).reverse.join("/") || v.to_s.light_blue }.join(", ")+"]"
|
490
|
+
slack += " #{tier[:action].to_s}: "+tier[:value].map { |v| MU::MommaCat.getChunkName(v, type_of).reverse.join("/") || v.to_s }.join(", ")
|
491
|
+
end
|
492
|
+
else
|
493
|
+
tier[:value] ||= "<nil>"
|
494
|
+
if ![:removed].include?(tier[:action])
|
495
|
+
myreport["slack"] += ". New #{tier[:field] ? "`"+tier[:field]+"`" : :value}: \*#{tier[:value]}\*"
|
496
|
+
else
|
497
|
+
myreport["slack"] += " (was \*#{tier[:value]}\*)"
|
498
|
+
end
|
499
|
+
append = tier[:value].to_s.bold
|
500
|
+
end
|
501
|
+
|
502
|
+
if append and !append.empty?
|
503
|
+
myreport["plain"] += " =>\n "+indent+append
|
504
|
+
myreport["color"] += " =>\n "+indent+append
|
505
|
+
end
|
506
|
+
|
507
|
+
report << myreport if tier[:action]
|
508
|
+
end
|
509
|
+
|
510
|
+
# Just because we've got changes at this level doesn't mean there aren't
|
511
|
+
# more further down.
|
512
|
+
tier.each_pair { |k, v|
|
513
|
+
next if !(v.is_a?(Hash) or v.is_a?(Array))
|
514
|
+
sub_report = crawlChangeReport(v, k, indent: indent+" ")
|
515
|
+
report.concat(sub_report) if sub_report and !sub_report.empty?
|
516
|
+
}
|
517
|
+
end
|
518
|
+
|
519
|
+
report
|
520
|
+
end
|
521
|
+
|
522
|
+
|
523
|
+
def notifyChanges(deploy, report)
|
524
|
+
snippet_threshold = (MU.muCfg['adopt_change_notify'] && MU.muCfg['adopt_change_notify']['slack_snippet_threshold']) || 5
|
525
|
+
|
526
|
+
report.each_pair { |res_type, resources|
|
527
|
+
shortclass, _cfg_name, _cfg_plural, _classname = MU::Cloud.getResourceNames(res_type, false)
|
528
|
+
next if !shortclass # we don't really care about Mu metadata changes
|
529
|
+
resources.each_pair { |name, data|
|
530
|
+
if MU::MommaCat.getChunkName(data[:value], res_type).first.nil?
|
531
|
+
symbol = if data[:action] == :added
|
532
|
+
"+".green
|
533
|
+
elsif data[:action] == :removed
|
534
|
+
"-".red
|
535
|
+
else
|
536
|
+
"~".yellow
|
537
|
+
end
|
538
|
+
puts (symbol+" "+res_type+"["+name+"]")
|
539
|
+
end
|
540
|
+
|
541
|
+
noun = shortclass ? shortclass.to_s : res_type.capitalize
|
542
|
+
verb = if data[:action]
|
543
|
+
data[:action].to_s
|
544
|
+
else
|
545
|
+
"modified"
|
546
|
+
end
|
547
|
+
|
548
|
+
changes = crawlChangeReport(data.freeze, res_type)
|
549
|
+
|
550
|
+
slacktext = "#{noun} \*#{name}\* was #{verb}"
|
551
|
+
if data[:habitat]
|
552
|
+
slacktext += " in \*#{data[:habitat]}\*"
|
553
|
+
end
|
554
|
+
snippets = []
|
555
|
+
|
556
|
+
if [:added, :removed].include?(data[:action]) and data[:value]
|
557
|
+
snippets << { text: "```"+JSON.pretty_generate(data[:value])+"```" }
|
558
|
+
else
|
559
|
+
changes.each { |c|
|
560
|
+
slacktext += "\n • "+c["slack"]
|
561
|
+
if c["details"]
|
562
|
+
details = JSON.pretty_generate(c["details"])
|
563
|
+
snippets << { text: "```"+JSON.pretty_generate(c["details"])+"```" }
|
564
|
+
end
|
565
|
+
}
|
566
|
+
end
|
567
|
+
|
568
|
+
changes.each { |c|
|
569
|
+
puts c["color"]
|
570
|
+
}
|
571
|
+
puts ""
|
572
|
+
|
573
|
+
if MU.muCfg['adopt_change_notify'] and MU.muCfg['adopt_change_notify']['slack']
|
574
|
+
deploy.sendAdminSlack(slacktext, scrub_mu_isms: MU.muCfg['adopt_scrub_mu_isms'], snippets: snippets, noop: false)
|
575
|
+
end
|
576
|
+
|
577
|
+
}
|
578
|
+
}
|
579
|
+
|
580
|
+
end
|
581
|
+
|
582
|
+
def scrubSchemaDefaults(conf_chunk, schema_chunk, depth = 0, type: nil)
|
311
583
|
return if schema_chunk.nil?
|
312
584
|
|
313
585
|
if !conf_chunk.nil? and schema_chunk["properties"].kind_of?(Hash) and conf_chunk.is_a?(Hash)
|
314
586
|
deletia = []
|
315
587
|
schema_chunk["properties"].each_pair { |key, subschema|
|
316
588
|
next if !conf_chunk[key]
|
317
|
-
shortclass,
|
589
|
+
shortclass, _cfg_name, _cfg_plural, _classname = MU::Cloud.getResourceNames(key, false)
|
318
590
|
|
319
591
|
if subschema["default_if"]
|
320
592
|
subschema["default_if"].each { |cond|
|
@@ -328,7 +600,7 @@ module MU
|
|
328
600
|
if subschema["default"] and conf_chunk[key] == subschema["default"]
|
329
601
|
deletia << key
|
330
602
|
elsif ["array", "object"].include?(subschema["type"])
|
331
|
-
scrubSchemaDefaults(conf_chunk[key], subschema, depth+1,
|
603
|
+
scrubSchemaDefaults(conf_chunk[key], subschema, depth+1, type: shortclass)
|
332
604
|
end
|
333
605
|
}
|
334
606
|
deletia.each { |key| conf_chunk.delete(key) }
|
@@ -338,8 +610,7 @@ module MU
|
|
338
610
|
# theory
|
339
611
|
realschema = if type and schema_chunk["items"] and schema_chunk["items"]["properties"] and item["cloud"] and MU::Cloud.supportedClouds.include?(item['cloud'])
|
340
612
|
|
341
|
-
|
342
|
-
toplevel_required, cloudschema = cloudclass.schema(self)
|
613
|
+
_toplevel_required, cloudschema = MU::Cloud.resourceClass(item['cloud'], type).schema(self)
|
343
614
|
|
344
615
|
newschema = schema_chunk["items"].dup
|
345
616
|
newschema["properties"].merge!(cloudschema)
|
@@ -349,7 +620,7 @@ module MU
|
|
349
620
|
end
|
350
621
|
next if ["array", "object"].include?(realschema["type"])
|
351
622
|
|
352
|
-
scrubSchemaDefaults(item, realschema, depth+1,
|
623
|
+
scrubSchemaDefaults(item, realschema, depth+1, type: type)
|
353
624
|
}
|
354
625
|
end
|
355
626
|
|
@@ -363,8 +634,7 @@ module MU
|
|
363
634
|
# Do the same for our main objects: if they all use the same credentials,
|
364
635
|
# for example, remove the explicit +credentials+ attributes and set that
|
365
636
|
# value globally, once.
|
366
|
-
def vacuum(bok, origin: nil, save: false, deploy: nil)
|
367
|
-
deploy ||= generateStubDeploy(bok)
|
637
|
+
def vacuum(bok, origin: nil, save: false, deploy: nil, copy_from: nil, keep_missing: false)
|
368
638
|
|
369
639
|
globals = {
|
370
640
|
'cloud' => {},
|
@@ -373,10 +643,7 @@ module MU
|
|
373
643
|
'billing_acct' => {},
|
374
644
|
'us_only' => {},
|
375
645
|
}
|
376
|
-
|
377
|
-
credentials = {}
|
378
|
-
regions = {}
|
379
|
-
MU::Cloud.resource_types.each_pair { |typename, attrs|
|
646
|
+
MU::Cloud.resource_types.values.each { |attrs|
|
380
647
|
if bok[attrs[:cfg_plural]]
|
381
648
|
processed = []
|
382
649
|
bok[attrs[:cfg_plural]].each { |resource|
|
@@ -387,11 +654,24 @@ module MU
|
|
387
654
|
end
|
388
655
|
}
|
389
656
|
obj = deploy.findLitterMate(type: attrs[:cfg_plural], name: resource['name'])
|
657
|
+
inject_metadata = save
|
658
|
+
if obj.nil? and copy_from
|
659
|
+
obj = copy_from.findLitterMate(type: attrs[:cfg_plural], name: resource['name'])
|
660
|
+
if obj
|
661
|
+
inject_metadata = true
|
662
|
+
obj.intoDeploy(deploy, force: true)
|
663
|
+
end
|
664
|
+
end
|
665
|
+
|
390
666
|
begin
|
391
667
|
raise Incomplete if obj.nil?
|
668
|
+
if inject_metadata
|
669
|
+
deploydata = obj.notify
|
670
|
+
deploy.notify(attrs[:cfg_plural], resource['name'], deploydata, triggering_node: obj)
|
671
|
+
end
|
392
672
|
new_cfg = resolveReferences(resource, deploy, obj)
|
393
673
|
new_cfg.delete("cloud_id")
|
394
|
-
cred_cfg = MU::Cloud.
|
674
|
+
cred_cfg = MU::Cloud.cloudClass(obj.cloud).credConfig(obj.credentials)
|
395
675
|
if cred_cfg['region'] == new_cfg['region']
|
396
676
|
new_cfg.delete('region')
|
397
677
|
end
|
@@ -401,6 +681,11 @@ module MU
|
|
401
681
|
end
|
402
682
|
processed << new_cfg
|
403
683
|
rescue Incomplete
|
684
|
+
if keep_missing
|
685
|
+
processed << resource
|
686
|
+
else
|
687
|
+
MU.log "#{attrs[:cfg_name]} #{resource['name']} didn't show up from findLitterMate", MU::WARN, details: deploy.original_config[attrs[:cfg_plural]].reject { |r| r['name'] != "" }
|
688
|
+
end
|
404
689
|
end
|
405
690
|
}
|
406
691
|
|
@@ -411,34 +696,33 @@ module MU
|
|
411
696
|
|
412
697
|
# Pare out global values like +cloud+ or +region+ that appear to be
|
413
698
|
# universal in the deploy we're creating.
|
414
|
-
|
699
|
+
scrub_globals = Proc.new { |h, field|
|
415
700
|
if h.is_a?(Hash)
|
416
701
|
newhash = {}
|
417
702
|
h.each_pair { |k, v|
|
418
703
|
next if k == field
|
419
|
-
newhash[k] = scrub_globals(v, field)
|
704
|
+
newhash[k] = scrub_globals.call(v, field)
|
420
705
|
}
|
421
706
|
h = newhash
|
422
707
|
elsif h.is_a?(Array)
|
423
708
|
newarr = []
|
424
709
|
h.each { |v|
|
425
|
-
newarr << scrub_globals(v, field)
|
710
|
+
newarr << scrub_globals.call(v, field)
|
426
711
|
}
|
427
|
-
h = newarr
|
712
|
+
h = newarr.uniq
|
428
713
|
end
|
429
|
-
|
430
714
|
h
|
431
|
-
|
715
|
+
}
|
432
716
|
|
433
717
|
globals.each_pair { |field, counts|
|
434
718
|
next if counts.size != 1
|
435
719
|
bok[field] = counts.keys.first
|
436
720
|
MU.log "Setting global default #{field} to #{bok[field]} (#{deploy.deploy_id})", MU::DEBUG
|
437
|
-
MU::Cloud.resource_types.
|
721
|
+
MU::Cloud.resource_types.values.each { |attrs|
|
438
722
|
if bok[attrs[:cfg_plural]]
|
439
723
|
new_resources = []
|
440
724
|
bok[attrs[:cfg_plural]].each { |resource|
|
441
|
-
new_resources << scrub_globals(resource, field)
|
725
|
+
new_resources << scrub_globals.call(resource, field)
|
442
726
|
}
|
443
727
|
bok[attrs[:cfg_plural]] = new_resources
|
444
728
|
end
|
@@ -456,9 +740,33 @@ module MU
|
|
456
740
|
end
|
457
741
|
|
458
742
|
def resolveReferences(cfg, deploy, parent)
|
743
|
+
mask_deploy_id = false
|
744
|
+
|
745
|
+
check_deploy_id = Proc.new { |cfgblob|
|
746
|
+
(deploy and
|
747
|
+
(cfgblob.is_a?(MU::Config::Ref) or cfgblob.is_a?(Hash)) and
|
748
|
+
cfgblob['deploy_id'] and
|
749
|
+
cfgblob['deploy_id'] != deploy.deploy_id and
|
750
|
+
@diff and
|
751
|
+
@types_found_in[cfgblob['type']] and
|
752
|
+
@types_found_in[cfgblob['type']].deploy_id == cfgblob['deploy_id']
|
753
|
+
)
|
754
|
+
}
|
755
|
+
|
756
|
+
mask_deploy_id = check_deploy_id.call(cfg)
|
757
|
+
|
459
758
|
if cfg.is_a?(MU::Config::Ref)
|
759
|
+
if mask_deploy_id
|
760
|
+
cfg.delete("deploy_id")
|
761
|
+
cfg.delete("mommacat")
|
762
|
+
cfg.kitten(deploy)
|
763
|
+
else
|
764
|
+
cfg.kitten(deploy) || cfg.kitten
|
765
|
+
end
|
766
|
+
|
460
767
|
hashcfg = cfg.to_h
|
461
|
-
|
768
|
+
|
769
|
+
if cfg.kitten
|
462
770
|
littermate = deploy.findLitterMate(type: cfg.type, name: cfg.name, cloud_id: cfg.id, habitat: cfg.habitat)
|
463
771
|
|
464
772
|
if littermate and littermate.config['name']
|
@@ -480,16 +788,16 @@ module MU
|
|
480
788
|
hashcfg.delete("name") if cfg.id and !cfg.deploy_id
|
481
789
|
end
|
482
790
|
end
|
483
|
-
elsif hashcfg["id"]
|
791
|
+
elsif hashcfg["id"] and !hashcfg["name"]
|
484
792
|
hashcfg.delete("deploy_id")
|
485
|
-
hashcfg.delete("name")
|
486
793
|
else
|
487
794
|
pp parent.cloud_desc
|
488
795
|
raise Incomplete, "Failed to resolve reference on behalf of #{parent}"
|
489
796
|
end
|
490
797
|
hashcfg.delete("deploy_id") if hashcfg['deploy_id'] == deploy.deploy_id
|
798
|
+
|
491
799
|
if parent and parent.config
|
492
|
-
cred_cfg = MU::Cloud.
|
800
|
+
cred_cfg = MU::Cloud.cloudClass(parent.cloud).credConfig(parent.credentials)
|
493
801
|
|
494
802
|
if parent.config['region'] == hashcfg['region'] or
|
495
803
|
cred_cfg['region'] == hashcfg['region']
|
@@ -548,7 +856,12 @@ module MU
|
|
548
856
|
MU.log "Dropping unresolved value", MU::WARN, details: value
|
549
857
|
end
|
550
858
|
}
|
551
|
-
cfg = new_array
|
859
|
+
cfg = new_array.uniq
|
860
|
+
end
|
861
|
+
|
862
|
+
if mask_deploy_id or check_deploy_id.call(cfg)
|
863
|
+
cfg.delete("deploy_id")
|
864
|
+
MU.log "#{parent} in #{deploy.deploy_id} references something in #{@types_found_in[cfg['type']].deploy_id}, ditching extraneous deploy_id", MU::DEBUG, details: cfg.to_h
|
552
865
|
end
|
553
866
|
|
554
867
|
cfg
|
@@ -598,6 +911,10 @@ module MU
|
|
598
911
|
|
599
912
|
if !@scraped[typename][kitten['cloud_id']]
|
600
913
|
MU.log "No object in scraped tree for #{attrs[:cfg_name]} #{kitten['cloud_id']} (#{kitten['name']})", MU::ERR, details: kitten
|
914
|
+
if kitten['cloud_id'].nil?
|
915
|
+
pp caller
|
916
|
+
exit
|
917
|
+
end
|
601
918
|
next
|
602
919
|
end
|
603
920
|
|
@@ -608,7 +925,8 @@ module MU
|
|
608
925
|
deploy.addKitten(
|
609
926
|
attrs[:cfg_plural],
|
610
927
|
kitten['name'],
|
611
|
-
@scraped[typename][kitten['cloud_id']]
|
928
|
+
@scraped[typename][kitten['cloud_id']],
|
929
|
+
do_notify: true
|
612
930
|
)
|
613
931
|
}
|
614
932
|
end
|
@@ -617,6 +935,21 @@ module MU
|
|
617
935
|
deploy
|
618
936
|
end
|
619
937
|
|
938
|
+
def self.deDuplicateName(kitten_cfg, res_class)
|
939
|
+
orig_name = kitten_cfg['name'].dup
|
940
|
+
if kitten_cfg['parent'] and kitten_cfg['parent'].respond_to?(:id) and kitten_cfg['parent'].id
|
941
|
+
kitten_cfg['name'] = kitten_cfg['name']+"-"+kitten_cfg['parent'].id
|
942
|
+
elsif kitten_cfg['project']
|
943
|
+
kitten_cfg['name'] = kitten_cfg['name']+"-"+kitten_cfg['project']
|
944
|
+
elsif kitten_cfg['region']
|
945
|
+
kitten_cfg['name'] = kitten_cfg['name']+"-"+kitten_cfg['region']
|
946
|
+
elsif kitten_cfg['cloud_id']
|
947
|
+
kitten_cfg['name'] = kitten_cfg['name']+"-"+kitten_cfg['cloud_id'].gsub(/[^a-z0-9]/i, "-")
|
948
|
+
else
|
949
|
+
raise MU::Config::DuplicateNameError, "Saw duplicate #{res_class.cfg_name} name #{orig_name} and couldn't come up with a good way to differentiate them"
|
950
|
+
end
|
951
|
+
end
|
952
|
+
|
620
953
|
# Go through everything we've scraped and update our mappings of cloud ids
|
621
954
|
# and bare name fields, so that resources can reference one another
|
622
955
|
# portably by name.
|