cloud-mu 3.1.3 → 3.3.0
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 +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 +21 -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 +4 -4
- data/bin/mu-node-manage +15 -16
- data/bin/mu-run-tests +147 -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 +158 -111
- data/modules/mu/adoption.rb +404 -71
- data/modules/mu/cleanup.rb +221 -306
- data/modules/mu/cloud.rb +129 -1633
- 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 +171 -1767
- 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 +4 -4
- data/modules/mu/config/container_cluster.rb +9 -4
- data/modules/mu/config/database.rb +84 -105
- data/modules/mu/config/database.yml +1 -2
- data/modules/mu/config/dnszone.rb +10 -9
- data/modules/mu/config/doc_helpers.rb +516 -0
- data/modules/mu/config/endpoint.rb +5 -4
- data/modules/mu/config/firewall_rule.rb +103 -4
- data/modules/mu/config/folder.rb +4 -4
- data/modules/mu/config/function.rb +19 -10
- data/modules/mu/config/group.rb +4 -4
- data/modules/mu/config/habitat.rb +4 -4
- data/modules/mu/config/job.rb +89 -0
- 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 +10 -21
- data/modules/mu/config/ref.rb +411 -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 +98 -71
- 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 +71 -27
- 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 +3 -2
- data/modules/mu/deploy.rb +43 -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 +410 -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 +218 -2612
- data/modules/mu/mommacat/daemon.rb +403 -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 +380 -122
- data/modules/mu/{clouds → providers}/aws/alarm.rb +7 -5
- data/modules/mu/{clouds → providers}/aws/bucket.rb +297 -59
- data/modules/mu/{clouds → providers}/aws/cache_cluster.rb +37 -71
- data/modules/mu/providers/aws/cdn.rb +782 -0
- data/modules/mu/{clouds → providers}/aws/collection.rb +26 -25
- data/modules/mu/{clouds → providers}/aws/container_cluster.rb +724 -744
- data/modules/mu/providers/aws/database.rb +1744 -0
- data/modules/mu/{clouds → providers}/aws/dnszone.rb +88 -70
- data/modules/mu/providers/aws/endpoint.rb +1072 -0
- data/modules/mu/{clouds → providers}/aws/firewall_rule.rb +220 -247
- data/modules/mu/{clouds → providers}/aws/folder.rb +8 -8
- data/modules/mu/{clouds → providers}/aws/function.rb +300 -142
- data/modules/mu/{clouds → providers}/aws/group.rb +31 -29
- data/modules/mu/{clouds → providers}/aws/habitat.rb +18 -15
- data/modules/mu/providers/aws/job.rb +466 -0
- data/modules/mu/{clouds → providers}/aws/loadbalancer.rb +66 -56
- data/modules/mu/{clouds → providers}/aws/log.rb +17 -14
- data/modules/mu/{clouds → providers}/aws/msg_queue.rb +29 -19
- data/modules/mu/{clouds → providers}/aws/nosqldb.rb +114 -16
- data/modules/mu/{clouds → providers}/aws/notifier.rb +142 -65
- data/modules/mu/{clouds → providers}/aws/role.rb +158 -118
- data/modules/mu/{clouds → providers}/aws/search_domain.rb +201 -59
- data/modules/mu/{clouds → providers}/aws/server.rb +844 -1139
- data/modules/mu/{clouds → providers}/aws/server_pool.rb +74 -65
- data/modules/mu/{clouds → providers}/aws/storage_pool.rb +26 -44
- data/modules/mu/{clouds → providers}/aws/user.rb +24 -25
- 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 +525 -931
- 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 +97 -49
- 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 +68 -30
- data/modules/mu/{clouds → providers}/google/bucket.rb +13 -15
- data/modules/mu/{clouds → providers}/google/container_cluster.rb +85 -78
- data/modules/mu/{clouds → providers}/google/database.rb +11 -21
- 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 +140 -168
- 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 +19 -21
- data/modules/mu/{clouds → providers}/google/role.rb +94 -58
- data/modules/mu/{clouds → providers}/google/server.rb +243 -156
- data/modules/mu/{clouds → providers}/google/server_pool.rb +26 -45
- 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/aws-jobs-functions.yaml +46 -0
- data/modules/tests/bucket.yml +4 -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/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 +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 +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 +240 -154
- data/extras/image-generators/AWS/windows.yaml +0 -18
- data/modules/mu/clouds/aws/database.rb +0 -1985
- data/modules/mu/clouds/aws/endpoint.rb +0 -592
data/modules/mu/config/log.rb
CHANGED
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
|
|
15
15
|
module MU
|
|
16
16
|
class Config
|
|
17
|
-
# Basket of Kittens config schema and parser logic. See modules/mu/
|
|
17
|
+
# Basket of Kittens config schema and parser logic. See modules/mu/providers/*/log.rb
|
|
18
18
|
class Log
|
|
19
19
|
|
|
20
20
|
# Base configuration schema for a Log
|
|
@@ -36,10 +36,10 @@ module MU
|
|
|
36
36
|
end
|
|
37
37
|
|
|
38
38
|
# Generic pre-processing of {MU::Config::BasketofKittens::logs}, bare and unvalidated.
|
|
39
|
-
# @param
|
|
40
|
-
# @param
|
|
39
|
+
# @param _log [Hash]: The resource to process and validate
|
|
40
|
+
# @param _configurator [MU::Config]: The overall deployment configurator of which this resource is a member
|
|
41
41
|
# @return [Boolean]: True if validation succeeded, False otherwise
|
|
42
|
-
def self.validate(
|
|
42
|
+
def self.validate(_log, _configurator)
|
|
43
43
|
ok = true
|
|
44
44
|
ok
|
|
45
45
|
end
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
|
|
15
15
|
module MU
|
|
16
16
|
class Config
|
|
17
|
-
# Basket of Kittens config schema and parser logic. See modules/mu/
|
|
17
|
+
# Basket of Kittens config schema and parser logic. See modules/mu/providers/*/msg_queue.rb
|
|
18
18
|
class MsgQueue
|
|
19
19
|
|
|
20
20
|
# Base configuration schema for a MsgQueue
|
|
@@ -34,10 +34,10 @@ module MU
|
|
|
34
34
|
end
|
|
35
35
|
|
|
36
36
|
# Generic pre-processing of {MU::Config::BasketofKittens::msg_queues}, bare and unvalidated.
|
|
37
|
-
# @param
|
|
38
|
-
# @param
|
|
37
|
+
# @param _queue [Hash]: The resource to process and validate
|
|
38
|
+
# @param _configurator [MU::Config]: The overall deployment configurator of which this resource is a member
|
|
39
39
|
# @return [Boolean]: True if validation succeeded, False otherwise
|
|
40
|
-
def self.validate(
|
|
40
|
+
def self.validate(_queue, _configurator)
|
|
41
41
|
ok = true
|
|
42
42
|
ok
|
|
43
43
|
end
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
|
|
15
15
|
module MU
|
|
16
16
|
class Config
|
|
17
|
-
# Basket of Kittens config schema and parser logic. See modules/mu/
|
|
17
|
+
# Basket of Kittens config schema and parser logic. See modules/mu/providers/*/nosqldb.rb
|
|
18
18
|
class NoSQLDB
|
|
19
19
|
|
|
20
20
|
# Base configuration schema for a Bucket
|
|
@@ -35,10 +35,10 @@ module MU
|
|
|
35
35
|
end
|
|
36
36
|
|
|
37
37
|
# Generic pre-processing of {MU::Config::BasketofKittens::nosqldbs}, bare and unvalidated.
|
|
38
|
-
# @param
|
|
39
|
-
# @param
|
|
38
|
+
# @param _db [Hash]: The resource to process and validate
|
|
39
|
+
# @param _configurator [MU::Config]: The overall deployment configurator of which this resource is a member
|
|
40
40
|
# @return [Boolean]: True if validation succeeded, False otherwise
|
|
41
|
-
def self.validate(
|
|
41
|
+
def self.validate(_db, _configurator)
|
|
42
42
|
ok = true
|
|
43
43
|
|
|
44
44
|
ok
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
|
|
15
15
|
module MU
|
|
16
16
|
class Config
|
|
17
|
-
# Basket of Kittens config schema and parser logic. See modules/mu/
|
|
17
|
+
# Basket of Kittens config schema and parser logic. See modules/mu/providers/*/notifier.rb
|
|
18
18
|
class Notifier
|
|
19
19
|
|
|
20
20
|
# Base configuration schema for a Notifier
|
|
@@ -36,12 +36,12 @@ module MU
|
|
|
36
36
|
"items" => {
|
|
37
37
|
"type" => "object",
|
|
38
38
|
"description" => "A list of people or resources which should receive notifications",
|
|
39
|
-
"required" => ["endpoint"],
|
|
40
39
|
"properties" => {
|
|
41
40
|
"endpoint" => {
|
|
42
41
|
"type" => "string",
|
|
43
|
-
"description" => "
|
|
44
|
-
}
|
|
42
|
+
"description" => "Shorthand for an endpoint which should be subscribed to this notifier, typically an email address or SMS-enabled phone number. For complex cases, such as referencing an AWS Lambda function defined elsewhere in your Mu stack, use +resource+ instead."
|
|
43
|
+
},
|
|
44
|
+
"resource" => MU::Config::Ref.schema(desc: "A cloud resource that is a valid notification target for this notifier. For simple use cases, such as external email addresses or SMS, use +endpoint+ instead.")
|
|
45
45
|
}
|
|
46
46
|
}
|
|
47
47
|
}
|
|
@@ -51,28 +51,17 @@ module MU
|
|
|
51
51
|
|
|
52
52
|
# Generic pre-processing of {MU::Config::BasketofKittens::notifiers}, bare and unvalidated.
|
|
53
53
|
# @param notifier [Hash]: The resource to process and validate
|
|
54
|
-
# @param
|
|
54
|
+
# @param _configurator [MU::Config]: The overall deployment configurator of which this resource is a member
|
|
55
55
|
# @return [Boolean]: True if validation succeeded, False otherwise
|
|
56
|
-
def self.validate(notifier,
|
|
56
|
+
def self.validate(notifier, _configurator)
|
|
57
57
|
ok = true
|
|
58
58
|
|
|
59
|
+
|
|
59
60
|
if notifier['subscriptions']
|
|
60
61
|
notifier['subscriptions'].each { |sub|
|
|
61
|
-
if !sub[
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
elsif sub["endpoint"].match(/^https:/i)
|
|
65
|
-
sub["type"] = "https"
|
|
66
|
-
elsif sub["endpoint"].match(/^sqs:/i)
|
|
67
|
-
sub["type"] = "sqs"
|
|
68
|
-
elsif sub["endpoint"].match(/^\+?[\d\-]+$/)
|
|
69
|
-
sub["type"] = "sms"
|
|
70
|
-
elsif sub["endpoint"].match(/\A[\w+\-.]+@[a-z\d\-]+(\.[a-z]+)*\.[a-z]+\z/i)
|
|
71
|
-
sub["type"] = "email"
|
|
72
|
-
else
|
|
73
|
-
MU.log "Notifier #{notifier['name']} subscription #{sub['endpoint']} did not specify a type, and I'm unable to guess one", MU::ERR
|
|
74
|
-
ok = false
|
|
75
|
-
end
|
|
62
|
+
if !sub['endpoint'] and !sub['resource']
|
|
63
|
+
MU.log "Notifier '#{notifier['name']}' must specify either resource or endpoint in subscription", MU::ERR, details: sub
|
|
64
|
+
ok = false
|
|
76
65
|
end
|
|
77
66
|
}
|
|
78
67
|
end
|
|
@@ -0,0 +1,411 @@
|
|
|
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
|
+
# Methods and structures for parsing Mu's configuration files. See also {MU::Config::BasketofKittens}.
|
|
18
|
+
class Config
|
|
19
|
+
|
|
20
|
+
# A wrapper class for resources to refer to other resources, whether they
|
|
21
|
+
# be a sibling object in the current deploy, an object in another deploy,
|
|
22
|
+
# or a plain cloud id from outside of Mu.
|
|
23
|
+
class Ref
|
|
24
|
+
attr_reader :name
|
|
25
|
+
attr_reader :type
|
|
26
|
+
attr_reader :cloud
|
|
27
|
+
attr_reader :deploy_id
|
|
28
|
+
attr_reader :region
|
|
29
|
+
attr_reader :credentials
|
|
30
|
+
attr_reader :habitat
|
|
31
|
+
attr_reader :mommacat
|
|
32
|
+
attr_reader :tag_key
|
|
33
|
+
attr_reader :tag_value
|
|
34
|
+
attr_reader :obj
|
|
35
|
+
|
|
36
|
+
@@refs = []
|
|
37
|
+
@@ref_semaphore = Mutex.new
|
|
38
|
+
|
|
39
|
+
# Little bit of a factory pattern... given a hash of options for a {MU::Config::Ref} objects, first see if we have an existing one that matches our more immutable attributes (+cloud+, +id+, etc). If we do, return that. If we do not, create one, add that to our inventory, and return that instead.
|
|
40
|
+
# @param cfg [Hash]:
|
|
41
|
+
# @return [MU::Config::Ref]
|
|
42
|
+
def self.get(cfg)
|
|
43
|
+
return cfg if cfg.is_a?(MU::Config::Ref)
|
|
44
|
+
checkfields = cfg.keys.map { |k| k.to_sym }
|
|
45
|
+
required = [:id, :type]
|
|
46
|
+
|
|
47
|
+
@@ref_semaphore.synchronize {
|
|
48
|
+
@@refs.each { |ref|
|
|
49
|
+
saw_mismatch = false
|
|
50
|
+
saw_match = false
|
|
51
|
+
needed_values = []
|
|
52
|
+
checkfields.each { |field|
|
|
53
|
+
next if !cfg[field]
|
|
54
|
+
ext_value = ref.instance_variable_get("@#{field.to_s}".to_sym)
|
|
55
|
+
if !ext_value
|
|
56
|
+
needed_values << field
|
|
57
|
+
next
|
|
58
|
+
end
|
|
59
|
+
if cfg[field] != ext_value
|
|
60
|
+
saw_mismatch = true
|
|
61
|
+
elsif required.include?(field) and cfg[field] == ext_value
|
|
62
|
+
saw_match = true
|
|
63
|
+
end
|
|
64
|
+
}
|
|
65
|
+
if saw_match and !saw_mismatch
|
|
66
|
+
# populate empty fields we got from this request
|
|
67
|
+
if needed_values.size > 0
|
|
68
|
+
newref = ref.dup
|
|
69
|
+
needed_values.each { |field|
|
|
70
|
+
newref.instance_variable_set("@#{field.to_s}".to_sym, cfg[field])
|
|
71
|
+
if !newref.respond_to?(field)
|
|
72
|
+
newref.singleton_class.instance_eval { attr_reader field.to_sym }
|
|
73
|
+
end
|
|
74
|
+
}
|
|
75
|
+
@@refs << newref
|
|
76
|
+
return newref
|
|
77
|
+
else
|
|
78
|
+
return ref
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
# if we get here, there was no match
|
|
86
|
+
newref = MU::Config::Ref.new(cfg)
|
|
87
|
+
@@ref_semaphore.synchronize {
|
|
88
|
+
@@refs << newref
|
|
89
|
+
return newref
|
|
90
|
+
}
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
# A way of dynamically defining +attr_reader+ without leaking memory
|
|
94
|
+
def self.define_reader(name)
|
|
95
|
+
define_method(name) {
|
|
96
|
+
instance_variable_get("@#{name.to_s}")
|
|
97
|
+
}
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
# @param cfg [Hash]: A Basket of Kittens configuration hash containing
|
|
101
|
+
# lookup information for a cloud object
|
|
102
|
+
def initialize(cfg)
|
|
103
|
+
cfg.keys.each { |field|
|
|
104
|
+
next if field == "tag"
|
|
105
|
+
if !cfg[field].nil?
|
|
106
|
+
self.instance_variable_set("@#{field}".to_sym, cfg[field])
|
|
107
|
+
elsif !cfg[field.to_sym].nil?
|
|
108
|
+
self.instance_variable_set("@#{field.to_s}".to_sym, cfg[field.to_sym])
|
|
109
|
+
end
|
|
110
|
+
MU::Config::Ref.define_reader(field)
|
|
111
|
+
}
|
|
112
|
+
if cfg['tag'] and cfg['tag']['key'] and
|
|
113
|
+
!cfg['tag']['key'].empty? and cfg['tag']['value']
|
|
114
|
+
@tag_key = cfg['tag']['key']
|
|
115
|
+
@tag_value = cfg['tag']['value']
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
if @deploy_id and !@mommacat
|
|
119
|
+
@mommacat = MU::MommaCat.getLitter(@deploy_id, set_context_to_me: false)
|
|
120
|
+
elsif @mommacat and !@deploy_id
|
|
121
|
+
@deploy_id = @mommacat.deploy_id
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
# canonicalize the 'type' argument
|
|
125
|
+
_shortclass, _cfg_name, cfg_plural, _classname, _attrs = MU::Cloud.getResourceNames(@type, false)
|
|
126
|
+
@type = cfg_plural if cfg_plural
|
|
127
|
+
|
|
128
|
+
kitten(shallow: true) if @mommacat # try to populate the actual cloud object for this
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
# Comparison operator
|
|
132
|
+
def <=>(other)
|
|
133
|
+
return 1 if other.nil?
|
|
134
|
+
self.to_s <=> other.to_s
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
# Lets callers access us like a {Hash}
|
|
138
|
+
# @param attribute [String,Symbol]
|
|
139
|
+
def [](attribute)
|
|
140
|
+
if respond_to?(attribute.to_sym)
|
|
141
|
+
send(attribute.to_sym)
|
|
142
|
+
else
|
|
143
|
+
nil
|
|
144
|
+
end
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
# Lets callers set attributes like a {Hash}
|
|
148
|
+
# @param attribute [String,Symbol]
|
|
149
|
+
def []=(attribute, value)
|
|
150
|
+
instance_variable_set("@#{attribute.to_s}".to_sym, value)
|
|
151
|
+
self.class.define_reader(attribute)
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
# Unset an attribute. Sort of. We can't actually do that, so nil it out
|
|
155
|
+
# and we get the behavior we want.
|
|
156
|
+
def delete(attribute)
|
|
157
|
+
attribute = ("@"+attribute).to_sym if attribute.to_s !~ /^@/
|
|
158
|
+
instance_variable_set(attribute.to_sym, nil)
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
# Base configuration schema for declared kittens referencing other cloud objects. This is essentially a set of filters that we're going to pass to {MU::MommaCat.findStray}.
|
|
162
|
+
# @param aliases [Array<Hash>]: Key => value mappings to set backwards-compatibility aliases for attributes, such as the ubiquitous +vpc_id+ (+vpc_id+ => +id+).
|
|
163
|
+
# @return [Hash]
|
|
164
|
+
def self.schema(aliases = [], type: nil, parent_obj: nil, desc: nil, omit_fields: [], any_type: false)
|
|
165
|
+
parent_obj ||= caller[1].gsub(/.*?\/([^\.\/]+)\.rb:.*/, '\1')
|
|
166
|
+
desc ||= "Reference a #{type ? "'#{type}' resource" : "resource" } from this #{parent_obj ? "'#{parent_obj}'" : "" } resource"
|
|
167
|
+
schema = {
|
|
168
|
+
"type" => "object",
|
|
169
|
+
"#MU_REFERENCE" => true,
|
|
170
|
+
"minProperties" => 1,
|
|
171
|
+
"description" => desc,
|
|
172
|
+
"properties" => {
|
|
173
|
+
"id" => {
|
|
174
|
+
"type" => "string",
|
|
175
|
+
"description" => "Cloud identifier of a resource we want to reference, typically used when leveraging resources not managed by MU"
|
|
176
|
+
},
|
|
177
|
+
"name" => {
|
|
178
|
+
"type" => "string",
|
|
179
|
+
"description" => "The short (internal Mu) name of a resource we're attempting to reference. Typically used when referring to a sibling resource elsewhere in the same deploy, or in another known Mu deploy in conjunction with +deploy_id+."
|
|
180
|
+
},
|
|
181
|
+
"type" => {
|
|
182
|
+
"type" => "string",
|
|
183
|
+
"description" => "The resource type we're attempting to reference.",
|
|
184
|
+
"enum" => MU::Cloud.resource_types.values.map { |t| t[:cfg_plural] }
|
|
185
|
+
},
|
|
186
|
+
"deploy_id" => {
|
|
187
|
+
"type" => "string",
|
|
188
|
+
"description" => "Our target resource should be found in this Mu deploy."
|
|
189
|
+
},
|
|
190
|
+
"credentials" => MU::Config.credentials_primitive,
|
|
191
|
+
"region" => MU::Config.region_primitive,
|
|
192
|
+
"cloud" => MU::Config.cloud_primitive,
|
|
193
|
+
"tag" => {
|
|
194
|
+
"type" => "object",
|
|
195
|
+
"description" => "If the target resource supports tagging and our resource implementations +find+ method supports it, we can attempt to locate it by tag.",
|
|
196
|
+
"properties" => {
|
|
197
|
+
"key" => {
|
|
198
|
+
"type" => "string",
|
|
199
|
+
"description" => "The tag or label key to search against"
|
|
200
|
+
},
|
|
201
|
+
"value" => {
|
|
202
|
+
"type" => "string",
|
|
203
|
+
"description" => "The tag or label value to match"
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
if !["folders", "habitats"].include?(type)
|
|
210
|
+
schema["properties"]["habitat"] = MU::Config::Habitat.reference
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
if omit_fields
|
|
214
|
+
omit_fields.each { |f|
|
|
215
|
+
schema["properties"].delete(f)
|
|
216
|
+
}
|
|
217
|
+
end
|
|
218
|
+
|
|
219
|
+
if any_type
|
|
220
|
+
schema["properties"]["type"].delete("enum")
|
|
221
|
+
elsif !type.nil?
|
|
222
|
+
schema["required"] = ["type"]
|
|
223
|
+
schema["properties"]["type"]["default"] = type
|
|
224
|
+
schema["properties"]["type"]["enum"] = [type]
|
|
225
|
+
end
|
|
226
|
+
|
|
227
|
+
aliases.each { |a|
|
|
228
|
+
a.each_pair { |k, v|
|
|
229
|
+
if schema["properties"][v]
|
|
230
|
+
schema["properties"][k] = schema["properties"][v].dup
|
|
231
|
+
schema["properties"][k]["description"] = "Alias for <tt>#{v}</tt>"
|
|
232
|
+
else
|
|
233
|
+
MU.log "Reference schema alias #{k} wants to alias #{v}, but no such attribute exists", MU::WARN, details: caller[4]
|
|
234
|
+
end
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
schema
|
|
239
|
+
end
|
|
240
|
+
|
|
241
|
+
# Is our +@type+ attribute a Mu-supported type, or some rando string?
|
|
242
|
+
# @return [Boolean]
|
|
243
|
+
def is_mu_type?
|
|
244
|
+
_shortclass, _cfg_name, type, _classname, _attrs = MU::Cloud.getResourceNames(@type, false)
|
|
245
|
+
!type.nil?
|
|
246
|
+
end
|
|
247
|
+
|
|
248
|
+
# Decompose into a plain-jane {MU::Config::BasketOfKittens} hash fragment,
|
|
249
|
+
# of the sort that would have been used to declare this reference in the
|
|
250
|
+
# first place.
|
|
251
|
+
def to_h
|
|
252
|
+
me = { }
|
|
253
|
+
|
|
254
|
+
self.instance_variables.each { |var|
|
|
255
|
+
next if [:@obj, :@mommacat, :@tag_key, :@tag_value].include?(var)
|
|
256
|
+
val = self.instance_variable_get(var)
|
|
257
|
+
next if val.nil?
|
|
258
|
+
val = val.to_h if val.is_a?(MU::Config::Ref)
|
|
259
|
+
me[var.to_s.sub(/^@/, '')] = val
|
|
260
|
+
}
|
|
261
|
+
if @tag_key and !@tag_key.empty?
|
|
262
|
+
me['tag'] = {
|
|
263
|
+
'key' => @tag_key,
|
|
264
|
+
'value' => @tag_value
|
|
265
|
+
}
|
|
266
|
+
end
|
|
267
|
+
me
|
|
268
|
+
end
|
|
269
|
+
|
|
270
|
+
# Getter for the #{id} instance variable that attempts to populate it if
|
|
271
|
+
# it's not set.
|
|
272
|
+
# @return [String,nil]
|
|
273
|
+
def id
|
|
274
|
+
return @id if @id
|
|
275
|
+
kitten # if it's not defined, attempt to define it
|
|
276
|
+
@id
|
|
277
|
+
end
|
|
278
|
+
|
|
279
|
+
# Alias for {id}
|
|
280
|
+
# @return [String,nil]
|
|
281
|
+
def cloud_id
|
|
282
|
+
id
|
|
283
|
+
end
|
|
284
|
+
|
|
285
|
+
# Return a {MU::Cloud} object for this reference. This is only meant to be
|
|
286
|
+
# called in a live deploy, which is to say that if called during initial
|
|
287
|
+
# configuration parsing, results may be incorrect.
|
|
288
|
+
# @param mommacat [MU::MommaCat]: A deploy object which will be searched for the referenced resource if provided, before restoring to broader, less efficient searches.
|
|
289
|
+
def kitten(mommacat = @mommacat, shallow: false, debug: false, cloud: nil)
|
|
290
|
+
cloud ||= @cloud
|
|
291
|
+
return nil if !cloud or !@type
|
|
292
|
+
|
|
293
|
+
_shortclass, _cfg_name, cfg_plural, _classname, _attrs = MU::Cloud.getResourceNames(@type, false)
|
|
294
|
+
if cfg_plural
|
|
295
|
+
@type = cfg_plural # make sure this is the thing we expect
|
|
296
|
+
else
|
|
297
|
+
return nil # we don't do non-muish resources
|
|
298
|
+
end
|
|
299
|
+
|
|
300
|
+
loglevel = debug ? MU::NOTICE : MU::DEBUG
|
|
301
|
+
|
|
302
|
+
if debug
|
|
303
|
+
MU.log "this mf kitten", MU::WARN, details: caller
|
|
304
|
+
end
|
|
305
|
+
|
|
306
|
+
if @obj
|
|
307
|
+
@deploy_id ||= @obj.deploy_id
|
|
308
|
+
@id ||= @obj.cloud_id
|
|
309
|
+
@name ||= @obj.config['name'] if @obj.config
|
|
310
|
+
return @obj
|
|
311
|
+
end
|
|
312
|
+
|
|
313
|
+
if mommacat and !caller.grep(/`findLitterMate'/) # XXX the dumbest
|
|
314
|
+
MU.log "Looking for #{@type} #{@name} #{@id} in deploy #{mommacat.deploy_id}", loglevel
|
|
315
|
+
begin
|
|
316
|
+
@obj = mommacat.findLitterMate(type: @type, name: @name, cloud_id: @id, credentials: @credentials, debug: debug)
|
|
317
|
+
rescue StandardError => e
|
|
318
|
+
if e.message =~ /deadlock/
|
|
319
|
+
MU.log "Saw a recursive deadlock trying to fetch kitten for Ref object in deploy #{mmommacat.deploy_id}", MU::ERR, details: to_h
|
|
320
|
+
end
|
|
321
|
+
raise e
|
|
322
|
+
end
|
|
323
|
+
if @obj # initialize missing attributes, if we can
|
|
324
|
+
@id ||= @obj.cloud_id
|
|
325
|
+
@mommacat ||= mommacat
|
|
326
|
+
@obj.intoDeploy(@mommacat) # make real sure these are set
|
|
327
|
+
@deploy_id ||= mommacat.deploy_id
|
|
328
|
+
|
|
329
|
+
if !@name
|
|
330
|
+
if @obj.config and @obj.config['name']
|
|
331
|
+
@name = @obj.config['name']
|
|
332
|
+
elsif @obj.mu_name
|
|
333
|
+
if @type == "folders"
|
|
334
|
+
MU.log "would assign name '#{@obj.mu_name}' in ref to this folder if I were feeling aggressive", MU::WARN, details: self.to_h
|
|
335
|
+
end
|
|
336
|
+
# @name = @obj.mu_name
|
|
337
|
+
end
|
|
338
|
+
end
|
|
339
|
+
return @obj
|
|
340
|
+
else
|
|
341
|
+
# MU.log "Failed to find a live '#{@type.to_s}' object named #{@name}#{@id ? " (#{@id})" : "" }#{ @habitat ? " in habitat #{@habitat}" : "" }", MU::WARN, details: self
|
|
342
|
+
end
|
|
343
|
+
end
|
|
344
|
+
|
|
345
|
+
if !@obj and !(cloud == "Google" and @id and @type == "users" and MU::Cloud.resourceClass("Google", "User").cannedServiceAcctName?(@id)) and !shallow
|
|
346
|
+
try_deploy_id = @deploy_id
|
|
347
|
+
|
|
348
|
+
begin
|
|
349
|
+
hab_arg = if @habitat.nil?
|
|
350
|
+
[nil]
|
|
351
|
+
elsif @habitat.is_a?(MU::Config::Ref)
|
|
352
|
+
[@habitat.id]
|
|
353
|
+
elsif @habitat.is_a?(Hash)
|
|
354
|
+
[@habitat["id"]]
|
|
355
|
+
else
|
|
356
|
+
[@habitat.to_s]
|
|
357
|
+
end
|
|
358
|
+
|
|
359
|
+
MU.log "Ref#kitten calling findStray", loglevel, details: {
|
|
360
|
+
cloud: cloud,
|
|
361
|
+
type: @type,
|
|
362
|
+
name: @name,
|
|
363
|
+
cloud_id: @id,
|
|
364
|
+
deploy_id: try_deploy_id,
|
|
365
|
+
region: @region,
|
|
366
|
+
habitats: hab_arg,
|
|
367
|
+
credentials: @credentials,
|
|
368
|
+
dummy_ok: (["habitats", "folders", "users", "groups", "vpcs"].include?(@type))
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
found = MU::MommaCat.findStray(
|
|
372
|
+
cloud,
|
|
373
|
+
@type,
|
|
374
|
+
name: @name,
|
|
375
|
+
cloud_id: @id,
|
|
376
|
+
deploy_id: try_deploy_id,
|
|
377
|
+
region: @region,
|
|
378
|
+
habitats: hab_arg,
|
|
379
|
+
credentials: @credentials,
|
|
380
|
+
dummy_ok: (["habitats", "folders", "users", "groups", "vpcs"].include?(@type))
|
|
381
|
+
)
|
|
382
|
+
MU.log "Ref#kitten results from findStray", loglevel, details: found
|
|
383
|
+
@obj ||= found.first if found
|
|
384
|
+
rescue MU::MommaCat::MultipleMatches => e
|
|
385
|
+
if try_deploy_id.nil? and MU.deploy_id
|
|
386
|
+
MU.log "Attempting to narrow down #{cloud} #{@type} to #{MU.deploy_id}", MU::NOTICE
|
|
387
|
+
try_deploy_id = MU.deploy_id
|
|
388
|
+
retry
|
|
389
|
+
else
|
|
390
|
+
raise e
|
|
391
|
+
end
|
|
392
|
+
rescue ThreadError => e
|
|
393
|
+
# Sometimes MommaCat calls us in a potential deadlock situation;
|
|
394
|
+
# don't be the cause of a fatal error if so, we don't need this
|
|
395
|
+
# object that badly.
|
|
396
|
+
raise e if !e.message.match(/recursive locking/)
|
|
397
|
+
end
|
|
398
|
+
end
|
|
399
|
+
|
|
400
|
+
if @obj
|
|
401
|
+
@deploy_id ||= @obj.deploy_id
|
|
402
|
+
@id ||= @obj.cloud_id
|
|
403
|
+
@name ||= @obj.config['name']
|
|
404
|
+
end
|
|
405
|
+
|
|
406
|
+
@obj
|
|
407
|
+
end
|
|
408
|
+
|
|
409
|
+
end
|
|
410
|
+
end
|
|
411
|
+
end
|