cloud-mu 3.1.4 → 3.3.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (203) hide show
  1. checksums.yaml +4 -4
  2. data/Dockerfile +5 -1
  3. data/ansible/roles/mu-windows/README.md +33 -0
  4. data/ansible/roles/mu-windows/defaults/main.yml +2 -0
  5. data/ansible/roles/mu-windows/files/LaunchConfig.json +9 -0
  6. data/ansible/roles/mu-windows/files/config.xml +76 -0
  7. data/ansible/roles/mu-windows/handlers/main.yml +2 -0
  8. data/ansible/roles/mu-windows/meta/main.yml +53 -0
  9. data/ansible/roles/mu-windows/tasks/main.yml +36 -0
  10. data/ansible/roles/mu-windows/tests/inventory +2 -0
  11. data/ansible/roles/mu-windows/tests/test.yml +5 -0
  12. data/ansible/roles/mu-windows/vars/main.yml +2 -0
  13. data/bin/mu-adopt +16 -12
  14. data/bin/mu-azure-tests +57 -0
  15. data/bin/mu-cleanup +2 -4
  16. data/bin/mu-configure +52 -0
  17. data/bin/mu-deploy +3 -3
  18. data/bin/mu-findstray-tests +25 -0
  19. data/bin/mu-gen-docs +2 -4
  20. data/bin/mu-load-config.rb +2 -1
  21. data/bin/mu-node-manage +15 -16
  22. data/bin/mu-run-tests +37 -12
  23. data/cloud-mu.gemspec +5 -3
  24. data/cookbooks/mu-activedirectory/resources/domain.rb +4 -4
  25. data/cookbooks/mu-activedirectory/resources/domain_controller.rb +4 -4
  26. data/cookbooks/mu-tools/libraries/helper.rb +1 -1
  27. data/cookbooks/mu-tools/recipes/apply_security.rb +14 -14
  28. data/cookbooks/mu-tools/recipes/aws_api.rb +9 -0
  29. data/cookbooks/mu-tools/recipes/eks.rb +2 -2
  30. data/cookbooks/mu-tools/recipes/selinux.rb +2 -1
  31. data/cookbooks/mu-tools/recipes/windows-client.rb +163 -164
  32. data/cookbooks/mu-tools/resources/windows_users.rb +44 -43
  33. data/extras/clean-stock-amis +25 -19
  34. data/extras/generate-stock-images +1 -0
  35. data/extras/image-generators/AWS/win2k12.yaml +18 -13
  36. data/extras/image-generators/AWS/win2k16.yaml +18 -13
  37. data/extras/image-generators/AWS/win2k19.yaml +21 -0
  38. data/modules/mommacat.ru +1 -1
  39. data/modules/mu.rb +158 -107
  40. data/modules/mu/adoption.rb +386 -59
  41. data/modules/mu/cleanup.rb +214 -303
  42. data/modules/mu/cloud.rb +128 -1632
  43. data/modules/mu/cloud/database.rb +49 -0
  44. data/modules/mu/cloud/dnszone.rb +44 -0
  45. data/modules/mu/cloud/machine_images.rb +212 -0
  46. data/modules/mu/cloud/providers.rb +81 -0
  47. data/modules/mu/cloud/resource_base.rb +926 -0
  48. data/modules/mu/cloud/server.rb +40 -0
  49. data/modules/mu/cloud/server_pool.rb +1 -0
  50. data/modules/mu/cloud/ssh_sessions.rb +228 -0
  51. data/modules/mu/cloud/winrm_sessions.rb +237 -0
  52. data/modules/mu/cloud/wrappers.rb +169 -0
  53. data/modules/mu/config.rb +135 -82
  54. data/modules/mu/config/alarm.rb +2 -6
  55. data/modules/mu/config/bucket.rb +32 -3
  56. data/modules/mu/config/cache_cluster.rb +2 -2
  57. data/modules/mu/config/cdn.rb +100 -0
  58. data/modules/mu/config/collection.rb +1 -1
  59. data/modules/mu/config/container_cluster.rb +7 -2
  60. data/modules/mu/config/database.rb +84 -105
  61. data/modules/mu/config/database.yml +1 -2
  62. data/modules/mu/config/dnszone.rb +5 -4
  63. data/modules/mu/config/doc_helpers.rb +5 -6
  64. data/modules/mu/config/endpoint.rb +2 -1
  65. data/modules/mu/config/firewall_rule.rb +3 -19
  66. data/modules/mu/config/folder.rb +1 -1
  67. data/modules/mu/config/function.rb +17 -8
  68. data/modules/mu/config/group.rb +1 -1
  69. data/modules/mu/config/habitat.rb +1 -1
  70. data/modules/mu/config/job.rb +89 -0
  71. data/modules/mu/config/loadbalancer.rb +57 -11
  72. data/modules/mu/config/log.rb +1 -1
  73. data/modules/mu/config/msg_queue.rb +1 -1
  74. data/modules/mu/config/nosqldb.rb +1 -1
  75. data/modules/mu/config/notifier.rb +8 -19
  76. data/modules/mu/config/ref.rb +92 -14
  77. data/modules/mu/config/role.rb +1 -1
  78. data/modules/mu/config/schema_helpers.rb +38 -37
  79. data/modules/mu/config/search_domain.rb +1 -1
  80. data/modules/mu/config/server.rb +12 -13
  81. data/modules/mu/config/server.yml +1 -0
  82. data/modules/mu/config/server_pool.rb +3 -7
  83. data/modules/mu/config/storage_pool.rb +1 -1
  84. data/modules/mu/config/tail.rb +11 -0
  85. data/modules/mu/config/user.rb +1 -1
  86. data/modules/mu/config/vpc.rb +27 -23
  87. data/modules/mu/config/vpc.yml +0 -1
  88. data/modules/mu/defaults/AWS.yaml +91 -68
  89. data/modules/mu/defaults/Azure.yaml +1 -0
  90. data/modules/mu/defaults/Google.yaml +1 -0
  91. data/modules/mu/deploy.rb +33 -19
  92. data/modules/mu/groomer.rb +16 -1
  93. data/modules/mu/groomers/ansible.rb +123 -21
  94. data/modules/mu/groomers/chef.rb +64 -11
  95. data/modules/mu/logger.rb +120 -144
  96. data/modules/mu/master.rb +97 -4
  97. data/modules/mu/master/ssl.rb +0 -1
  98. data/modules/mu/mommacat.rb +154 -867
  99. data/modules/mu/mommacat/daemon.rb +23 -14
  100. data/modules/mu/mommacat/naming.rb +110 -3
  101. data/modules/mu/mommacat/search.rb +495 -0
  102. data/modules/mu/mommacat/storage.rb +225 -192
  103. data/modules/mu/{clouds → providers}/README.md +1 -1
  104. data/modules/mu/{clouds → providers}/aws.rb +281 -64
  105. data/modules/mu/{clouds → providers}/aws/alarm.rb +3 -3
  106. data/modules/mu/{clouds → providers}/aws/bucket.rb +275 -41
  107. data/modules/mu/{clouds → providers}/aws/cache_cluster.rb +14 -50
  108. data/modules/mu/providers/aws/cdn.rb +782 -0
  109. data/modules/mu/{clouds → providers}/aws/collection.rb +5 -5
  110. data/modules/mu/{clouds → providers}/aws/container_cluster.rb +708 -749
  111. data/modules/mu/providers/aws/database.rb +1744 -0
  112. data/modules/mu/{clouds → providers}/aws/dnszone.rb +75 -57
  113. data/modules/mu/providers/aws/endpoint.rb +1072 -0
  114. data/modules/mu/{clouds → providers}/aws/firewall_rule.rb +212 -242
  115. data/modules/mu/{clouds → providers}/aws/folder.rb +1 -1
  116. data/modules/mu/{clouds → providers}/aws/function.rb +289 -134
  117. data/modules/mu/{clouds → providers}/aws/group.rb +18 -20
  118. data/modules/mu/{clouds → providers}/aws/habitat.rb +3 -3
  119. data/modules/mu/providers/aws/job.rb +466 -0
  120. data/modules/mu/{clouds → providers}/aws/loadbalancer.rb +50 -41
  121. data/modules/mu/{clouds → providers}/aws/log.rb +5 -5
  122. data/modules/mu/{clouds → providers}/aws/msg_queue.rb +14 -11
  123. data/modules/mu/{clouds → providers}/aws/nosqldb.rb +96 -5
  124. data/modules/mu/{clouds → providers}/aws/notifier.rb +135 -63
  125. data/modules/mu/{clouds → providers}/aws/role.rb +94 -57
  126. data/modules/mu/{clouds → providers}/aws/search_domain.rb +173 -42
  127. data/modules/mu/{clouds → providers}/aws/server.rb +782 -1107
  128. data/modules/mu/{clouds → providers}/aws/server_pool.rb +36 -46
  129. data/modules/mu/{clouds → providers}/aws/storage_pool.rb +21 -38
  130. data/modules/mu/{clouds → providers}/aws/user.rb +12 -16
  131. data/modules/mu/{clouds → providers}/aws/userdata/README.md +0 -0
  132. data/modules/mu/{clouds → providers}/aws/userdata/linux.erb +5 -4
  133. data/modules/mu/{clouds → providers}/aws/userdata/windows.erb +2 -1
  134. data/modules/mu/{clouds → providers}/aws/vpc.rb +429 -849
  135. data/modules/mu/providers/aws/vpc_subnet.rb +286 -0
  136. data/modules/mu/{clouds → providers}/azure.rb +13 -0
  137. data/modules/mu/{clouds → providers}/azure/container_cluster.rb +1 -5
  138. data/modules/mu/{clouds → providers}/azure/firewall_rule.rb +8 -1
  139. data/modules/mu/{clouds → providers}/azure/habitat.rb +0 -0
  140. data/modules/mu/{clouds → providers}/azure/loadbalancer.rb +0 -0
  141. data/modules/mu/{clouds → providers}/azure/role.rb +0 -0
  142. data/modules/mu/{clouds → providers}/azure/server.rb +32 -24
  143. data/modules/mu/{clouds → providers}/azure/user.rb +1 -1
  144. data/modules/mu/{clouds → providers}/azure/userdata/README.md +0 -0
  145. data/modules/mu/{clouds → providers}/azure/userdata/linux.erb +0 -0
  146. data/modules/mu/{clouds → providers}/azure/userdata/windows.erb +0 -0
  147. data/modules/mu/{clouds → providers}/azure/vpc.rb +4 -6
  148. data/modules/mu/{clouds → providers}/cloudformation.rb +10 -0
  149. data/modules/mu/{clouds → providers}/cloudformation/alarm.rb +3 -3
  150. data/modules/mu/{clouds → providers}/cloudformation/cache_cluster.rb +3 -3
  151. data/modules/mu/{clouds → providers}/cloudformation/collection.rb +3 -3
  152. data/modules/mu/{clouds → providers}/cloudformation/database.rb +6 -17
  153. data/modules/mu/{clouds → providers}/cloudformation/dnszone.rb +3 -3
  154. data/modules/mu/{clouds → providers}/cloudformation/firewall_rule.rb +3 -3
  155. data/modules/mu/{clouds → providers}/cloudformation/loadbalancer.rb +3 -3
  156. data/modules/mu/{clouds → providers}/cloudformation/log.rb +3 -3
  157. data/modules/mu/{clouds → providers}/cloudformation/server.rb +7 -7
  158. data/modules/mu/{clouds → providers}/cloudformation/server_pool.rb +5 -5
  159. data/modules/mu/{clouds → providers}/cloudformation/vpc.rb +3 -3
  160. data/modules/mu/{clouds → providers}/docker.rb +0 -0
  161. data/modules/mu/{clouds → providers}/google.rb +29 -6
  162. data/modules/mu/{clouds → providers}/google/bucket.rb +5 -5
  163. data/modules/mu/{clouds → providers}/google/container_cluster.rb +59 -37
  164. data/modules/mu/{clouds → providers}/google/database.rb +5 -12
  165. data/modules/mu/{clouds → providers}/google/firewall_rule.rb +5 -5
  166. data/modules/mu/{clouds → providers}/google/folder.rb +5 -9
  167. data/modules/mu/{clouds → providers}/google/function.rb +14 -8
  168. data/modules/mu/{clouds → providers}/google/group.rb +9 -17
  169. data/modules/mu/{clouds → providers}/google/habitat.rb +4 -8
  170. data/modules/mu/{clouds → providers}/google/loadbalancer.rb +5 -5
  171. data/modules/mu/{clouds → providers}/google/role.rb +50 -31
  172. data/modules/mu/{clouds → providers}/google/server.rb +142 -55
  173. data/modules/mu/{clouds → providers}/google/server_pool.rb +14 -14
  174. data/modules/mu/{clouds → providers}/google/user.rb +34 -24
  175. data/modules/mu/{clouds → providers}/google/userdata/README.md +0 -0
  176. data/modules/mu/{clouds → providers}/google/userdata/linux.erb +0 -0
  177. data/modules/mu/{clouds → providers}/google/userdata/windows.erb +0 -0
  178. data/modules/mu/{clouds → providers}/google/vpc.rb +46 -15
  179. data/modules/tests/aws-jobs-functions.yaml +46 -0
  180. data/modules/tests/centos6.yaml +15 -0
  181. data/modules/tests/centos7.yaml +15 -0
  182. data/modules/tests/centos8.yaml +12 -0
  183. data/modules/tests/ecs.yaml +23 -0
  184. data/modules/tests/eks.yaml +1 -1
  185. data/modules/tests/functions/node-function/lambda_function.js +10 -0
  186. data/modules/tests/functions/python-function/lambda_function.py +12 -0
  187. data/modules/tests/includes-and-params.yaml +2 -1
  188. data/modules/tests/microservice_app.yaml +288 -0
  189. data/modules/tests/rds.yaml +108 -0
  190. data/modules/tests/regrooms/rds.yaml +123 -0
  191. data/modules/tests/server-with-scrub-muisms.yaml +2 -1
  192. data/modules/tests/super_complex_bok.yml +2 -2
  193. data/modules/tests/super_simple_bok.yml +3 -5
  194. data/modules/tests/win2k12.yaml +25 -0
  195. data/modules/tests/win2k16.yaml +25 -0
  196. data/modules/tests/win2k19.yaml +25 -0
  197. data/requirements.txt +1 -0
  198. data/spec/mu/clouds/azure_spec.rb +2 -2
  199. metadata +169 -93
  200. data/extras/image-generators/AWS/windows.yaml +0 -18
  201. data/modules/mu/clouds/aws/database.rb +0 -1974
  202. data/modules/mu/clouds/aws/endpoint.rb +0 -596
  203. data/modules/tests/needwork/win2k12.yaml +0 -13
@@ -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|