cloud-mu 3.1.2 → 3.2.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 +10 -13
- data/bin/mu-azure-tests +57 -0
- data/bin/mu-cleanup +2 -4
- data/bin/mu-configure +52 -0
- data/bin/mu-deploy +3 -3
- data/bin/mu-findstray-tests +25 -0
- data/bin/mu-gen-docs +2 -4
- data/bin/mu-load-config.rb +2 -3
- data/bin/mu-node-manage +15 -16
- data/bin/mu-run-tests +135 -37
- data/cloud-mu.gemspec +22 -20
- data/cookbooks/mu-activedirectory/resources/domain.rb +4 -4
- data/cookbooks/mu-activedirectory/resources/domain_controller.rb +4 -4
- data/cookbooks/mu-tools/libraries/helper.rb +3 -2
- data/cookbooks/mu-tools/libraries/monkey.rb +35 -0
- data/cookbooks/mu-tools/recipes/apply_security.rb +14 -14
- data/cookbooks/mu-tools/recipes/aws_api.rb +9 -0
- data/cookbooks/mu-tools/recipes/eks.rb +2 -2
- data/cookbooks/mu-tools/recipes/google_api.rb +2 -2
- data/cookbooks/mu-tools/recipes/selinux.rb +2 -1
- data/cookbooks/mu-tools/recipes/windows-client.rb +163 -164
- data/cookbooks/mu-tools/resources/disk.rb +1 -1
- data/cookbooks/mu-tools/resources/windows_users.rb +44 -43
- data/extras/clean-stock-amis +25 -19
- data/extras/generate-stock-images +1 -0
- data/extras/image-generators/AWS/win2k12.yaml +18 -13
- data/extras/image-generators/AWS/win2k16.yaml +18 -13
- data/extras/image-generators/AWS/win2k19.yaml +21 -0
- data/extras/image-generators/Google/centos6.yaml +1 -0
- data/extras/image-generators/Google/centos7.yaml +1 -1
- data/modules/mommacat.ru +6 -16
- data/modules/mu.rb +165 -111
- data/modules/mu/adoption.rb +401 -68
- data/modules/mu/cleanup.rb +199 -306
- data/modules/mu/cloud.rb +100 -1632
- data/modules/mu/cloud/database.rb +49 -0
- data/modules/mu/cloud/dnszone.rb +46 -0
- data/modules/mu/cloud/machine_images.rb +212 -0
- data/modules/mu/cloud/providers.rb +81 -0
- data/modules/mu/cloud/resource_base.rb +920 -0
- data/modules/mu/cloud/server.rb +40 -0
- data/modules/mu/cloud/server_pool.rb +1 -0
- data/modules/mu/cloud/ssh_sessions.rb +228 -0
- data/modules/mu/cloud/winrm_sessions.rb +237 -0
- data/modules/mu/cloud/wrappers.rb +165 -0
- data/modules/mu/config.rb +171 -1767
- data/modules/mu/config/alarm.rb +2 -6
- data/modules/mu/config/bucket.rb +4 -4
- data/modules/mu/config/cache_cluster.rb +1 -1
- data/modules/mu/config/collection.rb +4 -4
- data/modules/mu/config/container_cluster.rb +9 -4
- data/modules/mu/config/database.rb +83 -104
- data/modules/mu/config/database.yml +1 -2
- data/modules/mu/config/dnszone.rb +6 -6
- data/modules/mu/config/doc_helpers.rb +516 -0
- data/modules/mu/config/endpoint.rb +4 -4
- data/modules/mu/config/firewall_rule.rb +103 -4
- data/modules/mu/config/folder.rb +4 -4
- data/modules/mu/config/function.rb +3 -3
- data/modules/mu/config/group.rb +4 -4
- data/modules/mu/config/habitat.rb +4 -4
- data/modules/mu/config/loadbalancer.rb +60 -14
- data/modules/mu/config/log.rb +4 -4
- data/modules/mu/config/msg_queue.rb +4 -4
- data/modules/mu/config/nosqldb.rb +4 -4
- data/modules/mu/config/notifier.rb +3 -3
- data/modules/mu/config/ref.rb +365 -0
- data/modules/mu/config/role.rb +4 -4
- data/modules/mu/config/schema_helpers.rb +509 -0
- data/modules/mu/config/search_domain.rb +4 -4
- data/modules/mu/config/server.rb +97 -70
- data/modules/mu/config/server.yml +1 -0
- data/modules/mu/config/server_pool.rb +5 -9
- data/modules/mu/config/storage_pool.rb +1 -1
- data/modules/mu/config/tail.rb +200 -0
- data/modules/mu/config/user.rb +4 -4
- data/modules/mu/config/vpc.rb +70 -27
- data/modules/mu/config/vpc.yml +0 -1
- data/modules/mu/defaults/AWS.yaml +83 -60
- data/modules/mu/defaults/Azure.yaml +1 -0
- data/modules/mu/defaults/Google.yaml +3 -2
- data/modules/mu/deploy.rb +30 -26
- data/modules/mu/groomer.rb +17 -2
- data/modules/mu/groomers/ansible.rb +188 -41
- data/modules/mu/groomers/chef.rb +116 -55
- data/modules/mu/logger.rb +127 -148
- data/modules/mu/master.rb +389 -2
- data/modules/mu/master/chef.rb +3 -4
- data/modules/mu/master/ldap.rb +3 -3
- data/modules/mu/master/ssl.rb +12 -3
- data/modules/mu/mommacat.rb +217 -2612
- data/modules/mu/mommacat/daemon.rb +397 -0
- data/modules/mu/mommacat/naming.rb +473 -0
- data/modules/mu/mommacat/search.rb +495 -0
- data/modules/mu/mommacat/storage.rb +722 -0
- data/modules/mu/{clouds → providers}/README.md +1 -1
- data/modules/mu/{clouds → providers}/aws.rb +271 -112
- data/modules/mu/{clouds → providers}/aws/alarm.rb +5 -3
- data/modules/mu/{clouds → providers}/aws/bucket.rb +26 -22
- data/modules/mu/{clouds → providers}/aws/cache_cluster.rb +33 -67
- data/modules/mu/{clouds → providers}/aws/collection.rb +24 -23
- data/modules/mu/{clouds → providers}/aws/container_cluster.rb +681 -721
- data/modules/mu/providers/aws/database.rb +1744 -0
- data/modules/mu/{clouds → providers}/aws/dnszone.rb +64 -63
- data/modules/mu/{clouds → providers}/aws/endpoint.rb +22 -27
- data/modules/mu/{clouds → providers}/aws/firewall_rule.rb +214 -244
- data/modules/mu/{clouds → providers}/aws/folder.rb +7 -7
- data/modules/mu/{clouds → providers}/aws/function.rb +17 -22
- data/modules/mu/{clouds → providers}/aws/group.rb +23 -23
- data/modules/mu/{clouds → providers}/aws/habitat.rb +17 -14
- data/modules/mu/{clouds → providers}/aws/loadbalancer.rb +57 -48
- data/modules/mu/{clouds → providers}/aws/log.rb +15 -12
- data/modules/mu/{clouds → providers}/aws/msg_queue.rb +17 -16
- data/modules/mu/{clouds → providers}/aws/nosqldb.rb +18 -11
- data/modules/mu/{clouds → providers}/aws/notifier.rb +11 -6
- data/modules/mu/{clouds → providers}/aws/role.rb +112 -86
- data/modules/mu/{clouds → providers}/aws/search_domain.rb +39 -33
- data/modules/mu/{clouds → providers}/aws/server.rb +835 -1133
- data/modules/mu/{clouds → providers}/aws/server_pool.rb +56 -60
- data/modules/mu/{clouds → providers}/aws/storage_pool.rb +24 -42
- data/modules/mu/{clouds → providers}/aws/user.rb +21 -22
- data/modules/mu/{clouds → providers}/aws/userdata/README.md +0 -0
- data/modules/mu/{clouds → providers}/aws/userdata/linux.erb +0 -0
- data/modules/mu/{clouds → providers}/aws/userdata/windows.erb +2 -1
- data/modules/mu/{clouds → providers}/aws/vpc.rb +523 -929
- data/modules/mu/providers/aws/vpc_subnet.rb +286 -0
- data/modules/mu/{clouds → providers}/azure.rb +29 -9
- data/modules/mu/{clouds → providers}/azure/container_cluster.rb +3 -8
- data/modules/mu/{clouds → providers}/azure/firewall_rule.rb +18 -11
- data/modules/mu/{clouds → providers}/azure/habitat.rb +8 -6
- data/modules/mu/{clouds → providers}/azure/loadbalancer.rb +5 -5
- data/modules/mu/{clouds → providers}/azure/role.rb +8 -10
- data/modules/mu/{clouds → providers}/azure/server.rb +95 -48
- data/modules/mu/{clouds → providers}/azure/user.rb +6 -8
- data/modules/mu/{clouds → providers}/azure/userdata/README.md +0 -0
- data/modules/mu/{clouds → providers}/azure/userdata/linux.erb +0 -0
- data/modules/mu/{clouds → providers}/azure/userdata/windows.erb +0 -0
- data/modules/mu/{clouds → providers}/azure/vpc.rb +16 -21
- data/modules/mu/{clouds → providers}/cloudformation.rb +18 -7
- data/modules/mu/{clouds → providers}/cloudformation/alarm.rb +3 -3
- data/modules/mu/{clouds → providers}/cloudformation/cache_cluster.rb +3 -3
- data/modules/mu/{clouds → providers}/cloudformation/collection.rb +3 -3
- data/modules/mu/{clouds → providers}/cloudformation/database.rb +6 -17
- data/modules/mu/{clouds → providers}/cloudformation/dnszone.rb +3 -3
- data/modules/mu/{clouds → providers}/cloudformation/firewall_rule.rb +3 -3
- data/modules/mu/{clouds → providers}/cloudformation/loadbalancer.rb +3 -3
- data/modules/mu/{clouds → providers}/cloudformation/log.rb +3 -3
- data/modules/mu/{clouds → providers}/cloudformation/server.rb +7 -7
- data/modules/mu/{clouds → providers}/cloudformation/server_pool.rb +5 -5
- data/modules/mu/{clouds → providers}/cloudformation/vpc.rb +5 -7
- data/modules/mu/{clouds → providers}/docker.rb +0 -0
- data/modules/mu/{clouds → providers}/google.rb +67 -30
- data/modules/mu/{clouds → providers}/google/bucket.rb +13 -15
- data/modules/mu/{clouds → providers}/google/container_cluster.rb +84 -77
- data/modules/mu/{clouds → providers}/google/database.rb +10 -20
- data/modules/mu/{clouds → providers}/google/firewall_rule.rb +15 -14
- data/modules/mu/{clouds → providers}/google/folder.rb +20 -17
- data/modules/mu/{clouds → providers}/google/function.rb +139 -167
- data/modules/mu/{clouds → providers}/google/group.rb +29 -34
- data/modules/mu/{clouds → providers}/google/habitat.rb +21 -22
- data/modules/mu/{clouds → providers}/google/loadbalancer.rb +18 -20
- data/modules/mu/{clouds → providers}/google/role.rb +92 -58
- data/modules/mu/{clouds → providers}/google/server.rb +242 -155
- data/modules/mu/{clouds → providers}/google/server_pool.rb +25 -44
- data/modules/mu/{clouds → providers}/google/user.rb +95 -31
- data/modules/mu/{clouds → providers}/google/userdata/README.md +0 -0
- data/modules/mu/{clouds → providers}/google/userdata/linux.erb +0 -0
- data/modules/mu/{clouds → providers}/google/userdata/windows.erb +0 -0
- data/modules/mu/{clouds → providers}/google/vpc.rb +103 -79
- data/modules/tests/bucket.yml +4 -0
- data/modules/tests/centos6.yaml +11 -0
- data/modules/tests/centos7.yaml +11 -0
- data/modules/tests/centos8.yaml +12 -0
- data/modules/tests/ecs.yaml +23 -0
- data/modules/tests/includes-and-params.yaml +2 -1
- data/modules/tests/rds.yaml +108 -0
- data/modules/tests/regrooms/aws-iam.yaml +201 -0
- data/modules/tests/regrooms/bucket.yml +19 -0
- data/modules/tests/regrooms/rds.yaml +123 -0
- data/modules/tests/server-with-scrub-muisms.yaml +1 -0
- data/modules/tests/super_simple_bok.yml +1 -3
- data/modules/tests/win2k12.yaml +17 -5
- data/modules/tests/win2k16.yaml +25 -0
- data/modules/tests/win2k19.yaml +25 -0
- data/requirements.txt +1 -0
- data/spec/mu/clouds/azure_spec.rb +2 -2
- metadata +232 -154
- data/extras/image-generators/AWS/windows.yaml +0 -18
- data/modules/mu/clouds/aws/database.rb +0 -1985
|
@@ -25,14 +25,7 @@ module MU
|
|
|
25
25
|
@config["groomer"] = MU::Config.defaultGroomer unless @config["groomer"]
|
|
26
26
|
@groomclass = MU::Groomer.loadGroomer(@config["groomer"])
|
|
27
27
|
|
|
28
|
-
@mu_name ||=
|
|
29
|
-
if @config and @config['engine'] and @config["engine"].match(/^sqlserver/)
|
|
30
|
-
@deploy.getResourceName(@config["name"], max_length: 15)
|
|
31
|
-
else
|
|
32
|
-
@deploy.getResourceName(@config["name"], max_length: 63)
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
@mu_name.gsub(/(--|-$)/i, "").gsub(/(_)/, "-").gsub!(/^[^a-z]/i, "")
|
|
28
|
+
@mu_name ||= @deploy.getResourceName(@config["name"], max_length: 63)
|
|
36
29
|
end
|
|
37
30
|
|
|
38
31
|
# Called automatically by {MU::Deploy#createResources}
|
|
@@ -68,8 +61,7 @@ module MU
|
|
|
68
61
|
# Locate an existing Database or Databases and return an array containing matching GCP resource descriptors for those that match.
|
|
69
62
|
# @return [Array<Hash<String,OpenStruct>>]: The cloud provider's complete descriptions of matching Databases
|
|
70
63
|
def self.find(**args)
|
|
71
|
-
args
|
|
72
|
-
args[:project] ||= MU::Cloud::Google.defaultProject(args[:credentials])
|
|
64
|
+
args = MU::Cloud::Google.findLocationArgs(args)
|
|
73
65
|
end
|
|
74
66
|
|
|
75
67
|
# Called automatically by {MU::Deploy#createResources}
|
|
@@ -109,21 +101,21 @@ module MU
|
|
|
109
101
|
# @param region [String]: The cloud provider region in which to operate
|
|
110
102
|
# @return [void]
|
|
111
103
|
def self.cleanup(noop: false, ignoremaster: false, region: MU.curRegion, credentials: nil, flags: {})
|
|
112
|
-
flags["
|
|
113
|
-
|
|
114
|
-
# instances = MU::Cloud::Google.sql(credentials: credentials).list_instances(flags['
|
|
104
|
+
flags["habitat"] ||= MU::Cloud::Google.defaultProject(credentials)
|
|
105
|
+
|
|
106
|
+
# instances = MU::Cloud::Google.sql(credentials: credentials).list_instances(flags['habitat'], filter: %Q{userLabels.mu-id:"#{MU.deploy_id.downcase}"})
|
|
115
107
|
# if instances and instances.items
|
|
116
108
|
# instances.items.each { |instance|
|
|
117
109
|
# MU.log "Deleting Cloud SQL instance #{instance.name}"
|
|
118
|
-
# MU::Cloud::Google.sql(credentials: credentials).delete_instance(flags['
|
|
110
|
+
# MU::Cloud::Google.sql(credentials: credentials).delete_instance(flags['habitat'], instance.name) if !noop
|
|
119
111
|
# }
|
|
120
112
|
# end
|
|
121
113
|
end
|
|
122
114
|
|
|
123
115
|
# Cloud-specific configuration properties.
|
|
124
|
-
# @param
|
|
116
|
+
# @param _config [MU::Config]: The calling MU::Config object
|
|
125
117
|
# @return [Array<Array,Hash>]: List of required fields, and json-schema Hash of cloud-specific configuration parameters for this resource
|
|
126
|
-
def self.schema(
|
|
118
|
+
def self.schema(_config)
|
|
127
119
|
toplevel_required = []
|
|
128
120
|
schema = {}
|
|
129
121
|
[toplevel_required, schema]
|
|
@@ -131,9 +123,9 @@ module MU
|
|
|
131
123
|
|
|
132
124
|
# Cloud-specific pre-processing of {MU::Config::BasketofKittens::databases}, bare and unvalidated.
|
|
133
125
|
# @param db [Hash]: The resource to process and validate
|
|
134
|
-
# @param
|
|
126
|
+
# @param _configurator [MU::Config]: The overall deployment configurator of which this resource is a member
|
|
135
127
|
# @return [Boolean]: True if validation succeeded, False otherwise
|
|
136
|
-
def self.validateConfig(db,
|
|
128
|
+
def self.validateConfig(db, _configurator)
|
|
137
129
|
ok = true
|
|
138
130
|
|
|
139
131
|
if db["create_cluster"]
|
|
@@ -144,8 +136,6 @@ module MU
|
|
|
144
136
|
ok
|
|
145
137
|
end
|
|
146
138
|
|
|
147
|
-
private
|
|
148
|
-
|
|
149
139
|
end #class
|
|
150
140
|
end #class
|
|
151
141
|
end
|
|
@@ -172,8 +172,7 @@ end
|
|
|
172
172
|
# @param args [Hash]: Hash of named arguments passed via Ruby's double-splat
|
|
173
173
|
# @return [Hash<String,OpenStruct>]: The cloud provider's complete descriptions of matching resources
|
|
174
174
|
def self.find(**args)
|
|
175
|
-
args
|
|
176
|
-
args[:project] ||= MU::Cloud::Google.defaultProject(args[:credentials])
|
|
175
|
+
args = MU::Cloud::Google.findLocationArgs(args)
|
|
177
176
|
|
|
178
177
|
found = {}
|
|
179
178
|
resp = begin
|
|
@@ -207,15 +206,19 @@ end
|
|
|
207
206
|
# Remove all security groups (firewall rulesets) associated with the currently loaded deployment.
|
|
208
207
|
# @param noop [Boolean]: If true, will only print what would be done
|
|
209
208
|
# @param ignoremaster [Boolean]: If true, will remove resources not flagged as originating from this Mu server
|
|
210
|
-
# @param region [String]: The cloud provider region
|
|
211
209
|
# @return [void]
|
|
212
|
-
def self.cleanup(noop: false, ignoremaster: false,
|
|
213
|
-
flags["
|
|
214
|
-
return if !MU::Cloud
|
|
210
|
+
def self.cleanup(noop: false, ignoremaster: false, credentials: nil, flags: {})
|
|
211
|
+
flags["habitat"] ||= MU::Cloud::Google.defaultProject(credentials)
|
|
212
|
+
return if !MU::Cloud.resourceClass("Google", "Habitat").isLive?(flags["habitat"], credentials)
|
|
213
|
+
filter = %Q{(labels.mu-id = "#{MU.deploy_id.downcase}")}
|
|
214
|
+
if !ignoremaster and MU.mu_public_ip
|
|
215
|
+
filter += %Q{ AND (labels.mu-master-ip = "#{MU.mu_public_ip.gsub(/\./, "_")}")}
|
|
216
|
+
end
|
|
217
|
+
MU.log "Placeholder: Google FirewallRule artifacts do not support labels, so ignoremaster cleanup flag has no effect", MU::DEBUG, details: filter
|
|
215
218
|
|
|
216
219
|
MU::Cloud::Google.compute(credentials: credentials).delete(
|
|
217
220
|
"firewall",
|
|
218
|
-
flags["
|
|
221
|
+
flags["habitat"],
|
|
219
222
|
nil,
|
|
220
223
|
noop
|
|
221
224
|
)
|
|
@@ -224,7 +227,7 @@ end
|
|
|
224
227
|
# Reverse-map our cloud description into a runnable config hash.
|
|
225
228
|
# We assume that any values we have in +@config+ are placeholders, and
|
|
226
229
|
# calculate our own accordingly based on what's live in the cloud.
|
|
227
|
-
def toKitten(
|
|
230
|
+
def toKitten(**_args)
|
|
228
231
|
|
|
229
232
|
if cloud_desc.name.match(/^[a-f0-9]+$/)
|
|
230
233
|
gke_ish = true
|
|
@@ -362,9 +365,9 @@ end
|
|
|
362
365
|
end
|
|
363
366
|
|
|
364
367
|
# Cloud-specific configuration properties.
|
|
365
|
-
# @param
|
|
368
|
+
# @param _config [MU::Config]: The calling MU::Config object
|
|
366
369
|
# @return [Array<Array,Hash>]: List of required fields, and json-schema Hash of cloud-specific configuration parameters for this resource
|
|
367
|
-
def self.schema(
|
|
370
|
+
def self.schema(_config = nil)
|
|
368
371
|
toplevel_required = []
|
|
369
372
|
schema = {
|
|
370
373
|
"rules" => {
|
|
@@ -437,7 +440,7 @@ end
|
|
|
437
440
|
elsif acl['vpc']['habitat'] and acl['vpc']['habitat']['name']
|
|
438
441
|
acl['vpc']['project'] = acl['vpc']['habitat']['name']
|
|
439
442
|
end
|
|
440
|
-
correct_vpc = MU::Cloud
|
|
443
|
+
correct_vpc = MU::Cloud.resourceClass("Google", "VPC").pickVPC(
|
|
441
444
|
acl['vpc'],
|
|
442
445
|
acl,
|
|
443
446
|
"firewall_rule",
|
|
@@ -523,7 +526,7 @@ end
|
|
|
523
526
|
end
|
|
524
527
|
}
|
|
525
528
|
|
|
526
|
-
rules_by_class.reject! { |
|
|
529
|
+
rules_by_class.reject! { |_k, v| v.size == 0 }
|
|
527
530
|
|
|
528
531
|
# Generate other firewall rule objects to cover the other behaviors
|
|
529
532
|
# we've requested, if indeed we've done so.
|
|
@@ -543,8 +546,6 @@ end
|
|
|
543
546
|
ok
|
|
544
547
|
end
|
|
545
548
|
|
|
546
|
-
private
|
|
547
|
-
|
|
548
549
|
end #class
|
|
549
550
|
end #class
|
|
550
551
|
end
|
|
@@ -48,7 +48,7 @@ module MU
|
|
|
48
48
|
folder_obj = MU::Cloud::Google.folder(:Folder).new(params)
|
|
49
49
|
|
|
50
50
|
MU.log "Creating folder #{name_string} under #{parent}", details: folder_obj
|
|
51
|
-
|
|
51
|
+
MU::Cloud::Google.folder(credentials: @config['credentials']).create_folder(folder_obj, parent: parent)
|
|
52
52
|
|
|
53
53
|
# Wait for list_folders output to be consistent (for the folder we
|
|
54
54
|
# just created to show up)
|
|
@@ -125,10 +125,12 @@ module MU
|
|
|
125
125
|
nil
|
|
126
126
|
end
|
|
127
127
|
|
|
128
|
+
@cached_cloud_desc = nil
|
|
128
129
|
# Return the cloud descriptor for the Folder
|
|
129
130
|
# @return [Google::Apis::Core::Hashable]
|
|
130
|
-
def cloud_desc
|
|
131
|
-
@cached_cloud_desc
|
|
131
|
+
def cloud_desc(use_cache: true)
|
|
132
|
+
return @cached_cloud_desc if @cached_cloud_desc and use_cache
|
|
133
|
+
@cached_cloud_desc = MU::Cloud::Google::Folder.find(cloud_id: @cloud_id, credentials: @config['credentials']).values.first
|
|
132
134
|
@habitat_id ||= @cached_cloud_desc.parent.sub(/^(folders|organizations)\//, "")
|
|
133
135
|
@cached_cloud_desc
|
|
134
136
|
end
|
|
@@ -136,7 +138,7 @@ module MU
|
|
|
136
138
|
# Return the metadata for this folders's configuration
|
|
137
139
|
# @return [Hash]
|
|
138
140
|
def notify
|
|
139
|
-
desc = MU.structToHash(
|
|
141
|
+
desc = MU.structToHash(cloud_desc)
|
|
140
142
|
desc["mu_name"] = @mu_name
|
|
141
143
|
desc["parent"] = @parent
|
|
142
144
|
desc["cloud_id"] = @cloud_id
|
|
@@ -160,7 +162,12 @@ module MU
|
|
|
160
162
|
# @param noop [Boolean]: If true, will only print what would be done
|
|
161
163
|
# @param ignoremaster [Boolean]: If true, will remove resources not flagged as originating from this Mu server
|
|
162
164
|
# @return [void]
|
|
163
|
-
def self.cleanup(noop: false, ignoremaster: false, credentials: nil, flags: {}
|
|
165
|
+
def self.cleanup(noop: false, ignoremaster: false, credentials: nil, flags: {})
|
|
166
|
+
filter = %Q{(labels.mu-id = "#{MU.deploy_id.downcase}")}
|
|
167
|
+
if !ignoremaster and MU.mu_public_ip
|
|
168
|
+
filter += %Q{ AND (labels.mu-master-ip = "#{MU.mu_public_ip.gsub(/\./, "_")}")}
|
|
169
|
+
end
|
|
170
|
+
MU.log "Placeholder: Google Folder artifacts do not support labels, so ignoremaster cleanup flag has no effect", MU::DEBUG, details: filter
|
|
164
171
|
# We can't label GCP folders, and their names are too short to encode
|
|
165
172
|
# Mu deploy IDs, so all we can do is rely on flags['known'] passed in
|
|
166
173
|
# from cleanup, which relies on our metadata to know what's ours.
|
|
@@ -229,10 +236,10 @@ module MU
|
|
|
229
236
|
# @return [Hash<String,OpenStruct>]: The cloud provider's complete descriptions of matching resources
|
|
230
237
|
def self.find(**args)
|
|
231
238
|
found = {}
|
|
232
|
-
|
|
233
239
|
# Recursively search a GCP folder hierarchy for a folder matching our
|
|
234
240
|
# supplied name or identifier.
|
|
235
241
|
def self.find_matching_folder(parent, name: nil, id: nil, credentials: nil)
|
|
242
|
+
|
|
236
243
|
resp = MU::Cloud::Google.folder(credentials: credentials).list_folders(parent: parent)
|
|
237
244
|
if resp and resp.folders
|
|
238
245
|
resp.folders.each { |f|
|
|
@@ -271,6 +278,7 @@ module MU
|
|
|
271
278
|
end
|
|
272
279
|
else
|
|
273
280
|
resp = MU::Cloud::Google.folder(credentials: args[:credentials]).list_folders(parent: parent)
|
|
281
|
+
|
|
274
282
|
if resp and resp.folders
|
|
275
283
|
resp.folders.each { |folder|
|
|
276
284
|
next if folder.lifecycle_state == "DELETE_REQUESTED"
|
|
@@ -293,7 +301,7 @@ module MU
|
|
|
293
301
|
# Reverse-map our cloud description into a runnable config hash.
|
|
294
302
|
# We assume that any values we have in +@config+ are placeholders, and
|
|
295
303
|
# calculate our own accordingly based on what's live in the cloud.
|
|
296
|
-
def toKitten(
|
|
304
|
+
def toKitten(**args)
|
|
297
305
|
bok = {
|
|
298
306
|
"cloud" => "Google",
|
|
299
307
|
"credentials" => @config['credentials']
|
|
@@ -303,16 +311,15 @@ module MU
|
|
|
303
311
|
bok['cloud_id'] = cloud_desc.name
|
|
304
312
|
bok['name'] = cloud_desc.display_name#+bok['cloud_id'] # only way to guarantee uniqueness
|
|
305
313
|
if cloud_desc.parent.match(/^folders\/(.*)/)
|
|
306
|
-
MU.log bok['display_name']+" generating reference", MU::NOTICE, details: cloud_desc.parent
|
|
307
314
|
bok['parent'] = MU::Config::Ref.get(
|
|
308
315
|
id: cloud_desc.parent,
|
|
309
316
|
cloud: "Google",
|
|
310
317
|
credentials: @config['credentials'],
|
|
311
318
|
type: "folders"
|
|
312
319
|
)
|
|
313
|
-
elsif rootparent
|
|
320
|
+
elsif args[:rootparent]
|
|
314
321
|
bok['parent'] = {
|
|
315
|
-
'id' => rootparent.is_a?(String) ? rootparent : rootparent.cloud_desc.name
|
|
322
|
+
'id' => args[:rootparent].is_a?(String) ? args[:rootparent] : args[:rootparent].cloud_desc.name
|
|
316
323
|
}
|
|
317
324
|
else
|
|
318
325
|
bok['parent'] = { 'id' => cloud_desc.parent }
|
|
@@ -322,9 +329,9 @@ MU.log bok['display_name']+" generating reference", MU::NOTICE, details: cloud_d
|
|
|
322
329
|
end
|
|
323
330
|
|
|
324
331
|
# Cloud-specific configuration properties.
|
|
325
|
-
# @param
|
|
332
|
+
# @param _config [MU::Config]: The calling MU::Config object
|
|
326
333
|
# @return [Array<Array,Hash>]: List of required fields, and json-schema Hash of cloud-specific configuration parameters for this resource
|
|
327
|
-
def self.schema(
|
|
334
|
+
def self.schema(_config)
|
|
328
335
|
toplevel_required = []
|
|
329
336
|
schema = {
|
|
330
337
|
"display_name" => {
|
|
@@ -348,11 +355,7 @@ MU.log bok['display_name']+" generating reference", MU::NOTICE, details: cloud_d
|
|
|
348
355
|
end
|
|
349
356
|
|
|
350
357
|
if folder['parent'] and folder['parent']['name'] and !folder['parent']['deploy_id'] and configurator.haveLitterMate?(folder['parent']['name'], "folders")
|
|
351
|
-
folder[
|
|
352
|
-
folder["dependencies"] << {
|
|
353
|
-
"type" => "folder",
|
|
354
|
-
"name" => folder['parent']['name']
|
|
355
|
-
}
|
|
358
|
+
MU::Config.addDependency(folder, folder['parent']['name'], "folder")
|
|
356
359
|
end
|
|
357
360
|
|
|
358
361
|
ok
|
|
@@ -108,98 +108,9 @@ module example.com/cloudfunction
|
|
|
108
108
|
|
|
109
109
|
# Called automatically by {MU::Deploy#createResources}
|
|
110
110
|
def create
|
|
111
|
-
labels = Hash[@tags.keys.map { |k|
|
|
112
|
-
[k.downcase, @tags[k].downcase.gsub(/[^-_a-z0-9]/, '-')] }
|
|
113
|
-
]
|
|
114
|
-
labels["name"] = MU::Cloud::Google.nameStr(@mu_name)
|
|
115
111
|
|
|
116
112
|
location = "projects/"+@config['project']+"/locations/"+@config['region']
|
|
117
|
-
|
|
118
|
-
retries = 0
|
|
119
|
-
begin
|
|
120
|
-
sa_ref = MU::Config::Ref.get(@config['service_account'])
|
|
121
|
-
sa = @deploy.findLitterMate(name: sa_ref.name, type: "users")
|
|
122
|
-
if !sa or !sa.cloud_desc
|
|
123
|
-
sleep 10
|
|
124
|
-
end
|
|
125
|
-
rescue ::Google::Apis::ClientError => e
|
|
126
|
-
if e.message.match(/notFound:/)
|
|
127
|
-
sleep 10
|
|
128
|
-
retries += 1
|
|
129
|
-
retry
|
|
130
|
-
end
|
|
131
|
-
end while !sa or !sa.cloud_desc and retries < 5
|
|
132
|
-
|
|
133
|
-
if !sa or !sa.cloud_desc
|
|
134
|
-
raise MuError, "Failed to get service account cloud id from #{@config['service_account'].to_s}"
|
|
135
|
-
end
|
|
136
|
-
|
|
137
|
-
desc = {
|
|
138
|
-
name: location+"/functions/"+@mu_name.downcase,
|
|
139
|
-
runtime: @config['runtime'],
|
|
140
|
-
timeout: @config['timeout'].to_s+"s",
|
|
141
|
-
# entry_point: "hello_world",
|
|
142
|
-
entry_point: @config['handler'],
|
|
143
|
-
description: @deploy.deploy_id,
|
|
144
|
-
service_account_email: sa.cloud_desc.email,
|
|
145
|
-
labels: labels,
|
|
146
|
-
available_memory_mb: @config['memory']
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
# XXX This network argument is deprecated in favor of using VPC
|
|
150
|
-
# Connectors. Which would be fine, except there's no API support for
|
|
151
|
-
# interacting with VPC Connectors. Can't create them, can't list them,
|
|
152
|
-
# can't do anything except pass their ids into Cloud Functions or
|
|
153
|
-
# AppEngine and hope for the best.
|
|
154
|
-
if @config['vpc_connector']
|
|
155
|
-
desc[:vpc_connector] = @config['vpc_connector']
|
|
156
|
-
elsif @vpc
|
|
157
|
-
desc[:network] = @vpc.url.sub(/^.*?\/projects\//, 'projects/')
|
|
158
|
-
end
|
|
159
|
-
|
|
160
|
-
if @config['triggers']
|
|
161
|
-
desc[:event_trigger] = MU::Cloud::Google.function(:EventTrigger).new(
|
|
162
|
-
event_type: @config['triggers'].first['event'],
|
|
163
|
-
resource: @config['triggers'].first['resource']
|
|
164
|
-
)
|
|
165
|
-
else
|
|
166
|
-
desc[:https_trigger] = MU::Cloud::Google.function(:HttpsTrigger).new
|
|
167
|
-
end
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
if @config['environment_variable']
|
|
171
|
-
@config['environment_variable'].each { |var|
|
|
172
|
-
desc[:environment_variables] ||= {}
|
|
173
|
-
desc[:environment_variables][var["key"].to_s] = var["value"].to_s
|
|
174
|
-
}
|
|
175
|
-
end
|
|
176
|
-
|
|
177
|
-
# hello_code = nil
|
|
178
|
-
# HELLO_WORLDS.each_pair { |runtime, code|
|
|
179
|
-
# if @config['runtime'].match(/^#{Regexp.quote(runtime)}/)
|
|
180
|
-
# hello_code = code
|
|
181
|
-
# break
|
|
182
|
-
# end
|
|
183
|
-
# }
|
|
184
|
-
if @config['code']['gs_url']
|
|
185
|
-
desc[:source_archive_url] = @config['code']['gs_url']
|
|
186
|
-
elsif @config['code']['zip_file']
|
|
187
|
-
desc[:source_archive_url] = MU::Cloud::Google::Function.uploadPackage(@config['code']['zip_file'], @mu_name+"-cloudfunction.zip", credentials: @credentials)
|
|
188
|
-
end
|
|
189
|
-
|
|
190
|
-
# Dir.mktmpdir(@mu_name) { |dir|
|
|
191
|
-
# hello_code.each_pair { |file, contents|
|
|
192
|
-
# f = File.open(dir+"/"+file, "w")
|
|
193
|
-
# f.puts contents
|
|
194
|
-
# f.close
|
|
195
|
-
# Zip::File.open(dir+"/function.zip", Zip::File::CREATE) { |z|
|
|
196
|
-
# z.add(file, dir+"/"+file)
|
|
197
|
-
# }
|
|
198
|
-
# }
|
|
199
|
-
# desc[:source_archive_url] = MU::Cloud::Google::Function.uploadPackage(dir+"/function.zip", @mu_name+"-cloudfunction.zip", credentials: @credentials)
|
|
200
|
-
# }
|
|
201
|
-
|
|
202
|
-
func_obj = MU::Cloud::Google.function(:CloudFunction).new(desc)
|
|
113
|
+
func_obj = buildDesc
|
|
203
114
|
MU.log "Creating Cloud Function #{@mu_name} in #{location}", details: func_obj
|
|
204
115
|
resp = MU::Cloud::Google.function(credentials: @credentials).create_project_location_function(location, func_obj)
|
|
205
116
|
@cloud_id = resp.name
|
|
@@ -214,27 +125,26 @@ module example.com/cloudfunction
|
|
|
214
125
|
labels["name"] = MU::Cloud::Google.nameStr(@mu_name)
|
|
215
126
|
|
|
216
127
|
if cloud_desc.labels != labels
|
|
217
|
-
|
|
128
|
+
need_update = true
|
|
218
129
|
end
|
|
219
130
|
|
|
220
131
|
if cloud_desc.runtime != @config['runtime']
|
|
221
|
-
|
|
132
|
+
need_update = true
|
|
222
133
|
end
|
|
223
134
|
if cloud_desc.timeout != @config['timeout'].to_s+"s"
|
|
224
|
-
|
|
135
|
+
need_update = true
|
|
225
136
|
end
|
|
226
137
|
if cloud_desc.entry_point != @config['handler']
|
|
227
|
-
|
|
138
|
+
need_update = true
|
|
228
139
|
end
|
|
229
140
|
if cloud_desc.available_memory_mb != @config['memory']
|
|
230
|
-
|
|
141
|
+
need_update = true
|
|
231
142
|
end
|
|
232
143
|
if @config['environment_variable']
|
|
233
144
|
@config['environment_variable'].each { |var|
|
|
234
145
|
if !cloud_desc.environment_variables or
|
|
235
146
|
cloud_desc.environment_variables[var["key"].to_s] != var["value"].to_s
|
|
236
|
-
|
|
237
|
-
desc[:environment_variables][var["key"].to_s] = var["value"].to_s
|
|
147
|
+
need_update = true
|
|
238
148
|
end
|
|
239
149
|
}
|
|
240
150
|
end
|
|
@@ -242,10 +152,7 @@ module example.com/cloudfunction
|
|
|
242
152
|
if !cloud_desc.event_trigger or
|
|
243
153
|
cloud_desc.event_trigger.event_type != @config['triggers'].first['event'] or
|
|
244
154
|
cloud_desc.event_trigger.resource != @config['triggers'].first['resource']
|
|
245
|
-
|
|
246
|
-
event_type: @config['triggers'].first['event'],
|
|
247
|
-
resource: @config['triggers'].first['resource']
|
|
248
|
-
)
|
|
155
|
+
need_update = true
|
|
249
156
|
end
|
|
250
157
|
end
|
|
251
158
|
|
|
@@ -254,7 +161,6 @@ module example.com/cloudfunction
|
|
|
254
161
|
File.read("#{dir}/current.zip")
|
|
255
162
|
}
|
|
256
163
|
|
|
257
|
-
source_url = nil
|
|
258
164
|
new = if @config['code']['zip_file']
|
|
259
165
|
File.read(@config['code']['zip_file'])
|
|
260
166
|
elsif @config['code']['gs_url']
|
|
@@ -269,37 +175,21 @@ module example.com/cloudfunction
|
|
|
269
175
|
if @config['code']['gs_url'] and
|
|
270
176
|
(@config['code']['gs_url'] != cloud_desc.source_archive_url or
|
|
271
177
|
current != new)
|
|
272
|
-
|
|
178
|
+
need_update = true
|
|
273
179
|
elsif @config['code']['zip_file'] and current != new
|
|
180
|
+
need_update = true
|
|
274
181
|
desc[:source_archive_url] = MU::Cloud::Google::Function.uploadPackage(@config['code']['zip_file'], @mu_name+"-cloudfunction.zip", credentials: @credentials)
|
|
275
182
|
end
|
|
276
183
|
|
|
277
|
-
if
|
|
278
|
-
|
|
279
|
-
# endpoint hangs indefinitely if either is missing. Charming.
|
|
280
|
-
if !desc[:https_trigger] and !desc[:event_trigger]
|
|
281
|
-
if cloud_desc.https_trigger
|
|
282
|
-
desc[:https_trigger] = MU::Cloud::Google.function(:HttpsTrigger).new
|
|
283
|
-
else
|
|
284
|
-
desc[:event_trigger] = cloud_desc.event_trigger
|
|
285
|
-
end
|
|
286
|
-
end
|
|
287
|
-
if !desc[:source_archive_url] and !desc[:source_upload_url]
|
|
288
|
-
if cloud_desc.source_archive_url
|
|
289
|
-
desc[:source_archive_url] = cloud_desc.source_archive_url
|
|
290
|
-
else
|
|
291
|
-
desc[:source_upload_url] = cloud_desc.source_upload_url
|
|
292
|
-
end
|
|
293
|
-
end
|
|
294
|
-
|
|
295
|
-
func_obj = MU::Cloud::Google.function(:CloudFunction).new(desc)
|
|
184
|
+
if need_update
|
|
185
|
+
func_obj = buildDesc
|
|
296
186
|
MU.log "Updating Cloud Function #{@mu_name}", MU::NOTICE, details: func_obj
|
|
297
187
|
begin
|
|
298
|
-
MU::Cloud::Google.function(credentials: @credentials).patch_project_location_function(
|
|
299
|
-
@cloud_id,
|
|
300
|
-
func_obj
|
|
301
|
-
)
|
|
302
|
-
rescue ::Google::Apis::ClientError
|
|
188
|
+
# MU::Cloud::Google.function(credentials: @credentials).patch_project_location_function(
|
|
189
|
+
# @cloud_id,
|
|
190
|
+
# func_obj
|
|
191
|
+
# )
|
|
192
|
+
rescue ::Google::Apis::ClientError
|
|
303
193
|
MU.log "Error updating Cloud Function #{@mu_name}.", MU::ERR
|
|
304
194
|
if desc[:source_archive_url]
|
|
305
195
|
main_file = nil
|
|
@@ -344,13 +234,13 @@ module example.com/cloudfunction
|
|
|
344
234
|
# @param region [String]: The cloud provider region
|
|
345
235
|
# @return [void]
|
|
346
236
|
def self.cleanup(noop: false, ignoremaster: false, region: MU.curRegion, credentials: nil, flags: {})
|
|
347
|
-
flags["
|
|
348
|
-
return if !MU::Cloud
|
|
237
|
+
flags["habitat"] ||= MU::Cloud::Google.defaultProject(credentials)
|
|
238
|
+
return if !MU::Cloud.resourceClass("Google", "Habitat").isLive?(flags["habitat"], credentials)
|
|
349
239
|
# Make sure we catch regional *and* zone functions
|
|
350
|
-
found = MU::Cloud::Google::Function.find(credentials: credentials, region: region, project: flags["
|
|
240
|
+
found = MU::Cloud::Google::Function.find(credentials: credentials, region: region, project: flags["habitat"])
|
|
351
241
|
found.each_pair { |cloud_id, desc|
|
|
352
242
|
if (desc.description and desc.description == MU.deploy_id) or
|
|
353
|
-
(desc.labels and desc.labels["mu-id"] == MU.deploy_id.downcase) or
|
|
243
|
+
(desc.labels and desc.labels["mu-id"] == MU.deploy_id.downcase and (ignoremaster or desc.labels["mu-master-ip"] == MU.mu_public_ip.gsub(/\./, "_"))) or
|
|
354
244
|
(flags["known"] and flags["known"].include?(cloud_id))
|
|
355
245
|
MU.log "Deleting Cloud Function #{desc.name}"
|
|
356
246
|
if !noop
|
|
@@ -364,9 +254,7 @@ module example.com/cloudfunction
|
|
|
364
254
|
# Locate an existing project
|
|
365
255
|
# @return [Hash<OpenStruct>]: The cloud provider's complete descriptions of matching project
|
|
366
256
|
def self.find(**args)
|
|
367
|
-
args
|
|
368
|
-
args[:project] ||= MU::Cloud::Google.defaultProject(args[:credentials])
|
|
369
|
-
location = args[:region] || args[:availability_zone] || "-"
|
|
257
|
+
args = MU::Cloud::Google.findLocationArgs(args)
|
|
370
258
|
|
|
371
259
|
found = {}
|
|
372
260
|
|
|
@@ -379,7 +267,7 @@ module example.com/cloudfunction
|
|
|
379
267
|
found[args[:cloud_id]] = resp if resp
|
|
380
268
|
else
|
|
381
269
|
resp = begin
|
|
382
|
-
MU::Cloud::Google.function(credentials: args[:credentials]).list_project_location_functions("projects/#{args[:project]}/locations/#{location}")
|
|
270
|
+
MU::Cloud::Google.function(credentials: args[:credentials]).list_project_location_functions("projects/#{args[:project]}/locations/#{args[:location]}")
|
|
383
271
|
rescue ::Google::Apis::ClientError => e
|
|
384
272
|
raise e if !e.message.match(/forbidden:/)
|
|
385
273
|
end
|
|
@@ -397,7 +285,7 @@ module example.com/cloudfunction
|
|
|
397
285
|
# Reverse-map our cloud description into a runnable config hash.
|
|
398
286
|
# We assume that any values we have in +@config+ are placeholders, and
|
|
399
287
|
# calculate our own accordingly based on what's live in the cloud.
|
|
400
|
-
def toKitten(
|
|
288
|
+
def toKitten(**_args)
|
|
401
289
|
bok = {
|
|
402
290
|
"cloud" => "Google",
|
|
403
291
|
"cloud_id" => @cloud_id,
|
|
@@ -452,7 +340,7 @@ module example.com/cloudfunction
|
|
|
452
340
|
end
|
|
453
341
|
|
|
454
342
|
codefile = bok["project"]+"_"+bok["region"]+"_"+bok["name"]+".zip"
|
|
455
|
-
MU::Cloud::Google::Function.downloadPackage(@cloud_id, codefile, credentials: @config['credentials'])
|
|
343
|
+
return nil if !MU::Cloud::Google::Function.downloadPackage(@cloud_id, codefile, credentials: @config['credentials'])
|
|
456
344
|
bok['code'] = {
|
|
457
345
|
'zip_file' => codefile
|
|
458
346
|
}
|
|
@@ -460,7 +348,6 @@ module example.com/cloudfunction
|
|
|
460
348
|
bok
|
|
461
349
|
end
|
|
462
350
|
|
|
463
|
-
|
|
464
351
|
# Cloud-specific configuration properties.
|
|
465
352
|
# @param config [MU::Config]: The calling MU::Config object
|
|
466
353
|
# @return [Array<Array,Hash>]: List of required fields, and json-schema Hash of cloud-specific configuration parameters for this resource
|
|
@@ -486,7 +373,7 @@ module example.com/cloudfunction
|
|
|
486
373
|
}
|
|
487
374
|
}
|
|
488
375
|
},
|
|
489
|
-
"service_account" => MU::Cloud
|
|
376
|
+
"service_account" => MU::Cloud.resourceClass("Google", "Server").schema(config)[1]["service_account"],
|
|
490
377
|
"runtime" => {
|
|
491
378
|
"type" => "string",
|
|
492
379
|
"enum" => %w{nodejs go python nodejs8 nodejs10 python37 go111 go113},
|
|
@@ -495,8 +382,14 @@ module example.com/cloudfunction
|
|
|
495
382
|
"type" => "string",
|
|
496
383
|
"description" => "+DEPRECATED+ VPC Connector to attach, of the form +projects/my-project/locations/some-region/connectors/my-connector+. This option will be removed once proper google-cloud-sdk support for VPC Connectors becomes available, at which point we will piggyback on the normal +vpc+ stanza and resolve connectors as needed."
|
|
497
384
|
},
|
|
385
|
+
"vpc_connector_allow_all_egress" => {
|
|
386
|
+
"type" => "boolean",
|
|
387
|
+
"default" => false,
|
|
388
|
+
"description" => "+DEPRECATED+ Allow VPC connector egress traffic to any IP range, instead of just private IPs. This option will be removed once proper google-cloud-sdk support for VPC Connectors becomes available, at which point we will piggyback on the normal +vpc+ stanza and resolve connectors as needed."
|
|
389
|
+
},
|
|
498
390
|
"code" => {
|
|
499
391
|
"type" => "object",
|
|
392
|
+
"description" => "Zipped deployment package to upload to our function.",
|
|
500
393
|
"properties" => {
|
|
501
394
|
"gs_url" => {
|
|
502
395
|
"type" => "string",
|
|
@@ -523,8 +416,13 @@ module example.com/cloudfunction
|
|
|
523
416
|
cloud_desc.source_archive_url.match(/^gs:\/\/([^\/]+)\/(.*)/)
|
|
524
417
|
bucket = Regexp.last_match[1]
|
|
525
418
|
path = Regexp.last_match[2]
|
|
526
|
-
|
|
527
|
-
|
|
419
|
+
|
|
420
|
+
begin
|
|
421
|
+
MU::Cloud::Google.storage(credentials: credentials).get_object(bucket, path, download_dest: zipfile)
|
|
422
|
+
rescue ::Google::Apis::ClientError => e
|
|
423
|
+
MU.log "Couldn't retrieve gs://#{bucket}/#{path} for #{function_id}", MU::WARN, details: e.inspect
|
|
424
|
+
return false
|
|
425
|
+
end
|
|
528
426
|
elsif cloud_desc.source_upload_url
|
|
529
427
|
resp = MU::Cloud::Google.function(credentials: credentials).generate_function_download_url(
|
|
530
428
|
function_id
|
|
@@ -535,6 +433,7 @@ module example.com/cloudfunction
|
|
|
535
433
|
f.close
|
|
536
434
|
end
|
|
537
435
|
end
|
|
436
|
+
true
|
|
538
437
|
end
|
|
539
438
|
|
|
540
439
|
# Upload a zipfile to our admin Cloud Storage bucket, for use by
|
|
@@ -625,32 +524,7 @@ module example.com/cloudfunction
|
|
|
625
524
|
ok = false
|
|
626
525
|
end
|
|
627
526
|
else
|
|
628
|
-
|
|
629
|
-
"name" => function['name'],
|
|
630
|
-
"cloud" => "Google",
|
|
631
|
-
"project" => function["project"],
|
|
632
|
-
"credentials" => function["credentials"],
|
|
633
|
-
"type" => "service"
|
|
634
|
-
}
|
|
635
|
-
if user["name"].length < 6
|
|
636
|
-
user["name"] += Password.pronounceable(6)
|
|
637
|
-
end
|
|
638
|
-
if function['roles']
|
|
639
|
-
user['roles'] = function['roles'].dup
|
|
640
|
-
end
|
|
641
|
-
configurator.insertKitten(user, "users", true)
|
|
642
|
-
function['dependencies'] ||= []
|
|
643
|
-
function['service_account'] = MU::Config::Ref.get(
|
|
644
|
-
type: "users",
|
|
645
|
-
cloud: "Google",
|
|
646
|
-
name: user["name"],
|
|
647
|
-
project: user["project"],
|
|
648
|
-
credentials: user["credentials"]
|
|
649
|
-
)
|
|
650
|
-
function['dependencies'] << {
|
|
651
|
-
"type" => "user",
|
|
652
|
-
"name" => user["name"]
|
|
653
|
-
}
|
|
527
|
+
function = MU::Cloud.resourceClass("Google", "User").genericServiceAccount(function, configurator)
|
|
654
528
|
end
|
|
655
529
|
|
|
656
530
|
# siblings = configurator.haveLitterMate?(nil, "vpcs", has_multiple: true)
|
|
@@ -673,6 +547,104 @@ module example.com/cloudfunction
|
|
|
673
547
|
ok
|
|
674
548
|
end
|
|
675
549
|
|
|
550
|
+
private
|
|
551
|
+
|
|
552
|
+
def buildDesc
|
|
553
|
+
labels = Hash[@tags.keys.map { |k|
|
|
554
|
+
[k.downcase, @tags[k].downcase.gsub(/[^-_a-z0-9]/, '-')] }
|
|
555
|
+
]
|
|
556
|
+
labels["name"] = MU::Cloud::Google.nameStr(@mu_name)
|
|
557
|
+
|
|
558
|
+
location = "projects/"+@config['project']+"/locations/"+@config['region']
|
|
559
|
+
sa = nil
|
|
560
|
+
retries = 0
|
|
561
|
+
begin
|
|
562
|
+
sa_ref = MU::Config::Ref.get(@config['service_account'])
|
|
563
|
+
sa = @deploy.findLitterMate(name: sa_ref.name, type: "users")
|
|
564
|
+
if !sa or !sa.cloud_desc
|
|
565
|
+
sleep 10
|
|
566
|
+
end
|
|
567
|
+
rescue ::Google::Apis::ClientError => e
|
|
568
|
+
if e.message.match(/notFound:/)
|
|
569
|
+
sleep 10
|
|
570
|
+
retries += 1
|
|
571
|
+
retry
|
|
572
|
+
end
|
|
573
|
+
end while !sa or !sa.cloud_desc and retries < 5
|
|
574
|
+
|
|
575
|
+
if !sa or !sa.cloud_desc
|
|
576
|
+
raise MuError, "Failed to get service account cloud id from #{@config['service_account'].to_s}"
|
|
577
|
+
end
|
|
578
|
+
|
|
579
|
+
desc = {
|
|
580
|
+
name: location+"/functions/"+@mu_name.downcase,
|
|
581
|
+
runtime: @config['runtime'],
|
|
582
|
+
timeout: @config['timeout'].to_s+"s",
|
|
583
|
+
# entry_point: "hello_world",
|
|
584
|
+
entry_point: @config['handler'],
|
|
585
|
+
description: @deploy.deploy_id,
|
|
586
|
+
service_account_email: sa.cloud_desc.email,
|
|
587
|
+
labels: labels,
|
|
588
|
+
available_memory_mb: @config['memory']
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
# XXX This network argument is deprecated in favor of using VPC
|
|
592
|
+
# Connectors. Which would be fine, except there's no API support for
|
|
593
|
+
# interacting with VPC Connectors. Can't create them, can't list them,
|
|
594
|
+
# can't do anything except pass their ids into Cloud Functions or
|
|
595
|
+
# AppEngine and hope for the best.
|
|
596
|
+
if @config['vpc_connector']
|
|
597
|
+
desc[:vpc_connector] = @config['vpc_connector']
|
|
598
|
+
desc[:vpc_connector_egress_settings] = @config['vpc_connector_allow_all_egress'] ? "ALL_TRAFFIC" : "PRIVATE_RANGES_ONLY"
|
|
599
|
+
pp desc
|
|
600
|
+
elsif @vpc
|
|
601
|
+
desc[:network] = @vpc.url.sub(/^.*?\/projects\//, 'projects/')
|
|
602
|
+
end
|
|
603
|
+
|
|
604
|
+
if @config['triggers']
|
|
605
|
+
desc[:event_trigger] = MU::Cloud::Google.function(:EventTrigger).new(
|
|
606
|
+
event_type: @config['triggers'].first['event'],
|
|
607
|
+
resource: @config['triggers'].first['resource']
|
|
608
|
+
)
|
|
609
|
+
else
|
|
610
|
+
desc[:https_trigger] = MU::Cloud::Google.function(:HttpsTrigger).new
|
|
611
|
+
end
|
|
612
|
+
|
|
613
|
+
|
|
614
|
+
if @config['environment_variable']
|
|
615
|
+
@config['environment_variable'].each { |var|
|
|
616
|
+
desc[:environment_variables] ||= {}
|
|
617
|
+
desc[:environment_variables][var["key"].to_s] = var["value"].to_s
|
|
618
|
+
}
|
|
619
|
+
end
|
|
620
|
+
|
|
621
|
+
# hello_code = nil
|
|
622
|
+
# HELLO_WORLDS.each_pair { |runtime, code|
|
|
623
|
+
# if @config['runtime'].match(/^#{Regexp.quote(runtime)}/)
|
|
624
|
+
# hello_code = code
|
|
625
|
+
# break
|
|
626
|
+
# end
|
|
627
|
+
# }
|
|
628
|
+
if @config['code']['gs_url']
|
|
629
|
+
desc[:source_archive_url] = @config['code']['gs_url']
|
|
630
|
+
elsif @config['code']['zip_file']
|
|
631
|
+
desc[:source_archive_url] = MU::Cloud::Google::Function.uploadPackage(@config['code']['zip_file'], @mu_name+"-cloudfunction.zip", credentials: @credentials)
|
|
632
|
+
end
|
|
633
|
+
|
|
634
|
+
# Dir.mktmpdir(@mu_name) { |dir|
|
|
635
|
+
# hello_code.each_pair { |file, contents|
|
|
636
|
+
# f = File.open(dir+"/"+file, "w")
|
|
637
|
+
# f.puts contents
|
|
638
|
+
# f.close
|
|
639
|
+
# Zip::File.open(dir+"/function.zip", Zip::File::CREATE) { |z|
|
|
640
|
+
# z.add(file, dir+"/"+file)
|
|
641
|
+
# }
|
|
642
|
+
# }
|
|
643
|
+
# desc[:source_archive_url] = MU::Cloud::Google::Function.uploadPackage(dir+"/function.zip", @mu_name+"-cloudfunction.zip", credentials: @credentials)
|
|
644
|
+
# }
|
|
645
|
+
MU::Cloud::Google.function(:CloudFunction).new(desc)
|
|
646
|
+
end
|
|
647
|
+
|
|
676
648
|
end
|
|
677
649
|
end
|
|
678
650
|
end
|