cloud-mu 2.0.0.pre.beta2 → 2.0.0.pre.beta3
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.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
|