cloud-mu 3.1.4 → 3.3.1
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 +5 -1
- 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 +16 -12
- 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 -1
- data/bin/mu-node-manage +15 -16
- data/bin/mu-run-tests +37 -12
- data/cloud-mu.gemspec +5 -3
- 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 +1 -1
- 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/selinux.rb +2 -1
- data/cookbooks/mu-tools/recipes/windows-client.rb +163 -164
- 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/modules/mommacat.ru +1 -1
- data/modules/mu.rb +158 -107
- data/modules/mu/adoption.rb +386 -59
- data/modules/mu/cleanup.rb +214 -303
- data/modules/mu/cloud.rb +128 -1632
- data/modules/mu/cloud/database.rb +49 -0
- data/modules/mu/cloud/dnszone.rb +44 -0
- data/modules/mu/cloud/machine_images.rb +212 -0
- data/modules/mu/cloud/providers.rb +81 -0
- data/modules/mu/cloud/resource_base.rb +926 -0
- data/modules/mu/cloud/server.rb +40 -0
- data/modules/mu/cloud/server_pool.rb +1 -0
- data/modules/mu/cloud/ssh_sessions.rb +228 -0
- data/modules/mu/cloud/winrm_sessions.rb +237 -0
- data/modules/mu/cloud/wrappers.rb +169 -0
- data/modules/mu/config.rb +135 -82
- data/modules/mu/config/alarm.rb +2 -6
- data/modules/mu/config/bucket.rb +32 -3
- data/modules/mu/config/cache_cluster.rb +2 -2
- data/modules/mu/config/cdn.rb +100 -0
- data/modules/mu/config/collection.rb +1 -1
- data/modules/mu/config/container_cluster.rb +7 -2
- data/modules/mu/config/database.rb +84 -105
- data/modules/mu/config/database.yml +1 -2
- data/modules/mu/config/dnszone.rb +5 -4
- data/modules/mu/config/doc_helpers.rb +5 -6
- data/modules/mu/config/endpoint.rb +2 -1
- data/modules/mu/config/firewall_rule.rb +3 -19
- data/modules/mu/config/folder.rb +1 -1
- data/modules/mu/config/function.rb +17 -8
- data/modules/mu/config/group.rb +1 -1
- data/modules/mu/config/habitat.rb +1 -1
- data/modules/mu/config/job.rb +89 -0
- data/modules/mu/config/loadbalancer.rb +57 -11
- data/modules/mu/config/log.rb +1 -1
- data/modules/mu/config/msg_queue.rb +1 -1
- data/modules/mu/config/nosqldb.rb +1 -1
- data/modules/mu/config/notifier.rb +8 -19
- data/modules/mu/config/ref.rb +92 -14
- data/modules/mu/config/role.rb +1 -1
- data/modules/mu/config/schema_helpers.rb +38 -37
- data/modules/mu/config/search_domain.rb +1 -1
- data/modules/mu/config/server.rb +12 -13
- data/modules/mu/config/server.yml +1 -0
- data/modules/mu/config/server_pool.rb +3 -7
- data/modules/mu/config/storage_pool.rb +1 -1
- data/modules/mu/config/tail.rb +11 -0
- data/modules/mu/config/user.rb +1 -1
- data/modules/mu/config/vpc.rb +27 -23
- data/modules/mu/config/vpc.yml +0 -1
- data/modules/mu/defaults/AWS.yaml +91 -68
- data/modules/mu/defaults/Azure.yaml +1 -0
- data/modules/mu/defaults/Google.yaml +1 -0
- data/modules/mu/deploy.rb +33 -19
- data/modules/mu/groomer.rb +16 -1
- data/modules/mu/groomers/ansible.rb +123 -21
- data/modules/mu/groomers/chef.rb +64 -11
- data/modules/mu/logger.rb +120 -144
- data/modules/mu/master.rb +97 -4
- data/modules/mu/master/ssl.rb +0 -1
- data/modules/mu/mommacat.rb +154 -867
- data/modules/mu/mommacat/daemon.rb +23 -14
- data/modules/mu/mommacat/naming.rb +110 -3
- data/modules/mu/mommacat/search.rb +495 -0
- data/modules/mu/mommacat/storage.rb +225 -192
- data/modules/mu/{clouds → providers}/README.md +1 -1
- data/modules/mu/{clouds → providers}/aws.rb +281 -64
- data/modules/mu/{clouds → providers}/aws/alarm.rb +3 -3
- data/modules/mu/{clouds → providers}/aws/bucket.rb +275 -41
- data/modules/mu/{clouds → providers}/aws/cache_cluster.rb +14 -50
- data/modules/mu/providers/aws/cdn.rb +782 -0
- data/modules/mu/{clouds → providers}/aws/collection.rb +5 -5
- data/modules/mu/{clouds → providers}/aws/container_cluster.rb +708 -749
- data/modules/mu/providers/aws/database.rb +1744 -0
- data/modules/mu/{clouds → providers}/aws/dnszone.rb +75 -57
- data/modules/mu/providers/aws/endpoint.rb +1072 -0
- data/modules/mu/{clouds → providers}/aws/firewall_rule.rb +212 -242
- data/modules/mu/{clouds → providers}/aws/folder.rb +1 -1
- data/modules/mu/{clouds → providers}/aws/function.rb +289 -134
- data/modules/mu/{clouds → providers}/aws/group.rb +18 -20
- data/modules/mu/{clouds → providers}/aws/habitat.rb +3 -3
- data/modules/mu/providers/aws/job.rb +466 -0
- data/modules/mu/{clouds → providers}/aws/loadbalancer.rb +50 -41
- data/modules/mu/{clouds → providers}/aws/log.rb +5 -5
- data/modules/mu/{clouds → providers}/aws/msg_queue.rb +14 -11
- data/modules/mu/{clouds → providers}/aws/nosqldb.rb +96 -5
- data/modules/mu/{clouds → providers}/aws/notifier.rb +135 -63
- data/modules/mu/{clouds → providers}/aws/role.rb +94 -57
- data/modules/mu/{clouds → providers}/aws/search_domain.rb +173 -42
- data/modules/mu/{clouds → providers}/aws/server.rb +782 -1107
- data/modules/mu/{clouds → providers}/aws/server_pool.rb +36 -46
- data/modules/mu/{clouds → providers}/aws/storage_pool.rb +21 -38
- data/modules/mu/{clouds → providers}/aws/user.rb +12 -16
- data/modules/mu/{clouds → providers}/aws/userdata/README.md +0 -0
- data/modules/mu/{clouds → providers}/aws/userdata/linux.erb +5 -4
- data/modules/mu/{clouds → providers}/aws/userdata/windows.erb +2 -1
- data/modules/mu/{clouds → providers}/aws/vpc.rb +429 -849
- data/modules/mu/providers/aws/vpc_subnet.rb +286 -0
- data/modules/mu/{clouds → providers}/azure.rb +13 -0
- data/modules/mu/{clouds → providers}/azure/container_cluster.rb +1 -5
- data/modules/mu/{clouds → providers}/azure/firewall_rule.rb +8 -1
- data/modules/mu/{clouds → providers}/azure/habitat.rb +0 -0
- data/modules/mu/{clouds → providers}/azure/loadbalancer.rb +0 -0
- data/modules/mu/{clouds → providers}/azure/role.rb +0 -0
- data/modules/mu/{clouds → providers}/azure/server.rb +32 -24
- data/modules/mu/{clouds → providers}/azure/user.rb +1 -1
- 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 +4 -6
- data/modules/mu/{clouds → providers}/cloudformation.rb +10 -0
- 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 +3 -3
- data/modules/mu/{clouds → providers}/docker.rb +0 -0
- data/modules/mu/{clouds → providers}/google.rb +29 -6
- data/modules/mu/{clouds → providers}/google/bucket.rb +5 -5
- data/modules/mu/{clouds → providers}/google/container_cluster.rb +59 -37
- data/modules/mu/{clouds → providers}/google/database.rb +5 -12
- data/modules/mu/{clouds → providers}/google/firewall_rule.rb +5 -5
- data/modules/mu/{clouds → providers}/google/folder.rb +5 -9
- data/modules/mu/{clouds → providers}/google/function.rb +14 -8
- data/modules/mu/{clouds → providers}/google/group.rb +9 -17
- data/modules/mu/{clouds → providers}/google/habitat.rb +4 -8
- data/modules/mu/{clouds → providers}/google/loadbalancer.rb +5 -5
- data/modules/mu/{clouds → providers}/google/role.rb +50 -31
- data/modules/mu/{clouds → providers}/google/server.rb +142 -55
- data/modules/mu/{clouds → providers}/google/server_pool.rb +14 -14
- data/modules/mu/{clouds → providers}/google/user.rb +34 -24
- 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 +46 -15
- data/modules/tests/aws-jobs-functions.yaml +46 -0
- data/modules/tests/centos6.yaml +15 -0
- data/modules/tests/centos7.yaml +15 -0
- data/modules/tests/centos8.yaml +12 -0
- data/modules/tests/ecs.yaml +23 -0
- data/modules/tests/eks.yaml +1 -1
- data/modules/tests/functions/node-function/lambda_function.js +10 -0
- data/modules/tests/functions/python-function/lambda_function.py +12 -0
- data/modules/tests/includes-and-params.yaml +2 -1
- data/modules/tests/microservice_app.yaml +288 -0
- data/modules/tests/rds.yaml +108 -0
- data/modules/tests/regrooms/rds.yaml +123 -0
- data/modules/tests/server-with-scrub-muisms.yaml +2 -1
- data/modules/tests/super_complex_bok.yml +2 -2
- data/modules/tests/super_simple_bok.yml +3 -5
- data/modules/tests/win2k12.yaml +25 -0
- 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 +169 -93
- data/extras/image-generators/AWS/windows.yaml +0 -18
- data/modules/mu/clouds/aws/database.rb +0 -1974
- data/modules/mu/clouds/aws/endpoint.rb +0 -596
- data/modules/tests/needwork/win2k12.yaml +0 -13
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
# Copyright:: Copyright (c) 2020 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
|
+
# Plugins under this namespace serve as interfaces to cloud providers and
|
|
17
|
+
# other provisioning layers.
|
|
18
|
+
class Cloud
|
|
19
|
+
|
|
20
|
+
# In this file: generic class method wrappers for all resource types.
|
|
21
|
+
|
|
22
|
+
@@resource_types.keys.each { |name|
|
|
23
|
+
Object.const_get("MU").const_get("Cloud").const_get(name).class_eval {
|
|
24
|
+
|
|
25
|
+
def self.shortname
|
|
26
|
+
name.sub(/.*?::([^:]+)$/, '\1')
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def self.cfg_plural
|
|
30
|
+
MU::Cloud.resource_types[shortname.to_sym][:cfg_plural]
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def self.has_multiples
|
|
34
|
+
MU::Cloud.resource_types[shortname.to_sym][:has_multiples]
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def self.cfg_name
|
|
38
|
+
MU::Cloud.resource_types[shortname.to_sym][:cfg_name]
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def self.can_live_in_vpc
|
|
42
|
+
MU::Cloud.resource_types[shortname.to_sym][:can_live_in_vpc]
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def self.waits_on_parent_completion
|
|
46
|
+
MU::Cloud.resource_types[shortname.to_sym][:waits_on_parent_completion]
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def self.deps_wait_on_my_creation
|
|
50
|
+
MU::Cloud.resource_types[shortname.to_sym][:deps_wait_on_my_creation]
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# Defaults any resources that don't declare their release-readiness to
|
|
54
|
+
# ALPHA. That'll learn 'em.
|
|
55
|
+
def self.quality
|
|
56
|
+
MU::Cloud::ALPHA
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# Return a list of "container" artifacts, by class, that apply to this
|
|
60
|
+
# resource type in a cloud provider. This is so methods that call find
|
|
61
|
+
# know whether to call +find+ with identifiers for parent resources.
|
|
62
|
+
# This is similar in purpose to the +isGlobal?+ resource class method,
|
|
63
|
+
# which tells our search functions whether or not a resource scopes to
|
|
64
|
+
# a region. In almost all cases this is one-entry list consisting of
|
|
65
|
+
# +:Habitat+. Notable exceptions include most implementations of
|
|
66
|
+
# +Habitat+, which either reside inside a +:Folder+ or nothing at all;
|
|
67
|
+
# whereas a +:Folder+ tends to not have any containing parent. Very few
|
|
68
|
+
# resource implementations will need to override this.
|
|
69
|
+
# A +nil+ entry in this list is interpreted as "this resource can be
|
|
70
|
+
# global."
|
|
71
|
+
# @return [Array<Symbol,nil>]
|
|
72
|
+
def self.canLiveIn
|
|
73
|
+
if self.shortname == "Folder"
|
|
74
|
+
[nil, :Folder]
|
|
75
|
+
elsif self.shortname == "Habitat"
|
|
76
|
+
[:Folder]
|
|
77
|
+
else
|
|
78
|
+
[:Habitat]
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def self.find(*flags)
|
|
83
|
+
allfound = {}
|
|
84
|
+
|
|
85
|
+
MU::Cloud.availableClouds.each { |cloud|
|
|
86
|
+
begin
|
|
87
|
+
args = flags.first
|
|
88
|
+
next if args[:cloud] and args[:cloud] != cloud
|
|
89
|
+
# skip this cloud if we have a region argument that makes no
|
|
90
|
+
# sense there
|
|
91
|
+
cloudbase = MU::Cloud.cloudClass(cloud)
|
|
92
|
+
next if cloudbase.listCredentials.nil? or cloudbase.listCredentials.empty? or cloudbase.credConfig(args[:credentials]).nil?
|
|
93
|
+
if args[:region] and cloudbase.respond_to?(:listRegions)
|
|
94
|
+
if !cloudbase.listRegions(credentials: args[:credentials])
|
|
95
|
+
MU.log "Failed to get region list for credentials #{args[:credentials]} in cloud #{cloud}", MU::ERR, details: caller
|
|
96
|
+
else
|
|
97
|
+
next if !cloudbase.listRegions(credentials: args[:credentials]).include?(args[:region])
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
begin
|
|
101
|
+
cloudclass = MU::Cloud.resourceClass(cloud, shortname)
|
|
102
|
+
rescue MU::MuError
|
|
103
|
+
next
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
found = cloudclass.find(args)
|
|
107
|
+
if !found.nil?
|
|
108
|
+
if found.is_a?(Hash)
|
|
109
|
+
allfound.merge!(found)
|
|
110
|
+
else
|
|
111
|
+
raise MuError, "#{cloudclass}.find returned a non-Hash result"
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
rescue MuCloudResourceNotImplemented
|
|
115
|
+
end
|
|
116
|
+
}
|
|
117
|
+
allfound
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
# Wrapper for the cleanup class method of underlying cloud object implementations.
|
|
121
|
+
def self.cleanup(*flags)
|
|
122
|
+
ok = true
|
|
123
|
+
params = flags.first
|
|
124
|
+
clouds = MU::Cloud.supportedClouds
|
|
125
|
+
if params[:cloud]
|
|
126
|
+
clouds = [params[:cloud]]
|
|
127
|
+
params.delete(:cloud)
|
|
128
|
+
end
|
|
129
|
+
params[:deploy_id] ||= MU.deploy_id
|
|
130
|
+
if !params[:deploy_id] or params[:deploy_id].empty?
|
|
131
|
+
raise MuError, "Can't call cleanup methods without a deploy id"
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
clouds.each { |cloud|
|
|
135
|
+
begin
|
|
136
|
+
cloudclass = MU::Cloud.resourceClass(cloud, shortname)
|
|
137
|
+
|
|
138
|
+
if cloudclass.isGlobal?
|
|
139
|
+
params.delete(:region)
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
raise MuCloudResourceNotImplemented if !cloudclass.respond_to?(:cleanup) or cloudclass.method(:cleanup).owner.to_s != "#<Class:#{cloudclass}>"
|
|
143
|
+
MU.log "Invoking #{cloudclass}.cleanup from #{shortname}", MU::DEBUG, details: flags
|
|
144
|
+
cloudclass.cleanup(params)
|
|
145
|
+
rescue MuCloudResourceNotImplemented
|
|
146
|
+
MU.log "No #{cloud} implementation of #{shortname}.cleanup, skipping", MU::DEBUG, details: flags
|
|
147
|
+
rescue StandardError => e
|
|
148
|
+
in_msg = cloud
|
|
149
|
+
if params and params[:region]
|
|
150
|
+
in_msg += " "+params[:region]
|
|
151
|
+
end
|
|
152
|
+
if params and params[:flags] and params[:flags]["project"] and !params[:flags]["project"].empty?
|
|
153
|
+
in_msg += " project "+params[:flags]["project"]
|
|
154
|
+
end
|
|
155
|
+
MU.log "Skipping #{shortname} cleanup method in #{in_msg} due to #{e.class.name}: #{e.message}", MU::WARN, details: e.backtrace
|
|
156
|
+
ok = false
|
|
157
|
+
end
|
|
158
|
+
}
|
|
159
|
+
MU::MommaCat.unlockAll
|
|
160
|
+
|
|
161
|
+
ok
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
} # end dynamic class generation block
|
|
165
|
+
} # end resource type iteration
|
|
166
|
+
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
end
|
data/modules/mu/config.rb
CHANGED
|
@@ -77,7 +77,7 @@ module MU
|
|
|
77
77
|
if config.is_a?(Hash)
|
|
78
78
|
newhash = {}
|
|
79
79
|
config.each_pair { |key, val|
|
|
80
|
-
next if remove_runtime_keys and key.match(/^#MU_/)
|
|
80
|
+
next if remove_runtime_keys and (key.nil? or key.match(/^#MU_/))
|
|
81
81
|
next if val.is_a?(Array) and val.empty?
|
|
82
82
|
newhash[key] = self.manxify(val, remove_runtime_keys: remove_runtime_keys)
|
|
83
83
|
}
|
|
@@ -180,8 +180,19 @@ module MU
|
|
|
180
180
|
$file_format = MU::Config.guessFormat(path)
|
|
181
181
|
$yaml_refs = {}
|
|
182
182
|
erb = ERB.new(File.read(path), nil, "<>")
|
|
183
|
+
erb.filename = path
|
|
183
184
|
|
|
184
|
-
|
|
185
|
+
begin
|
|
186
|
+
raw_text = erb.result(erb_binding)
|
|
187
|
+
rescue NameError => e
|
|
188
|
+
loc = e.backtrace[0].sub(/:(\d+):.*/, ':\1')
|
|
189
|
+
msg = if e.message.match(/wrong constant name Config.getTail PLACEHOLDER ([^\s]+) REDLOHECALP/)
|
|
190
|
+
"Variable '#{Regexp.last_match[1]}' referenced in config, but not defined. Missing required parameter?"
|
|
191
|
+
else
|
|
192
|
+
e.message
|
|
193
|
+
end
|
|
194
|
+
raise ValidationError, msg+" at "+loc
|
|
195
|
+
end
|
|
185
196
|
raw_json = nil
|
|
186
197
|
|
|
187
198
|
# If we're working in YAML, do some magic to make includes work better.
|
|
@@ -419,6 +430,39 @@ module MU
|
|
|
419
430
|
@config.freeze
|
|
420
431
|
end
|
|
421
432
|
|
|
433
|
+
# Insert a dependency into the config hash of a resource, with sensible
|
|
434
|
+
# error checking and de-duplication.
|
|
435
|
+
# @param resource [Hash]
|
|
436
|
+
# @param name [String]
|
|
437
|
+
# @param type [String]
|
|
438
|
+
# @param phase [String]
|
|
439
|
+
# @param no_create_wait [Boolean]
|
|
440
|
+
def self.addDependency(resource, name, type, phase: "create", no_create_wait: false)
|
|
441
|
+
if ![nil, "create", "groom"].include?(phase)
|
|
442
|
+
raise MuError, "Invalid phase '#{phase}' while adding dependency #{type} #{name} to #{resource['name']}"
|
|
443
|
+
end
|
|
444
|
+
resource['dependencies'] ||= []
|
|
445
|
+
_shortclass, cfg_name, _cfg_plural, _classname = MU::Cloud.getResourceNames(type)
|
|
446
|
+
|
|
447
|
+
resource['dependencies'].each { |dep|
|
|
448
|
+
if dep['type'] == cfg_name and dep['name'].to_s == name.to_s
|
|
449
|
+
dep["no_create_wait"] = no_create_wait
|
|
450
|
+
dep["phase"] = phase if phase
|
|
451
|
+
return
|
|
452
|
+
end
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
newdep = {
|
|
456
|
+
"type" => cfg_name,
|
|
457
|
+
"name" => name.to_s,
|
|
458
|
+
"no_create_wait" => no_create_wait
|
|
459
|
+
}
|
|
460
|
+
newdep["phase"] = phase if phase
|
|
461
|
+
|
|
462
|
+
resource['dependencies'] << newdep
|
|
463
|
+
|
|
464
|
+
end
|
|
465
|
+
|
|
422
466
|
# See if a given resource is configured in the current stack
|
|
423
467
|
# @param name [String]: The name of the resource being checked
|
|
424
468
|
# @param type [String]: The type of resource being checked
|
|
@@ -474,7 +518,8 @@ module MU
|
|
|
474
518
|
# @param ignore_duplicates [Boolean]: Do not raise an exception if we attempt to insert a resource with a +name+ field that's already in use
|
|
475
519
|
def insertKitten(descriptor, type, delay_validation = false, ignore_duplicates: false, overwrite: false)
|
|
476
520
|
append = false
|
|
477
|
-
|
|
521
|
+
start = Time.now
|
|
522
|
+
|
|
478
523
|
shortclass, cfg_name, cfg_plural, classname = MU::Cloud.getResourceNames(type)
|
|
479
524
|
MU.log "insertKitten on #{cfg_name} #{descriptor['name']} (delay_validation: #{delay_validation.to_s})", MU::DEBUG, details: caller[0]
|
|
480
525
|
|
|
@@ -514,7 +559,7 @@ module MU
|
|
|
514
559
|
# cloud-specific schema.
|
|
515
560
|
schemaclass = Object.const_get("MU").const_get("Config").const_get(shortclass)
|
|
516
561
|
myschema = Marshal.load(Marshal.dump(MU::Config.schema["properties"][cfg_plural]["items"]))
|
|
517
|
-
more_required, more_schema =
|
|
562
|
+
more_required, more_schema = MU::Cloud.resourceClass(descriptor["cloud"], type).schema(self)
|
|
518
563
|
if more_schema
|
|
519
564
|
MU::Config.schemaMerge(myschema["properties"], more_schema, descriptor["cloud"])
|
|
520
565
|
end
|
|
@@ -533,7 +578,7 @@ module MU
|
|
|
533
578
|
end
|
|
534
579
|
|
|
535
580
|
# Make sure a sensible region has been targeted, if applicable
|
|
536
|
-
classobj =
|
|
581
|
+
classobj = MU::Cloud.cloudClass(descriptor["cloud"])
|
|
537
582
|
if descriptor["region"]
|
|
538
583
|
valid_regions = classobj.listRegions
|
|
539
584
|
if !valid_regions.include?(descriptor["region"])
|
|
@@ -546,11 +591,7 @@ module MU
|
|
|
546
591
|
if descriptor['project'].nil?
|
|
547
592
|
descriptor.delete('project')
|
|
548
593
|
elsif haveLitterMate?(descriptor['project'], "habitats")
|
|
549
|
-
descriptor['
|
|
550
|
-
descriptor['dependencies'] << {
|
|
551
|
-
"type" => "habitat",
|
|
552
|
-
"name" => descriptor['project']
|
|
553
|
-
}
|
|
594
|
+
MU::Config.addDependency(descriptor, descriptor['project'], "habitat")
|
|
554
595
|
end
|
|
555
596
|
end
|
|
556
597
|
|
|
@@ -578,21 +619,16 @@ module MU
|
|
|
578
619
|
if !descriptor["vpc"]["name"].nil? and
|
|
579
620
|
haveLitterMate?(descriptor["vpc"]["name"], "vpcs") and
|
|
580
621
|
descriptor["vpc"]['deploy_id'].nil? and
|
|
581
|
-
descriptor["vpc"]['id'].nil?
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
"name" => descriptor["vpc"]["name"],
|
|
585
|
-
}
|
|
622
|
+
descriptor["vpc"]['id'].nil? and
|
|
623
|
+
!(cfg_name == "vpc" and descriptor['name'] == descriptor['vpc']['name'])
|
|
624
|
+
MU::Config.addDependency(descriptor, descriptor['vpc']['name'], "vpc")
|
|
586
625
|
siblingvpc = haveLitterMate?(descriptor["vpc"]["name"], "vpcs")
|
|
587
626
|
|
|
588
627
|
if siblingvpc and siblingvpc['bastion'] and
|
|
589
628
|
["server", "server_pool", "container_cluster"].include?(cfg_name) and
|
|
590
629
|
!descriptor['bastion']
|
|
591
|
-
if descriptor['name'] != siblingvpc['bastion']
|
|
592
|
-
descriptor["
|
|
593
|
-
"type" => "server",
|
|
594
|
-
"name" => siblingvpc['bastion'].to_h['name']
|
|
595
|
-
}
|
|
630
|
+
if descriptor['name'] != siblingvpc['bastion']['name']
|
|
631
|
+
MU::Config.addDependency(descriptor, siblingvpc['bastion']['name'], "server")
|
|
596
632
|
end
|
|
597
633
|
end
|
|
598
634
|
|
|
@@ -654,7 +690,6 @@ module MU
|
|
|
654
690
|
if (descriptor['ingress_rules'] or
|
|
655
691
|
["server", "server_pool", "database", "cache_cluster"].include?(cfg_name))
|
|
656
692
|
descriptor['ingress_rules'] ||= []
|
|
657
|
-
fw_classobj = Object.const_get("MU").const_get("Cloud").const_get(descriptor["cloud"]).const_get("FirewallRule")
|
|
658
693
|
|
|
659
694
|
acl = haveLitterMate?(fwname, "firewall_rules")
|
|
660
695
|
already_exists = !acl.nil?
|
|
@@ -665,7 +700,7 @@ module MU
|
|
|
665
700
|
"region" => descriptor['region'],
|
|
666
701
|
"credentials" => descriptor["credentials"]
|
|
667
702
|
}
|
|
668
|
-
if !
|
|
703
|
+
if !MU::Cloud.resourceClass(descriptor["cloud"], "FirewallRule").isGlobal?
|
|
669
704
|
acl['region'] = descriptor['region']
|
|
670
705
|
acl['region'] ||= classobj.myRegion(acl['credentials'])
|
|
671
706
|
else
|
|
@@ -691,10 +726,7 @@ module MU
|
|
|
691
726
|
if !descriptor["loadbalancers"].nil?
|
|
692
727
|
descriptor["loadbalancers"].each { |lb|
|
|
693
728
|
if !lb["concurrent_load_balancer"].nil?
|
|
694
|
-
descriptor["
|
|
695
|
-
"type" => "loadbalancer",
|
|
696
|
-
"name" => lb["concurrent_load_balancer"]
|
|
697
|
-
}
|
|
729
|
+
MU::Config.addDependency(descriptor, lb["concurrent_load_balancer"], "loadbalancer")
|
|
698
730
|
end
|
|
699
731
|
}
|
|
700
732
|
end
|
|
@@ -703,10 +735,7 @@ module MU
|
|
|
703
735
|
if !descriptor["storage_pools"].nil?
|
|
704
736
|
descriptor["storage_pools"].each { |sp|
|
|
705
737
|
if sp["name"]
|
|
706
|
-
descriptor["
|
|
707
|
-
"type" => "storage_pool",
|
|
708
|
-
"name" => sp["name"]
|
|
709
|
-
}
|
|
738
|
+
MU::Config.addDependency(descriptor, sp["name"], "storage_pool")
|
|
710
739
|
end
|
|
711
740
|
}
|
|
712
741
|
end
|
|
@@ -717,10 +746,7 @@ module MU
|
|
|
717
746
|
next if !acl_include["name"] and !acl_include["rule_name"]
|
|
718
747
|
acl_include["name"] ||= acl_include["rule_name"]
|
|
719
748
|
if haveLitterMate?(acl_include["name"], "firewall_rules")
|
|
720
|
-
descriptor["
|
|
721
|
-
"type" => "firewall_rule",
|
|
722
|
-
"name" => acl_include["name"]
|
|
723
|
-
}
|
|
749
|
+
MU::Config.addDependency(descriptor, acl_include["name"], "firewall_rule", no_create_wait: (cfg_name == "vpc"))
|
|
724
750
|
elsif acl_include["name"]
|
|
725
751
|
MU.log shortclass.to_s+" #{descriptor['name']} depends on FirewallRule #{acl_include["name"]}, but no such rule declared.", MU::ERR
|
|
726
752
|
ok = false
|
|
@@ -820,7 +846,7 @@ module MU
|
|
|
820
846
|
# Run the cloud class's deeper validation, unless we've already failed
|
|
821
847
|
# on stuff that will cause spurious alarms further in
|
|
822
848
|
if ok
|
|
823
|
-
parser =
|
|
849
|
+
parser = MU::Cloud.resourceClass(descriptor['cloud'], type)
|
|
824
850
|
original_descriptor = MU::Config.stripConfig(descriptor)
|
|
825
851
|
passed = parser.validateConfig(descriptor, self)
|
|
826
852
|
|
|
@@ -830,7 +856,7 @@ module MU
|
|
|
830
856
|
end
|
|
831
857
|
|
|
832
858
|
# Make sure we've been configured with the right credentials
|
|
833
|
-
cloudbase =
|
|
859
|
+
cloudbase = MU::Cloud.cloudClass(descriptor['cloud'])
|
|
834
860
|
credcfg = cloudbase.credConfig(descriptor['credentials'])
|
|
835
861
|
if !credcfg or credcfg.empty?
|
|
836
862
|
raise ValidationError, "#{descriptor['cloud']} #{cfg_name} #{descriptor['name']} declares credential set #{descriptor['credentials']}, but no such credentials exist for that cloud provider"
|
|
@@ -846,60 +872,92 @@ module MU
|
|
|
846
872
|
@kittens[cfg_plural] << descriptor if append
|
|
847
873
|
}
|
|
848
874
|
|
|
875
|
+
MU.log "insertKitten completed #{cfg_name} #{descriptor['name']} in #{sprintf("%.2fs", Time.now-start)}", MU::DEBUG
|
|
876
|
+
|
|
849
877
|
ok
|
|
850
878
|
end
|
|
851
879
|
|
|
852
880
|
# For our resources which specify intra-stack dependencies, make sure those
|
|
853
881
|
# dependencies are actually declared.
|
|
854
|
-
|
|
855
|
-
def self.check_dependencies(config)
|
|
882
|
+
def check_dependencies
|
|
856
883
|
ok = true
|
|
857
884
|
|
|
858
|
-
config.each_pair { |type, values|
|
|
859
|
-
if values.instance_of?(Array)
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
885
|
+
@config.each_pair { |type, values|
|
|
886
|
+
next if !values.instance_of?(Array)
|
|
887
|
+
_shortclass, cfg_name, _cfg_plural, _classname = MU::Cloud.getResourceNames(type, false)
|
|
888
|
+
next if !cfg_name
|
|
889
|
+
values.each { |resource|
|
|
890
|
+
next if !resource.kind_of?(Hash) or resource["dependencies"].nil?
|
|
891
|
+
addme = []
|
|
892
|
+
deleteme = []
|
|
893
|
+
|
|
894
|
+
resource["dependencies"].each { |dependency|
|
|
895
|
+
# make sure the thing we depend on really exists
|
|
896
|
+
sibling = haveLitterMate?(dependency['name'], dependency['type'])
|
|
897
|
+
if !sibling
|
|
898
|
+
MU.log "Missing dependency: #{type}{#{resource['name']}} needs #{cfg_name}{#{dependency['name']}}", MU::ERR
|
|
899
|
+
ok = false
|
|
900
|
+
next
|
|
901
|
+
end
|
|
902
|
+
|
|
903
|
+
# Fudge dependency declarations to quash virtual_names that we know
|
|
904
|
+
# are extraneous. Note that wee can't do all virtual names here; we
|
|
905
|
+
# have no way to guess which of a collection of resources is the
|
|
906
|
+
# real correct one.
|
|
907
|
+
if sibling['virtual_name'] == dependency['name']
|
|
908
|
+
real_resources = []
|
|
909
|
+
found_exact = false
|
|
910
|
+
resource["dependencies"].each { |dep_again|
|
|
911
|
+
if dep_again['type'] == dependency['type'] and sibling['name'] == dep_again['name']
|
|
912
|
+
dependency['name'] = sibling['name']
|
|
913
|
+
found_exact = true
|
|
914
|
+
break
|
|
915
|
+
end
|
|
916
|
+
}
|
|
917
|
+
if !found_exact
|
|
918
|
+
all_siblings = haveLitterMate?(dependency['name'], dependency['type'], has_multiple: true)
|
|
919
|
+
if all_siblings.size > 0
|
|
920
|
+
all_siblings.each { |s|
|
|
921
|
+
newguy = dependency.clone
|
|
922
|
+
newguy['name'] = s['name']
|
|
923
|
+
addme << newguy
|
|
882
924
|
}
|
|
925
|
+
deleteme << dependency
|
|
926
|
+
MU.log "Expanding dependency which maps to virtual resources to all matching real resources", MU::NOTICE, details: { sibling['virtual_name'] => addme }
|
|
927
|
+
next
|
|
883
928
|
end
|
|
884
|
-
|
|
885
|
-
|
|
929
|
+
end
|
|
930
|
+
end
|
|
931
|
+
|
|
932
|
+
# Check for a circular relationship that will lead to a deadlock
|
|
933
|
+
# when creating resource. This only goes one layer deep, and does
|
|
934
|
+
# not consider groom-phase deadlocks.
|
|
935
|
+
if dependency['phase'] == "groom" or dependency['no_create_wait'] or (
|
|
936
|
+
!MU::Cloud.resourceClass(sibling['cloud'], type).deps_wait_on_my_creation and
|
|
937
|
+
!MU::Cloud.resourceClass(resource['cloud'], type).waits_on_parent_completion
|
|
938
|
+
)
|
|
939
|
+
next
|
|
940
|
+
end
|
|
941
|
+
|
|
942
|
+
if sibling['dependencies']
|
|
943
|
+
sibling['dependencies'].each { |sib_dep|
|
|
944
|
+
next if sib_dep['type'] != cfg_name or sib_dep['no_create_wait']
|
|
945
|
+
cousin = haveLitterMate?(sib_dep['name'], sib_dep['type'])
|
|
946
|
+
if cousin and cousin['name'] == resource['name']
|
|
947
|
+
MU.log "Circular dependency between #{type} #{resource['name']} <=> #{dependency['type']} #{dependency['name']}", MU::ERR, details: [ resource['name'] => dependency, sibling['name'] => sib_dep ]
|
|
886
948
|
ok = false
|
|
887
949
|
end
|
|
888
950
|
}
|
|
889
|
-
if append.size > 0
|
|
890
|
-
append.uniq!
|
|
891
|
-
resource["dependencies"].concat(append)
|
|
892
|
-
end
|
|
893
|
-
if delete.size > 0
|
|
894
|
-
delete.each { |delete_me|
|
|
895
|
-
resource["dependencies"].delete(delete_me)
|
|
896
|
-
}
|
|
897
|
-
end
|
|
898
951
|
end
|
|
899
952
|
}
|
|
900
|
-
|
|
953
|
+
resource["dependencies"].reject! { |dep| deleteme.include?(dep) }
|
|
954
|
+
resource["dependencies"].concat(addme)
|
|
955
|
+
resource["dependencies"].uniq!
|
|
956
|
+
|
|
957
|
+
}
|
|
901
958
|
}
|
|
902
|
-
|
|
959
|
+
|
|
960
|
+
ok
|
|
903
961
|
end
|
|
904
962
|
|
|
905
963
|
# Ugly text-manipulation to recursively resolve some placeholder strings
|
|
@@ -1180,12 +1238,7 @@ module MU
|
|
|
1180
1238
|
"port" => db["port"],
|
|
1181
1239
|
"sgs" => [cfg_name+server['name']]
|
|
1182
1240
|
}
|
|
1183
|
-
|
|
1184
|
-
ruleset["dependencies"] << {
|
|
1185
|
-
"name" => cfg_name+server['name'],
|
|
1186
|
-
"type" => "firewall_rule",
|
|
1187
|
-
"no_create_wait" => true
|
|
1188
|
-
}
|
|
1241
|
+
MU::Config.addDependency(ruleset, cfg_name+server['name'], "firewall_rule", no_create_wait: true)
|
|
1189
1242
|
end
|
|
1190
1243
|
}
|
|
1191
1244
|
}
|
|
@@ -1203,7 +1256,7 @@ module MU
|
|
|
1203
1256
|
types.each { |type|
|
|
1204
1257
|
config[type] = @kittens[type] if @kittens[type].size > 0
|
|
1205
1258
|
}
|
|
1206
|
-
ok = false if !
|
|
1259
|
+
ok = false if !check_dependencies
|
|
1207
1260
|
|
|
1208
1261
|
# TODO enforce uniqueness of resource names
|
|
1209
1262
|
raise ValidationError if !ok
|