cloud-mu 3.1.5 → 3.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (185) hide show
  1. checksums.yaml +4 -4
  2. data/Dockerfile +5 -1
  3. data/ansible/roles/mu-windows/files/LaunchConfig.json +9 -0
  4. data/ansible/roles/mu-windows/files/config.xml +76 -0
  5. data/ansible/roles/mu-windows/tasks/main.yml +16 -0
  6. data/bin/mu-adopt +16 -12
  7. data/bin/mu-azure-tests +57 -0
  8. data/bin/mu-cleanup +2 -4
  9. data/bin/mu-configure +52 -0
  10. data/bin/mu-deploy +3 -3
  11. data/bin/mu-findstray-tests +25 -0
  12. data/bin/mu-gen-docs +2 -4
  13. data/bin/mu-load-config.rb +2 -1
  14. data/bin/mu-node-manage +15 -16
  15. data/bin/mu-run-tests +37 -12
  16. data/cloud-mu.gemspec +3 -3
  17. data/cookbooks/mu-activedirectory/resources/domain.rb +4 -4
  18. data/cookbooks/mu-activedirectory/resources/domain_controller.rb +4 -4
  19. data/cookbooks/mu-tools/libraries/helper.rb +1 -1
  20. data/cookbooks/mu-tools/recipes/apply_security.rb +14 -14
  21. data/cookbooks/mu-tools/recipes/aws_api.rb +9 -0
  22. data/cookbooks/mu-tools/recipes/eks.rb +2 -2
  23. data/cookbooks/mu-tools/recipes/windows-client.rb +25 -22
  24. data/extras/clean-stock-amis +25 -19
  25. data/extras/generate-stock-images +1 -0
  26. data/extras/image-generators/AWS/win2k12.yaml +2 -0
  27. data/extras/image-generators/AWS/win2k16.yaml +2 -0
  28. data/extras/image-generators/AWS/win2k19.yaml +2 -0
  29. data/modules/mommacat.ru +1 -1
  30. data/modules/mu.rb +86 -98
  31. data/modules/mu/adoption.rb +373 -58
  32. data/modules/mu/cleanup.rb +214 -303
  33. data/modules/mu/cloud.rb +128 -1733
  34. data/modules/mu/cloud/database.rb +49 -0
  35. data/modules/mu/cloud/dnszone.rb +44 -0
  36. data/modules/mu/cloud/machine_images.rb +212 -0
  37. data/modules/mu/cloud/providers.rb +81 -0
  38. data/modules/mu/cloud/resource_base.rb +929 -0
  39. data/modules/mu/cloud/server.rb +40 -0
  40. data/modules/mu/cloud/server_pool.rb +1 -0
  41. data/modules/mu/cloud/ssh_sessions.rb +228 -0
  42. data/modules/mu/cloud/winrm_sessions.rb +237 -0
  43. data/modules/mu/cloud/wrappers.rb +169 -0
  44. data/modules/mu/config.rb +123 -81
  45. data/modules/mu/config/alarm.rb +2 -6
  46. data/modules/mu/config/bucket.rb +32 -3
  47. data/modules/mu/config/cache_cluster.rb +2 -2
  48. data/modules/mu/config/cdn.rb +100 -0
  49. data/modules/mu/config/collection.rb +1 -1
  50. data/modules/mu/config/container_cluster.rb +7 -2
  51. data/modules/mu/config/database.rb +84 -105
  52. data/modules/mu/config/database.yml +1 -2
  53. data/modules/mu/config/dnszone.rb +5 -4
  54. data/modules/mu/config/doc_helpers.rb +5 -6
  55. data/modules/mu/config/endpoint.rb +2 -1
  56. data/modules/mu/config/firewall_rule.rb +3 -19
  57. data/modules/mu/config/folder.rb +1 -1
  58. data/modules/mu/config/function.rb +17 -8
  59. data/modules/mu/config/group.rb +1 -1
  60. data/modules/mu/config/habitat.rb +1 -1
  61. data/modules/mu/config/job.rb +89 -0
  62. data/modules/mu/config/loadbalancer.rb +57 -11
  63. data/modules/mu/config/log.rb +1 -1
  64. data/modules/mu/config/msg_queue.rb +1 -1
  65. data/modules/mu/config/nosqldb.rb +1 -1
  66. data/modules/mu/config/notifier.rb +8 -19
  67. data/modules/mu/config/ref.rb +92 -14
  68. data/modules/mu/config/role.rb +1 -1
  69. data/modules/mu/config/schema_helpers.rb +38 -37
  70. data/modules/mu/config/search_domain.rb +1 -1
  71. data/modules/mu/config/server.rb +12 -13
  72. data/modules/mu/config/server_pool.rb +3 -7
  73. data/modules/mu/config/storage_pool.rb +1 -1
  74. data/modules/mu/config/tail.rb +11 -0
  75. data/modules/mu/config/user.rb +1 -1
  76. data/modules/mu/config/vpc.rb +27 -23
  77. data/modules/mu/config/vpc.yml +0 -1
  78. data/modules/mu/defaults/AWS.yaml +90 -90
  79. data/modules/mu/defaults/Azure.yaml +1 -0
  80. data/modules/mu/defaults/Google.yaml +1 -0
  81. data/modules/mu/deploy.rb +34 -20
  82. data/modules/mu/groomer.rb +16 -1
  83. data/modules/mu/groomers/ansible.rb +69 -4
  84. data/modules/mu/groomers/chef.rb +51 -4
  85. data/modules/mu/logger.rb +120 -144
  86. data/modules/mu/master.rb +97 -4
  87. data/modules/mu/mommacat.rb +160 -874
  88. data/modules/mu/mommacat/daemon.rb +23 -14
  89. data/modules/mu/mommacat/naming.rb +110 -3
  90. data/modules/mu/mommacat/search.rb +497 -0
  91. data/modules/mu/mommacat/storage.rb +252 -194
  92. data/modules/mu/{clouds → providers}/README.md +1 -1
  93. data/modules/mu/{clouds → providers}/aws.rb +258 -57
  94. data/modules/mu/{clouds → providers}/aws/alarm.rb +3 -3
  95. data/modules/mu/{clouds → providers}/aws/bucket.rb +275 -41
  96. data/modules/mu/{clouds → providers}/aws/cache_cluster.rb +14 -50
  97. data/modules/mu/providers/aws/cdn.rb +782 -0
  98. data/modules/mu/{clouds → providers}/aws/collection.rb +5 -5
  99. data/modules/mu/{clouds → providers}/aws/container_cluster.rb +95 -84
  100. data/modules/mu/providers/aws/database.rb +1744 -0
  101. data/modules/mu/{clouds → providers}/aws/dnszone.rb +26 -12
  102. data/modules/mu/providers/aws/endpoint.rb +1072 -0
  103. data/modules/mu/{clouds → providers}/aws/firewall_rule.rb +39 -32
  104. data/modules/mu/{clouds → providers}/aws/folder.rb +1 -1
  105. data/modules/mu/{clouds → providers}/aws/function.rb +289 -134
  106. data/modules/mu/{clouds → providers}/aws/group.rb +18 -20
  107. data/modules/mu/{clouds → providers}/aws/habitat.rb +3 -3
  108. data/modules/mu/providers/aws/job.rb +466 -0
  109. data/modules/mu/{clouds → providers}/aws/loadbalancer.rb +77 -47
  110. data/modules/mu/{clouds → providers}/aws/log.rb +5 -5
  111. data/modules/mu/{clouds → providers}/aws/msg_queue.rb +14 -11
  112. data/modules/mu/{clouds → providers}/aws/nosqldb.rb +96 -5
  113. data/modules/mu/{clouds → providers}/aws/notifier.rb +135 -63
  114. data/modules/mu/{clouds → providers}/aws/role.rb +76 -48
  115. data/modules/mu/{clouds → providers}/aws/search_domain.rb +172 -41
  116. data/modules/mu/{clouds → providers}/aws/server.rb +66 -98
  117. data/modules/mu/{clouds → providers}/aws/server_pool.rb +42 -60
  118. data/modules/mu/{clouds → providers}/aws/storage_pool.rb +21 -38
  119. data/modules/mu/{clouds → providers}/aws/user.rb +12 -16
  120. data/modules/mu/{clouds → providers}/aws/userdata/README.md +0 -0
  121. data/modules/mu/{clouds → providers}/aws/userdata/linux.erb +5 -4
  122. data/modules/mu/{clouds → providers}/aws/userdata/windows.erb +0 -0
  123. data/modules/mu/{clouds → providers}/aws/vpc.rb +143 -74
  124. data/modules/mu/{clouds → providers}/aws/vpc_subnet.rb +0 -0
  125. data/modules/mu/{clouds → providers}/azure.rb +13 -0
  126. data/modules/mu/{clouds → providers}/azure/container_cluster.rb +1 -5
  127. data/modules/mu/{clouds → providers}/azure/firewall_rule.rb +8 -1
  128. data/modules/mu/{clouds → providers}/azure/habitat.rb +0 -0
  129. data/modules/mu/{clouds → providers}/azure/loadbalancer.rb +0 -0
  130. data/modules/mu/{clouds → providers}/azure/role.rb +0 -0
  131. data/modules/mu/{clouds → providers}/azure/server.rb +32 -24
  132. data/modules/mu/{clouds → providers}/azure/user.rb +1 -1
  133. data/modules/mu/{clouds → providers}/azure/userdata/README.md +0 -0
  134. data/modules/mu/{clouds → providers}/azure/userdata/linux.erb +0 -0
  135. data/modules/mu/{clouds → providers}/azure/userdata/windows.erb +0 -0
  136. data/modules/mu/{clouds → providers}/azure/vpc.rb +4 -6
  137. data/modules/mu/{clouds → providers}/cloudformation.rb +10 -0
  138. data/modules/mu/{clouds → providers}/cloudformation/alarm.rb +3 -3
  139. data/modules/mu/{clouds → providers}/cloudformation/cache_cluster.rb +3 -3
  140. data/modules/mu/{clouds → providers}/cloudformation/collection.rb +3 -3
  141. data/modules/mu/{clouds → providers}/cloudformation/database.rb +6 -17
  142. data/modules/mu/{clouds → providers}/cloudformation/dnszone.rb +3 -3
  143. data/modules/mu/{clouds → providers}/cloudformation/firewall_rule.rb +3 -3
  144. data/modules/mu/{clouds → providers}/cloudformation/loadbalancer.rb +3 -3
  145. data/modules/mu/{clouds → providers}/cloudformation/log.rb +3 -3
  146. data/modules/mu/{clouds → providers}/cloudformation/server.rb +7 -7
  147. data/modules/mu/{clouds → providers}/cloudformation/server_pool.rb +5 -5
  148. data/modules/mu/{clouds → providers}/cloudformation/vpc.rb +3 -3
  149. data/modules/mu/{clouds → providers}/docker.rb +0 -0
  150. data/modules/mu/{clouds → providers}/google.rb +29 -6
  151. data/modules/mu/{clouds → providers}/google/bucket.rb +4 -4
  152. data/modules/mu/{clouds → providers}/google/container_cluster.rb +38 -20
  153. data/modules/mu/{clouds → providers}/google/database.rb +5 -12
  154. data/modules/mu/{clouds → providers}/google/firewall_rule.rb +5 -5
  155. data/modules/mu/{clouds → providers}/google/folder.rb +5 -9
  156. data/modules/mu/{clouds → providers}/google/function.rb +6 -6
  157. data/modules/mu/{clouds → providers}/google/group.rb +9 -17
  158. data/modules/mu/{clouds → providers}/google/habitat.rb +4 -8
  159. data/modules/mu/{clouds → providers}/google/loadbalancer.rb +5 -5
  160. data/modules/mu/{clouds → providers}/google/role.rb +50 -31
  161. data/modules/mu/{clouds → providers}/google/server.rb +41 -24
  162. data/modules/mu/{clouds → providers}/google/server_pool.rb +14 -14
  163. data/modules/mu/{clouds → providers}/google/user.rb +34 -24
  164. data/modules/mu/{clouds → providers}/google/userdata/README.md +0 -0
  165. data/modules/mu/{clouds → providers}/google/userdata/linux.erb +0 -0
  166. data/modules/mu/{clouds → providers}/google/userdata/windows.erb +0 -0
  167. data/modules/mu/{clouds → providers}/google/vpc.rb +45 -14
  168. data/modules/tests/aws-jobs-functions.yaml +46 -0
  169. data/modules/tests/centos6.yaml +15 -0
  170. data/modules/tests/centos7.yaml +15 -0
  171. data/modules/tests/centos8.yaml +12 -0
  172. data/modules/tests/ecs.yaml +2 -2
  173. data/modules/tests/eks.yaml +1 -1
  174. data/modules/tests/functions/node-function/lambda_function.js +10 -0
  175. data/modules/tests/functions/python-function/lambda_function.py +12 -0
  176. data/modules/tests/microservice_app.yaml +288 -0
  177. data/modules/tests/rds.yaml +108 -0
  178. data/modules/tests/regrooms/rds.yaml +123 -0
  179. data/modules/tests/server-with-scrub-muisms.yaml +1 -1
  180. data/modules/tests/super_complex_bok.yml +2 -2
  181. data/modules/tests/super_simple_bok.yml +3 -5
  182. data/spec/mu/clouds/azure_spec.rb +2 -2
  183. metadata +122 -92
  184. data/modules/mu/clouds/aws/database.rb +0 -1974
  185. data/modules/mu/clouds/aws/endpoint.rb +0 -596
@@ -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/clouds/*/alarm.rb
17
+ # Basket of Kittens config schema and parser logic. See modules/mu/providers/*/alarm.rb
18
18
  class Alarm
19
19
 
20
20
  # Sections of Alarm schema shared between Alarms as a first-class
@@ -281,11 +281,7 @@ module MU
281
281
  }
282
282
  ok = false if !configurator.insertKitten(notifier, "notifiers")
283
283
  end
284
- alarm["dependencies"] ||= []
285
- alarm["dependencies"] << {
286
- "name" => alarm["notification_group"],
287
- "type" => "notifier"
288
- }
284
+ MU::Config.addDependency(alarm, alarm["notification_group"], "notifier")
289
285
  end
290
286
  end
291
287
 
@@ -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/clouds/*/bucket.rb
17
+ # Basket of Kittens config schema and parser logic. See modules/mu/providers/*/bucket.rb
18
18
  class Bucket
19
19
 
20
20
  # Base configuration schema for a Bucket
@@ -50,6 +50,24 @@ module MU
50
50
  "default" => "index.html",
51
51
  "description" => "If +web_enabled+, return this object when \"diretory\" (a path not ending in a key/object) is invoked."
52
52
  },
53
+ "upload" => {
54
+ "type" => "array",
55
+ "items" => {
56
+ "type" => "object",
57
+ "description" => "Upload objects to a bucket, where supported",
58
+ "required" => ["source", "destination"],
59
+ "properties" => {
60
+ "source" => {
61
+ "type" => "string",
62
+ "description" => "A file or directory to upload. If a directory is specified, it will be recursively mirrored to the bucket +destination+."
63
+ },
64
+ "destination" => {
65
+ "type" => "string",
66
+ "description" => "Path to which +source+ file(s) will be uploaded in the bucket, relative to +/+"
67
+ }
68
+ }
69
+ }
70
+ },
53
71
  "policies" => {
54
72
  "type" => "array",
55
73
  "items" => MU::Config::Role.policy_primitive(subobjects: true, grant_to: true, permissions_optional: true, targets_optional: true)
@@ -59,12 +77,23 @@ module MU
59
77
  end
60
78
 
61
79
  # Generic pre-processing of {MU::Config::BasketofKittens::buckets}, bare and unvalidated.
62
- # @param _bucket [Hash]: The resource to process and validate
80
+ # @param bucket [Hash]: The resource to process and validate
63
81
  # @param _configurator [MU::Config]: The overall deployment configurator of which this resource is a member
64
82
  # @return [Boolean]: True if validation succeeded, False otherwise
65
- def self.validate(_bucket, _configurator)
83
+ def self.validate(bucket, _configurator)
66
84
  ok = true
67
85
 
86
+ if bucket['upload']
87
+ bucket['upload'].each { |batch|
88
+ if !File.exists?(batch['source'])
89
+ MU.log "Bucket '#{bucket['name']}' specifies upload for file/directory that does not exist", MU::ERR, details: batch
90
+ ok = false
91
+ next
92
+ end
93
+ batch['source'] = File.realpath(File.expand_path(batch['source']))
94
+ }
95
+ end
96
+
68
97
  ok
69
98
  end
70
99
 
@@ -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/clouds/*/cache_cluster.rb
17
+ # Basket of Kittens config schema and parser logic. See modules/mu/providers/*/cache_cluster.rb
18
18
  class CacheCluster
19
19
 
20
20
  # Base configuration schema for a CacheCluster
@@ -54,7 +54,7 @@ module MU
54
54
  "type" => "string",
55
55
  "default" => "redis"
56
56
  },
57
- "dns_records" => MU::Config::DNSZone.records_primitive(need_target: false, default_type: "CNAME", need_zone: true),
57
+ "dns_records" => MU::Config::DNSZone.records_primitive(need_target: false, default_type: "CNAME", need_zone: true, embedded_type: "cache_cluster"),
58
58
  "dns_sync_wait" => {
59
59
  "type" => "boolean",
60
60
  "description" => "Wait for DNS record to propagate in DNS Zone.",
@@ -0,0 +1,100 @@
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
+ class Config
17
+ # Basket of Kittens config schema and parser logic. See modules/mu/providers/*/job.rb
18
+ class CDN
19
+
20
+ # Base configuration schema for a scheduled job
21
+ # @return [Hash]
22
+ def self.schema
23
+ {
24
+ "type" => "object",
25
+ "additionalProperties" => false,
26
+ "required" => ["origins"],
27
+ "properties" => {
28
+ "name" => {
29
+ "type" => "string"
30
+ },
31
+ "dns_records" => MU::Config::DNSZone.records_primitive(need_target: false, default_type: "CNAME", need_zone: true, embedded_type: "cdn"),
32
+ "default_object" => {
33
+ "type" => "string",
34
+ "default" => "index.html"
35
+ },
36
+ "credentials" => MU::Config.credentials_primitive,
37
+ "aliases" => {
38
+ "type" => "array",
39
+ "items" => {
40
+ "type" => "string"
41
+ }
42
+ },
43
+ "origins" => {
44
+ "type" => "array",
45
+ "minItems" => 1,
46
+ "items" => {
47
+ "type" => "object",
48
+ "description" => "One or more back-end sources which this CDN will cache",
49
+ "required" => ["name"],
50
+ "properties" => {
51
+ "name" => {
52
+ "type" => "string",
53
+ "description" => "A unique identifying string which other components of this distribution may use to reference this origin"
54
+ },
55
+ "domain_name" => {
56
+ "type" => "string",
57
+ "description" => "Domain name of the back-end web server or other resource behind this CDN"
58
+ },
59
+ "path" => {
60
+ "type" => "string",
61
+ "default" => "",
62
+ "description" => "Optional path on back-end service to which to map front-end requests"
63
+ }
64
+ }
65
+ }
66
+ },
67
+ "behaviors" => {
68
+ "type" => "array",
69
+ "items" => {
70
+ "description" => "Customize the behavior of requests sent to one of this CDN's configured +origins+",
71
+ "type" => "object",
72
+ "properties" => {
73
+ "origin" => {
74
+ "type" => "string",
75
+ "description" => "Which of our +origins+ this set of behaviors should map to, by its +name+ field."
76
+ },
77
+ "path_pattern" => {
78
+ "type" => "string",
79
+ "description" => "The request path or paths for which this behavior should be invoked"
80
+ }
81
+ }
82
+ }
83
+ }
84
+ }
85
+ }
86
+ end
87
+
88
+ # Generic pre-processing of {MU::Config::BasketofKittens::jobs}, bare and unvalidated.
89
+ # @param _job [Hash]: The resource to process and validate
90
+ # @param _configurator [MU::Config]: The overall deployment configurator of which this resource is a member
91
+ # @return [Boolean]: True if validation succeeded, False otherwise
92
+ def self.validate(_job, _configurator)
93
+ ok = true
94
+
95
+ ok
96
+ end
97
+
98
+ end
99
+ end
100
+ 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/clouds/*/collection.rb
17
+ # Basket of Kittens config schema and parser logic. See modules/mu/providers/*/collection.rb
18
18
  class Collection
19
19
 
20
20
  # Base configuration schema for a Collection
@@ -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/clouds/*/container_cluster.rb
17
+ # Basket of Kittens config schema and parser logic. See modules/mu/providers/*/container_cluster.rb
18
18
  class ContainerCluster
19
19
 
20
20
  # Base configuration schema for a ContainerCluster
@@ -48,7 +48,7 @@ module MU
48
48
  "properties" => {
49
49
  "version" => {
50
50
  "type" => "string",
51
- "default" => "1.13",
51
+ "default" => "1.15",
52
52
  "description" => "Version of Kubernetes control plane to deploy",
53
53
  },
54
54
  "max_pods" => {
@@ -104,6 +104,11 @@ module MU
104
104
  cluster["min_size"] ||= [cluster["instance_count"], cluster["min_size"]].reject { |c| c.nil? }.min
105
105
  end
106
106
 
107
+ if cluster['kubernetes_resources'] and !MU::Master.kubectl
108
+ MU.log "Cannot apply kubernetes resources without a working kubectl executable", MU::ERR
109
+ ok = false
110
+ end
111
+
107
112
  ok
108
113
  end
109
114
 
@@ -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/clouds/*/database.rb
17
+ # Basket of Kittens config schema and parser logic. See modules/mu/providers/*/database.rb
18
18
  class Database
19
19
 
20
20
  # Base configuration schema for a Database
@@ -23,7 +23,7 @@ module MU
23
23
  {
24
24
  "type" => "object",
25
25
  "description" => "Create a dedicated database server.",
26
- "required" => ["name", "engine", "size", "cloud", "storage"],
26
+ "required" => ["name", "engine", "size", "cloud"],
27
27
  "additionalProperties" => false,
28
28
  "properties" => {
29
29
  "groomer" => {
@@ -53,7 +53,7 @@ module MU
53
53
  },
54
54
  "engine_version" => {"type" => "string"},
55
55
  "engine" => {
56
- "enum" => ["mysql", "postgres", "oracle-se1", "oracle-se2", "oracle-se", "oracle-ee", "sqlserver-ee", "sqlserver-se", "sqlserver-ex", "sqlserver-web", "aurora", "mariadb"],
56
+ "enum" => ["mysql", "postgres", "oracle", "oracle-se1", "oracle-se2", "oracle-se", "oracle-ee", "sqlserver-ee", "sqlserver-se", "sqlserver-ex", "sqlserver-web", "aurora", "mariadb"],
57
57
  "type" => "string"
58
58
  },
59
59
  "add_cluster_node" => {
@@ -61,11 +61,8 @@ module MU
61
61
  "description" => "Internal use",
62
62
  "default" => false
63
63
  },
64
- "member_of_cluster" => {
65
- "description" => "Internal use",
66
- "type" => "object"
67
- },
68
- "dns_records" => MU::Config::DNSZone.records_primitive(need_target: false, default_type: "CNAME", need_zone: true),
64
+ "member_of_cluster" => MU::Config::Ref.schema(type: "databases", desc: "Internal use"),
65
+ "dns_records" => MU::Config::DNSZone.records_primitive(need_target: false, default_type: "CNAME", need_zone: true, embedded_type: "database"),
69
66
  "dns_sync_wait" => {
70
67
  "type" => "boolean",
71
68
  "description" => "Wait for DNS record to propagate in DNS Zone.",
@@ -78,20 +75,16 @@ module MU
78
75
  },
79
76
  "storage" => {
80
77
  "type" => "integer",
81
- "description" => "Storage space for this database instance (GB)."
82
- },
83
- "storage_type" => {
84
- "enum" => ["standard", "gp2", "io1"],
85
- "type" => "string",
86
- "default" => "gp2"
78
+ "description" => "Storage space for this database instance (GB).",
79
+ "default" => 20
87
80
  },
88
81
  "run_sql_on_deploy" => {
89
- "type" => "array",
90
- "minItems" => 1,
91
- "items" => {
92
- "description" => "Arbitrary SQL commands to run after the database is fully configred (PostgreSQL databases only).",
93
- "type" => "string"
94
- }
82
+ "type" => "array",
83
+ "minItems" => 1,
84
+ "items" => {
85
+ "description" => "Arbitrary SQL commands to run after the database is fully configred (PostgreSQL databases only).",
86
+ "type" => "string"
87
+ }
95
88
  },
96
89
  "port" => {"type" => "integer"},
97
90
  "vpc" => MU::Config::VPC.reference(MU::Config::VPC::MANY_SUBNETS, MU::Config::VPC::NAT_OPTS, "all_public"),
@@ -144,22 +137,24 @@ module MU
144
137
  "default" => false
145
138
  },
146
139
  "creation_style" => {
147
- "type" => "string",
148
- "enum" => ["existing", "new", "new_snapshot", "existing_snapshot", "point_in_time"],
149
- "description" => "'new' - create a pristine database instances; 'existing' - use an existing database instance; 'new_snapshot' - create a snapshot of an existing database, and create a new one from that snapshot; 'existing_snapshot' - create database from an existing snapshot.; 'point_in_time' - create database from point in time backup of an existing database",
150
- "default" => "new"
140
+ "type" => "string",
141
+ "enum" => ["existing", "new", "new_snapshot", "existing_snapshot", "point_in_time"],
142
+ "description" => "+new+ creates a pristine database instance; +existing+ clones an existing database instance; +new_snapshot+ creates a snapshot of an existing database, then creates a new instance from that snapshot; +existing_snapshot+ creates database from a pre-existing snapshot; +point_in_time+ create database from point in time backup of an existing database. All styles other than +new+ require that +identifier+ or +source+ be set.",
143
+ "default" => "new"
151
144
  },
152
145
  "identifier" => {
153
- "type" => "string",
154
- "description" => "For any creation_style other than 'new' this parameter identifies the database to use. In the case of new_snapshot or point_in_time this is the identifier of an existing database instance; in the case of existing_snapshot this is the identifier of the snapshot."
146
+ "type" => "string",
147
+ "description" => "Cloud id of a source database to use for creation styles other than +new+; use +source+ for more sophisticated resource references."
155
148
  },
149
+ "source" => MU::Config::Ref.schema(type: "databases", "desc": "Reference a source database to use for +creation_style+ settings +existing+, +new_snapshot+, +existing_snapshot+, or +point_in_time+."),
156
150
  "master_user" => {
157
151
  "type" => "string",
158
152
  "description" => "Set master user name for this database instance; if not specified a random username will be generated"
159
153
  },
160
154
  "restore_time" => {
161
155
  "type" => "string",
162
- "description" => "Must either be set to 'latest' or date/time value in the following format: 2015-09-12T22:30:00Z. Applies only to point_in_time creation_style"
156
+ "description" => "Must either be set to 'latest' or date/time value in the following format: 2015-09-12T22:30:00Z. Applies only to point_in_time creation_style",
157
+ "default" => "latest"
163
158
  },
164
159
  "create_read_replica" => {
165
160
  "type" => "boolean",
@@ -215,27 +210,11 @@ module MU
215
210
  # Schema block for other resources to use when referencing a sibling Database
216
211
  # @return [Hash]
217
212
  def self.reference
218
- {
219
- "type" => "object",
220
- "description" => "Incorporate a database object",
221
- "minProperties" => 1,
222
- "additionalProperties" => false,
223
- "properties" => {
224
- "db_id" => {"type" => "string"},
225
- "db_name" => {"type" => "string"},
226
- "region" => MU::Config.region_primitive,
227
- "cloud" => MU::Config.cloud_primitive,
228
- "tag" => {
229
- "type" => "string",
230
- "description" => "Identify this Database by a tag (key=value). Note that this tag must not match more than one resource.",
231
- "pattern" => "^[^=]+=.+"
232
- },
233
- "deploy_id" => {
234
- "type" => "string",
235
- "description" => "Look for a Database fitting this description in another Mu deployment with this id.",
236
- }
237
- }
238
- }
213
+ schema_aliases = [
214
+ { "db_id" => "id" },
215
+ { "db_name" => "name" }
216
+ ]
217
+ MU::Config::Ref.schema(schema_aliases, type: "databases")
239
218
  end
240
219
 
241
220
  # Generic pre-processing of {MU::Config::BasketofKittens::databases}, bare and unvalidated.
@@ -266,6 +245,22 @@ module MU
266
245
  end
267
246
  end
268
247
 
248
+ if db["identifier"]
249
+ if db["source"]
250
+ if db["source"]["id"] != db["identifier"]
251
+ MU.log "Database #{db['name']} specified identifier '#{db["identifier"]}' with a source parameter that doesn't match", MU::ERR, db["source"]
252
+ ok = false
253
+ end
254
+ else
255
+ db["source"] = MU::Config::Ref.get(
256
+ id: db["identifier"],
257
+ cloud: db["cloud"],
258
+ credentials: db["credentials"],
259
+ type: "databases"
260
+ )
261
+ end
262
+ db.delete("identifier")
263
+ end
269
264
 
270
265
  if db["storage"].nil? and db["creation_style"] == "new" and !db['create_cluster']
271
266
  MU.log "Must provide a value for 'storage' when creating a new database.", MU::ERR, details: db
@@ -296,13 +291,13 @@ module MU
296
291
 
297
292
  if db["creation_style"] == "point_in_time" && db["restore_time"].nil?
298
293
  ok = false
299
- MU.log "You must provide restore_time when creation_style is point_in_time", MU::ERR
294
+ MU.log "Database '#{db['name']}' must provide restore_time when creation_style is point_in_time", MU::ERR
300
295
  end
301
296
 
302
297
  if %w{existing new_snapshot existing_snapshot point_in_time}.include?(db["creation_style"])
303
- if db["identifier"].nil?
298
+ if db["source"].nil?
304
299
  ok = false
305
- MU.log "Using existing database (or snapshot thereof), but no identifier given", MU::ERR
300
+ MU.log "Database '#{db['name']}' needs existing database/snapshot, but no identifier or source was specified", MU::ERR
306
301
  end
307
302
  end
308
303
 
@@ -336,16 +331,17 @@ module MU
336
331
  replica["credentials"] = db["credentials"]
337
332
  replica['create_read_replica'] = false
338
333
  replica["create_cluster"] = false
334
+ replica["region"] = db['read_replica_region']
335
+ if db['region'] != replica['region']
336
+ replica.delete("vpc")
337
+ end
339
338
  replica['read_replica_of'] = {
340
- "db_name" => db['name'],
339
+ "name" => db['name'],
341
340
  "cloud" => db['cloud'],
342
- "region" => db['read_replica_region'] || db['region']
343
- }
344
- replica['dependencies'] << {
345
- "type" => "database",
346
- "name" => db["name"],
347
- "phase" => "groom"
341
+ "region" => db['region'],
342
+ "credentials" => db['credentials'],
348
343
  }
344
+ MU::Config.addDependency(replica, db["name"], "database", phase: "groom")
349
345
  read_replicas << replica
350
346
  end
351
347
  end
@@ -354,6 +350,7 @@ module MU
354
350
  # duplicating the declaration of the master as a new first-class
355
351
  # resource and tweaking it.
356
352
  if db["create_cluster"] and db['cluster_mode'] != "serverless"
353
+ db["add_cluster_node"] = false
357
354
  (1..db["cluster_node_count"]).each{ |num|
358
355
  node = Marshal.load(Marshal.dump(db))
359
356
  node["name"] = "#{db['name']}-#{num}"
@@ -363,16 +360,14 @@ module MU
363
360
  node["creation_style"] = "new"
364
361
  node["add_cluster_node"] = true
365
362
  node["member_of_cluster"] = {
366
- "db_name" => db['name'],
363
+ "name" => db['name'],
367
364
  "cloud" => db['cloud'],
368
- "region" => db['region']
365
+ "region" => db['region'],
366
+ "credentials" => db['credentials'],
367
+ "type" => "databases"
369
368
  }
370
369
  # AWS will figure out for us which database instance is the writer/master so we can create all of them concurrently.
371
- node['dependencies'] << {
372
- "type" => "database",
373
- "name" => db["name"],
374
- "phase" => "groom"
375
- }
370
+ MU::Config.addDependency(node, db["name"], "database", phase: "groom")
376
371
  cluster_nodes << node
377
372
 
378
373
  # Alarms are set on each DB cluster node, not on the cluster itself,
@@ -387,55 +382,39 @@ module MU
387
382
  end
388
383
 
389
384
  if !db['read_replica_of'].nil?
390
- rr = db['read_replica_of']
391
- if !rr['db_name'].nil?
392
- db['dependencies'] << { "name" => rr['db_name'], "type" => "database" }
393
- else
394
- rr['cloud'] = db['cloud'] if rr['cloud'].nil?
395
- tag_key, tag_value = rr['tag'].split(/=/, 2) if !rr['tag'].nil?
396
- found = MU::MommaCat.findStray(
397
- rr['cloud'],
398
- "database",
399
- deploy_id: rr["deploy_id"],
400
- cloud_id: rr["db_id"],
401
- tag_key: tag_key,
402
- tag_value: tag_value,
403
- region: rr["region"],
404
- dummy_ok: true
405
- )
406
- ext_database = found.first if !found.nil? and found.size == 1
407
- if !ext_database
408
- MU.log "Couldn't resolve Database reference to a unique live Database in #{db['name']}", MU::ERR, details: rr
409
- ok = false
410
- end
385
+ rr = MU::Config::Ref.get(db['read_replica_of'])
386
+ if rr.name and !rr.deploy_id
387
+ db['dependencies'] << { "name" => rr.name, "type" => "database" }
388
+ MU::Config.addDependency(db, rr.name, "database")
389
+ elsif !rr.kitten
390
+ MU.log "Couldn't resolve Database reference to a unique live Database in #{db['name']}", MU::ERR, details: rr
391
+ ok = false
411
392
  end
412
393
  elsif db["member_of_cluster"]
413
- rr = db["member_of_cluster"]
414
- if rr['db_name']
415
- if !configurator.haveLitterMate?(rr['db_name'], "databases")
416
- MU.log "Database cluster node #{db['name']} references sibling source #{rr['db_name']}, but I have no such database", MU::ERR
394
+ cluster = MU::Config::Ref.get(db["member_of_cluster"])
395
+ if cluster['name']
396
+ if !configurator.haveLitterMate?(cluster['name'], "databases")
397
+ MU.log "Database cluster node #{db['name']} references sibling source #{cluster['name']}, but I have no such database", MU::ERR
417
398
  ok = false
418
399
  end
419
400
  else
420
- rr['cloud'] = db['cloud'] if rr['cloud'].nil?
421
- tag_key, tag_value = rr['tag'].split(/=/, 2) if !rr['tag'].nil?
422
- found = MU::MommaCat.findStray(
423
- rr['cloud'],
424
- "database",
425
- deploy_id: rr["deploy_id"],
426
- cloud_id: rr["db_id"],
427
- tag_key: tag_key,
428
- tag_value: tag_value,
429
- region: rr["region"],
430
- dummy_ok: true
431
- )
432
- ext_database = found.first if !found.nil? and found.size == 1
433
- if !ext_database
434
- MU.log "Couldn't resolve Database reference to a unique live Database in #{db['name']}", MU::ERR, details: rr
401
+ if !cluster.kitten
402
+ MU.log "Couldn't resolve Database reference to a unique live Database in #{db['name']}", MU::ERR, details: cluster.to_h
435
403
  ok = false
436
404
  end
437
405
  end
438
406
  end
407
+
408
+ if db["source"]
409
+
410
+ if db["source"]["name"] and
411
+ !db["source"]["deploy_id"] and
412
+ configurator.haveLitterMate?(db["source"]["name"], "databases")
413
+ MU::Config.addDependency(db, db["source"]["name"], "database")
414
+ end
415
+ db["source"]["cloud"] ||= db["cloud"]
416
+ end
417
+
439
418
  db['dependencies'].uniq!
440
419
 
441
420
  read_replicas.each { |new_replica|