cloud-mu 2.0.0.pre.beta2 → 2.0.0.pre.beta3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Berksfile.lock +1 -1
- data/cloud-mu.gemspec +4 -3
- data/cookbooks/mu-master/templates/default/mu.rc.erb +2 -2
- data/cookbooks/mu-tools/files/default/Mu_CA.pem +18 -19
- data/cookbooks/mu-tools/recipes/rsyslog.rb +1 -1
- data/modules/mu/cleanup.rb +14 -1
- data/modules/mu/cloud.rb +40 -22
- data/modules/mu/clouds/aws/alarm.rb +6 -0
- data/modules/mu/clouds/aws/bucket.rb +29 -0
- data/modules/mu/clouds/aws/cache_cluster.rb +6 -0
- data/modules/mu/clouds/aws/container_cluster.rb +6 -0
- data/modules/mu/clouds/aws/database.rb +6 -0
- data/modules/mu/clouds/aws/dnszone.rb +6 -0
- data/modules/mu/clouds/aws/endpoint.rb +6 -0
- data/modules/mu/clouds/aws/firewall_rule.rb +6 -0
- data/modules/mu/clouds/aws/folder.rb +6 -0
- data/modules/mu/clouds/aws/function.rb +6 -0
- data/modules/mu/clouds/aws/group.rb +6 -0
- data/modules/mu/clouds/aws/loadbalancer.rb +6 -0
- data/modules/mu/clouds/aws/log.rb +6 -0
- data/modules/mu/clouds/aws/msg_queue.rb +6 -0
- data/modules/mu/clouds/aws/nosqldb.rb +6 -0
- data/modules/mu/clouds/aws/notifier.rb +6 -0
- data/modules/mu/clouds/aws/role.rb +97 -11
- data/modules/mu/clouds/aws/search_domain.rb +6 -0
- data/modules/mu/clouds/aws/server.rb +6 -0
- data/modules/mu/clouds/aws/server_pool.rb +6 -0
- data/modules/mu/clouds/aws/storage_pool.rb +6 -0
- data/modules/mu/clouds/aws/user.rb +6 -0
- data/modules/mu/clouds/aws/vpc.rb +25 -1
- data/modules/mu/clouds/google.rb +86 -16
- data/modules/mu/clouds/google/bucket.rb +78 -3
- data/modules/mu/clouds/google/container_cluster.rb +12 -0
- data/modules/mu/clouds/google/database.rb +15 -1
- data/modules/mu/clouds/google/firewall_rule.rb +18 -2
- data/modules/mu/clouds/google/folder.rb +183 -16
- data/modules/mu/clouds/google/group.rb +7 -1
- data/modules/mu/clouds/google/habitat.rb +139 -24
- data/modules/mu/clouds/google/loadbalancer.rb +26 -12
- data/modules/mu/clouds/google/server.rb +25 -10
- data/modules/mu/clouds/google/server_pool.rb +16 -3
- data/modules/mu/clouds/google/user.rb +7 -1
- data/modules/mu/clouds/google/vpc.rb +87 -76
- data/modules/mu/config.rb +12 -0
- data/modules/mu/config/bucket.rb +4 -0
- data/modules/mu/config/folder.rb +1 -0
- data/modules/mu/config/habitat.rb +1 -1
- data/modules/mu/config/role.rb +78 -34
- data/modules/mu/config/vpc.rb +1 -0
- data/modules/mu/groomers/chef.rb +1 -1
- data/modules/mu/kittens.rb +689 -283
- metadata +5 -4
@@ -19,6 +19,7 @@ module MU
|
|
19
19
|
class ServerPool < MU::Cloud::ServerPool
|
20
20
|
|
21
21
|
@deploy = nil
|
22
|
+
@project_id = nil
|
22
23
|
@config = nil
|
23
24
|
attr_reader :mu_name
|
24
25
|
attr_reader :cloud_id
|
@@ -32,6 +33,11 @@ module MU
|
|
32
33
|
@cloud_id ||= cloud_id
|
33
34
|
if !mu_name.nil?
|
34
35
|
@mu_name = mu_name
|
36
|
+
@config['project'] ||= MU::Cloud::Google.defaultProject(@config['credentials'])
|
37
|
+
if !@project_id
|
38
|
+
project = MU::Cloud::Google.projectLookup(@config['project'], @deploy, sibling_only: true, raise_on_fail: false)
|
39
|
+
@project_id = project.nil? ? @config['project'] : project.cloudobj.cloud_id
|
40
|
+
end
|
35
41
|
elsif @config['scrub_mu_isms']
|
36
42
|
@mu_name = @config['name']
|
37
43
|
else
|
@@ -41,6 +47,7 @@ module MU
|
|
41
47
|
|
42
48
|
# Called automatically by {MU::Deploy#createResources}
|
43
49
|
def create
|
50
|
+
@project_id = MU::Cloud::Google.projectLookup(@config['project'], @deploy).cloudobj.cloud_id
|
44
51
|
port_objs = []
|
45
52
|
|
46
53
|
@config['named_ports'].each { |port_cfg|
|
@@ -95,7 +102,7 @@ module MU
|
|
95
102
|
|
96
103
|
MU.log "Creating instance template #{@mu_name}", details: template_obj
|
97
104
|
template = MU::Cloud::Google.compute(credentials: @config['credentials']).insert_instance_template(
|
98
|
-
@
|
105
|
+
@project_id,
|
99
106
|
template_obj
|
100
107
|
)
|
101
108
|
|
@@ -117,7 +124,7 @@ module MU
|
|
117
124
|
|
118
125
|
MU.log "Creating region instance group manager #{@mu_name}", details: mgr_obj
|
119
126
|
mgr = MU::Cloud::Google.compute(credentials: @config['credentials']).insert_region_instance_group_manager(
|
120
|
-
@
|
127
|
+
@project_id,
|
121
128
|
@config['region'],
|
122
129
|
mgr_obj
|
123
130
|
)
|
@@ -143,7 +150,7 @@ module MU
|
|
143
150
|
|
144
151
|
MU.log "Creating autoscaler policy #{@mu_name}", details: scaler_obj
|
145
152
|
MU::Cloud::Google.compute(credentials: @config['credentials']).insert_region_autoscaler(
|
146
|
-
@
|
153
|
+
@project_id,
|
147
154
|
@config['region'],
|
148
155
|
scaler_obj
|
149
156
|
)
|
@@ -250,6 +257,12 @@ module MU
|
|
250
257
|
false
|
251
258
|
end
|
252
259
|
|
260
|
+
# Denote whether this resource implementation is experiment, ready for
|
261
|
+
# testing, or ready for production use.
|
262
|
+
def self.quality
|
263
|
+
MU::Cloud::RELEASE
|
264
|
+
end
|
265
|
+
|
253
266
|
# Remove all autoscale groups associated with the currently loaded deployment.
|
254
267
|
# @param noop [Boolean]: If true, will only print what would be done
|
255
268
|
# @param ignoremaster [Boolean]: If true, will remove resources not flagged as originating from this Mu server
|
@@ -110,6 +110,12 @@ module MU
|
|
110
110
|
true
|
111
111
|
end
|
112
112
|
|
113
|
+
# Denote whether this resource implementation is experiment, ready for
|
114
|
+
# testing, or ready for production use.
|
115
|
+
def self.quality
|
116
|
+
MU::Cloud::ALPHA
|
117
|
+
end
|
118
|
+
|
113
119
|
# Remove all users associated with the currently loaded deployment.
|
114
120
|
# @param noop [Boolean]: If true, will only print what would be done
|
115
121
|
# @param ignoremaster [Boolean]: If true, will remove resources not flagged as originating from this Mu server
|
@@ -142,7 +148,7 @@ module MU
|
|
142
148
|
# @param region [String]: The cloud provider region.
|
143
149
|
# @param flags [Hash]: Optional flags
|
144
150
|
# @return [OpenStruct]: The cloud provider's complete descriptions of matching user group.
|
145
|
-
def self.find(cloud_id: nil, region: MU.curRegion, credentials: nil, flags: {})
|
151
|
+
def self.find(cloud_id: nil, region: MU.curRegion, credentials: nil, flags: {}, tag_key: nil, tag_value: nil)
|
146
152
|
flags["project"] ||= MU::Cloud::Google.defaultProject(credentials)
|
147
153
|
found = nil
|
148
154
|
resp = MU::Cloud::Google.iam(credentials: credentials).list_project_service_accounts(
|
@@ -21,6 +21,7 @@ module MU
|
|
21
21
|
|
22
22
|
@deploy = nil
|
23
23
|
@config = nil
|
24
|
+
@project_id = nil
|
24
25
|
attr_reader :mu_name
|
25
26
|
attr_reader :cloud_id
|
26
27
|
attr_reader :url
|
@@ -45,6 +46,11 @@ module MU
|
|
45
46
|
if @cloud_id.nil? or @cloud_id.empty?
|
46
47
|
@cloud_id = MU::Cloud::Google.nameStr(@mu_name)
|
47
48
|
end
|
49
|
+
@config['project'] ||= MU::Cloud::Google.defaultProject(@config['credentials'])
|
50
|
+
if !@project_id
|
51
|
+
project = MU::Cloud::Google.projectLookup(@config['project'], @deploy, sibling_only: true, raise_on_fail: false)
|
52
|
+
@project_id = project.nil? ? @config['project'] : project.cloudobj.cloud_id
|
53
|
+
end
|
48
54
|
loadSubnets
|
49
55
|
elsif @config['scrub_mu_isms']
|
50
56
|
@mu_name = @config['name']
|
@@ -56,14 +62,17 @@ module MU
|
|
56
62
|
|
57
63
|
# Called automatically by {MU::Deploy#createResources}
|
58
64
|
def create
|
65
|
+
@project_id = MU::Cloud::Google.projectLookup(@config['project'], @deploy).cloudobj.cloud_id
|
66
|
+
|
59
67
|
networkobj = MU::Cloud::Google.compute(:Network).new(
|
60
68
|
name: MU::Cloud::Google.nameStr(@mu_name),
|
61
69
|
description: @deploy.deploy_id,
|
62
70
|
auto_create_subnetworks: false
|
63
71
|
# i_pv4_range: @config['ip_block']
|
64
72
|
)
|
65
|
-
MU.log "Creating network #{@mu_name} (#{@config['ip_block']}) in project #{@
|
66
|
-
|
73
|
+
MU.log "Creating network #{@mu_name} (#{@config['ip_block']}) in project #{@project_id}", details: networkobj
|
74
|
+
|
75
|
+
resp = MU::Cloud::Google.compute(credentials: @config['credentials']).insert_network(@project_id, networkobj)
|
67
76
|
@url = resp.self_link # XXX needs to go in notify
|
68
77
|
@cloud_id = resp.name
|
69
78
|
|
@@ -75,7 +84,7 @@ module MU
|
|
75
84
|
MU.dupGlobals(parent_thread_id)
|
76
85
|
subnet_name = @config['name']+"-"+subnet['name']
|
77
86
|
subnet_mu_name = MU::Cloud::Google.nameStr(@deploy.getResourceName(subnet_name))
|
78
|
-
MU.log "Creating subnetwork #{subnet_mu_name} (#{subnet['ip_block']}) in project #{@
|
87
|
+
MU.log "Creating subnetwork #{subnet_mu_name} (#{subnet['ip_block']}) in project #{@project_id}", details: subnet
|
79
88
|
subnetobj = MU::Cloud::Google.compute(:Subnetwork).new(
|
80
89
|
name: subnet_mu_name,
|
81
90
|
description: @deploy.deploy_id,
|
@@ -83,7 +92,7 @@ module MU
|
|
83
92
|
network: @url,
|
84
93
|
region: subnet['availability_zone']
|
85
94
|
)
|
86
|
-
resp = MU::Cloud::Google.compute(credentials: @config['credentials']).insert_subnetwork(@
|
95
|
+
resp = MU::Cloud::Google.compute(credentials: @config['credentials']).insert_subnetwork(@project_id, subnet['availability_zone'], subnetobj)
|
87
96
|
|
88
97
|
}
|
89
98
|
}
|
@@ -120,21 +129,16 @@ module MU
|
|
120
129
|
def notify
|
121
130
|
base = MU.structToHash(cloud_desc)
|
122
131
|
base["cloud_id"] = @cloud_id
|
132
|
+
base["project_id"] = @project_id
|
123
133
|
base.merge!(@config.to_h)
|
124
|
-
if @config['name'] == "gkeprivate"
|
125
|
-
pp base.keys
|
126
|
-
puts base['cloud_id']
|
127
|
-
end
|
128
|
-
|
129
134
|
base
|
130
135
|
end
|
131
136
|
|
132
137
|
# Describe this VPC from the cloud platform's perspective
|
133
138
|
# @return [Hash]
|
134
139
|
def cloud_desc
|
135
|
-
@config['project'] ||= MU::Cloud::Google.defaultProject(@config['credentials'])
|
136
140
|
|
137
|
-
resp = MU::Cloud::Google.compute(credentials: @config['credentials']).get_network(@
|
141
|
+
resp = MU::Cloud::Google.compute(credentials: @config['credentials']).get_network(@project_id, @cloud_id)
|
138
142
|
if @cloud_id.nil? or @cloud_id == ""
|
139
143
|
MU.log "Couldn't describe #{self}, @cloud_id #{@cloud_id.nil? ? "undefined" : "empty" }", MU::ERR
|
140
144
|
return nil
|
@@ -143,7 +147,7 @@ end
|
|
143
147
|
resp = resp.to_h
|
144
148
|
@url ||= resp[:self_link]
|
145
149
|
routes = MU::Cloud::Google.compute(credentials: @config['credentials']).list_routes(
|
146
|
-
@
|
150
|
+
@project_id,
|
147
151
|
filter: "network eq #{@cloud_id}"
|
148
152
|
).items
|
149
153
|
resp[:routes] = routes.map { |r| r.to_h } if routes
|
@@ -154,6 +158,8 @@ end
|
|
154
158
|
|
155
159
|
# Called automatically by {MU::Deploy#createResources}
|
156
160
|
def groom
|
161
|
+
@project_id = MU::Cloud::Google.projectLookup(@config['project'], @deploy).cloudobj.cloud_id
|
162
|
+
|
157
163
|
rtb = @config['route_tables'].first
|
158
164
|
|
159
165
|
rtb['routes'].each { |route|
|
@@ -169,21 +175,6 @@ end
|
|
169
175
|
@config['peers'].each { |peer|
|
170
176
|
if peer['vpc']['vpc_name']
|
171
177
|
peer_obj = @deploy.findLitterMate(name: peer['vpc']['vpc_name'], type: "vpcs")
|
172
|
-
if peer_obj
|
173
|
-
if peer_obj.config['peers']
|
174
|
-
skipme = false
|
175
|
-
peer_obj.config['peers'].each { |peerpeer|
|
176
|
-
if peerpeer['vpc']['vpc_name'] == @config['name'] and
|
177
|
-
(peer['vpc']['vpc_name'] <=> @config['name']) == -1
|
178
|
-
skipme = true
|
179
|
-
MU.log "VPCs #{peer['vpc']['vpc_name']} and #{@config['name']} both declare mutual peering connection, ignoring #{@config['name']}'s redundant declaration", MU::DEBUG
|
180
|
-
# XXX and if deploy_id matches or is unset
|
181
|
-
end
|
182
|
-
}
|
183
|
-
next if skipme
|
184
|
-
end
|
185
|
-
end
|
186
|
-
|
187
178
|
else
|
188
179
|
tag_key, tag_value = peer['vpc']['tag'].split(/=/, 2) if !peer['vpc']['tag'].nil?
|
189
180
|
if peer['vpc']['deploy_id'].nil? and peer['vpc']['vpc_id'].nil? and tag_key.nil?
|
@@ -219,13 +210,20 @@ end
|
|
219
210
|
peer_network: url
|
220
211
|
)
|
221
212
|
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
213
|
+
begin
|
214
|
+
MU.log "Peering #{@cloud_id} with #{peer_obj.cloudobj.cloud_id}, connection name is #{cnxn_name}", details: peerreq
|
215
|
+
MU::Cloud::Google.compute(credentials: @config['credentials']).add_network_peering(
|
216
|
+
@project_id,
|
217
|
+
@cloud_id,
|
218
|
+
peerreq
|
219
|
+
)
|
220
|
+
rescue ::Google::Apis::ClientError => e
|
221
|
+
if e.message.match(/operation in progress on the local or peer network/)
|
222
|
+
MU.log e.message, MU::DEBUG, details: peerreq
|
223
|
+
sleep 10
|
224
|
+
retry
|
225
|
+
end
|
226
|
+
end
|
229
227
|
count += 1
|
230
228
|
}
|
231
229
|
end
|
@@ -293,7 +291,7 @@ end
|
|
293
291
|
resp = nil
|
294
292
|
MU::Cloud::Google.listRegions(@config['us_only']).each { |r|
|
295
293
|
resp = MU::Cloud::Google.compute(credentials: @config['credentials']).list_subnetworks(
|
296
|
-
@
|
294
|
+
@project_id,
|
297
295
|
r,
|
298
296
|
filter: "network eq #{network[:self_link]}"
|
299
297
|
)
|
@@ -496,6 +494,12 @@ MU.log "ROUTES TO #{target_instance.name}", MU::WARN, details: resp
|
|
496
494
|
true
|
497
495
|
end
|
498
496
|
|
497
|
+
# Denote whether this resource implementation is experiment, ready for
|
498
|
+
# testing, or ready for production use.
|
499
|
+
def self.quality
|
500
|
+
MU::Cloud::RELEASE
|
501
|
+
end
|
502
|
+
|
499
503
|
# Remove all VPC resources associated with the currently loaded deployment.
|
500
504
|
# @param noop [Boolean]: If true, will only print what would be done
|
501
505
|
# @param ignoremaster [Boolean]: If true, will remove resources not flagged as originating from this Mu server
|
@@ -543,6 +547,7 @@ MU.log "ROUTES TO #{target_instance.name}", MU::WARN, details: resp
|
|
543
547
|
def self.validateConfig(vpc, configurator)
|
544
548
|
ok = true
|
545
549
|
|
550
|
+
|
546
551
|
if vpc['create_standard_subnets']
|
547
552
|
# Manufacture some generic routes, if applicable.
|
548
553
|
if !vpc['route_tables'] or vpc['route_tables'].empty?
|
@@ -557,46 +562,46 @@ MU.log "ROUTES TO #{target_instance.name}", MU::WARN, details: resp
|
|
557
562
|
}
|
558
563
|
]
|
559
564
|
end
|
560
|
-
|
561
|
-
#
|
562
|
-
|
563
|
-
|
564
|
-
|
565
|
-
|
566
|
-
|
567
|
-
|
568
|
-
|
569
|
-
|
570
|
-
vpc['route_tables'].each { |t|
|
571
|
-
count = 0
|
572
|
-
vpc['regions'].each { |r|
|
573
|
-
block = blocks.shift
|
574
|
-
vpc["subnets"] << {
|
575
|
-
"availability_zone" => r,
|
576
|
-
"route_table" => t["name"],
|
577
|
-
"ip_block" => block.to_s,
|
578
|
-
"name" => "Subnet"+count.to_s+t["name"].capitalize,
|
579
|
-
"map_public_ips" => true
|
565
|
+
else
|
566
|
+
# If create_standard_subnets is off, and no route_tables were
|
567
|
+
# declared at all, let's assume we want purely self-contained
|
568
|
+
# private VPC, and create a dummy route accordingly.
|
569
|
+
vpc['route_tables'] ||= [
|
570
|
+
{
|
571
|
+
"name" => "private",
|
572
|
+
"routes" => [
|
573
|
+
{
|
574
|
+
"destination_network" => "0.0.0.0/0"
|
580
575
|
}
|
581
|
-
|
582
|
-
}
|
576
|
+
]
|
583
577
|
}
|
584
|
-
|
578
|
+
]
|
585
579
|
end
|
586
580
|
|
587
|
-
#
|
588
|
-
|
589
|
-
|
590
|
-
|
591
|
-
|
592
|
-
|
593
|
-
|
594
|
-
|
595
|
-
|
581
|
+
# Generate a set of subnets per route, if none are declared
|
582
|
+
if !vpc['subnets'] or vpc['subnets'].empty?
|
583
|
+
if vpc['regions'].nil? or vpc['regions'].empty?
|
584
|
+
vpc['regions'] = MU::Cloud::Google.listRegions(vpc['us_only'])
|
585
|
+
end
|
586
|
+
blocks = configurator.divideNetwork(vpc['ip_block'], vpc['regions'].size*vpc['route_tables'].size, 29)
|
587
|
+
ok = false if blocks.nil?
|
588
|
+
|
589
|
+
vpc["subnets"] = []
|
590
|
+
vpc['route_tables'].each { |t|
|
591
|
+
count = 0
|
592
|
+
vpc['regions'].each { |r|
|
593
|
+
block = blocks.shift
|
594
|
+
vpc["subnets"] << {
|
595
|
+
"availability_zone" => r,
|
596
|
+
"route_table" => t["name"],
|
597
|
+
"ip_block" => block.to_s,
|
598
|
+
"name" => "Subnet"+count.to_s+t["name"].capitalize,
|
599
|
+
"map_public_ips" => true
|
596
600
|
}
|
597
|
-
|
601
|
+
count = count + 1
|
602
|
+
}
|
598
603
|
}
|
599
|
-
|
604
|
+
end
|
600
605
|
|
601
606
|
# Google VPCs can't have routes that are anything other than global
|
602
607
|
# (they can be tied to individual instances by tags, but w/e). So we
|
@@ -617,7 +622,8 @@ MU.log "ROUTES TO #{target_instance.name}", MU::WARN, details: resp
|
|
617
622
|
"ip_block" => blocks.shift,
|
618
623
|
"route_tables" => [tbl],
|
619
624
|
"parent_block" => vpc['ip_block'],
|
620
|
-
"subnets" => []
|
625
|
+
"subnets" => [],
|
626
|
+
"peers" => vpc['peers']
|
621
627
|
}
|
622
628
|
MU.log "Splitting VPC #{newvpc['name']} off from #{vpc['name']}", MU::NOTICE
|
623
629
|
|
@@ -626,11 +632,16 @@ MU.log "ROUTES TO #{target_instance.name}", MU::WARN, details: resp
|
|
626
632
|
newvpc[key] = val
|
627
633
|
}
|
628
634
|
newvpc['peers'] ||= []
|
635
|
+
# Add the peer connections we're generating, in addition
|
629
636
|
peernames.each { |peer|
|
630
|
-
if peer !=
|
637
|
+
if peer != newvpc['name']
|
631
638
|
newvpc['peers'] << { "vpc" => { "vpc_name" => peer } }
|
632
639
|
end
|
633
640
|
}
|
641
|
+
newvpc['peers'].reject! { |p|
|
642
|
+
p.values.first['vpc_name'] == newvpc['name'] or p.values.first['vpc_name'] == vpc['name']
|
643
|
+
}
|
644
|
+
|
634
645
|
vpc["subnets"].each { |subnet|
|
635
646
|
newvpc["subnets"] << subnet if subnet["route_table"] == tbl["name"]
|
636
647
|
}
|
@@ -771,7 +782,7 @@ MU.log "ROUTES TO #{target_instance.name}", MU::WARN, details: resp
|
|
771
782
|
# several other cases missing for various types of routers (raw IPs, instance ids, etc) XXX
|
772
783
|
elsif route['gateway'] == "#DENY"
|
773
784
|
resp = MU::Cloud::Google.compute(credentials: @config['credentials']).list_routes(
|
774
|
-
@
|
785
|
+
@project_id,
|
775
786
|
filter: "network eq #{network}"
|
776
787
|
)
|
777
788
|
|
@@ -779,7 +790,7 @@ MU.log "ROUTES TO #{target_instance.name}", MU::WARN, details: resp
|
|
779
790
|
resp.items.each { |r|
|
780
791
|
next if r.next_hop_gateway.nil? or !r.next_hop_gateway.match(/\/global\/gateways\/default-internet-gateway$/)
|
781
792
|
MU.log "Removing standard route #{r.name} per our #DENY entry"
|
782
|
-
MU::Cloud::Google.compute(credentials: @config['credentials']).delete_route(@
|
793
|
+
MU::Cloud::Google.compute(credentials: @config['credentials']).delete_route(@project_id, r.name)
|
783
794
|
}
|
784
795
|
end
|
785
796
|
elsif route['gateway'] == "#INTERNET"
|
@@ -796,11 +807,11 @@ MU.log "ROUTES TO #{target_instance.name}", MU::WARN, details: resp
|
|
796
807
|
|
797
808
|
if route['gateway'] != "#DENY" and routeobj
|
798
809
|
begin
|
799
|
-
MU::Cloud::Google.compute(credentials: @config['credentials']).get_route(@
|
810
|
+
MU::Cloud::Google.compute(credentials: @config['credentials']).get_route(@project_id, routename)
|
800
811
|
rescue ::Google::Apis::ClientError, MU::MuError => e
|
801
812
|
if e.message.match(/notFound/)
|
802
|
-
MU.log "Creating route #{routename} in project #{@
|
803
|
-
resp = MU::Cloud::Google.compute(credentials: @config['credentials']).insert_route(@
|
813
|
+
MU.log "Creating route #{routename} in project #{@project_id}", details: routeobj
|
814
|
+
resp = MU::Cloud::Google.compute(credentials: @config['credentials']).insert_route(@project_id, routeobj)
|
804
815
|
else
|
805
816
|
# TODO can't update GCP routes, would have to delete and re-create
|
806
817
|
end
|
data/modules/mu/config.rb
CHANGED
@@ -156,6 +156,8 @@ module MU
|
|
156
156
|
end
|
157
157
|
res_class = Object.const_get("MU").const_get("Cloud").const_get(cloud).const_get(classname)
|
158
158
|
required, res_schema = res_class.schema(self)
|
159
|
+
docschema["properties"][attrs[:cfg_plural]]["items"]["description"] ||= ""
|
160
|
+
docschema["properties"][attrs[:cfg_plural]]["items"]["description"] += "\n#\n# `#{cloud}`: "+res_class.quality
|
159
161
|
res_schema.each { |key, cfg|
|
160
162
|
if !docschema["properties"][attrs[:cfg_plural]]["items"]["properties"][key]
|
161
163
|
only_children[attrs[:cfg_plural]] ||= {}
|
@@ -888,6 +890,16 @@ module MU
|
|
888
890
|
end
|
889
891
|
end
|
890
892
|
|
893
|
+
if descriptor['project']
|
894
|
+
if haveLitterMate?(descriptor['project'], "habitats")
|
895
|
+
descriptor['dependencies'] ||= []
|
896
|
+
descriptor['dependencies'] << {
|
897
|
+
"type" => "habitat",
|
898
|
+
"name" => descriptor['project']
|
899
|
+
}
|
900
|
+
end
|
901
|
+
end
|
902
|
+
|
891
903
|
# Does this resource go in a VPC?
|
892
904
|
if !descriptor["vpc"].nil? and !delay_validation
|
893
905
|
descriptor['vpc']['cloud'] = descriptor['cloud']
|
data/modules/mu/config/bucket.rb
CHANGED
@@ -49,6 +49,10 @@ module MU
|
|
49
49
|
"type" => "string",
|
50
50
|
"default" => "index.html",
|
51
51
|
"description" => "If +web_enabled+, return this object when \"diretory\" (a path not ending in a key/object) is invoked."
|
52
|
+
},
|
53
|
+
"policies" => {
|
54
|
+
"type" => "array",
|
55
|
+
"items" => MU::Config::Role.policy_primitive(subobjects: true, grant_to: true, permissions_optional: true)
|
52
56
|
}
|
53
57
|
}
|
54
58
|
}
|
data/modules/mu/config/folder.rb
CHANGED
@@ -26,7 +26,7 @@ module MU
|
|
26
26
|
"description" => "Generate a cloud habitat (AWS account, Google Cloud project, Azure Directory, etc)",
|
27
27
|
"properties" => {
|
28
28
|
"name" => { "type" => "string" },
|
29
|
-
"
|
29
|
+
"parent" => MU::Config::Folder.reference
|
30
30
|
}
|
31
31
|
}
|
32
32
|
end
|