cloud-mu 3.1.3 → 3.3.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 +21 -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 +4 -4
- data/bin/mu-node-manage +15 -16
- data/bin/mu-run-tests +147 -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 +158 -111
- data/modules/mu/adoption.rb +404 -71
- data/modules/mu/cleanup.rb +221 -306
- data/modules/mu/cloud.rb +129 -1633
- data/modules/mu/cloud/database.rb +49 -0
- data/modules/mu/cloud/dnszone.rb +44 -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 +926 -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 +169 -0
- data/modules/mu/config.rb +171 -1767
- data/modules/mu/config/alarm.rb +2 -6
- data/modules/mu/config/bucket.rb +32 -3
- data/modules/mu/config/cache_cluster.rb +2 -2
- data/modules/mu/config/cdn.rb +100 -0
- data/modules/mu/config/collection.rb +4 -4
- data/modules/mu/config/container_cluster.rb +9 -4
- data/modules/mu/config/database.rb +84 -105
- data/modules/mu/config/database.yml +1 -2
- data/modules/mu/config/dnszone.rb +10 -9
- data/modules/mu/config/doc_helpers.rb +516 -0
- data/modules/mu/config/endpoint.rb +5 -4
- data/modules/mu/config/firewall_rule.rb +103 -4
- data/modules/mu/config/folder.rb +4 -4
- data/modules/mu/config/function.rb +19 -10
- data/modules/mu/config/group.rb +4 -4
- data/modules/mu/config/habitat.rb +4 -4
- data/modules/mu/config/job.rb +89 -0
- 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 +10 -21
- data/modules/mu/config/ref.rb +411 -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 +98 -71
- 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 +71 -27
- data/modules/mu/config/vpc.yml +0 -1
- data/modules/mu/defaults/AWS.yaml +91 -68
- data/modules/mu/defaults/Azure.yaml +1 -0
- data/modules/mu/defaults/Google.yaml +3 -2
- data/modules/mu/deploy.rb +43 -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 +410 -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 +218 -2612
- data/modules/mu/mommacat/daemon.rb +403 -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 +380 -122
- data/modules/mu/{clouds → providers}/aws/alarm.rb +7 -5
- data/modules/mu/{clouds → providers}/aws/bucket.rb +297 -59
- data/modules/mu/{clouds → providers}/aws/cache_cluster.rb +37 -71
- data/modules/mu/providers/aws/cdn.rb +782 -0
- data/modules/mu/{clouds → providers}/aws/collection.rb +26 -25
- data/modules/mu/{clouds → providers}/aws/container_cluster.rb +724 -744
- data/modules/mu/providers/aws/database.rb +1744 -0
- data/modules/mu/{clouds → providers}/aws/dnszone.rb +88 -70
- data/modules/mu/providers/aws/endpoint.rb +1072 -0
- data/modules/mu/{clouds → providers}/aws/firewall_rule.rb +220 -247
- data/modules/mu/{clouds → providers}/aws/folder.rb +8 -8
- data/modules/mu/{clouds → providers}/aws/function.rb +300 -142
- data/modules/mu/{clouds → providers}/aws/group.rb +31 -29
- data/modules/mu/{clouds → providers}/aws/habitat.rb +18 -15
- data/modules/mu/providers/aws/job.rb +466 -0
- data/modules/mu/{clouds → providers}/aws/loadbalancer.rb +66 -56
- data/modules/mu/{clouds → providers}/aws/log.rb +17 -14
- data/modules/mu/{clouds → providers}/aws/msg_queue.rb +29 -19
- data/modules/mu/{clouds → providers}/aws/nosqldb.rb +114 -16
- data/modules/mu/{clouds → providers}/aws/notifier.rb +142 -65
- data/modules/mu/{clouds → providers}/aws/role.rb +158 -118
- data/modules/mu/{clouds → providers}/aws/search_domain.rb +201 -59
- data/modules/mu/{clouds → providers}/aws/server.rb +844 -1139
- data/modules/mu/{clouds → providers}/aws/server_pool.rb +74 -65
- data/modules/mu/{clouds → providers}/aws/storage_pool.rb +26 -44
- data/modules/mu/{clouds → providers}/aws/user.rb +24 -25
- data/modules/mu/{clouds → providers}/aws/userdata/README.md +0 -0
- data/modules/mu/{clouds → providers}/aws/userdata/linux.erb +5 -4
- data/modules/mu/{clouds → providers}/aws/userdata/windows.erb +2 -1
- data/modules/mu/{clouds → providers}/aws/vpc.rb +525 -931
- 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 +97 -49
- 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 +68 -30
- data/modules/mu/{clouds → providers}/google/bucket.rb +13 -15
- data/modules/mu/{clouds → providers}/google/container_cluster.rb +85 -78
- data/modules/mu/{clouds → providers}/google/database.rb +11 -21
- 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 +140 -168
- 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 +19 -21
- data/modules/mu/{clouds → providers}/google/role.rb +94 -58
- data/modules/mu/{clouds → providers}/google/server.rb +243 -156
- data/modules/mu/{clouds → providers}/google/server_pool.rb +26 -45
- 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/aws-jobs-functions.yaml +46 -0
- data/modules/tests/bucket.yml +4 -0
- data/modules/tests/centos6.yaml +15 -0
- data/modules/tests/centos7.yaml +15 -0
- data/modules/tests/centos8.yaml +12 -0
- data/modules/tests/ecs.yaml +23 -0
- data/modules/tests/eks.yaml +1 -1
- data/modules/tests/functions/node-function/lambda_function.js +10 -0
- data/modules/tests/functions/python-function/lambda_function.py +12 -0
- data/modules/tests/includes-and-params.yaml +2 -1
- data/modules/tests/microservice_app.yaml +288 -0
- 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 +2 -1
- data/modules/tests/super_complex_bok.yml +2 -2
- data/modules/tests/super_simple_bok.yml +3 -5
- 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 +240 -154
- data/extras/image-generators/AWS/windows.yaml +0 -18
- data/modules/mu/clouds/aws/database.rb +0 -1985
- data/modules/mu/clouds/aws/endpoint.rb +0 -592
@@ -44,7 +44,7 @@ module MU
|
|
44
44
|
resp = MU::Cloud::Google.admin_directory(credentials: @credentials).insert_group(group_obj)
|
45
45
|
@cloud_id = resp.email
|
46
46
|
|
47
|
-
MU::Cloud
|
47
|
+
MU::Cloud.resourceClass("Google", "Role").bindFromConfig("group", @cloud_id, @config['roles'], credentials: @config['credentials'])
|
48
48
|
else
|
49
49
|
@cloud_id = @config['name'].sub(/@.*/, "")+"@"+@config['domain']
|
50
50
|
end
|
@@ -52,7 +52,7 @@ module MU
|
|
52
52
|
|
53
53
|
# Called automatically by {MU::Deploy#createResources}
|
54
54
|
def groom
|
55
|
-
MU::Cloud
|
55
|
+
MU::Cloud.resourceClass("Google", "Role").bindFromConfig("group", @cloud_id, @config['roles'], credentials: @config['credentials'], debug: true)
|
56
56
|
|
57
57
|
if @config['members']
|
58
58
|
resolved_desired = []
|
@@ -139,12 +139,17 @@ module MU
|
|
139
139
|
# Remove all groups associated with the currently loaded deployment.
|
140
140
|
# @param noop [Boolean]: If true, will only print what would be done
|
141
141
|
# @param ignoremaster [Boolean]: If true, will remove resources not flagged as originating from this Mu server
|
142
|
-
# @param region [String]: The cloud provider region
|
143
142
|
# @return [void]
|
144
|
-
def self.cleanup(noop: false,
|
145
|
-
|
143
|
+
def self.cleanup(noop: false, deploy_id: MU.deploy_id, ignoremaster: false, credentials: nil, flags: {})
|
144
|
+
MU::Cloud::Google.getDomains(credentials)
|
146
145
|
my_org = MU::Cloud::Google.getOrg(credentials)
|
147
146
|
|
147
|
+
filter = %Q{(labels.mu-id = "#{MU.deploy_id.downcase}")}
|
148
|
+
if !ignoremaster and MU.mu_public_ip
|
149
|
+
filter += %Q{ AND (labels.mu-master-ip = "#{MU.mu_public_ip.gsub(/\./, "_")}")}
|
150
|
+
end
|
151
|
+
MU.log "Placeholder: Google Group artifacts do not support labels, so ignoremaster cleanup flag has no effect", MU::DEBUG, details: filter
|
152
|
+
|
148
153
|
if my_org
|
149
154
|
groups = MU::Cloud::Google.admin_directory(credentials: credentials).list_groups(customer: MU::Cloud::Google.customerID(credentials)).groups
|
150
155
|
if groups
|
@@ -161,7 +166,7 @@ module MU
|
|
161
166
|
|
162
167
|
if flags['known']
|
163
168
|
flags['known'].each { |group|
|
164
|
-
MU::Cloud
|
169
|
+
MU::Cloud.resourceClass("Google", "Role").removeBindings("group", group, credentials: credentials, noop: noop)
|
165
170
|
}
|
166
171
|
end
|
167
172
|
end
|
@@ -199,7 +204,7 @@ module MU
|
|
199
204
|
# Reverse-map our cloud description into a runnable config hash.
|
200
205
|
# We assume that any values we have in +@config+ are placeholders, and
|
201
206
|
# calculate our own accordingly based on what's live in the cloud.
|
202
|
-
def toKitten(
|
207
|
+
def toKitten(**_args)
|
203
208
|
|
204
209
|
bok = {
|
205
210
|
"cloud" => "Google",
|
@@ -208,28 +213,28 @@ module MU
|
|
208
213
|
|
209
214
|
bok['name'] = cloud_desc.name
|
210
215
|
bok['cloud_id'] = cloud_desc.email
|
211
|
-
bok['members'] = members
|
212
|
-
bok['members'].
|
213
|
-
|
214
|
-
id: m,
|
215
|
-
cloud: "Google",
|
216
|
-
credentials: @config['credentials'],
|
217
|
-
type: "users"
|
218
|
-
)
|
219
|
-
}
|
220
|
-
group_roles = MU::Cloud
|
216
|
+
bok['members'] = members.dup
|
217
|
+
# bok['members'] = members.map { |m|
|
218
|
+
# MU::Config::Ref.get(
|
219
|
+
# id: m,
|
220
|
+
# cloud: "Google",
|
221
|
+
# credentials: @config['credentials'],
|
222
|
+
# type: "users"
|
223
|
+
# )
|
224
|
+
# }
|
225
|
+
group_roles = MU::Cloud.resourceClass("Google", "Role").getAllBindings(@config['credentials'])["by_entity"]
|
221
226
|
if group_roles["group"] and group_roles["group"][bok['cloud_id']] and
|
222
227
|
group_roles["group"][bok['cloud_id']].size > 0
|
223
|
-
bok['roles'] = MU::Cloud
|
228
|
+
bok['roles'] = MU::Cloud.resourceClass("Google", "Role").entityBindingsToSchema(group_roles["group"][bok['cloud_id']], credentials: @config['credentials'])
|
224
229
|
end
|
225
230
|
|
226
231
|
bok
|
227
232
|
end
|
228
233
|
|
229
234
|
# Cloud-specific configuration properties.
|
230
|
-
# @param
|
235
|
+
# @param _config [MU::Config]: The calling MU::Config object
|
231
236
|
# @return [Array<Array,Hash>]: List of required fields, and json-schema Hash of cloud-specific configuration parameters for this resource
|
232
|
-
def self.schema(
|
237
|
+
def self.schema(_config)
|
233
238
|
toplevel_required = []
|
234
239
|
schema = {
|
235
240
|
"name" => {
|
@@ -259,7 +264,7 @@ If we are binding (rather than creating) a group and no roles are specified, we
|
|
259
264
|
|
260
265
|
"roles" => {
|
261
266
|
"type" => "array",
|
262
|
-
"items" => MU::Cloud
|
267
|
+
"items" => MU::Cloud.resourceClass("Google", "Role").ref_schema
|
263
268
|
}
|
264
269
|
}
|
265
270
|
[toplevel_required, schema]
|
@@ -322,7 +327,7 @@ If we are binding (rather than creating) a group and no roles are specified, we
|
|
322
327
|
end
|
323
328
|
|
324
329
|
|
325
|
-
|
330
|
+
MU::Cloud::Google.credConfig(group['credentials'])
|
326
331
|
|
327
332
|
if group['external'] and group['members']
|
328
333
|
MU.log "Cannot manage memberships for external group #{group['name']}", MU::ERR
|
@@ -335,11 +340,7 @@ If we are binding (rather than creating) a group and no roles are specified, we
|
|
335
340
|
if group['members']
|
336
341
|
group['members'].each { |m|
|
337
342
|
if configurator.haveLitterMate?(m, "users")
|
338
|
-
group
|
339
|
-
group['dependencies'] << {
|
340
|
-
"name" => m,
|
341
|
-
"type" => "user"
|
342
|
-
}
|
343
|
+
MU::Config.addDependency(group, m, "user")
|
343
344
|
end
|
344
345
|
}
|
345
346
|
end
|
@@ -348,11 +349,7 @@ If we are binding (rather than creating) a group and no roles are specified, we
|
|
348
349
|
group['roles'].each { |r|
|
349
350
|
if r['role'] and r['role']['name'] and
|
350
351
|
(!r['role']['deploy_id'] and !r['role']['id'])
|
351
|
-
group['
|
352
|
-
group['dependencies'] << {
|
353
|
-
"type" => "role",
|
354
|
-
"name" => r['role']['name']
|
355
|
-
}
|
352
|
+
MU::Config.addDependency(group, r['role']['name'], "role")
|
356
353
|
end
|
357
354
|
}
|
358
355
|
end
|
@@ -360,8 +357,6 @@ If we are binding (rather than creating) a group and no roles are specified, we
|
|
360
357
|
ok
|
361
358
|
end
|
362
359
|
|
363
|
-
private
|
364
|
-
|
365
360
|
end
|
366
361
|
end
|
367
362
|
end
|
@@ -61,7 +61,7 @@ module MU
|
|
61
61
|
if @config['parent']['name'] and !@config['parent']['id']
|
62
62
|
@config['parent']['deploy_id'] = @deploy.deploy_id
|
63
63
|
end
|
64
|
-
parent = MU::Cloud
|
64
|
+
parent = MU::Cloud.resourceClass("Google", "Folder").resolveParent(@config['parent'], credentials: @config['credentials'])
|
65
65
|
if !parent
|
66
66
|
MU.log "Unable to resolve parent resource of Google Project #{@config['name']}", MU::ERR, details: @config['parent']
|
67
67
|
raise "Unable to resolve parent resource of Google Project #{@config['name']}"
|
@@ -113,7 +113,7 @@ module MU
|
|
113
113
|
@habitat_id = parent_id
|
114
114
|
begin
|
115
115
|
setProjectBilling
|
116
|
-
rescue
|
116
|
+
rescue StandardError => e
|
117
117
|
MU.log "Failed to set billing account #{@config['billing_acct']} on project #{@cloud_id}: #{e.message}", MU::ERR
|
118
118
|
MU::Cloud::Google.resource_manager(credentials: @config['credentials']).delete_project(@cloud_id)
|
119
119
|
raise e
|
@@ -167,10 +167,12 @@ module MU
|
|
167
167
|
end
|
168
168
|
end
|
169
169
|
|
170
|
+
@cached_cloud_desc = nil
|
170
171
|
# Return the cloud descriptor for the Habitat
|
171
172
|
# @return [Google::Apis::Core::Hashable]
|
172
|
-
def cloud_desc
|
173
|
-
@cached_cloud_desc
|
173
|
+
def cloud_desc(use_cache: true)
|
174
|
+
return @cached_cloud_desc if @cached_cloud_desc and use_cache
|
175
|
+
@cached_cloud_desc = MU::Cloud::Google::Habitat.find(cloud_id: @cloud_id).values.first
|
174
176
|
if @cached_cloud_desc and @cached_cloud_desc.parent
|
175
177
|
@habitat_id ||= @cached_cloud_desc.parent.id
|
176
178
|
end
|
@@ -209,7 +211,7 @@ module MU
|
|
209
211
|
billing.billing_account_name.empty?
|
210
212
|
return false
|
211
213
|
end
|
212
|
-
rescue ::Google::Apis::ClientError
|
214
|
+
rescue ::Google::Apis::ClientError
|
213
215
|
return false
|
214
216
|
end
|
215
217
|
|
@@ -219,14 +221,15 @@ module MU
|
|
219
221
|
# Remove all Google projects associated with the currently loaded deployment. Try to, anyway.
|
220
222
|
# @param noop [Boolean]: If true, will only print what would be done
|
221
223
|
# @param ignoremaster [Boolean]: If true, will remove resources not flagged as originating from this Mu server
|
222
|
-
# @param region [String]: The cloud provider region
|
223
224
|
# @return [void]
|
224
|
-
def self.cleanup(noop: false,
|
225
|
+
def self.cleanup(noop: false, deploy_id: MU.deploy_id, ignoremaster: false, credentials: nil, flags: {})
|
225
226
|
resp = MU::Cloud::Google.resource_manager(credentials: credentials).list_projects
|
227
|
+
|
226
228
|
if resp and resp.projects
|
227
229
|
resp.projects.each { |p|
|
228
|
-
|
229
|
-
|
230
|
+
labelmatch = (p.labels and (p.labels["mu-id"] == MU.deploy_id.downcase and (ignoremaster or p.labels["mu-master-ip"] == MU.mu_public_ip.gsub(/\./, "_"))))
|
231
|
+
flagmatch = (flags and flags['known'] and flags['known'].include?(p.project_id))
|
232
|
+
if (labelmatch or flagmatch) and p.lifecycle_state == "ACTIVE"
|
230
233
|
MU.log "Deleting project #{p.project_id} (#{p.name})", details: p
|
231
234
|
if !noop
|
232
235
|
begin
|
@@ -282,7 +285,7 @@ module MU
|
|
282
285
|
next if p.lifecycle_state == "DELETE_REQUESTED"
|
283
286
|
found[p.project_id] = p
|
284
287
|
}
|
285
|
-
@@list_projects_cache = found
|
288
|
+
@@list_projects_cache = found.clone
|
286
289
|
end
|
287
290
|
|
288
291
|
found
|
@@ -291,7 +294,7 @@ module MU
|
|
291
294
|
# Reverse-map our cloud description into a runnable config hash.
|
292
295
|
# We assume that any values we have in +@config+ are placeholders, and
|
293
296
|
# calculate our own accordingly based on what's live in the cloud.
|
294
|
-
def toKitten(
|
297
|
+
def toKitten(**args)
|
295
298
|
bok = {
|
296
299
|
"cloud" => "Google",
|
297
300
|
"credentials" => @config['credentials']
|
@@ -311,17 +314,17 @@ module MU
|
|
311
314
|
credentials: @config['credentials'],
|
312
315
|
type: "folders"
|
313
316
|
)
|
314
|
-
elsif rootparent
|
317
|
+
elsif args[:rootparent]
|
315
318
|
bok['parent'] = {
|
316
|
-
'id' => rootparent.is_a?(String) ? rootparent : rootparent.cloud_desc.name
|
319
|
+
'id' => args[:rootparent].is_a?(String) ? args[:rootparent] : args[:rootparent].cloud_desc.name
|
317
320
|
}
|
318
321
|
else
|
319
322
|
# org parent is *probably* safe to infer from credentials
|
320
323
|
end
|
321
324
|
end
|
322
325
|
|
323
|
-
if billing
|
324
|
-
bok['billing_acct'] = billing
|
326
|
+
if args[:billing]
|
327
|
+
bok['billing_acct'] = args[:billing]
|
325
328
|
else
|
326
329
|
cur_billing = MU::Cloud::Google.billing(credentials: @config['credentials']).get_project_billing_info("projects/"+@cloud_id)
|
327
330
|
if cur_billing and cur_billing.billing_account_name
|
@@ -334,9 +337,9 @@ module MU
|
|
334
337
|
|
335
338
|
|
336
339
|
# Cloud-specific configuration properties.
|
337
|
-
# @param
|
340
|
+
# @param _config [MU::Config]: The calling MU::Config object
|
338
341
|
# @return [Array<Array,Hash>]: List of required fields, and json-schema Hash of cloud-specific configuration parameters for this resource
|
339
|
-
def self.schema(
|
342
|
+
def self.schema(_config)
|
340
343
|
toplevel_required = []
|
341
344
|
schema = {
|
342
345
|
"billing_acct" => {
|
@@ -373,11 +376,7 @@ module MU
|
|
373
376
|
end
|
374
377
|
|
375
378
|
if habitat['parent'] and habitat['parent']['name'] and !habitat['parent']['deploy_id'] and configurator.haveLitterMate?(habitat['parent']['name'], "folders")
|
376
|
-
habitat[
|
377
|
-
habitat["dependencies"] << {
|
378
|
-
"type" => "folder",
|
379
|
-
"name" => habitat['parent']['name']
|
380
|
-
}
|
379
|
+
MU::Config.addDependency(habitat, habitat['parent']['name'], "folder")
|
381
380
|
end
|
382
381
|
|
383
382
|
ok
|
@@ -79,13 +79,13 @@ module MU
|
|
79
79
|
end
|
80
80
|
if @config['global']
|
81
81
|
MU.log "Creating Global Forwarding Rule #{@mu_name}", MU::NOTICE, details: ruleobj
|
82
|
-
|
82
|
+
MU::Cloud::Google.compute(credentials: @config['credentials']).insert_global_forwarding_rule(
|
83
83
|
@project_id,
|
84
84
|
ruleobj
|
85
85
|
)
|
86
86
|
else
|
87
87
|
MU.log "Creating regional Forwarding Rule #{@mu_name} in #{@config['region']}", MU::NOTICE, details: ruleobj
|
88
|
-
|
88
|
+
MU::Cloud::Google.compute(credentials: @config['credentials']).insert_forwarding_rule(
|
89
89
|
@project_id,
|
90
90
|
@config['region'],
|
91
91
|
ruleobj
|
@@ -146,15 +146,20 @@ module MU
|
|
146
146
|
# @param ignoremaster [Boolean]: If true, will remove resources not flagged as originating from this Mu server
|
147
147
|
# @param region [String]: The cloud provider region
|
148
148
|
# @return [void]
|
149
|
-
def self.cleanup(noop: false, ignoremaster: false, region: nil, credentials: nil, flags: {})
|
150
|
-
flags["
|
151
|
-
return if !MU::Cloud
|
149
|
+
def self.cleanup(noop: false, deploy_id: MU.deploy_id, ignoremaster: false, region: nil, credentials: nil, flags: {})
|
150
|
+
flags["habitat"] ||= MU::Cloud::Google.defaultProject(credentials)
|
151
|
+
return if !MU::Cloud.resourceClass("Google", "Habitat").isLive?(flags["habitat"], credentials)
|
152
|
+
filter = %Q{(labels.mu-id = "#{MU.deploy_id.downcase}")}
|
153
|
+
if !ignoremaster and MU.mu_public_ip
|
154
|
+
filter += %Q{ AND (labels.mu-master-ip = "#{MU.mu_public_ip.gsub(/\./, "_")}")}
|
155
|
+
end
|
156
|
+
MU.log "Placeholder: Google LoadBalancer artifacts do not support labels, so ignoremaster cleanup flag has no effect", MU::DEBUG, details: filter
|
152
157
|
|
153
158
|
if region
|
154
159
|
["forwarding_rule", "region_backend_service"].each { |type|
|
155
160
|
MU::Cloud::Google.compute(credentials: credentials).delete(
|
156
161
|
type,
|
157
|
-
flags["
|
162
|
+
flags["habitat"],
|
158
163
|
region,
|
159
164
|
noop
|
160
165
|
)
|
@@ -165,7 +170,7 @@ module MU
|
|
165
170
|
["global_forwarding_rule", "target_http_proxy", "target_https_proxy", "url_map", "backend_service", "health_check", "http_health_check", "https_health_check"].each { |type|
|
166
171
|
MU::Cloud::Google.compute(credentials: credentials).delete(
|
167
172
|
type,
|
168
|
-
flags["
|
173
|
+
flags["habitat"],
|
169
174
|
nil,
|
170
175
|
noop
|
171
176
|
)
|
@@ -174,9 +179,9 @@ module MU
|
|
174
179
|
end
|
175
180
|
|
176
181
|
# Cloud-specific configuration properties.
|
177
|
-
# @param
|
182
|
+
# @param _config [MU::Config]: The calling MU::Config object
|
178
183
|
# @return [Array<Array,Hash>]: List of required fields, and json-schema Hash of cloud-specific configuration parameters for this resource
|
179
|
-
def self.schema(
|
184
|
+
def self.schema(_config)
|
180
185
|
toplevel_required = []
|
181
186
|
schema = {
|
182
187
|
"named_ports" => {
|
@@ -202,9 +207,9 @@ module MU
|
|
202
207
|
|
203
208
|
# Cloud-specific pre-processing of {MU::Config::BasketofKittens::loadbalancers}, bare and unvalidated.
|
204
209
|
# @param lb [Hash]: The resource to process and validate
|
205
|
-
# @param
|
210
|
+
# @param _configurator [MU::Config]: The overall deployment configurator of which this resource is a member
|
206
211
|
# @return [Boolean]: True if validation succeeded, False otherwise
|
207
|
-
def self.validateConfig(lb,
|
212
|
+
def self.validateConfig(lb, _configurator)
|
208
213
|
ok = true
|
209
214
|
if lb['classic']
|
210
215
|
MU.log "LoadBalancer 'classic' flag has no meaning in Google Cloud", MU::WARN
|
@@ -236,7 +241,6 @@ module MU
|
|
236
241
|
end
|
237
242
|
|
238
243
|
lb["listeners"].each { |l|
|
239
|
-
ruleobj = nil
|
240
244
|
if lb["private"] and !["TCP", "UDP"].include?(l['lb_protocol'])
|
241
245
|
MU.log "Only TCP and UDP listeners are valid for private LoadBalancers in Google Cloud", MU::ERR
|
242
246
|
ok = false
|
@@ -255,7 +259,6 @@ module MU
|
|
255
259
|
lb["targetgroups"].each { |tg|
|
256
260
|
if tg["healthcheck"]
|
257
261
|
target = tg["healthcheck"]['target'].match(/^([^:]+):(\d+)(.*)/)
|
258
|
-
proto = target[1]
|
259
262
|
if tg["proto"] != target[1]
|
260
263
|
MU.log "LoadBalancer #{lb['name']} can't mix and match target group and health check protocols in Google Cloud", MU::ERR, details: tg
|
261
264
|
ok = false
|
@@ -286,14 +289,9 @@ module MU
|
|
286
289
|
end
|
287
290
|
|
288
291
|
# Locate an existing LoadBalancer or LoadBalancers and return an array containing matching Google resource descriptors for those that match.
|
289
|
-
# @
|
290
|
-
|
291
|
-
|
292
|
-
# @param tag_value [String]: The value of the tag specified by tag_key to match when searching by tag.
|
293
|
-
# @param flags [Hash]: Optional flags
|
294
|
-
# @return [Array<Hash<String,OpenStruct>>]: The cloud provider's complete descriptions of matching LoadBalancers
|
295
|
-
def self.find(cloud_id: nil, region: MU.curRegion, tag_key: "Name", tag_value: nil, flags: {}, credentials: nil)
|
296
|
-
flags["project"] ||= MU::Cloud::Google.defaultProject(credentials)
|
292
|
+
# @return [Hash<String,OpenStruct>]: The cloud provider's complete descriptions of matching LoadBalancers
|
293
|
+
def self.find(**args)
|
294
|
+
args = MU::Cloud::Google.findLocationArgs(args)
|
297
295
|
end
|
298
296
|
|
299
297
|
private
|
@@ -32,6 +32,7 @@ module MU
|
|
32
32
|
# If we're being reverse-engineered from a cloud descriptor, use that
|
33
33
|
# to determine what sort of account we are.
|
34
34
|
if args[:from_cloud_desc]
|
35
|
+
require 'google/apis/admin_directory_v1'
|
35
36
|
@cloud_desc_cache = args[:from_cloud_desc]
|
36
37
|
if args[:from_cloud_desc].class == ::Google::Apis::AdminDirectoryV1::Role
|
37
38
|
@config['role_source'] = "directory"
|
@@ -87,7 +88,7 @@ module MU
|
|
87
88
|
resp = if @config['role_source'] == "org"
|
88
89
|
my_org = MU::Cloud::Google.getOrg(@config['credentials'])
|
89
90
|
MU.log "Creating IAM organization role #{@mu_name} in #{my_org.display_name}", details: create_role_obj
|
90
|
-
|
91
|
+
MU::Cloud::Google.iam(credentials: @credentials).create_organization_role(my_org.name, create_role_obj)
|
91
92
|
elsif @config['role_source'] == "project"
|
92
93
|
if !@project_id
|
93
94
|
raise MuError, "Role #{@mu_name} is supposed to be in project #{@config['project']}, but no such project was found"
|
@@ -133,12 +134,13 @@ module MU
|
|
133
134
|
}
|
134
135
|
end
|
135
136
|
|
137
|
+
@cloud_desc_cache = nil
|
136
138
|
# Return the cloud descriptor for the Role
|
137
139
|
# @return [Google::Apis::Core::Hashable]
|
138
|
-
def cloud_desc
|
139
|
-
return @cloud_desc_cache if @cloud_desc_cache
|
140
|
+
def cloud_desc(use_cache: true)
|
141
|
+
return @cloud_desc_cache if @cloud_desc_cache and use_cache
|
140
142
|
|
141
|
-
|
143
|
+
MU::Cloud::Google.getOrg(@config['credentials'])
|
142
144
|
|
143
145
|
@cloud_desc_cache = if @config['role_source'] == "directory"
|
144
146
|
MU::Cloud::Google.admin_directory(credentials: @config['credentials']).get_role(@customer, @cloud_id)
|
@@ -238,7 +240,7 @@ module MU
|
|
238
240
|
req_obj = MU::Cloud::Google.resource_manager(:SetIamPolicyRequest).new(
|
239
241
|
policy: policy
|
240
242
|
)
|
241
|
-
|
243
|
+
if scope_type == "organizations"
|
242
244
|
MU::Cloud::Google.resource_manager(credentials: credentials).set_organization_iam_policy(
|
243
245
|
scope_id,
|
244
246
|
req_obj
|
@@ -269,13 +271,13 @@ module MU
|
|
269
271
|
my_org = MU::Cloud::Google.getOrg(credentials)
|
270
272
|
if my_org
|
271
273
|
scopes["organizations"] = [my_org.name]
|
272
|
-
folders = MU::Cloud
|
274
|
+
folders = MU::Cloud.resourceClass("Google", "Folder").find(credentials: credentials)
|
273
275
|
if folders and folders.size > 0
|
274
276
|
scopes["folders"] = folders.keys
|
275
277
|
end
|
276
278
|
end
|
277
279
|
|
278
|
-
projects = MU::Cloud
|
280
|
+
projects = MU::Cloud.resourceClass("Google", "Habitat").find(credentials: credentials)
|
279
281
|
if projects and projects.size > 0
|
280
282
|
scopes["projects"] = projects.keys
|
281
283
|
end
|
@@ -310,7 +312,7 @@ module MU
|
|
310
312
|
policy: policy
|
311
313
|
)
|
312
314
|
|
313
|
-
|
315
|
+
if scope_type == "organizations"
|
314
316
|
MU::Cloud::Google.resource_manager(credentials: credentials).set_organization_iam_policy(
|
315
317
|
scope_id,
|
316
318
|
req_obj
|
@@ -340,8 +342,6 @@ module MU
|
|
340
342
|
def self.bindFromConfig(entity_type, entity_id, cfg, credentials: nil, deploy: nil, debug: false)
|
341
343
|
loglevel = debug ? MU::NOTICE : MU::DEBUG
|
342
344
|
|
343
|
-
bindings = []
|
344
|
-
|
345
345
|
return if !cfg
|
346
346
|
MU.log "Google::Role::bindFromConfig binding called for #{entity_type} #{entity_id}", loglevel, details: cfg
|
347
347
|
|
@@ -407,12 +407,12 @@ module MU
|
|
407
407
|
# email field (which is the "real" id most of the time)
|
408
408
|
real_id = nil
|
409
409
|
if entity_type == "group"
|
410
|
-
found = MU::Cloud
|
410
|
+
found = MU::Cloud.resourceClass("Google", "Group").find(cloud_id: entity_id, credentials: credentials)
|
411
411
|
if found[entity_id]
|
412
412
|
real_id = found[entity_id].id
|
413
413
|
end
|
414
414
|
elsif entity_type == "user"
|
415
|
-
found = MU::Cloud
|
415
|
+
found = MU::Cloud.resourceClass("Google", "User").find(cloud_id: entity_id, credentials: credentials)
|
416
416
|
if found[entity_id]
|
417
417
|
real_id = found[entity_id].id
|
418
418
|
end
|
@@ -464,12 +464,17 @@ module MU
|
|
464
464
|
# Remove all roles associated with the currently loaded deployment.
|
465
465
|
# @param noop [Boolean]: If true, will only print what would be done
|
466
466
|
# @param ignoremaster [Boolean]: If true, will remove resources not flagged as originating from this Mu server
|
467
|
-
# @param region [String]: The cloud provider region
|
468
467
|
# @return [void]
|
469
|
-
def self.cleanup(noop: false,
|
468
|
+
def self.cleanup(noop: false, deploy_id: MU.deploy_id, ignoremaster: false, credentials: nil, flags: {})
|
470
469
|
customer = MU::Cloud::Google.customerID(credentials)
|
471
470
|
my_org = MU::Cloud::Google.getOrg(credentials)
|
472
471
|
|
472
|
+
filter = %Q{(labels.mu-id = "#{MU.deploy_id.downcase}")}
|
473
|
+
if !ignoremaster and MU.mu_public_ip
|
474
|
+
filter += %Q{ AND (labels.mu-master-ip = "#{MU.mu_public_ip.gsub(/\./, "_")}")}
|
475
|
+
end
|
476
|
+
MU.log "Placeholder: Google Role artifacts do not support labels, so ignoremaster cleanup flag has no effect", MU::DEBUG, details: filter
|
477
|
+
|
473
478
|
if flags['known']
|
474
479
|
flags['known'].each { |id|
|
475
480
|
next if id.nil?
|
@@ -558,7 +563,7 @@ module MU
|
|
558
563
|
if args[:project]
|
559
564
|
canned = Hash[MU::Cloud::Google.iam(credentials: args[:credentials]).list_roles.roles.map { |r| [r.name, r] }]
|
560
565
|
begin
|
561
|
-
MU::Cloud
|
566
|
+
MU::Cloud.resourceClass("Google", "Habitat").bindings(args[:project], credentials: args[:credentials]).each { |binding|
|
562
567
|
found[binding.role] = canned[binding.role]
|
563
568
|
}
|
564
569
|
rescue ::Google::Apis::ClientError => e
|
@@ -576,7 +581,7 @@ module MU
|
|
576
581
|
}
|
577
582
|
end
|
578
583
|
if args[:cloud_id]
|
579
|
-
found.reject! { |k,
|
584
|
+
found.reject! { |k, _v| k != role.name }
|
580
585
|
end
|
581
586
|
|
582
587
|
# Now go get everything that's bound here
|
@@ -586,10 +591,15 @@ module MU
|
|
586
591
|
bindings['by_scope']['projects'][args[:project]]
|
587
592
|
bindings['by_scope']['projects'][args[:project]].keys.each { |r|
|
588
593
|
if r.match(/^roles\//)
|
589
|
-
|
590
|
-
|
594
|
+
begin
|
595
|
+
role = MU::Cloud::Google.iam(credentials: args[:credentials]).get_role(r)
|
596
|
+
found[role.name] = role
|
597
|
+
rescue ::Google::Apis::ClientError => e
|
598
|
+
raise e if !e.message.match(/(?:forbidden|notFound): /)
|
599
|
+
MU.log "Failed MU::Cloud::Google.iam(credentials: #{args[:credentials]}).get_role(#{r})", MU::WARN, details: e.message
|
600
|
+
end
|
591
601
|
elsif !found[r]
|
592
|
-
MU.log "NEED TO GET #{r}", MU::WARN
|
602
|
+
# MU.log "NEED TO GET #{r}", MU::WARN
|
593
603
|
end
|
594
604
|
}
|
595
605
|
end
|
@@ -626,15 +636,17 @@ module MU
|
|
626
636
|
}
|
627
637
|
end
|
628
638
|
|
629
|
-
|
630
|
-
|
631
|
-
|
632
|
-
|
633
|
-
|
634
|
-
|
635
|
-
resp.roles
|
636
|
-
|
637
|
-
|
639
|
+
if my_org
|
640
|
+
resp = begin
|
641
|
+
MU::Cloud::Google.iam(credentials: args[:credentials]).list_organization_roles(my_org.name)
|
642
|
+
rescue ::Google::Apis::ClientError => e
|
643
|
+
raise e if !e.message.match(/forbidden: /)
|
644
|
+
end
|
645
|
+
if resp and resp.roles
|
646
|
+
resp.roles.each { |role|
|
647
|
+
found[role.name] = role
|
648
|
+
}
|
649
|
+
end
|
638
650
|
end
|
639
651
|
end
|
640
652
|
|
@@ -644,7 +656,8 @@ module MU
|
|
644
656
|
# Reverse-map our cloud description into a runnable config hash.
|
645
657
|
# We assume that any values we have in +@config+ are placeholders, and
|
646
658
|
# calculate our own accordingly based on what's live in the cloud.
|
647
|
-
def toKitten(
|
659
|
+
def toKitten(**args)
|
660
|
+
|
648
661
|
bok = {
|
649
662
|
"cloud" => "Google",
|
650
663
|
"credentials" => @config['credentials'],
|
@@ -677,10 +690,10 @@ module MU
|
|
677
690
|
end
|
678
691
|
if !cloud_desc.role_privileges.nil? and !cloud_desc.role_privileges.empty?
|
679
692
|
bok['import'] = []
|
680
|
-
ids,
|
693
|
+
ids, _names, _privs = MU::Cloud::Google::Role.privilege_service_to_name(@config['credentials'])
|
681
694
|
cloud_desc.role_privileges.each { |priv|
|
682
695
|
if !ids[priv.service_id]
|
683
|
-
MU.log "Role privilege defined for a service id with no name I can find, writing with raw id", MU::
|
696
|
+
MU.log "Role privilege defined for a service id with no name I can find, writing with raw id", MU::DEBUG, details: priv
|
684
697
|
bok["import"] << priv.service_id+"/"+priv.privilege_name
|
685
698
|
else
|
686
699
|
bok["import"] << ids[priv.service_id]+"/"+priv.privilege_name
|
@@ -696,7 +709,7 @@ module MU
|
|
696
709
|
bok['name'] = name.gsub(/[^a-z0-9]/i, '-')
|
697
710
|
bok['role_source'] = "canned"
|
698
711
|
elsif cloud_desc.name.match(/^([^\/]+?)\/([^\/]+?)\/roles\/(.*)/)
|
699
|
-
|
712
|
+
_junk, type, parent, name = Regexp.last_match.to_a
|
700
713
|
bok['name'] = name.gsub(/[^a-z0-9]/i, '-')
|
701
714
|
bok['role_source'] = type == "organizations" ? "org" : "project"
|
702
715
|
if bok['role_source'] == "project"
|
@@ -723,25 +736,45 @@ module MU
|
|
723
736
|
bindings[scopetype].each_pair { |scope_id, entity_types|
|
724
737
|
# If we've been given a habitat filter, skip over bindings
|
725
738
|
# that don't match it.
|
726
|
-
if scopetype == "projects"
|
727
|
-
|
728
|
-
|
739
|
+
if scopetype == "projects"
|
740
|
+
if (args[:habitats] and !args[:habitats].empty? and
|
741
|
+
!args[:habitats].include?(scope_id)) or
|
742
|
+
!MU::Cloud::Google.listHabitats(@credentials).include?(scope_id)
|
743
|
+
next
|
744
|
+
end
|
729
745
|
end
|
730
746
|
|
731
747
|
entity_types.each_pair { |entity_type, entities|
|
732
748
|
mu_entitytype = (entity_type == "serviceAccount" ? "user" : entity_type)+"s"
|
733
749
|
entities.each { |entity|
|
750
|
+
next if entity.nil?
|
751
|
+
foreign = if entity_type == "serviceAccount" and entity.match(/@(.*?)\.iam\.gserviceaccount\.com/)
|
752
|
+
!MU::Cloud::Google.listHabitats(@credentials).include?(Regexp.last_match[1])
|
753
|
+
end
|
754
|
+
|
734
755
|
entity_ref = if entity_type == "organizations"
|
735
756
|
{ "id" => ((org == my_org.name and @config['credentials']) ? @config['credentials'] : org) }
|
736
757
|
elsif entity_type == "domain"
|
737
758
|
{ "id" => entity }
|
738
759
|
else
|
760
|
+
shortclass, _cfg_name, _cfg_plural, _classname = MU::Cloud.getResourceNames(mu_entitytype)
|
761
|
+
if args[:types].include?(shortclass) and
|
762
|
+
!(entity_type == "serviceAccount" and
|
763
|
+
MU::Cloud::Google::User.cannedServiceAcctName?(entity))
|
764
|
+
MU.log "Role #{@cloud_id}: Skipping #{shortclass} binding for #{entity}; we are adopting that type and will set bindings from that resource", MU::DEBUG
|
765
|
+
next
|
766
|
+
end
|
767
|
+
|
739
768
|
MU::Config::Ref.get(
|
740
769
|
id: entity,
|
741
770
|
cloud: "Google",
|
742
771
|
type: mu_entitytype
|
743
772
|
)
|
744
773
|
end
|
774
|
+
if entity_ref.nil?
|
775
|
+
MU.log "I somehow ended up with a nil entity reference for #{entity_type} #{entity}", MU::ERR, details: [ bok, bindings ]
|
776
|
+
next
|
777
|
+
end
|
745
778
|
refmap ||= {}
|
746
779
|
refmap[entity_ref] ||= {}
|
747
780
|
refmap[entity_ref][scopetype] ||= []
|
@@ -760,6 +793,7 @@ module MU
|
|
760
793
|
}
|
761
794
|
}
|
762
795
|
}
|
796
|
+
|
763
797
|
bok["bindings"] ||= []
|
764
798
|
refmap.each_pair { |entity, scopes|
|
765
799
|
newbinding = { "entity" => entity }
|
@@ -882,7 +916,7 @@ module MU
|
|
882
916
|
end
|
883
917
|
|
884
918
|
role = MU::Cloud::Google.admin_directory(credentials: credentials).get_role(MU::Cloud::Google.customerID(credentials), binding.role_id)
|
885
|
-
MU.log "Failed to find entity #{binding.assigned_to} referenced in GSuite/Cloud Identity binding to role #{role.role_name}", MU::
|
919
|
+
MU.log "Failed to find entity #{binding.assigned_to} referenced in GSuite/Cloud Identity binding to role #{role.role_name}", MU::DEBUG, details: role
|
886
920
|
}
|
887
921
|
|
888
922
|
resp = MU::Cloud::Google.resource_manager(credentials: credentials).get_organization_iam_policy(my_org.name)
|
@@ -890,15 +924,17 @@ module MU
|
|
890
924
|
insertBinding("organizations", my_org.name, binding)
|
891
925
|
}
|
892
926
|
|
893
|
-
MU::Cloud
|
894
|
-
MU::Cloud
|
927
|
+
MU::Cloud.resourceClass("Google", "Folder").find(credentials: credentials).keys.each { |folder|
|
928
|
+
folder_bindings = MU::Cloud.resourceClass("Google", "Folder").bindings(folder, credentials: credentials)
|
929
|
+
next if !folder_bindings
|
930
|
+
folder_bindings.each { |binding|
|
895
931
|
insertBinding("folders", folder, binding)
|
896
932
|
}
|
897
933
|
}
|
898
934
|
end
|
899
|
-
MU::Cloud::Google
|
935
|
+
MU::Cloud::Google.listHabitats(credentials).each { |project|
|
900
936
|
begin
|
901
|
-
MU::Cloud
|
937
|
+
MU::Cloud.resourceClass("Google", "Habitat").bindings(project, credentials: credentials).each { |binding|
|
902
938
|
insertBinding("projects", project, binding)
|
903
939
|
}
|
904
940
|
rescue ::Google::Apis::ClientError => e
|
@@ -983,9 +1019,9 @@ module MU
|
|
983
1019
|
end
|
984
1020
|
|
985
1021
|
# Cloud-specific configuration properties.
|
986
|
-
# @param
|
1022
|
+
# @param _config [MU::Config]: The calling MU::Config object
|
987
1023
|
# @return [Array<Array,Hash>]: List of required fields, and json-schema Hash of cloud-specific configuration parameters for this resource
|
988
|
-
def self.schema(
|
1024
|
+
def self.schema(_config)
|
989
1025
|
toplevel_required = []
|
990
1026
|
schema = {
|
991
1027
|
"name" => {
|
@@ -1050,7 +1086,7 @@ If this value is not specified, and the role name matches the name of an existin
|
|
1050
1086
|
def self.validateConfig(role, configurator)
|
1051
1087
|
ok = true
|
1052
1088
|
|
1053
|
-
|
1089
|
+
MU::Cloud::Google.credConfig(role['credentials'])
|
1054
1090
|
|
1055
1091
|
my_org = MU::Cloud::Google.getOrg(role['credentials'])
|
1056
1092
|
if !role['role_source']
|
@@ -1059,7 +1095,7 @@ If this value is not specified, and the role name matches the name of an existin
|
|
1059
1095
|
if !lookup_name.match(/^roles\//)
|
1060
1096
|
lookup_name = "roles/"+lookup_name
|
1061
1097
|
end
|
1062
|
-
|
1098
|
+
MU::Cloud::Google.iam(credentials: role['credentials']).get_role(lookup_name)
|
1063
1099
|
MU.log "Role #{role['name']} appears to be a referenced to canned role #{role.name} (#{role.title})", MU::NOTICE
|
1064
1100
|
role['role_source'] = "canned"
|
1065
1101
|
rescue ::Google::Apis::ClientError
|
@@ -1081,7 +1117,7 @@ If this value is not specified, and the role name matches the name of an existin
|
|
1081
1117
|
MU.log "None of the directory service privileges available to credentials #{role['credentials']} map to the ones declared for role #{role['name']}", MU::ERR, details: role['import'].sort
|
1082
1118
|
ok = false
|
1083
1119
|
elsif missing.size > 0
|
1084
|
-
MU.log "Some directory service privileges declared for role #{role['name']} aren't available to credentials #{role['credentials']}, will skip", MU::
|
1120
|
+
MU.log "Some directory service privileges declared for role #{role['name']} aren't available to credentials #{role['credentials']}, will skip", MU::DEBUG, details: missing
|
1085
1121
|
end
|
1086
1122
|
end
|
1087
1123
|
end
|
@@ -1096,11 +1132,7 @@ If this value is not specified, and the role name matches the name of an existin
|
|
1096
1132
|
if role['role_source'] == "project"
|
1097
1133
|
role['project'] ||= MU::Cloud::Google.defaultProject(role['credentials'])
|
1098
1134
|
if configurator.haveLitterMate?(role['project'], "habitats")
|
1099
|
-
role['
|
1100
|
-
role['dependencies'] << {
|
1101
|
-
"type" => "habitat",
|
1102
|
-
"name" => role['project']
|
1103
|
-
}
|
1135
|
+
MU::Config.addDependency(role, role['project'], "habitat")
|
1104
1136
|
end
|
1105
1137
|
end
|
1106
1138
|
|
@@ -1108,26 +1140,25 @@ If this value is not specified, and the role name matches the name of an existin
|
|
1108
1140
|
role['bindings'].each { |binding|
|
1109
1141
|
if binding['entity'] and binding['entity']['name'] and
|
1110
1142
|
configurator.haveLitterMate?(binding['entity']['name'], binding['entity']['type'])
|
1111
|
-
role['
|
1112
|
-
role['dependencies'] << {
|
1113
|
-
"type" => binding['entity']['type'].sub(/s$/, ''),
|
1114
|
-
"name" => binding['entity']['name']
|
1115
|
-
}
|
1116
|
-
|
1143
|
+
MU::Config.addDependency(role, binding['entity']['name'], binding['entity']['type'])
|
1117
1144
|
end
|
1118
1145
|
}
|
1146
|
+
role['bindings'].uniq!
|
1119
1147
|
end
|
1120
1148
|
|
1121
1149
|
ok
|
1122
1150
|
end
|
1123
1151
|
|
1124
|
-
private
|
1125
|
-
|
1126
1152
|
@@service_id_to_name = {}
|
1127
1153
|
@@service_id_to_privs = {}
|
1128
1154
|
@@service_name_to_id = {}
|
1129
1155
|
@@service_name_map_semaphore = Mutex.new
|
1130
1156
|
|
1157
|
+
# Generate lookup tables mapping between hex service role identifiers,
|
1158
|
+
# human-readable names of services, and the privileges associated with
|
1159
|
+
# those roles.
|
1160
|
+
# @param credentials [String]
|
1161
|
+
# @return [Array<Hash,Hash,Hash>]
|
1131
1162
|
def self.privilege_service_to_name(credentials = nil)
|
1132
1163
|
|
1133
1164
|
customer = MU::Cloud::Google.customerID(credentials)
|
@@ -1176,6 +1207,11 @@ If this value is not specified, and the role name matches the name of an existin
|
|
1176
1207
|
}
|
1177
1208
|
end
|
1178
1209
|
|
1210
|
+
# Convert a list of shorthand GSuite/Cloud Identity privileges into
|
1211
|
+
# +RolePrivilege+ objects for consumption by other API calls
|
1212
|
+
# @param roles [Array<String>]:
|
1213
|
+
# @param credentials [String]:
|
1214
|
+
# @return [Array<Google::Apis::AdminDirectoryV1::DirectoryService::Role::RolePrivilege>]
|
1179
1215
|
def self.map_directory_privileges(roles, credentials: nil)
|
1180
1216
|
rolepriv_objs = []
|
1181
1217
|
notfound = []
|