cloud-mu 3.1.3 → 3.3.0
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.
- 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 = []
|