cloud-mu 3.1.2 → 3.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Dockerfile +15 -3
- 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 +10 -13
- 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 -3
- data/bin/mu-node-manage +15 -16
- data/bin/mu-run-tests +135 -37
- data/cloud-mu.gemspec +22 -20
- 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 +3 -2
- data/cookbooks/mu-tools/libraries/monkey.rb +35 -0
- 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/google_api.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/disk.rb +1 -1
- 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/extras/image-generators/Google/centos6.yaml +1 -0
- data/extras/image-generators/Google/centos7.yaml +1 -1
- data/modules/mommacat.ru +6 -16
- data/modules/mu.rb +165 -111
- data/modules/mu/adoption.rb +401 -68
- data/modules/mu/cleanup.rb +199 -306
- data/modules/mu/cloud.rb +100 -1632
- data/modules/mu/cloud/database.rb +49 -0
- data/modules/mu/cloud/dnszone.rb +46 -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 +920 -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 +165 -0
- data/modules/mu/config.rb +171 -1767
- data/modules/mu/config/alarm.rb +2 -6
- data/modules/mu/config/bucket.rb +4 -4
- data/modules/mu/config/cache_cluster.rb +1 -1
- data/modules/mu/config/collection.rb +4 -4
- data/modules/mu/config/container_cluster.rb +9 -4
- data/modules/mu/config/database.rb +83 -104
- data/modules/mu/config/database.yml +1 -2
- data/modules/mu/config/dnszone.rb +6 -6
- data/modules/mu/config/doc_helpers.rb +516 -0
- data/modules/mu/config/endpoint.rb +4 -4
- data/modules/mu/config/firewall_rule.rb +103 -4
- data/modules/mu/config/folder.rb +4 -4
- data/modules/mu/config/function.rb +3 -3
- data/modules/mu/config/group.rb +4 -4
- data/modules/mu/config/habitat.rb +4 -4
- data/modules/mu/config/loadbalancer.rb +60 -14
- data/modules/mu/config/log.rb +4 -4
- data/modules/mu/config/msg_queue.rb +4 -4
- data/modules/mu/config/nosqldb.rb +4 -4
- data/modules/mu/config/notifier.rb +3 -3
- data/modules/mu/config/ref.rb +365 -0
- data/modules/mu/config/role.rb +4 -4
- data/modules/mu/config/schema_helpers.rb +509 -0
- data/modules/mu/config/search_domain.rb +4 -4
- data/modules/mu/config/server.rb +97 -70
- data/modules/mu/config/server.yml +1 -0
- data/modules/mu/config/server_pool.rb +5 -9
- data/modules/mu/config/storage_pool.rb +1 -1
- data/modules/mu/config/tail.rb +200 -0
- data/modules/mu/config/user.rb +4 -4
- data/modules/mu/config/vpc.rb +70 -27
- data/modules/mu/config/vpc.yml +0 -1
- data/modules/mu/defaults/AWS.yaml +83 -60
- data/modules/mu/defaults/Azure.yaml +1 -0
- data/modules/mu/defaults/Google.yaml +3 -2
- data/modules/mu/deploy.rb +30 -26
- data/modules/mu/groomer.rb +17 -2
- data/modules/mu/groomers/ansible.rb +188 -41
- data/modules/mu/groomers/chef.rb +116 -55
- data/modules/mu/logger.rb +127 -148
- data/modules/mu/master.rb +389 -2
- data/modules/mu/master/chef.rb +3 -4
- data/modules/mu/master/ldap.rb +3 -3
- data/modules/mu/master/ssl.rb +12 -3
- data/modules/mu/mommacat.rb +217 -2612
- data/modules/mu/mommacat/daemon.rb +397 -0
- data/modules/mu/mommacat/naming.rb +473 -0
- data/modules/mu/mommacat/search.rb +495 -0
- data/modules/mu/mommacat/storage.rb +722 -0
- data/modules/mu/{clouds → providers}/README.md +1 -1
- data/modules/mu/{clouds → providers}/aws.rb +271 -112
- data/modules/mu/{clouds → providers}/aws/alarm.rb +5 -3
- data/modules/mu/{clouds → providers}/aws/bucket.rb +26 -22
- data/modules/mu/{clouds → providers}/aws/cache_cluster.rb +33 -67
- data/modules/mu/{clouds → providers}/aws/collection.rb +24 -23
- data/modules/mu/{clouds → providers}/aws/container_cluster.rb +681 -721
- data/modules/mu/providers/aws/database.rb +1744 -0
- data/modules/mu/{clouds → providers}/aws/dnszone.rb +64 -63
- data/modules/mu/{clouds → providers}/aws/endpoint.rb +22 -27
- data/modules/mu/{clouds → providers}/aws/firewall_rule.rb +214 -244
- data/modules/mu/{clouds → providers}/aws/folder.rb +7 -7
- data/modules/mu/{clouds → providers}/aws/function.rb +17 -22
- data/modules/mu/{clouds → providers}/aws/group.rb +23 -23
- data/modules/mu/{clouds → providers}/aws/habitat.rb +17 -14
- data/modules/mu/{clouds → providers}/aws/loadbalancer.rb +57 -48
- data/modules/mu/{clouds → providers}/aws/log.rb +15 -12
- data/modules/mu/{clouds → providers}/aws/msg_queue.rb +17 -16
- data/modules/mu/{clouds → providers}/aws/nosqldb.rb +18 -11
- data/modules/mu/{clouds → providers}/aws/notifier.rb +11 -6
- data/modules/mu/{clouds → providers}/aws/role.rb +112 -86
- data/modules/mu/{clouds → providers}/aws/search_domain.rb +39 -33
- data/modules/mu/{clouds → providers}/aws/server.rb +835 -1133
- data/modules/mu/{clouds → providers}/aws/server_pool.rb +56 -60
- data/modules/mu/{clouds → providers}/aws/storage_pool.rb +24 -42
- data/modules/mu/{clouds → providers}/aws/user.rb +21 -22
- data/modules/mu/{clouds → providers}/aws/userdata/README.md +0 -0
- data/modules/mu/{clouds → providers}/aws/userdata/linux.erb +0 -0
- data/modules/mu/{clouds → providers}/aws/userdata/windows.erb +2 -1
- data/modules/mu/{clouds → providers}/aws/vpc.rb +523 -929
- data/modules/mu/providers/aws/vpc_subnet.rb +286 -0
- data/modules/mu/{clouds → providers}/azure.rb +29 -9
- data/modules/mu/{clouds → providers}/azure/container_cluster.rb +3 -8
- data/modules/mu/{clouds → providers}/azure/firewall_rule.rb +18 -11
- data/modules/mu/{clouds → providers}/azure/habitat.rb +8 -6
- data/modules/mu/{clouds → providers}/azure/loadbalancer.rb +5 -5
- data/modules/mu/{clouds → providers}/azure/role.rb +8 -10
- data/modules/mu/{clouds → providers}/azure/server.rb +95 -48
- data/modules/mu/{clouds → providers}/azure/user.rb +6 -8
- 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 +16 -21
- data/modules/mu/{clouds → providers}/cloudformation.rb +18 -7
- 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 +5 -7
- data/modules/mu/{clouds → providers}/docker.rb +0 -0
- data/modules/mu/{clouds → providers}/google.rb +67 -30
- data/modules/mu/{clouds → providers}/google/bucket.rb +13 -15
- data/modules/mu/{clouds → providers}/google/container_cluster.rb +84 -77
- data/modules/mu/{clouds → providers}/google/database.rb +10 -20
- data/modules/mu/{clouds → providers}/google/firewall_rule.rb +15 -14
- data/modules/mu/{clouds → providers}/google/folder.rb +20 -17
- data/modules/mu/{clouds → providers}/google/function.rb +139 -167
- data/modules/mu/{clouds → providers}/google/group.rb +29 -34
- data/modules/mu/{clouds → providers}/google/habitat.rb +21 -22
- data/modules/mu/{clouds → providers}/google/loadbalancer.rb +18 -20
- data/modules/mu/{clouds → providers}/google/role.rb +92 -58
- data/modules/mu/{clouds → providers}/google/server.rb +242 -155
- data/modules/mu/{clouds → providers}/google/server_pool.rb +25 -44
- data/modules/mu/{clouds → providers}/google/user.rb +95 -31
- 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 +103 -79
- data/modules/tests/bucket.yml +4 -0
- data/modules/tests/centos6.yaml +11 -0
- data/modules/tests/centos7.yaml +11 -0
- data/modules/tests/centos8.yaml +12 -0
- data/modules/tests/ecs.yaml +23 -0
- data/modules/tests/includes-and-params.yaml +2 -1
- data/modules/tests/rds.yaml +108 -0
- data/modules/tests/regrooms/aws-iam.yaml +201 -0
- data/modules/tests/regrooms/bucket.yml +19 -0
- data/modules/tests/regrooms/rds.yaml +123 -0
- data/modules/tests/server-with-scrub-muisms.yaml +1 -0
- data/modules/tests/super_simple_bok.yml +1 -3
- data/modules/tests/win2k12.yaml +17 -5
- 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 +232 -154
- data/extras/image-generators/AWS/windows.yaml +0 -18
- data/modules/mu/clouds/aws/database.rb +0 -1985
@@ -0,0 +1,495 @@
|
|
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
|
+
|
17
|
+
# MommaCat is in charge of managing metadata about resources we've created,
|
18
|
+
# as well as orchestrating amongst them and bootstrapping nodes outside of
|
19
|
+
# the normal synchronous deploy sequence invoked by *mu-deploy*.
|
20
|
+
class MommaCat
|
21
|
+
|
22
|
+
@@desc_semaphore = Mutex.new
|
23
|
+
|
24
|
+
# A search which returned multiple matches, but is not allowed to
|
25
|
+
class MultipleMatches < MuError
|
26
|
+
def initialize(message = nil)
|
27
|
+
super(message, silent: true)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
# Locate a resource that's either a member of another deployment, or of no
|
32
|
+
# deployment at all, and return a {MU::Cloud} object for it.
|
33
|
+
# @param cloud [String]: The Cloud provider to use.
|
34
|
+
# @param type [String]: The resource type. Can be the full class name, symbolic name, or Basket of Kittens configuration shorthand for the resource type.
|
35
|
+
# @param deploy_id [String]: The identifier of an outside deploy to search.
|
36
|
+
# @param name [String]: The name of the resource as defined in its 'name' Basket of Kittens field, typically used in conjunction with deploy_id.
|
37
|
+
# @param mu_name [String]: The fully-resolved and deployed name of the resource, typically used in conjunction with deploy_id.
|
38
|
+
# @param cloud_id [String]: A cloud provider identifier for this resource.
|
39
|
+
# @param region [String]: The cloud provider region
|
40
|
+
# @param tag_key [String]: A cloud provider tag to help identify the resource, used in conjunction with tag_value.
|
41
|
+
# @param tag_value [String]: A cloud provider tag to help identify the resource, used in conjunction with tag_key.
|
42
|
+
# @param allow_multi [Boolean]: Permit an array of matching resources to be returned (if applicable) instead of just one.
|
43
|
+
# @param dummy_ok [Boolean]: Permit return of a faked {MU::Cloud} object if we don't have enough information to identify a real live one.
|
44
|
+
# @return [Array<MU::Cloud>]
|
45
|
+
def self.findStray(cloud, type,
|
46
|
+
dummy_ok: false,
|
47
|
+
no_deploy_search: false,
|
48
|
+
allow_multi: false,
|
49
|
+
deploy_id: nil,
|
50
|
+
name: nil,
|
51
|
+
mu_name: nil,
|
52
|
+
cloud_id: nil,
|
53
|
+
credentials: nil,
|
54
|
+
region: nil,
|
55
|
+
tag_key: nil,
|
56
|
+
tag_value: nil,
|
57
|
+
calling_deploy: MU.mommacat,
|
58
|
+
habitats: [],
|
59
|
+
**flags
|
60
|
+
)
|
61
|
+
_shortclass, _cfg_name, type, _classname, _attrs = MU::Cloud.getResourceNames(type, true)
|
62
|
+
|
63
|
+
cloudclass = MU::Cloud.cloudClass(cloud)
|
64
|
+
return nil if cloudclass.virtual?
|
65
|
+
|
66
|
+
if (tag_key and !tag_value) or (!tag_key and tag_value)
|
67
|
+
raise MuError, "Can't call findStray with only one of tag_key and tag_value set, must be both or neither"
|
68
|
+
end
|
69
|
+
|
70
|
+
credlist = credentials ? [credentials] : cloudclass.listCredentials
|
71
|
+
|
72
|
+
# Help ourselves by making more refined parameters out of mu_name, if
|
73
|
+
# they weren't passed explicitly
|
74
|
+
if mu_name
|
75
|
+
# We can extract a deploy_id from mu_name if we don't have one already
|
76
|
+
deploy_id ||= mu_name.sub(/^(\w+-\w+-\d{10}-[A-Z]{2})-/, '\1')
|
77
|
+
if !tag_key and !tag_value
|
78
|
+
tag_key = "Name"
|
79
|
+
tag_value = mu_name
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
# See if the thing we're looking for is a member of the deploy that's
|
84
|
+
# asking after it.
|
85
|
+
if !deploy_id.nil? and !calling_deploy.nil? and
|
86
|
+
calling_deploy.deploy_id == deploy_id and (!name.nil? or !mu_name.nil?)
|
87
|
+
kitten = calling_deploy.findLitterMate(type: type, name: name, mu_name: mu_name, cloud_id: cloud_id, credentials: credentials)
|
88
|
+
return [kitten] if !kitten.nil?
|
89
|
+
end
|
90
|
+
|
91
|
+
# See if we have it in deployment metadata generally
|
92
|
+
kittens = {}
|
93
|
+
if !no_deploy_search and (deploy_id or name or mu_name or cloud_id)
|
94
|
+
kittens = search_my_deploys(type, deploy_id: deploy_id, name: name, mu_name: mu_name, cloud_id: cloud_id, credentials: credentials)
|
95
|
+
return kittens.values if kittens.size == 1
|
96
|
+
|
97
|
+
# We can't refine any further by asking the cloud provider...
|
98
|
+
if kittens.size > 1 and !allow_multi and
|
99
|
+
!cloud_id and !tag_key and !tag_value
|
100
|
+
raise MultipleMatches, "Multiple matches in MU::MommaCat.findStray where none allowed from #{cloud}, #{type}, name: #{name}, mu_name: #{mu_name}, cloud_id: #{cloud_id}, credentials: #{credentials}, habitats: #{habitats} (#{caller(1..1)})"
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
if !cloud_id and !(tag_key and tag_value) and (name or mu_name or deploy_id)
|
105
|
+
return kittens.values
|
106
|
+
end
|
107
|
+
matches = []
|
108
|
+
|
109
|
+
credlist.each { |creds|
|
110
|
+
# next if region and region.is_a?(Array) and !region.empty? and !region.include?(r)
|
111
|
+
cloud_descs = search_cloud_provider(type, cloud, habitats, region, cloud_id: cloud_id, tag_key: tag_key, tag_value: tag_value, credentials: creds, flags: flags)
|
112
|
+
|
113
|
+
cloud_descs.each_pair.each { |p, regions|
|
114
|
+
regions.each_pair.each { |r, results|
|
115
|
+
results.each_pair { |kitten_cloud_id, descriptor|
|
116
|
+
# We already have a MU::Cloud object for this guy, use it
|
117
|
+
if kittens.has_key?(kitten_cloud_id)
|
118
|
+
matches << kittens[kitten_cloud_id]
|
119
|
+
elsif dummy_ok and kittens.empty?
|
120
|
+
# XXX this is why this was threaded
|
121
|
+
matches << generate_dummy_object(type, cloud, name, mu_name, kitten_cloud_id, descriptor, r, p, tag_value, calling_deploy, creds)
|
122
|
+
end
|
123
|
+
}
|
124
|
+
}
|
125
|
+
}
|
126
|
+
}
|
127
|
+
|
128
|
+
matches
|
129
|
+
end
|
130
|
+
|
131
|
+
@object_load_fails = false
|
132
|
+
|
133
|
+
# Return the resource object of another member of this deployment
|
134
|
+
# @param type [String,Symbol]: The type of resource
|
135
|
+
# @param name [String]: The name of the resource as defined in its 'name' Basket of Kittens field
|
136
|
+
# @param mu_name [String]: The fully-resolved and deployed name of the resource
|
137
|
+
# @param cloud_id [String]: The cloud provider's unique identifier for this resource
|
138
|
+
# @param created_only [Boolean]: Only return the littermate if its cloud_id method returns a value
|
139
|
+
# @param return_all [Boolean]: Return a Hash of matching objects indexed by their mu_name, instead of a single match. Only valid for resource types where has_multiples is true.
|
140
|
+
# @return [MU::Cloud]
|
141
|
+
def findLitterMate(type: nil, name: nil, mu_name: nil, cloud_id: nil, created_only: false, return_all: false, credentials: nil, habitat: nil, debug: false, **flags)
|
142
|
+
_shortclass, _cfg_name, type, _classname, attrs = MU::Cloud.getResourceNames(type)
|
143
|
+
|
144
|
+
# If we specified a habitat, which we may also have done by its shorthand
|
145
|
+
# sibling name, or a Ref. Convert to something we can use.
|
146
|
+
habitat = resolve_habitat(habitat, credentials: credentials)
|
147
|
+
|
148
|
+
nofilter = (mu_name.nil? and cloud_id.nil? and credentials.nil?)
|
149
|
+
|
150
|
+
does_match = Proc.new { |obj|
|
151
|
+
|
152
|
+
(!created_only or !obj.cloud_id.nil?) and (nofilter or (
|
153
|
+
(mu_name and obj.mu_name and mu_name.to_s == obj.mu_name) or
|
154
|
+
(cloud_id and obj.cloud_id and cloud_id.to_s == obj.cloud_id.to_s) or
|
155
|
+
(credentials and obj.credentials and credentials.to_s == obj.credentials.to_s) and
|
156
|
+
!(
|
157
|
+
(mu_name and obj.mu_name and mu_name.to_s != obj.mu_name) or
|
158
|
+
(cloud_id and obj.cloud_id and cloud_id.to_s != obj.cloud_id.to_s) or
|
159
|
+
(credentials and obj.credentials and credentials.to_s != obj.credentials.to_s)
|
160
|
+
)
|
161
|
+
))
|
162
|
+
}
|
163
|
+
|
164
|
+
@kitten_semaphore.synchronize {
|
165
|
+
|
166
|
+
if !@kittens.has_key?(type)
|
167
|
+
return nil if !@original_config or @original_config[type].nil? or @original_config[type].empty?
|
168
|
+
begin
|
169
|
+
loadObjects(false)
|
170
|
+
rescue ThreadError => e
|
171
|
+
if e.message !~ /deadlock/
|
172
|
+
raise e
|
173
|
+
end
|
174
|
+
end
|
175
|
+
if @object_load_fails or !@kittens[type]
|
176
|
+
MU.log "#{@deploy_id}'s original config has #{@original_config[type].size == 1 ? "a" : @original_config[type].size.to_s} #{type}, but loadObjects could not populate anything from deployment metadata", MU::ERR if !@object_load_fails
|
177
|
+
@object_load_fails = true
|
178
|
+
return nil
|
179
|
+
end
|
180
|
+
end
|
181
|
+
matches = {}
|
182
|
+
@kittens[type].each { |habitat_group, sib_classes|
|
183
|
+
next if habitat and habitat_group and habitat_group != habitat
|
184
|
+
sib_classes.each_pair { |sib_class, cloud_objs|
|
185
|
+
|
186
|
+
if attrs[:has_multiples]
|
187
|
+
next if !name.nil? and name != sib_class or cloud_objs.empty?
|
188
|
+
if !name.nil?
|
189
|
+
if return_all
|
190
|
+
matches.merge!(cloud_objs.clone)
|
191
|
+
next
|
192
|
+
elsif cloud_objs.size == 1 and does_match.call(cloud_objs.values.first)
|
193
|
+
return cloud_objs.values.first
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
197
|
+
cloud_objs.each_value { |obj|
|
198
|
+
if does_match.call(obj)
|
199
|
+
if return_all
|
200
|
+
matches.merge!(cloud_objs.clone)
|
201
|
+
else
|
202
|
+
return obj.clone
|
203
|
+
end
|
204
|
+
end
|
205
|
+
}
|
206
|
+
# has_multiples is false, "cloud_objs" is actually a singular object
|
207
|
+
elsif (name.nil? and does_match.call(cloud_objs)) or [sib_class, cloud_objs.virtual_name(name)].include?(name.to_s)
|
208
|
+
matches[cloud_objs.config['name']] = cloud_objs.clone
|
209
|
+
end
|
210
|
+
}
|
211
|
+
}
|
212
|
+
|
213
|
+
return matches if return_all and matches.size >= 1
|
214
|
+
|
215
|
+
return matches.values.first if matches.size == 1
|
216
|
+
|
217
|
+
}
|
218
|
+
|
219
|
+
return nil
|
220
|
+
end
|
221
|
+
|
222
|
+
|
223
|
+
private
|
224
|
+
|
225
|
+
def resolve_habitat(habitat, credentials: nil, debug: false)
|
226
|
+
return nil if habitat.nil?
|
227
|
+
if habitat.is_a?(MU::Config::Ref) and habitat.id
|
228
|
+
return habitat.id
|
229
|
+
else
|
230
|
+
realhabitat = findLitterMate(type: "habitat", name: habitat, credentials: credentials)
|
231
|
+
if realhabitat and realhabitat.mu_name
|
232
|
+
return realhabitat.cloud_id
|
233
|
+
elsif debug
|
234
|
+
MU.log "Failed to resolve habitat name #{habitat}", MU::WARN
|
235
|
+
end
|
236
|
+
end
|
237
|
+
end
|
238
|
+
|
239
|
+
def self.generate_dummy_object(type, cloud, name, mu_name, cloud_id, desc, region, habitat, tag_value, calling_deploy, credentials)
|
240
|
+
resourceclass = MU::Cloud.resourceClass(cloud, type)
|
241
|
+
|
242
|
+
use_name = if (name.nil? or name.empty?)
|
243
|
+
if !mu_name.nil?
|
244
|
+
mu_name
|
245
|
+
else
|
246
|
+
guessName(desc, resourceclass, cloud_id: cloud_id, tag_value: tag_value)
|
247
|
+
end
|
248
|
+
else
|
249
|
+
name
|
250
|
+
end
|
251
|
+
|
252
|
+
if use_name.nil?
|
253
|
+
return
|
254
|
+
end
|
255
|
+
|
256
|
+
cfg = {
|
257
|
+
"name" => use_name,
|
258
|
+
"cloud" => cloud,
|
259
|
+
"credentials" => credentials
|
260
|
+
}
|
261
|
+
if !region.nil? and !resourceclass.isGlobal?
|
262
|
+
cfg["region"] = region
|
263
|
+
end
|
264
|
+
|
265
|
+
if resourceclass.canLiveIn.include?(:Habitat) and habitat
|
266
|
+
cfg["project"] = habitat
|
267
|
+
end
|
268
|
+
|
269
|
+
# If we can at least find the config from the deploy this will
|
270
|
+
# belong with, use that, even if it's an ungroomed resource.
|
271
|
+
if !calling_deploy.nil? and
|
272
|
+
!calling_deploy.original_config.nil? and
|
273
|
+
!calling_deploy.original_config[type+"s"].nil?
|
274
|
+
calling_deploy.original_config[type+"s"].each { |s|
|
275
|
+
if s["name"] == use_name
|
276
|
+
cfg = s.dup
|
277
|
+
break
|
278
|
+
end
|
279
|
+
}
|
280
|
+
|
281
|
+
return resourceclass.new(mommacat: calling_deploy, kitten_cfg: cfg, cloud_id: cloud_id)
|
282
|
+
else
|
283
|
+
if !@@dummy_cache[type] or !@@dummy_cache[type][cfg.to_s]
|
284
|
+
newobj = resourceclass.new(mu_name: use_name, kitten_cfg: cfg, cloud_id: cloud_id, from_cloud_desc: desc)
|
285
|
+
@@desc_semaphore.synchronize {
|
286
|
+
@@dummy_cache[type] ||= {}
|
287
|
+
@@dummy_cache[type][cfg.to_s] = newobj
|
288
|
+
}
|
289
|
+
end
|
290
|
+
return @@dummy_cache[type][cfg.to_s]
|
291
|
+
end
|
292
|
+
end
|
293
|
+
private_class_method :generate_dummy_object
|
294
|
+
|
295
|
+
def self.search_cloud_provider(type, cloud, habitats, region, cloud_id: nil, tag_key: nil, tag_value: nil, credentials: nil, flags: nil)
|
296
|
+
cloudclass = MU::Cloud.cloudClass(cloud)
|
297
|
+
resourceclass = MU::Cloud.resourceClass(cloud, type)
|
298
|
+
|
299
|
+
# Decide what regions we'll search, if applicable for this resource
|
300
|
+
# type.
|
301
|
+
regions = if resourceclass.isGlobal?
|
302
|
+
[nil]
|
303
|
+
else
|
304
|
+
if region
|
305
|
+
if region.is_a?(Array) and !region.empty?
|
306
|
+
region
|
307
|
+
else
|
308
|
+
[region]
|
309
|
+
end
|
310
|
+
else
|
311
|
+
cloudclass.listRegions(credentials: credentials)
|
312
|
+
end
|
313
|
+
end
|
314
|
+
|
315
|
+
# Decide what habitats (accounts/projects/subscriptions) we'll
|
316
|
+
# search, if applicable for this resource type.
|
317
|
+
habitats ||= []
|
318
|
+
if habitats.empty?
|
319
|
+
if resourceclass.canLiveIn.include?(nil)
|
320
|
+
habitats << nil
|
321
|
+
end
|
322
|
+
if resourceclass.canLiveIn.include?(:Habitat)
|
323
|
+
habitats.concat(cloudclass.listHabitats(credentials, use_cache: false))
|
324
|
+
end
|
325
|
+
end
|
326
|
+
habitats << nil if habitats.empty?
|
327
|
+
habitats.uniq!
|
328
|
+
|
329
|
+
cloud_descs = {}
|
330
|
+
|
331
|
+
thread_waiter = Proc.new { |threads, threshold|
|
332
|
+
begin
|
333
|
+
threads.each { |t| t.join(0.1) }
|
334
|
+
threads.reject! { |t| t.nil? or !t.alive? or !t.status }
|
335
|
+
sleep 1 if threads.size > threshold
|
336
|
+
end while threads.size > threshold
|
337
|
+
}
|
338
|
+
|
339
|
+
habitat_threads = []
|
340
|
+
found_the_thing = false
|
341
|
+
habitats.each { |hab|
|
342
|
+
break if found_the_thing
|
343
|
+
thread_waiter.call(habitat_threads, 5)
|
344
|
+
|
345
|
+
habitat_threads << Thread.new(hab) { |habitat|
|
346
|
+
cloud_descs[habitat] = {}
|
347
|
+
region_threads = []
|
348
|
+
regions.each { |reg|
|
349
|
+
break if found_the_thing
|
350
|
+
region_threads << Thread.new(reg) { |r|
|
351
|
+
found = resourceclass.find(cloud_id: cloud_id, region: r, tag_key: tag_key, tag_value: tag_value, credentials: credentials, habitat: habitat, flags: flags)
|
352
|
+
|
353
|
+
if found
|
354
|
+
@@desc_semaphore.synchronize {
|
355
|
+
cloud_descs[habitat][r] = found
|
356
|
+
}
|
357
|
+
end
|
358
|
+
# Stop if you found the thing by a specific cloud_id
|
359
|
+
if cloud_id and found and !found.empty?
|
360
|
+
found_the_thing = true
|
361
|
+
end
|
362
|
+
}
|
363
|
+
}
|
364
|
+
thread_waiter.call(region_threads, 0)
|
365
|
+
}
|
366
|
+
}
|
367
|
+
thread_waiter.call(habitat_threads, 0)
|
368
|
+
|
369
|
+
cloud_descs
|
370
|
+
end
|
371
|
+
private_class_method :search_cloud_provider
|
372
|
+
|
373
|
+
def self.search_my_deploys(type, deploy_id: nil, name: nil, mu_name: nil, cloud_id: nil, credentials: nil)
|
374
|
+
kittens = {}
|
375
|
+
_shortclass, _cfg_name, type, _classname, attrs = MU::Cloud.getResourceNames(type, true)
|
376
|
+
|
377
|
+
# Check our in-memory cache of live deploys before resorting to
|
378
|
+
# metadata
|
379
|
+
littercache = nil
|
380
|
+
# Sometimes we're called inside a locked thread, sometimes not. Deal
|
381
|
+
# with locking gracefully.
|
382
|
+
begin
|
383
|
+
@@litter_semaphore.synchronize {
|
384
|
+
littercache = @@litters.dup
|
385
|
+
}
|
386
|
+
rescue ThreadError => e
|
387
|
+
raise e if !e.message.match(/recursive locking/)
|
388
|
+
littercache = @@litters.dup
|
389
|
+
end
|
390
|
+
|
391
|
+
# First, see what we have in deploys that already happen to be loaded in
|
392
|
+
# memory.
|
393
|
+
littercache.each_pair { |cur_deploy, momma|
|
394
|
+
next if deploy_id and deploy_id != cur_deploy
|
395
|
+
|
396
|
+
@@deploy_struct_semaphore.synchronize {
|
397
|
+
@deploy_cache[deploy_id] = {
|
398
|
+
"mtime" => Time.now,
|
399
|
+
"data" => momma.deployment
|
400
|
+
}
|
401
|
+
}
|
402
|
+
|
403
|
+
straykitten = momma.findLitterMate(type: type, cloud_id: cloud_id, name: name, mu_name: mu_name, credentials: credentials, created_only: true)
|
404
|
+
if straykitten
|
405
|
+
MU.log "Found matching kitten #{straykitten.mu_name} in-memory - #{sprintf("%.2fs", (Time.now-start))}", MU::DEBUG
|
406
|
+
# Peace out if we found the exact resource we want
|
407
|
+
if cloud_id and straykitten.cloud_id.to_s == cloud_id.to_s
|
408
|
+
return { straykitten.cloud_id => straykitten }
|
409
|
+
elsif mu_name and straykitten.mu_name == mu_name
|
410
|
+
return { straykitten.cloud_id => straykitten }
|
411
|
+
else
|
412
|
+
kittens[straykitten.cloud_id] ||= straykitten
|
413
|
+
end
|
414
|
+
end
|
415
|
+
}
|
416
|
+
|
417
|
+
# Now go rifle metadata from any other deploys we have on disk, if they
|
418
|
+
# weren't already there in memory.
|
419
|
+
cacheDeployMetadata(deploy_id) # freshen up @@deploy_cache
|
420
|
+
mu_descs = {}
|
421
|
+
if deploy_id.nil?
|
422
|
+
@@deploy_cache.each_key { |deploy|
|
423
|
+
next if littercache[deploy]
|
424
|
+
next if !@@deploy_cache[deploy].has_key?('data')
|
425
|
+
next if !@@deploy_cache[deploy]['data'].has_key?(type)
|
426
|
+
if !name.nil?
|
427
|
+
next if @@deploy_cache[deploy]['data'][type][name].nil?
|
428
|
+
mu_descs[deploy] ||= []
|
429
|
+
mu_descs[deploy] << @@deploy_cache[deploy]['data'][type][name].dup
|
430
|
+
else
|
431
|
+
mu_descs[deploy] ||= []
|
432
|
+
mu_descs[deploy].concat(@@deploy_cache[deploy]['data'][type].values)
|
433
|
+
end
|
434
|
+
}
|
435
|
+
elsif !@@deploy_cache[deploy_id].nil?
|
436
|
+
if !@@deploy_cache[deploy_id]['data'].nil? and
|
437
|
+
!@@deploy_cache[deploy_id]['data'][type].nil?
|
438
|
+
if !name.nil? and !@@deploy_cache[deploy_id]['data'][type][name].nil?
|
439
|
+
mu_descs[deploy_id] ||= []
|
440
|
+
mu_descs[deploy_id] << @@deploy_cache[deploy_id]['data'][type][name].dup
|
441
|
+
else
|
442
|
+
mu_descs[deploy_id] = @@deploy_cache[deploy_id]['data'][type].values
|
443
|
+
end
|
444
|
+
end
|
445
|
+
end
|
446
|
+
|
447
|
+
mu_descs.each_pair { |deploy, matches|
|
448
|
+
next if matches.nil? or matches.size == 0
|
449
|
+
momma = MU::MommaCat.getLitter(deploy)
|
450
|
+
|
451
|
+
# If we found exactly one match in this deploy, use its metadata to
|
452
|
+
# guess at resource names we weren't told.
|
453
|
+
straykitten = if matches.size > 1 and cloud_id
|
454
|
+
momma.findLitterMate(type: type, cloud_id: cloud_id, credentials: credentials, created_only: true)
|
455
|
+
elsif matches.size == 1 and (!attrs[:has_multiples] or matches.first.size == 1) and name.nil? and mu_name.nil?
|
456
|
+
actual_data = attrs[:has_multiples] ? matches.first.values.first : matches.first
|
457
|
+
if cloud_id.nil?
|
458
|
+
momma.findLitterMate(type: type, name: (actual_data["name"] || actual_data["MU_NODE_CLASS"]), cloud_id: actual_data["cloud_id"], credentials: credentials)
|
459
|
+
else
|
460
|
+
momma.findLitterMate(type: type, name: (actual_data["name"] || actual_data["MU_NODE_CLASS"]), cloud_id: cloud_id, credentials: credentials)
|
461
|
+
end
|
462
|
+
else
|
463
|
+
# There's more than one of this type of resource in the target
|
464
|
+
# deploy, so see if findLitterMate can narrow it down for us
|
465
|
+
momma.findLitterMate(type: type, name: name, mu_name: mu_name, cloud_id: cloud_id, credentials: credentials)
|
466
|
+
end
|
467
|
+
|
468
|
+
next if straykitten.nil?
|
469
|
+
straykitten.intoDeploy(momma)
|
470
|
+
|
471
|
+
if straykitten.cloud_id.nil?
|
472
|
+
MU.log "findStray: kitten #{straykitten.mu_name} came back with nil cloud_id", MU::WARN
|
473
|
+
next
|
474
|
+
end
|
475
|
+
next if cloud_id and straykitten.cloud_id.to_s != cloud_id.to_s
|
476
|
+
|
477
|
+
# Peace out if we found the exact resource we want
|
478
|
+
if (cloud_id and straykitten.cloud_id.to_s == cloud_id.to_s) or
|
479
|
+
(mu_descs.size == 1 and matches.size == 1) or
|
480
|
+
(credentials and straykitten.credentials == credentials)
|
481
|
+
# XXX strictly speaking this last check is only valid if findStray is searching
|
482
|
+
# exactly one set of credentials
|
483
|
+
|
484
|
+
return { straykitten.cloud_id => straykitten }
|
485
|
+
end
|
486
|
+
|
487
|
+
kittens[straykitten.cloud_id] ||= straykitten
|
488
|
+
}
|
489
|
+
|
490
|
+
kittens
|
491
|
+
end
|
492
|
+
private_class_method :search_my_deploys
|
493
|
+
|
494
|
+
end #class
|
495
|
+
end #module
|