cloud-mu 1.9.0.pre.beta → 2.0.0.pre.alpha
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Berksfile +16 -54
- data/Berksfile.lock +14 -62
- data/bin/mu-aws-setup +131 -108
- data/bin/mu-configure +311 -74
- data/bin/mu-gcp-setup +84 -62
- data/bin/mu-load-config.rb +46 -2
- data/bin/mu-self-update +11 -9
- data/bin/mu-upload-chef-artifacts +4 -4
- data/{mu.gemspec → cloud-mu.gemspec} +2 -2
- data/cookbooks/awscli/Berksfile +8 -0
- data/cookbooks/mu-activedirectory/Berksfile +11 -0
- data/cookbooks/mu-firewall/Berksfile +9 -0
- data/cookbooks/mu-firewall/metadata.rb +1 -1
- data/cookbooks/mu-glusterfs/Berksfile +10 -0
- data/cookbooks/mu-jenkins/Berksfile +14 -0
- data/cookbooks/mu-master/Berksfile +23 -0
- data/cookbooks/mu-master/attributes/default.rb +1 -1
- data/cookbooks/mu-master/metadata.rb +2 -2
- data/cookbooks/mu-master/recipes/default.rb +1 -1
- data/cookbooks/mu-master/recipes/init.rb +7 -3
- data/cookbooks/mu-master/recipes/ssl-certs.rb +1 -0
- data/cookbooks/mu-mongo/Berksfile +10 -0
- data/cookbooks/mu-openvpn/Berksfile +11 -0
- data/cookbooks/mu-php54/Berksfile +13 -0
- data/cookbooks/mu-splunk/Berksfile +10 -0
- data/cookbooks/mu-tools/Berksfile +21 -0
- data/cookbooks/mu-tools/files/default/Mu_CA.pem +15 -15
- data/cookbooks/mu-utility/Berksfile +9 -0
- data/cookbooks/mu-utility/metadata.rb +2 -1
- data/cookbooks/nagios/Berksfile +7 -4
- data/cookbooks/s3fs/Berksfile +9 -0
- data/environments/dev.json +6 -6
- data/environments/prod.json +6 -6
- data/modules/mu.rb +20 -42
- data/modules/mu/cleanup.rb +102 -100
- data/modules/mu/cloud.rb +90 -28
- data/modules/mu/clouds/aws.rb +449 -218
- data/modules/mu/clouds/aws/alarm.rb +29 -17
- data/modules/mu/clouds/aws/cache_cluster.rb +78 -64
- data/modules/mu/clouds/aws/collection.rb +25 -18
- data/modules/mu/clouds/aws/container_cluster.rb +73 -66
- data/modules/mu/clouds/aws/database.rb +124 -116
- data/modules/mu/clouds/aws/dnszone.rb +27 -20
- data/modules/mu/clouds/aws/firewall_rule.rb +30 -22
- data/modules/mu/clouds/aws/folder.rb +18 -3
- data/modules/mu/clouds/aws/function.rb +77 -23
- data/modules/mu/clouds/aws/group.rb +19 -12
- data/modules/mu/clouds/aws/habitat.rb +153 -0
- data/modules/mu/clouds/aws/loadbalancer.rb +59 -52
- data/modules/mu/clouds/aws/log.rb +30 -23
- data/modules/mu/clouds/aws/msg_queue.rb +29 -20
- data/modules/mu/clouds/aws/notifier.rb +222 -0
- data/modules/mu/clouds/aws/role.rb +178 -90
- data/modules/mu/clouds/aws/search_domain.rb +40 -24
- data/modules/mu/clouds/aws/server.rb +169 -137
- data/modules/mu/clouds/aws/server_pool.rb +60 -83
- data/modules/mu/clouds/aws/storage_pool.rb +59 -31
- data/modules/mu/clouds/aws/user.rb +36 -27
- data/modules/mu/clouds/aws/userdata/linux.erb +101 -93
- data/modules/mu/clouds/aws/vpc.rb +250 -189
- data/modules/mu/clouds/azure.rb +132 -0
- data/modules/mu/clouds/cloudformation.rb +65 -1
- data/modules/mu/clouds/cloudformation/alarm.rb +8 -0
- data/modules/mu/clouds/cloudformation/cache_cluster.rb +7 -0
- data/modules/mu/clouds/cloudformation/collection.rb +7 -0
- data/modules/mu/clouds/cloudformation/database.rb +7 -0
- data/modules/mu/clouds/cloudformation/dnszone.rb +7 -0
- data/modules/mu/clouds/cloudformation/firewall_rule.rb +9 -2
- data/modules/mu/clouds/cloudformation/loadbalancer.rb +7 -0
- data/modules/mu/clouds/cloudformation/log.rb +7 -0
- data/modules/mu/clouds/cloudformation/server.rb +7 -0
- data/modules/mu/clouds/cloudformation/server_pool.rb +7 -0
- data/modules/mu/clouds/cloudformation/vpc.rb +7 -0
- data/modules/mu/clouds/google.rb +214 -110
- data/modules/mu/clouds/google/container_cluster.rb +42 -24
- data/modules/mu/clouds/google/database.rb +15 -6
- data/modules/mu/clouds/google/firewall_rule.rb +17 -25
- data/modules/mu/clouds/google/group.rb +13 -5
- data/modules/mu/clouds/google/habitat.rb +105 -0
- data/modules/mu/clouds/google/loadbalancer.rb +28 -20
- data/modules/mu/clouds/google/server.rb +93 -354
- data/modules/mu/clouds/google/server_pool.rb +18 -10
- data/modules/mu/clouds/google/user.rb +22 -14
- data/modules/mu/clouds/google/vpc.rb +97 -69
- data/modules/mu/config.rb +133 -38
- data/modules/mu/config/alarm.rb +25 -0
- data/modules/mu/config/cache_cluster.rb +5 -3
- data/modules/mu/config/cache_cluster.yml +23 -0
- data/modules/mu/config/database.rb +25 -16
- data/modules/mu/config/database.yml +3 -3
- data/modules/mu/config/function.rb +1 -2
- data/modules/mu/config/{project.rb → habitat.rb} +10 -10
- data/modules/mu/config/notifier.rb +85 -0
- data/modules/mu/config/notifier.yml +9 -0
- data/modules/mu/config/role.rb +1 -1
- data/modules/mu/config/search_domain.yml +2 -2
- data/modules/mu/config/server.rb +13 -1
- data/modules/mu/config/server.yml +3 -3
- data/modules/mu/config/server_pool.rb +3 -1
- data/modules/mu/config/storage_pool.rb +3 -1
- data/modules/mu/config/storage_pool.yml +19 -0
- data/modules/mu/config/vpc.rb +70 -8
- data/modules/mu/groomers/chef.rb +2 -3
- data/modules/mu/kittens.rb +500 -122
- data/modules/mu/master.rb +5 -5
- data/modules/mu/mommacat.rb +151 -91
- data/modules/tests/super_complex_bok.yml +12 -0
- data/modules/tests/super_simple_bok.yml +12 -0
- data/spec/mu/clouds/azure_spec.rb +82 -0
- data/spec/spec_helper.rb +105 -0
- metadata +26 -5
- data/modules/mu/clouds/aws/notification.rb +0 -139
- data/modules/mu/config/notification.rb +0 -44
@@ -39,14 +39,7 @@ module MU
|
|
39
39
|
deploydata = describe[2]
|
40
40
|
@config['availability_zone'] = deploydata['zone']
|
41
41
|
else
|
42
|
-
@mu_name ||=
|
43
|
-
if @config and @config['engine'] and @config["engine"].match(/^sqlserver/)
|
44
|
-
@deploy.getResourceName(@config["name"], max_length: 15)
|
45
|
-
else
|
46
|
-
@deploy.getResourceName(@config["name"], max_length: 63)
|
47
|
-
end
|
48
|
-
|
49
|
-
@mu_name.gsub(/(--|-$)/i, "").gsub(/(_)/, "-").gsub!(/^[^a-z]/i, "")
|
42
|
+
@mu_name ||= @deploy.getResourceName(@config["name"], max_length: 40)
|
50
43
|
end
|
51
44
|
end
|
52
45
|
|
@@ -64,6 +57,14 @@ module MU
|
|
64
57
|
|
65
58
|
@config['availability_zone'] ||= MU::Cloud::Google.listAZs(@config['region']).sample
|
66
59
|
|
60
|
+
if @vpc.nil? and @config['vpc'] and @config['vpc']['vpc_name']
|
61
|
+
@vpc = @deploy.findLitterMate(name: @config['vpc']['vpc_name'], type: "vpcs")
|
62
|
+
end
|
63
|
+
|
64
|
+
if !@vpc
|
65
|
+
raise MuError, "ContainerCluster #{@config['name']} unable to locate its resident VPC from #{@config['vpc']}"
|
66
|
+
end
|
67
|
+
|
67
68
|
subnet = nil
|
68
69
|
@vpc.subnets.each { |s|
|
69
70
|
if s.az == @config['region']
|
@@ -71,12 +72,14 @@ module MU
|
|
71
72
|
break
|
72
73
|
end
|
73
74
|
}
|
74
|
-
|
75
|
+
puts @config['credentials']
|
75
76
|
service_acct = MU::Cloud::Google::Server.createServiceAccount(
|
76
77
|
@mu_name.downcase,
|
77
|
-
|
78
|
+
@deploy,
|
79
|
+
project: @config['project'],
|
80
|
+
credentials: @config['credentials']
|
78
81
|
)
|
79
|
-
MU::Cloud::Google.grantDeploySecretAccess(service_acct.email)
|
82
|
+
MU::Cloud::Google.grantDeploySecretAccess(service_acct.email, credentials: @config['credentials'])
|
80
83
|
|
81
84
|
@config['ssh_user'] ||= "mu"
|
82
85
|
|
@@ -118,7 +121,9 @@ module MU
|
|
118
121
|
)
|
119
122
|
|
120
123
|
MU.log "Creating GKE cluster #{@mu_name.downcase}", details: desc
|
121
|
-
|
124
|
+
pp @vpc.subnets.map { |x| x.config['name'] }
|
125
|
+
pp requestobj
|
126
|
+
cluster = MU::Cloud::Google.container(credentials: @config['credentials']).create_cluster(
|
122
127
|
@config['project'],
|
123
128
|
@config['availability_zone'],
|
124
129
|
requestobj
|
@@ -126,7 +131,7 @@ module MU
|
|
126
131
|
|
127
132
|
resp = nil
|
128
133
|
begin
|
129
|
-
resp = MU::Cloud::Google.container.get_zone_cluster(@config["project"], @config['availability_zone'], @mu_name.downcase)
|
134
|
+
resp = MU::Cloud::Google.container(credentials: @config['credentials']).get_zone_cluster(@config["project"], @config['availability_zone'], @mu_name.downcase)
|
130
135
|
sleep 30 if resp.status != "RUNNING"
|
131
136
|
end while resp.nil? or resp.status != "RUNNING"
|
132
137
|
# labelCluster # XXX need newer API release
|
@@ -142,14 +147,15 @@ module MU
|
|
142
147
|
# @param tag_value [String]: The value of the tag specified by tag_key to match when searching by tag.
|
143
148
|
# @param flags [Hash]: Optional flags
|
144
149
|
# @return [Array<Hash<String,OpenStruct>>]: The cloud provider's complete descriptions of matching ContainerClusters
|
145
|
-
def self.find(cloud_id: nil, region: MU.curRegion, tag_key: "Name", tag_value: nil, flags: {})
|
150
|
+
def self.find(cloud_id: nil, region: MU.curRegion, tag_key: "Name", tag_value: nil, flags: {}, credentials: nil)
|
151
|
+
flags["project"] ||= MU::Cloud::Google.defaultProject(credentials)
|
146
152
|
end
|
147
153
|
|
148
154
|
# Called automatically by {MU::Deploy#createResources}
|
149
155
|
def groom
|
150
156
|
deploydata = describe[2]
|
151
157
|
@config['availability_zone'] ||= deploydata['zone']
|
152
|
-
resp = MU::Cloud::Google.container.get_zone_cluster(@config["project"], @config['availability_zone'], @mu_name.downcase)
|
158
|
+
resp = MU::Cloud::Google.container(credentials: @config['credentials']).get_zone_cluster(@config["project"], @config['availability_zone'], @mu_name.downcase)
|
153
159
|
# pp resp
|
154
160
|
|
155
161
|
# labelCluster # XXX need newer API release
|
@@ -176,32 +182,44 @@ module MU
|
|
176
182
|
|
177
183
|
# Register a description of this cluster instance with this deployment's metadata.
|
178
184
|
def notify
|
179
|
-
desc = MU.structToHash(MU::Cloud::Google.container.get_zone_cluster(@config["project"], @config['availability_zone'], @mu_name.downcase))
|
185
|
+
desc = MU.structToHash(MU::Cloud::Google.container(credentials: @config['credentials']).get_zone_cluster(@config["project"], @config['availability_zone'], @mu_name.downcase))
|
180
186
|
desc["project"] = @config['project']
|
181
187
|
desc["cloud_id"] = @cloud_id
|
182
188
|
desc["mu_name"] = @mu_name.downcase
|
183
189
|
desc
|
184
190
|
end
|
185
191
|
|
192
|
+
# Does this resource type exist as a global (cloud-wide) artifact, or
|
193
|
+
# is it localized to a region/zone?
|
194
|
+
# @return [Boolean]
|
195
|
+
def self.isGlobal?
|
196
|
+
false
|
197
|
+
end
|
198
|
+
|
186
199
|
# Called by {MU::Cleanup}. Locates resources that were created by the
|
187
200
|
# currently-loaded deployment, and purges them.
|
188
201
|
# @param noop [Boolean]: If true, will only print what would be done
|
189
202
|
# @param ignoremaster [Boolean]: If true, will remove resources not flagged as originating from this Mu server
|
190
203
|
# @param region [String]: The cloud provider region in which to operate
|
191
204
|
# @return [void]
|
192
|
-
def self.cleanup(
|
193
|
-
flags["
|
205
|
+
def self.cleanup(noop: false, ignoremaster: false, region: MU.curRegion, credentials: nil, flags: {})
|
206
|
+
skipsnapshots = flags["skipsnapshots"]
|
207
|
+
|
208
|
+
flags["project"] ||= MU::Cloud::Google.defaultProject(credentials)
|
194
209
|
MU::Cloud::Google.listAZs(region).each { |az|
|
195
|
-
found = MU::Cloud::Google.container.list_zone_clusters(flags["project"], az)
|
196
|
-
#filter: "description eq #{MU.deploy_id}"
|
210
|
+
found = MU::Cloud::Google.container(credentials: credentials).list_zone_clusters(flags["project"], az)
|
197
211
|
if found and found.clusters
|
198
212
|
found.clusters.each { |cluster|
|
199
|
-
|
213
|
+
|
214
|
+
if !cluster.name.match(/^#{Regexp.quote(MU.deploy_id)}\-/i) and
|
215
|
+
cluster.resource_labels['mu-id'] != MU.deploy_id.downcase
|
216
|
+
next
|
217
|
+
end
|
200
218
|
MU.log "Deleting GKE cluster #{cluster.name}"
|
201
219
|
if !noop
|
202
|
-
MU::Cloud::Google.container.delete_zone_cluster(flags["project"], az, cluster.name)
|
220
|
+
MU::Cloud::Google.container(credentials: credentials).delete_zone_cluster(flags["project"], az, cluster.name)
|
203
221
|
begin
|
204
|
-
MU::Cloud::Google.container.get_zone_cluster(flags["project"], az, cluster.name)
|
222
|
+
MU::Cloud::Google.container(credentials: credentials).get_zone_cluster(flags["project"], az, cluster.name)
|
205
223
|
sleep 60
|
206
224
|
rescue ::Google::Apis::ClientError => e
|
207
225
|
if e.message.match(/is currently creating cluster/)
|
@@ -281,7 +299,7 @@ module MU
|
|
281
299
|
labelset = MU::Cloud::Google.container(:SetLabelsRequest).new(
|
282
300
|
resource_labels: labels
|
283
301
|
)
|
284
|
-
MU::Cloud::Google.container.resource_project_zone_cluster_labels(@config["project"], @config['availability_zone'], @mu_name.downcase, labelset)
|
302
|
+
MU::Cloud::Google.container(credentials: @config['credentials']).resource_project_zone_cluster_labels(@config["project"], @config['availability_zone'], @mu_name.downcase, labelset)
|
285
303
|
end
|
286
304
|
|
287
305
|
end #class
|
@@ -74,7 +74,7 @@ module MU
|
|
74
74
|
instance_type: "CLOUD_SQL_INSTANCE" # TODO: READ_REPLICA_INSTANCE
|
75
75
|
)
|
76
76
|
pp instance_desc
|
77
|
-
pp MU::Cloud::Google.sql.insert_instance(@config['project'], instance_desc)
|
77
|
+
pp MU::Cloud::Google.sql(credentials: @config['credentials']).insert_instance(@config['project'], instance_desc)
|
78
78
|
end
|
79
79
|
|
80
80
|
# Locate an existing Database or Databases and return an array containing matching GCP resource descriptors for those that match.
|
@@ -84,7 +84,8 @@ module MU
|
|
84
84
|
# @param tag_value [String]: The value of the tag specified by tag_key to match when searching by tag.
|
85
85
|
# @param flags [Hash]: Optional flags
|
86
86
|
# @return [Array<Hash<String,OpenStruct>>]: The cloud provider's complete descriptions of matching Databases
|
87
|
-
def self.find(cloud_id: nil, region: MU.curRegion, tag_key: "Name", tag_value: nil, flags: {})
|
87
|
+
def self.find(cloud_id: nil, region: MU.curRegion, tag_key: "Name", tag_value: nil, flags: {}, credentials: nil)
|
88
|
+
flags["project"] ||= MU::Cloud::Google.defaultProject(credentials)
|
88
89
|
end
|
89
90
|
|
90
91
|
# Called automatically by {MU::Deploy#createResources}
|
@@ -103,19 +104,27 @@ module MU
|
|
103
104
|
def allowHost(cidr)
|
104
105
|
end
|
105
106
|
|
107
|
+
# Does this resource type exist as a global (cloud-wide) artifact, or
|
108
|
+
# is it localized to a region/zone?
|
109
|
+
# @return [Boolean]
|
110
|
+
def self.isGlobal?
|
111
|
+
false
|
112
|
+
end
|
113
|
+
|
106
114
|
# Called by {MU::Cleanup}. Locates resources that were created by the
|
107
115
|
# currently-loaded deployment, and purges them.
|
108
116
|
# @param noop [Boolean]: If true, will only print what would be done
|
109
117
|
# @param ignoremaster [Boolean]: If true, will remove resources not flagged as originating from this Mu server
|
110
118
|
# @param region [String]: The cloud provider region in which to operate
|
111
119
|
# @return [void]
|
112
|
-
def self.cleanup(
|
113
|
-
flags["project"] ||= MU::Cloud::Google.defaultProject
|
114
|
-
|
120
|
+
def self.cleanup(noop: false, ignoremaster: false, region: MU.curRegion, credentials: nil, flags: {})
|
121
|
+
flags["project"] ||= MU::Cloud::Google.defaultProject(credentials)
|
122
|
+
skipsnapshots||= flags["skipsnapshots"]
|
123
|
+
instances = MU::Cloud::Google.sql(credentials: credentials).list_instances(flags['project'], filter: %Q{userLabels.mu-id:"#{MU.deploy_id.downcase}"})
|
115
124
|
if instances and instances.items
|
116
125
|
instances.items.each { |instance|
|
117
126
|
MU.log "Deleting Cloud SQL instance #{instance.name}"
|
118
|
-
MU::Cloud::Google.sql.delete_instance(flags['project'], instance.name) if !noop
|
127
|
+
MU::Cloud::Google.sql(credentials: credentials).delete_instance(flags['project'], instance.name) if !noop
|
119
128
|
}
|
120
129
|
end
|
121
130
|
end
|
@@ -40,9 +40,9 @@ module MU
|
|
40
40
|
@cloud_id ||= MU::Cloud::Google.nameStr(@mu_name+"-ingress-allow")
|
41
41
|
else
|
42
42
|
if !@vpc.nil?
|
43
|
-
@mu_name = @deploy.getResourceName(@config['name'], need_unique_string: true)
|
43
|
+
@mu_name = @deploy.getResourceName(@config['name'], need_unique_string: true, max_length: 61)
|
44
44
|
else
|
45
|
-
@mu_name = @deploy.getResourceName(@config['name'])
|
45
|
+
@mu_name = @deploy.getResourceName(@config['name'], max_length: 61)
|
46
46
|
end
|
47
47
|
end
|
48
48
|
|
@@ -77,7 +77,7 @@ module MU
|
|
77
77
|
|
78
78
|
["ingress", "egress"].each { |dir|
|
79
79
|
if rule[dir] or (dir == "ingress" and !rule.has_key?("egress"))
|
80
|
-
setname =
|
80
|
+
setname = @deploy.getResourceName(@mu_name+"-"+dir+"-"+(rule['deny'] ? "deny" : "allow"), max_length: 61).downcase
|
81
81
|
@cloud_id ||= setname
|
82
82
|
allrules[setname] ||= {
|
83
83
|
:name => setname,
|
@@ -110,7 +110,7 @@ module MU
|
|
110
110
|
threads << Thread.new {
|
111
111
|
fwobj = MU::Cloud::Google.compute(:Firewall).new(fwdesc)
|
112
112
|
MU.log "Creating firewall #{fwdesc[:name]} in project #{@config['project']}", details: fwobj
|
113
|
-
resp = MU::Cloud::Google.compute.insert_firewall(@config['project'], fwobj)
|
113
|
+
resp = MU::Cloud::Google.compute(credentials: @config['credentials']).insert_firewall(@config['project'], fwobj)
|
114
114
|
# XXX Check for empty (no hosts) sets
|
115
115
|
# MU.log "Can't create empty firewalls in Google Cloud, skipping #{@mu_name}", MU::WARN
|
116
116
|
}
|
@@ -155,11 +155,11 @@ module MU
|
|
155
155
|
# @param tag_value [String]: The value of the tag specified by tag_key to match when searching by tag.
|
156
156
|
# @param flags [Hash]: Optional flags
|
157
157
|
# @return [Array<Hash<String,OpenStruct>>]: The cloud provider's complete descriptions of matching FirewallRules
|
158
|
-
def self.find(cloud_id: nil, region: MU.curRegion, tag_key: "Name", tag_value: nil, flags: {})
|
159
|
-
flags["project"] ||= MU::Cloud::Google.defaultProject
|
158
|
+
def self.find(cloud_id: nil, region: MU.curRegion, tag_key: "Name", tag_value: nil, flags: {}, credentials: nil)
|
159
|
+
flags["project"] ||= MU::Cloud::Google.defaultProject(credentials)
|
160
160
|
|
161
161
|
found = {}
|
162
|
-
resp = MU::Cloud::Google.compute.list_firewalls(flags["project"])
|
162
|
+
resp = MU::Cloud::Google.compute(credentials: credentials).list_firewalls(flags["project"])
|
163
163
|
if resp and resp.items
|
164
164
|
resp.items.each { |fw|
|
165
165
|
next if !cloud_id.nil? and fw.name != cloud_id
|
@@ -169,15 +169,21 @@ module MU
|
|
169
169
|
found
|
170
170
|
end
|
171
171
|
|
172
|
+
# Does this resource type exist as a global (cloud-wide) artifact, or
|
173
|
+
# is it localized to a region/zone?
|
174
|
+
# @return [Boolean]
|
175
|
+
def self.isGlobal?
|
176
|
+
true
|
177
|
+
end
|
178
|
+
|
172
179
|
# Remove all security groups (firewall rulesets) associated with the currently loaded deployment.
|
173
180
|
# @param noop [Boolean]: If true, will only print what would be done
|
174
181
|
# @param ignoremaster [Boolean]: If true, will remove resources not flagged as originating from this Mu server
|
175
182
|
# @param region [String]: The cloud provider region
|
176
183
|
# @return [void]
|
177
|
-
def self.cleanup(noop: false, ignoremaster: false, region: MU.curRegion, flags: {})
|
178
|
-
flags["project"] ||= MU::Cloud::Google.defaultProject
|
179
|
-
|
180
|
-
MU::Cloud::Google.compute.delete(
|
184
|
+
def self.cleanup(noop: false, ignoremaster: false, region: MU.curRegion, credentials: nil, flags: {})
|
185
|
+
flags["project"] ||= MU::Cloud::Google.defaultProject(credentials)
|
186
|
+
MU::Cloud::Google.compute(credentials: credentials).delete(
|
181
187
|
"firewall",
|
182
188
|
flags["project"],
|
183
189
|
nil,
|
@@ -247,20 +253,6 @@ module MU
|
|
247
253
|
|
248
254
|
private
|
249
255
|
|
250
|
-
########################################################################
|
251
|
-
# Manufacture an EC2 security group. The second parameter, rules, is an
|
252
|
-
# "ingress_rules" structure parsed and validated by MU::Config.
|
253
|
-
########################################################################
|
254
|
-
def setRules(rules, add_to_self: false, ingress: true, egress: false)
|
255
|
-
end
|
256
|
-
|
257
|
-
########################################################################
|
258
|
-
# Convert our config languages description of firewall rules into
|
259
|
-
# Amazon's. This rule structure is as defined in MU::Config.
|
260
|
-
########################################################################
|
261
|
-
def convertToEc2(rules)
|
262
|
-
end
|
263
|
-
|
264
256
|
end #class
|
265
257
|
end #class
|
266
258
|
end
|
@@ -49,12 +49,19 @@ module MU
|
|
49
49
|
}
|
50
50
|
end
|
51
51
|
|
52
|
+
# Does this resource type exist as a global (cloud-wide) artifact, or
|
53
|
+
# is it localized to a region/zone?
|
54
|
+
# @return [Boolean]
|
55
|
+
def self.isGlobal?
|
56
|
+
true
|
57
|
+
end
|
58
|
+
|
52
59
|
# Remove all groups associated with the currently loaded deployment.
|
53
60
|
# @param noop [Boolean]: If true, will only print what would be done
|
54
61
|
# @param ignoremaster [Boolean]: If true, will remove resources not flagged as originating from this Mu server
|
55
62
|
# @param region [String]: The cloud provider region
|
56
63
|
# @return [void]
|
57
|
-
def self.cleanup(noop: false, ignoremaster: false, region: MU.curRegion, flags: {})
|
64
|
+
def self.cleanup(noop: false, ignoremaster: false, region: MU.curRegion, credentials: nil, flags: {})
|
58
65
|
end
|
59
66
|
|
60
67
|
# Locate an existing group group.
|
@@ -62,7 +69,8 @@ module MU
|
|
62
69
|
# @param region [String]: The cloud provider region.
|
63
70
|
# @param flags [Hash]: Optional flags
|
64
71
|
# @return [OpenStruct]: The cloud provider's complete descriptions of matching group group.
|
65
|
-
def self.find(cloud_id: nil, region: MU.curRegion, flags: {})
|
72
|
+
def self.find(cloud_id: nil, region: MU.curRegion, credentials: nil, flags: {})
|
73
|
+
flags["project"] ||= MU::Cloud::Google.defaultProject(credentials)
|
66
74
|
found = nil
|
67
75
|
found
|
68
76
|
end
|
@@ -113,7 +121,7 @@ module MU
|
|
113
121
|
|
114
122
|
def bind_group
|
115
123
|
bindings = []
|
116
|
-
ext_policy = MU::Cloud::Google.resource_manager.get_project_iam_policy(
|
124
|
+
ext_policy = MU::Cloud::Google.resource_manager(credentials: @config['credentials']).get_project_iam_policy(
|
117
125
|
@config['project']
|
118
126
|
)
|
119
127
|
|
@@ -145,12 +153,12 @@ module MU
|
|
145
153
|
MU.log "Adding group #{@config['name']} to Google Cloud project #{@config['project']}", details: @config['roles']
|
146
154
|
|
147
155
|
begin
|
148
|
-
MU::Cloud::Google.resource_manager.set_project_iam_policy(
|
156
|
+
MU::Cloud::Google.resource_manager(credentials: @config['credentials']).set_project_iam_policy(
|
149
157
|
@config['project'],
|
150
158
|
req_obj
|
151
159
|
)
|
152
160
|
rescue ::Google::Apis::ClientError => e
|
153
|
-
if e.message.match(/does not exist/i) and
|
161
|
+
if e.message.match(/does not exist/i) and !MU::Cloud::Google.credConfig(@config['credentials'])['masquerade_as']
|
154
162
|
raise MuError, "Group #{@config['name']} does not exist, and we cannot create Google groups in non-GSuite environments.\nVisit https://groups.google.com to manage groups."
|
155
163
|
end
|
156
164
|
raise e
|
@@ -0,0 +1,105 @@
|
|
1
|
+
# Copyright:: Copyright (c) 2019 eGlobalTech, Inc., all rights reserved
|
2
|
+
#
|
3
|
+
# Licensed under the BSD-3 license (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License in the root of the project or at
|
6
|
+
#
|
7
|
+
# http://egt-labs.com/mu/LICENSE.html
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
|
15
|
+
module MU
|
16
|
+
class Cloud
|
17
|
+
class Google
|
18
|
+
# Creates an Google project as configured in {MU::Config::BasketofKittens::habitats}
|
19
|
+
class Habitat < MU::Cloud::Habitat
|
20
|
+
@deploy = nil
|
21
|
+
@config = nil
|
22
|
+
|
23
|
+
attr_reader :mu_name
|
24
|
+
attr_reader :config
|
25
|
+
attr_reader :cloud_id
|
26
|
+
|
27
|
+
# @param mommacat [MU::MommaCat]: A {MU::Mommacat} object containing the deploy of which this resource is/will be a member.
|
28
|
+
# @param kitten_cfg [Hash]: The fully parsed and resolved {MU::Config} resource descriptor as defined in {MU::Config::BasketofKittens::habitats}
|
29
|
+
def initialize(mommacat: nil, kitten_cfg: nil, mu_name: nil, cloud_id: nil)
|
30
|
+
@deploy = mommacat
|
31
|
+
@config = MU::Config.manxify(kitten_cfg)
|
32
|
+
@cloud_id ||= cloud_id
|
33
|
+
@mu_name ||= @deploy.getResourceName(@config["name"])
|
34
|
+
end
|
35
|
+
|
36
|
+
# Called automatically by {MU::Deploy#createResources}
|
37
|
+
def create
|
38
|
+
end
|
39
|
+
|
40
|
+
# Return the cloud descriptor for the Habitat
|
41
|
+
def cloud_desc
|
42
|
+
MU::Cloud::Google::Habitat.find(cloud_id: @cloud_id).values.first
|
43
|
+
end
|
44
|
+
|
45
|
+
# Canonical Amazon Resource Number for this resource
|
46
|
+
# @return [String]
|
47
|
+
def arn
|
48
|
+
nil
|
49
|
+
end
|
50
|
+
|
51
|
+
# Return the metadata for this project's configuration
|
52
|
+
# @return [Hash]
|
53
|
+
def notify
|
54
|
+
{
|
55
|
+
}
|
56
|
+
end
|
57
|
+
|
58
|
+
# Does this resource type exist as a global (cloud-wide) artifact, or
|
59
|
+
# is it localized to a region/zone?
|
60
|
+
# @return [Boolean]
|
61
|
+
def self.isGlobal?
|
62
|
+
true
|
63
|
+
end
|
64
|
+
|
65
|
+
# Remove all Google projects associated with the currently loaded deployment. Try to, anyway.
|
66
|
+
# @param noop [Boolean]: If true, will only print what would be done
|
67
|
+
# @param ignoremaster [Boolean]: If true, will remove resources not flagged as originating from this Mu server
|
68
|
+
# @param region [String]: The cloud provider region
|
69
|
+
# @return [void]
|
70
|
+
def self.cleanup(noop: false, ignoremaster: false, region: MU.curRegion, credentials: nil, flags: {})
|
71
|
+
end
|
72
|
+
|
73
|
+
# Locate an existing project
|
74
|
+
# @param cloud_id [String]: The cloud provider's identifier for this resource.
|
75
|
+
# @param region [String]: The cloud provider region.
|
76
|
+
# @param flags [Hash]: Optional flags
|
77
|
+
# @return [OpenStruct]: The cloud provider's complete descriptions of matching project
|
78
|
+
def self.find(cloud_id: nil, region: MU.curRegion, credentials: nil, flags: {})
|
79
|
+
{}
|
80
|
+
end
|
81
|
+
|
82
|
+
# Cloud-specific configuration properties.
|
83
|
+
# @param config [MU::Config]: The calling MU::Config object
|
84
|
+
# @return [Array<Array,Hash>]: List of required fields, and json-schema Hash of cloud-specific configuration parameters for this resource
|
85
|
+
def self.schema(config)
|
86
|
+
toplevel_required = []
|
87
|
+
schema = {
|
88
|
+
}
|
89
|
+
[toplevel_required, schema]
|
90
|
+
end
|
91
|
+
|
92
|
+
# Cloud-specific pre-processing of {MU::Config::BasketofKittens::habitats}, bare and unvalidated.
|
93
|
+
# @param habitat [Hash]: The resource to process and validate
|
94
|
+
# @param configurator [MU::Config]: The overall deployment configurator of which this resource is a member
|
95
|
+
# @return [Boolean]: True if validation succeeded, False otherwise
|
96
|
+
def self.validateConfig(habitat, configurator)
|
97
|
+
ok = true
|
98
|
+
|
99
|
+
ok
|
100
|
+
end
|
101
|
+
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
@@ -95,13 +95,13 @@ module MU
|
|
95
95
|
end
|
96
96
|
if @config['global']
|
97
97
|
MU.log "Creating Global Forwarding Rule #{@mu_name}", MU::NOTICE, details: ruleobj
|
98
|
-
resp = MU::Cloud::Google.compute.insert_global_forwarding_rule(
|
98
|
+
resp = MU::Cloud::Google.compute(credentials: @config['credentials']).insert_global_forwarding_rule(
|
99
99
|
@config['project'],
|
100
100
|
ruleobj
|
101
101
|
)
|
102
102
|
else
|
103
103
|
MU.log "Creating regional Forwarding Rule #{@mu_name} in #{@config['region']}", MU::NOTICE, details: ruleobj
|
104
|
-
resp = MU::Cloud::Google.compute.insert_forwarding_rule(
|
104
|
+
resp = MU::Cloud::Google.compute(credentials: @config['credentials']).insert_forwarding_rule(
|
105
105
|
@config['project'],
|
106
106
|
@config['region'],
|
107
107
|
ruleobj
|
@@ -119,12 +119,12 @@ module MU
|
|
119
119
|
# @return [Hash]
|
120
120
|
def notify
|
121
121
|
rules = {}
|
122
|
-
resp = MU::Cloud::Google.compute.list_global_forwarding_rules(
|
122
|
+
resp = MU::Cloud::Google.compute(credentials: @config['credentials']).list_global_forwarding_rules(
|
123
123
|
@config["project"],
|
124
124
|
filter: "description eq #{@deploy.deploy_id}"
|
125
125
|
)
|
126
126
|
if resp.nil? or resp.items.nil? or resp.items.size == 0
|
127
|
-
resp = MU::Cloud::Google.compute.list_forwarding_rules(
|
127
|
+
resp = MU::Cloud::Google.compute(credentials: @config['credentials']).list_forwarding_rules(
|
128
128
|
@config["project"],
|
129
129
|
@config['region'],
|
130
130
|
filter: "description eq #{@deploy.deploy_id}"
|
@@ -147,17 +147,24 @@ module MU
|
|
147
147
|
def registerNode(instance_id, targetgroups: nil)
|
148
148
|
end
|
149
149
|
|
150
|
+
# Does this resource type exist as a global (cloud-wide) artifact, or
|
151
|
+
# is it localized to a region/zone?
|
152
|
+
# @return [Boolean]
|
153
|
+
def self.isGlobal?
|
154
|
+
true
|
155
|
+
end
|
156
|
+
|
150
157
|
# Remove all load balancers associated with the currently loaded deployment.
|
151
158
|
# @param noop [Boolean]: If true, will only print what would be done
|
152
159
|
# @param ignoremaster [Boolean]: If true, will remove resources not flagged as originating from this Mu server
|
153
160
|
# @param region [String]: The cloud provider region
|
154
161
|
# @return [void]
|
155
|
-
def self.cleanup(noop: false, ignoremaster: false, region:
|
156
|
-
flags["project"] ||= MU::Cloud::Google.defaultProject
|
162
|
+
def self.cleanup(noop: false, ignoremaster: false, region: nil, credentials: nil, flags: {})
|
163
|
+
flags["project"] ||= MU::Cloud::Google.defaultProject(credentials)
|
157
164
|
|
158
165
|
if region
|
159
166
|
["forwarding_rule", "region_backend_service"].each { |type|
|
160
|
-
MU::Cloud::Google.compute.delete(
|
167
|
+
MU::Cloud::Google.compute(credentials: credentials).delete(
|
161
168
|
type,
|
162
169
|
flags["project"],
|
163
170
|
region,
|
@@ -168,7 +175,7 @@ module MU
|
|
168
175
|
|
169
176
|
if flags['global']
|
170
177
|
["global_forwarding_rule", "target_http_proxy", "target_https_proxy", "url_map", "backend_service", "health_check", "http_health_check", "https_health_check"].each { |type|
|
171
|
-
MU::Cloud::Google.compute.delete(
|
178
|
+
MU::Cloud::Google.compute(credentials: credentials).delete(
|
172
179
|
type,
|
173
180
|
flags["project"],
|
174
181
|
noop
|
@@ -296,7 +303,8 @@ module MU
|
|
296
303
|
# @param tag_value [String]: The value of the tag specified by tag_key to match when searching by tag.
|
297
304
|
# @param flags [Hash]: Optional flags
|
298
305
|
# @return [Array<Hash<String,OpenStruct>>]: The cloud provider's complete descriptions of matching LoadBalancers
|
299
|
-
def self.find(cloud_id: nil, region: MU.curRegion, tag_key: "Name", tag_value: nil, flags: {})
|
306
|
+
def self.find(cloud_id: nil, region: MU.curRegion, tag_key: "Name", tag_value: nil, flags: {}, credentials: nil)
|
307
|
+
flags["project"] ||= MU::Cloud::Google.defaultProject(credentials)
|
300
308
|
end
|
301
309
|
|
302
310
|
private
|
@@ -312,7 +320,7 @@ module MU
|
|
312
320
|
default_service: backend.self_link
|
313
321
|
)
|
314
322
|
MU.log "Creating url map #{tg['name']}", details: urlmap_obj
|
315
|
-
urlmap = MU::Cloud::Google.compute.insert_url_map(
|
323
|
+
urlmap = MU::Cloud::Google.compute(credentials: @config['credentials']).insert_url_map(
|
316
324
|
@config['project'],
|
317
325
|
urlmap_obj
|
318
326
|
)
|
@@ -326,20 +334,20 @@ module MU
|
|
326
334
|
if tg['proto'] == "HTTP"
|
327
335
|
target_obj = MU::Cloud::Google.compute(:TargetHttpProxy).new(desc)
|
328
336
|
MU.log "Creating http target proxy #{tg['name']}", details: target_obj
|
329
|
-
MU::Cloud::Google.compute.insert_target_http_proxy(
|
337
|
+
MU::Cloud::Google.compute(credentials: @config['credentials']).insert_target_http_proxy(
|
330
338
|
@config['project'],
|
331
339
|
target_obj
|
332
340
|
)
|
333
341
|
else
|
334
|
-
certdata = @deploy.nodeSSLCerts(self, 2048)
|
342
|
+
certdata = @deploy.nodeSSLCerts(self, false, 2048)
|
335
343
|
cert_pem = certdata[0].to_s+File.read("/etc/pki/Mu_CA.pem")
|
336
|
-
gcpcert = MU::Cloud::Google.createSSLCertificate(@mu_name.downcase+"-"+tg['name'], cert_pem, certdata[1])
|
344
|
+
gcpcert = MU::Cloud::Google.createSSLCertificate(@mu_name.downcase+"-"+tg['name'], cert_pem, certdata[1], credentials: @config['credentials'])
|
337
345
|
|
338
346
|
# TODO we need a method like MU::Cloud::AWS.findSSLCertificate, with option to hunt down an existing one
|
339
347
|
desc[:ssl_certificates] = [gcpcert.self_link]
|
340
348
|
target_obj = MU::Cloud::Google.compute(:TargetHttpsProxy).new(desc)
|
341
349
|
MU.log "Creating https target proxy #{tg['name']}", details: target_obj
|
342
|
-
MU::Cloud::Google.compute.insert_target_https_proxy(
|
350
|
+
MU::Cloud::Google.compute(credentials: @config['credentials']).insert_target_https_proxy(
|
343
351
|
@config['project'],
|
344
352
|
target_obj
|
345
353
|
)
|
@@ -385,13 +393,13 @@ module MU
|
|
385
393
|
backend_obj = MU::Cloud::Google.compute(:BackendService).new(desc)
|
386
394
|
MU.log "Creating backend service #{MU::Cloud::Google.nameStr(@deploy.getResourceName(tg["name"]))}", details: backend_obj
|
387
395
|
if @config['private'] and !@config['global']
|
388
|
-
return MU::Cloud::Google.compute.insert_region_backend_service(
|
396
|
+
return MU::Cloud::Google.compute(credentials: @config['credentials']).insert_region_backend_service(
|
389
397
|
@config['project'],
|
390
398
|
@config['region'],
|
391
399
|
backend_obj
|
392
400
|
)
|
393
401
|
else
|
394
|
-
return MU::Cloud::Google.compute.insert_backend_service(
|
402
|
+
return MU::Cloud::Google.compute(credentials: @config['credentials']).insert_backend_service(
|
395
403
|
@config['project'],
|
396
404
|
backend_obj
|
397
405
|
)
|
@@ -399,7 +407,7 @@ module MU
|
|
399
407
|
end
|
400
408
|
|
401
409
|
def createHealthCheck(hc, namebase)
|
402
|
-
MU.log "HEALTH CHECK", MU::NOTICE, details: hc
|
410
|
+
# MU.log "HEALTH CHECK", MU::NOTICE, details: hc
|
403
411
|
target = hc['target'].match(/^([^:]+):(\d+)(.*)/)
|
404
412
|
proto = target[1]
|
405
413
|
port = target[2]
|
@@ -421,12 +429,12 @@ module MU
|
|
421
429
|
# type: SSL, HTTP2
|
422
430
|
MU.log "Creating #{proto} health check #{name}", details: hc_obj
|
423
431
|
if proto == "HTTP"
|
424
|
-
return MU::Cloud::Google.compute.insert_http_health_check(
|
432
|
+
return MU::Cloud::Google.compute(credentials: @config['credentials']).insert_http_health_check(
|
425
433
|
@config['project'],
|
426
434
|
hc_obj
|
427
435
|
)
|
428
436
|
else
|
429
|
-
return MU::Cloud::Google.compute.insert_https_health_check(
|
437
|
+
return MU::Cloud::Google.compute(credentials: @config['credentials']).insert_https_health_check(
|
430
438
|
@config['project'],
|
431
439
|
hc_obj
|
432
440
|
)
|
@@ -466,7 +474,7 @@ module MU
|
|
466
474
|
end
|
467
475
|
hc_obj = MU::Cloud::Google.compute(:HealthCheck).new(desc)
|
468
476
|
MU.log "INSERTING HEALTH CHECK", MU::NOTICE, details: hc_obj
|
469
|
-
return MU::Cloud::Google.compute.insert_health_check(
|
477
|
+
return MU::Cloud::Google.compute(credentials: @config['credentials']).insert_health_check(
|
470
478
|
@config['project'],
|
471
479
|
hc_obj
|
472
480
|
)
|