cloud-mu 3.1.3 → 3.3.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 +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
|