cloud-mu 3.1.5 → 3.3.2
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/files/LaunchConfig.json +9 -0
- data/ansible/roles/mu-windows/files/config.xml +76 -0
- data/ansible/roles/mu-windows/tasks/main.yml +16 -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 +3 -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/windows-client.rb +25 -22
- data/extras/clean-stock-amis +25 -19
- data/extras/generate-stock-images +1 -0
- data/extras/image-generators/AWS/win2k12.yaml +2 -0
- data/extras/image-generators/AWS/win2k16.yaml +2 -0
- data/extras/image-generators/AWS/win2k19.yaml +2 -0
- data/modules/mommacat.ru +1 -1
- data/modules/mu.rb +86 -98
- data/modules/mu/adoption.rb +373 -58
- data/modules/mu/cleanup.rb +214 -303
- data/modules/mu/cloud.rb +128 -1733
- 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 +929 -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 +123 -81
- 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_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 +90 -90
- data/modules/mu/defaults/Azure.yaml +1 -0
- data/modules/mu/defaults/Google.yaml +1 -0
- data/modules/mu/deploy.rb +34 -20
- data/modules/mu/groomer.rb +16 -1
- data/modules/mu/groomers/ansible.rb +69 -4
- data/modules/mu/groomers/chef.rb +51 -4
- data/modules/mu/logger.rb +120 -144
- data/modules/mu/master.rb +97 -4
- data/modules/mu/mommacat.rb +160 -874
- data/modules/mu/mommacat/daemon.rb +23 -14
- data/modules/mu/mommacat/naming.rb +110 -3
- data/modules/mu/mommacat/search.rb +497 -0
- data/modules/mu/mommacat/storage.rb +252 -194
- data/modules/mu/{clouds → providers}/README.md +1 -1
- data/modules/mu/{clouds → providers}/aws.rb +258 -57
- 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 +95 -84
- data/modules/mu/providers/aws/database.rb +1744 -0
- data/modules/mu/{clouds → providers}/aws/dnszone.rb +26 -12
- data/modules/mu/providers/aws/endpoint.rb +1072 -0
- data/modules/mu/{clouds → providers}/aws/firewall_rule.rb +39 -32
- 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 +77 -47
- 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 +76 -48
- data/modules/mu/{clouds → providers}/aws/search_domain.rb +172 -41
- data/modules/mu/{clouds → providers}/aws/server.rb +66 -98
- data/modules/mu/{clouds → providers}/aws/server_pool.rb +42 -60
- 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 +0 -0
- data/modules/mu/{clouds → providers}/aws/vpc.rb +143 -74
- data/modules/mu/{clouds → providers}/aws/vpc_subnet.rb +0 -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 +4 -4
- data/modules/mu/{clouds → providers}/google/container_cluster.rb +38 -20
- 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 +6 -6
- 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 +41 -24
- 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 +45 -14
- 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 +2 -2
- 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/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 +1 -1
- data/modules/tests/super_complex_bok.yml +2 -2
- data/modules/tests/super_simple_bok.yml +3 -5
- data/spec/mu/clouds/azure_spec.rb +2 -2
- metadata +122 -92
- data/modules/mu/clouds/aws/database.rb +0 -1974
- data/modules/mu/clouds/aws/endpoint.rb +0 -596
|
@@ -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
|
}
|
|
@@ -430,6 +430,39 @@ module MU
|
|
|
430
430
|
@config.freeze
|
|
431
431
|
end
|
|
432
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
|
+
|
|
433
466
|
# See if a given resource is configured in the current stack
|
|
434
467
|
# @param name [String]: The name of the resource being checked
|
|
435
468
|
# @param type [String]: The type of resource being checked
|
|
@@ -485,7 +518,8 @@ module MU
|
|
|
485
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
|
|
486
519
|
def insertKitten(descriptor, type, delay_validation = false, ignore_duplicates: false, overwrite: false)
|
|
487
520
|
append = false
|
|
488
|
-
|
|
521
|
+
start = Time.now
|
|
522
|
+
|
|
489
523
|
shortclass, cfg_name, cfg_plural, classname = MU::Cloud.getResourceNames(type)
|
|
490
524
|
MU.log "insertKitten on #{cfg_name} #{descriptor['name']} (delay_validation: #{delay_validation.to_s})", MU::DEBUG, details: caller[0]
|
|
491
525
|
|
|
@@ -525,7 +559,7 @@ module MU
|
|
|
525
559
|
# cloud-specific schema.
|
|
526
560
|
schemaclass = Object.const_get("MU").const_get("Config").const_get(shortclass)
|
|
527
561
|
myschema = Marshal.load(Marshal.dump(MU::Config.schema["properties"][cfg_plural]["items"]))
|
|
528
|
-
more_required, more_schema =
|
|
562
|
+
more_required, more_schema = MU::Cloud.resourceClass(descriptor["cloud"], type).schema(self)
|
|
529
563
|
if more_schema
|
|
530
564
|
MU::Config.schemaMerge(myschema["properties"], more_schema, descriptor["cloud"])
|
|
531
565
|
end
|
|
@@ -544,7 +578,7 @@ module MU
|
|
|
544
578
|
end
|
|
545
579
|
|
|
546
580
|
# Make sure a sensible region has been targeted, if applicable
|
|
547
|
-
classobj =
|
|
581
|
+
classobj = MU::Cloud.cloudClass(descriptor["cloud"])
|
|
548
582
|
if descriptor["region"]
|
|
549
583
|
valid_regions = classobj.listRegions
|
|
550
584
|
if !valid_regions.include?(descriptor["region"])
|
|
@@ -557,11 +591,7 @@ module MU
|
|
|
557
591
|
if descriptor['project'].nil?
|
|
558
592
|
descriptor.delete('project')
|
|
559
593
|
elsif haveLitterMate?(descriptor['project'], "habitats")
|
|
560
|
-
descriptor['
|
|
561
|
-
descriptor['dependencies'] << {
|
|
562
|
-
"type" => "habitat",
|
|
563
|
-
"name" => descriptor['project']
|
|
564
|
-
}
|
|
594
|
+
MU::Config.addDependency(descriptor, descriptor['project'], "habitat")
|
|
565
595
|
end
|
|
566
596
|
end
|
|
567
597
|
|
|
@@ -589,21 +619,16 @@ module MU
|
|
|
589
619
|
if !descriptor["vpc"]["name"].nil? and
|
|
590
620
|
haveLitterMate?(descriptor["vpc"]["name"], "vpcs") and
|
|
591
621
|
descriptor["vpc"]['deploy_id'].nil? and
|
|
592
|
-
descriptor["vpc"]['id'].nil?
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
"name" => descriptor["vpc"]["name"],
|
|
596
|
-
}
|
|
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")
|
|
597
625
|
siblingvpc = haveLitterMate?(descriptor["vpc"]["name"], "vpcs")
|
|
598
626
|
|
|
599
627
|
if siblingvpc and siblingvpc['bastion'] and
|
|
600
628
|
["server", "server_pool", "container_cluster"].include?(cfg_name) and
|
|
601
629
|
!descriptor['bastion']
|
|
602
|
-
if descriptor['name'] != siblingvpc['bastion']
|
|
603
|
-
descriptor["
|
|
604
|
-
"type" => "server",
|
|
605
|
-
"name" => siblingvpc['bastion'].to_h['name']
|
|
606
|
-
}
|
|
630
|
+
if descriptor['name'] != siblingvpc['bastion']['name']
|
|
631
|
+
MU::Config.addDependency(descriptor, siblingvpc['bastion']['name'], "server")
|
|
607
632
|
end
|
|
608
633
|
end
|
|
609
634
|
|
|
@@ -665,7 +690,6 @@ module MU
|
|
|
665
690
|
if (descriptor['ingress_rules'] or
|
|
666
691
|
["server", "server_pool", "database", "cache_cluster"].include?(cfg_name))
|
|
667
692
|
descriptor['ingress_rules'] ||= []
|
|
668
|
-
fw_classobj = Object.const_get("MU").const_get("Cloud").const_get(descriptor["cloud"]).const_get("FirewallRule")
|
|
669
693
|
|
|
670
694
|
acl = haveLitterMate?(fwname, "firewall_rules")
|
|
671
695
|
already_exists = !acl.nil?
|
|
@@ -676,7 +700,7 @@ module MU
|
|
|
676
700
|
"region" => descriptor['region'],
|
|
677
701
|
"credentials" => descriptor["credentials"]
|
|
678
702
|
}
|
|
679
|
-
if !
|
|
703
|
+
if !MU::Cloud.resourceClass(descriptor["cloud"], "FirewallRule").isGlobal?
|
|
680
704
|
acl['region'] = descriptor['region']
|
|
681
705
|
acl['region'] ||= classobj.myRegion(acl['credentials'])
|
|
682
706
|
else
|
|
@@ -702,10 +726,7 @@ module MU
|
|
|
702
726
|
if !descriptor["loadbalancers"].nil?
|
|
703
727
|
descriptor["loadbalancers"].each { |lb|
|
|
704
728
|
if !lb["concurrent_load_balancer"].nil?
|
|
705
|
-
descriptor["
|
|
706
|
-
"type" => "loadbalancer",
|
|
707
|
-
"name" => lb["concurrent_load_balancer"]
|
|
708
|
-
}
|
|
729
|
+
MU::Config.addDependency(descriptor, lb["concurrent_load_balancer"], "loadbalancer")
|
|
709
730
|
end
|
|
710
731
|
}
|
|
711
732
|
end
|
|
@@ -714,10 +735,7 @@ module MU
|
|
|
714
735
|
if !descriptor["storage_pools"].nil?
|
|
715
736
|
descriptor["storage_pools"].each { |sp|
|
|
716
737
|
if sp["name"]
|
|
717
|
-
descriptor["
|
|
718
|
-
"type" => "storage_pool",
|
|
719
|
-
"name" => sp["name"]
|
|
720
|
-
}
|
|
738
|
+
MU::Config.addDependency(descriptor, sp["name"], "storage_pool")
|
|
721
739
|
end
|
|
722
740
|
}
|
|
723
741
|
end
|
|
@@ -728,10 +746,7 @@ module MU
|
|
|
728
746
|
next if !acl_include["name"] and !acl_include["rule_name"]
|
|
729
747
|
acl_include["name"] ||= acl_include["rule_name"]
|
|
730
748
|
if haveLitterMate?(acl_include["name"], "firewall_rules")
|
|
731
|
-
descriptor["
|
|
732
|
-
"type" => "firewall_rule",
|
|
733
|
-
"name" => acl_include["name"]
|
|
734
|
-
}
|
|
749
|
+
MU::Config.addDependency(descriptor, acl_include["name"], "firewall_rule", no_create_wait: (cfg_name == "vpc"))
|
|
735
750
|
elsif acl_include["name"]
|
|
736
751
|
MU.log shortclass.to_s+" #{descriptor['name']} depends on FirewallRule #{acl_include["name"]}, but no such rule declared.", MU::ERR
|
|
737
752
|
ok = false
|
|
@@ -831,7 +846,7 @@ module MU
|
|
|
831
846
|
# Run the cloud class's deeper validation, unless we've already failed
|
|
832
847
|
# on stuff that will cause spurious alarms further in
|
|
833
848
|
if ok
|
|
834
|
-
parser =
|
|
849
|
+
parser = MU::Cloud.resourceClass(descriptor['cloud'], type)
|
|
835
850
|
original_descriptor = MU::Config.stripConfig(descriptor)
|
|
836
851
|
passed = parser.validateConfig(descriptor, self)
|
|
837
852
|
|
|
@@ -841,7 +856,7 @@ module MU
|
|
|
841
856
|
end
|
|
842
857
|
|
|
843
858
|
# Make sure we've been configured with the right credentials
|
|
844
|
-
cloudbase =
|
|
859
|
+
cloudbase = MU::Cloud.cloudClass(descriptor['cloud'])
|
|
845
860
|
credcfg = cloudbase.credConfig(descriptor['credentials'])
|
|
846
861
|
if !credcfg or credcfg.empty?
|
|
847
862
|
raise ValidationError, "#{descriptor['cloud']} #{cfg_name} #{descriptor['name']} declares credential set #{descriptor['credentials']}, but no such credentials exist for that cloud provider"
|
|
@@ -857,60 +872,92 @@ module MU
|
|
|
857
872
|
@kittens[cfg_plural] << descriptor if append
|
|
858
873
|
}
|
|
859
874
|
|
|
875
|
+
MU.log "insertKitten completed #{cfg_name} #{descriptor['name']} in #{sprintf("%.2fs", Time.now-start)}", MU::DEBUG
|
|
876
|
+
|
|
860
877
|
ok
|
|
861
878
|
end
|
|
862
879
|
|
|
863
880
|
# For our resources which specify intra-stack dependencies, make sure those
|
|
864
881
|
# dependencies are actually declared.
|
|
865
|
-
|
|
866
|
-
def self.check_dependencies(config)
|
|
882
|
+
def check_dependencies
|
|
867
883
|
ok = true
|
|
868
884
|
|
|
869
|
-
config.each_pair { |type, values|
|
|
870
|
-
if values.instance_of?(Array)
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
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
|
|
893
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
|
|
894
928
|
end
|
|
895
|
-
|
|
896
|
-
|
|
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 ]
|
|
897
948
|
ok = false
|
|
898
949
|
end
|
|
899
950
|
}
|
|
900
|
-
if append.size > 0
|
|
901
|
-
append.uniq!
|
|
902
|
-
resource["dependencies"].concat(append)
|
|
903
|
-
end
|
|
904
|
-
if delete.size > 0
|
|
905
|
-
delete.each { |delete_me|
|
|
906
|
-
resource["dependencies"].delete(delete_me)
|
|
907
|
-
}
|
|
908
|
-
end
|
|
909
951
|
end
|
|
910
952
|
}
|
|
911
|
-
|
|
953
|
+
resource["dependencies"].reject! { |dep| deleteme.include?(dep) }
|
|
954
|
+
resource["dependencies"].concat(addme)
|
|
955
|
+
resource["dependencies"].uniq!
|
|
956
|
+
|
|
957
|
+
}
|
|
912
958
|
}
|
|
913
|
-
|
|
959
|
+
|
|
960
|
+
ok
|
|
914
961
|
end
|
|
915
962
|
|
|
916
963
|
# Ugly text-manipulation to recursively resolve some placeholder strings
|
|
@@ -1191,12 +1238,7 @@ module MU
|
|
|
1191
1238
|
"port" => db["port"],
|
|
1192
1239
|
"sgs" => [cfg_name+server['name']]
|
|
1193
1240
|
}
|
|
1194
|
-
|
|
1195
|
-
ruleset["dependencies"] << {
|
|
1196
|
-
"name" => cfg_name+server['name'],
|
|
1197
|
-
"type" => "firewall_rule",
|
|
1198
|
-
"no_create_wait" => true
|
|
1199
|
-
}
|
|
1241
|
+
MU::Config.addDependency(ruleset, cfg_name+server['name'], "firewall_rule", no_create_wait: true)
|
|
1200
1242
|
end
|
|
1201
1243
|
}
|
|
1202
1244
|
}
|
|
@@ -1214,7 +1256,7 @@ module MU
|
|
|
1214
1256
|
types.each { |type|
|
|
1215
1257
|
config[type] = @kittens[type] if @kittens[type].size > 0
|
|
1216
1258
|
}
|
|
1217
|
-
ok = false if !
|
|
1259
|
+
ok = false if !check_dependencies
|
|
1218
1260
|
|
|
1219
1261
|
# TODO enforce uniqueness of resource names
|
|
1220
1262
|
raise ValidationError if !ok
|