cloud-mu 2.1.0beta → 3.0.0beta

Sign up to get free protection for your applications and to get access to all the features.
Files changed (291) hide show
  1. checksums.yaml +5 -5
  2. data/Berksfile +4 -5
  3. data/Berksfile.lock +179 -0
  4. data/README.md +1 -6
  5. data/ansible/roles/geerlingguy.firewall/templates/firewall.bash.j2 +0 -0
  6. data/ansible/roles/mu-installer/README.md +33 -0
  7. data/ansible/roles/mu-installer/defaults/main.yml +2 -0
  8. data/ansible/roles/mu-installer/handlers/main.yml +2 -0
  9. data/ansible/roles/mu-installer/meta/main.yml +60 -0
  10. data/ansible/roles/mu-installer/tasks/main.yml +13 -0
  11. data/ansible/roles/mu-installer/tests/inventory +2 -0
  12. data/ansible/roles/mu-installer/tests/test.yml +5 -0
  13. data/ansible/roles/mu-installer/vars/main.yml +2 -0
  14. data/bin/mu-adopt +125 -0
  15. data/bin/mu-aws-setup +4 -4
  16. data/bin/mu-azure-setup +265 -0
  17. data/bin/mu-azure-tests +43 -0
  18. data/bin/mu-cleanup +20 -8
  19. data/bin/mu-configure +224 -98
  20. data/bin/mu-deploy +8 -3
  21. data/bin/mu-gcp-setup +16 -8
  22. data/bin/mu-gen-docs +92 -8
  23. data/bin/mu-load-config.rb +52 -12
  24. data/bin/mu-momma-cat +36 -0
  25. data/bin/mu-node-manage +34 -27
  26. data/bin/mu-self-update +2 -2
  27. data/bin/mu-ssh +12 -8
  28. data/bin/mu-upload-chef-artifacts +11 -4
  29. data/bin/mu-user-manage +3 -0
  30. data/cloud-mu.gemspec +8 -11
  31. data/cookbooks/firewall/libraries/helpers_iptables.rb +2 -2
  32. data/cookbooks/firewall/metadata.json +1 -1
  33. data/cookbooks/firewall/recipes/default.rb +5 -9
  34. data/cookbooks/mu-firewall/attributes/default.rb +2 -0
  35. data/cookbooks/mu-firewall/metadata.rb +1 -1
  36. data/cookbooks/mu-glusterfs/templates/default/mu-gluster-client.erb +0 -0
  37. data/cookbooks/mu-master/Berksfile +2 -2
  38. data/cookbooks/mu-master/files/default/check_mem.pl +0 -0
  39. data/cookbooks/mu-master/files/default/cloudamatic.png +0 -0
  40. data/cookbooks/mu-master/metadata.rb +5 -4
  41. data/cookbooks/mu-master/recipes/389ds.rb +1 -1
  42. data/cookbooks/mu-master/recipes/basepackages.rb +30 -10
  43. data/cookbooks/mu-master/recipes/default.rb +59 -7
  44. data/cookbooks/mu-master/recipes/firewall-holes.rb +1 -1
  45. data/cookbooks/mu-master/recipes/init.rb +65 -47
  46. data/cookbooks/mu-master/recipes/{eks-kubectl.rb → kubectl.rb} +4 -10
  47. data/cookbooks/mu-master/recipes/sssd.rb +2 -1
  48. data/cookbooks/mu-master/recipes/update_nagios_only.rb +6 -6
  49. data/cookbooks/mu-master/templates/default/web_app.conf.erb +2 -2
  50. data/cookbooks/mu-master/templates/mods/ldap.conf.erb +4 -0
  51. data/cookbooks/mu-php54/Berksfile +1 -2
  52. data/cookbooks/mu-php54/metadata.rb +4 -5
  53. data/cookbooks/mu-php54/recipes/default.rb +1 -1
  54. data/cookbooks/mu-splunk/templates/default/splunk-init.erb +0 -0
  55. data/cookbooks/mu-tools/Berksfile +3 -2
  56. data/cookbooks/mu-tools/files/default/Mu_CA.pem +33 -0
  57. data/cookbooks/mu-tools/libraries/helper.rb +20 -8
  58. data/cookbooks/mu-tools/metadata.rb +5 -2
  59. data/cookbooks/mu-tools/recipes/apply_security.rb +2 -3
  60. data/cookbooks/mu-tools/recipes/eks.rb +1 -1
  61. data/cookbooks/mu-tools/recipes/gcloud.rb +5 -30
  62. data/cookbooks/mu-tools/recipes/nagios.rb +1 -1
  63. data/cookbooks/mu-tools/recipes/rsyslog.rb +1 -0
  64. data/cookbooks/mu-tools/recipes/selinux.rb +19 -0
  65. data/cookbooks/mu-tools/recipes/split_var_partitions.rb +0 -1
  66. data/cookbooks/mu-tools/recipes/windows-client.rb +256 -122
  67. data/cookbooks/mu-tools/resources/disk.rb +3 -1
  68. data/cookbooks/mu-tools/templates/amazon/sshd_config.erb +1 -1
  69. data/cookbooks/mu-tools/templates/default/etc_hosts.erb +1 -1
  70. data/cookbooks/mu-tools/templates/default/{kubeconfig.erb → kubeconfig-eks.erb} +0 -0
  71. data/cookbooks/mu-tools/templates/default/kubeconfig-gke.erb +27 -0
  72. data/cookbooks/mu-tools/templates/windows-10/sshd_config.erb +137 -0
  73. data/cookbooks/mu-utility/recipes/nat.rb +4 -0
  74. data/extras/alpha.png +0 -0
  75. data/extras/beta.png +0 -0
  76. data/extras/clean-stock-amis +2 -2
  77. data/extras/generate-stock-images +131 -0
  78. data/extras/git-fix-permissions-hook +0 -0
  79. data/extras/image-generators/AWS/centos6.yaml +17 -0
  80. data/extras/image-generators/{aws → AWS}/centos7-govcloud.yaml +0 -0
  81. data/extras/image-generators/{aws → AWS}/centos7.yaml +0 -0
  82. data/extras/image-generators/{aws → AWS}/rhel7.yaml +0 -0
  83. data/extras/image-generators/{aws → AWS}/win2k12.yaml +0 -0
  84. data/extras/image-generators/{aws → AWS}/win2k16.yaml +0 -0
  85. data/extras/image-generators/{aws → AWS}/windows.yaml +0 -0
  86. data/extras/image-generators/{gcp → Google}/centos6.yaml +1 -0
  87. data/extras/image-generators/Google/centos7.yaml +18 -0
  88. data/extras/python_rpm/build.sh +0 -0
  89. data/extras/release.png +0 -0
  90. data/extras/ruby_rpm/build.sh +0 -0
  91. data/extras/ruby_rpm/muby.spec +1 -1
  92. data/install/README.md +43 -5
  93. data/install/deprecated-bash-library.sh +0 -0
  94. data/install/installer +1 -1
  95. data/install/jenkinskeys.rb +0 -0
  96. data/install/mu-master.yaml +55 -0
  97. data/modules/mommacat.ru +41 -7
  98. data/modules/mu.rb +444 -149
  99. data/modules/mu/adoption.rb +500 -0
  100. data/modules/mu/cleanup.rb +235 -158
  101. data/modules/mu/cloud.rb +675 -138
  102. data/modules/mu/clouds/aws.rb +156 -24
  103. data/modules/mu/clouds/aws/alarm.rb +4 -14
  104. data/modules/mu/clouds/aws/bucket.rb +60 -18
  105. data/modules/mu/clouds/aws/cache_cluster.rb +8 -20
  106. data/modules/mu/clouds/aws/collection.rb +12 -22
  107. data/modules/mu/clouds/aws/container_cluster.rb +209 -118
  108. data/modules/mu/clouds/aws/database.rb +120 -45
  109. data/modules/mu/clouds/aws/dnszone.rb +7 -18
  110. data/modules/mu/clouds/aws/endpoint.rb +5 -15
  111. data/modules/mu/clouds/aws/firewall_rule.rb +144 -72
  112. data/modules/mu/clouds/aws/folder.rb +4 -11
  113. data/modules/mu/clouds/aws/function.rb +6 -16
  114. data/modules/mu/clouds/aws/group.rb +4 -12
  115. data/modules/mu/clouds/aws/habitat.rb +11 -13
  116. data/modules/mu/clouds/aws/loadbalancer.rb +40 -28
  117. data/modules/mu/clouds/aws/log.rb +5 -13
  118. data/modules/mu/clouds/aws/msg_queue.rb +9 -24
  119. data/modules/mu/clouds/aws/nosqldb.rb +4 -12
  120. data/modules/mu/clouds/aws/notifier.rb +6 -13
  121. data/modules/mu/clouds/aws/role.rb +69 -40
  122. data/modules/mu/clouds/aws/search_domain.rb +17 -20
  123. data/modules/mu/clouds/aws/server.rb +184 -94
  124. data/modules/mu/clouds/aws/server_pool.rb +33 -38
  125. data/modules/mu/clouds/aws/storage_pool.rb +5 -12
  126. data/modules/mu/clouds/aws/user.rb +59 -33
  127. data/modules/mu/clouds/aws/userdata/linux.erb +18 -30
  128. data/modules/mu/clouds/aws/userdata/windows.erb +9 -9
  129. data/modules/mu/clouds/aws/vpc.rb +214 -145
  130. data/modules/mu/clouds/azure.rb +978 -44
  131. data/modules/mu/clouds/azure/container_cluster.rb +413 -0
  132. data/modules/mu/clouds/azure/firewall_rule.rb +500 -0
  133. data/modules/mu/clouds/azure/habitat.rb +167 -0
  134. data/modules/mu/clouds/azure/loadbalancer.rb +205 -0
  135. data/modules/mu/clouds/azure/role.rb +211 -0
  136. data/modules/mu/clouds/azure/server.rb +810 -0
  137. data/modules/mu/clouds/azure/user.rb +257 -0
  138. data/modules/mu/clouds/azure/userdata/README.md +4 -0
  139. data/modules/mu/clouds/azure/userdata/linux.erb +137 -0
  140. data/modules/mu/clouds/azure/userdata/windows.erb +275 -0
  141. data/modules/mu/clouds/azure/vpc.rb +782 -0
  142. data/modules/mu/clouds/cloudformation.rb +12 -9
  143. data/modules/mu/clouds/cloudformation/firewall_rule.rb +5 -13
  144. data/modules/mu/clouds/cloudformation/server.rb +10 -1
  145. data/modules/mu/clouds/cloudformation/server_pool.rb +1 -0
  146. data/modules/mu/clouds/cloudformation/vpc.rb +0 -2
  147. data/modules/mu/clouds/google.rb +554 -117
  148. data/modules/mu/clouds/google/bucket.rb +173 -32
  149. data/modules/mu/clouds/google/container_cluster.rb +1112 -157
  150. data/modules/mu/clouds/google/database.rb +24 -47
  151. data/modules/mu/clouds/google/firewall_rule.rb +344 -89
  152. data/modules/mu/clouds/google/folder.rb +156 -79
  153. data/modules/mu/clouds/google/group.rb +272 -82
  154. data/modules/mu/clouds/google/habitat.rb +177 -52
  155. data/modules/mu/clouds/google/loadbalancer.rb +9 -34
  156. data/modules/mu/clouds/google/role.rb +1211 -0
  157. data/modules/mu/clouds/google/server.rb +491 -227
  158. data/modules/mu/clouds/google/server_pool.rb +233 -48
  159. data/modules/mu/clouds/google/user.rb +479 -125
  160. data/modules/mu/clouds/google/userdata/linux.erb +3 -3
  161. data/modules/mu/clouds/google/userdata/windows.erb +9 -9
  162. data/modules/mu/clouds/google/vpc.rb +381 -223
  163. data/modules/mu/config.rb +689 -214
  164. data/modules/mu/config/bucket.rb +1 -1
  165. data/modules/mu/config/cache_cluster.rb +1 -1
  166. data/modules/mu/config/cache_cluster.yml +0 -4
  167. data/modules/mu/config/container_cluster.rb +18 -9
  168. data/modules/mu/config/database.rb +6 -23
  169. data/modules/mu/config/firewall_rule.rb +9 -15
  170. data/modules/mu/config/folder.rb +22 -21
  171. data/modules/mu/config/habitat.rb +22 -21
  172. data/modules/mu/config/loadbalancer.rb +2 -2
  173. data/modules/mu/config/role.rb +9 -40
  174. data/modules/mu/config/server.rb +26 -5
  175. data/modules/mu/config/server_pool.rb +1 -1
  176. data/modules/mu/config/storage_pool.rb +2 -2
  177. data/modules/mu/config/user.rb +4 -0
  178. data/modules/mu/config/vpc.rb +350 -110
  179. data/modules/mu/defaults/{amazon_images.yaml → AWS.yaml} +37 -39
  180. data/modules/mu/defaults/Azure.yaml +17 -0
  181. data/modules/mu/defaults/Google.yaml +24 -0
  182. data/modules/mu/defaults/README.md +1 -1
  183. data/modules/mu/deploy.rb +168 -125
  184. data/modules/mu/groomer.rb +2 -1
  185. data/modules/mu/groomers/ansible.rb +104 -32
  186. data/modules/mu/groomers/chef.rb +96 -44
  187. data/modules/mu/kittens.rb +20602 -0
  188. data/modules/mu/logger.rb +38 -11
  189. data/modules/mu/master.rb +90 -8
  190. data/modules/mu/master/chef.rb +2 -3
  191. data/modules/mu/master/ldap.rb +0 -1
  192. data/modules/mu/master/ssl.rb +250 -0
  193. data/modules/mu/mommacat.rb +917 -513
  194. data/modules/scratchpad.erb +1 -1
  195. data/modules/tests/super_complex_bok.yml +0 -0
  196. data/modules/tests/super_simple_bok.yml +0 -0
  197. data/roles/mu-master.json +2 -1
  198. data/spec/azure_creds +5 -0
  199. data/spec/mu.yaml +56 -0
  200. data/spec/mu/clouds/azure_spec.rb +164 -27
  201. data/spec/spec_helper.rb +5 -0
  202. data/test/clean_up.py +0 -0
  203. data/test/exec_inspec.py +0 -0
  204. data/test/exec_mu_install.py +0 -0
  205. data/test/exec_retry.py +0 -0
  206. data/test/smoke_test.rb +0 -0
  207. metadata +90 -118
  208. data/cookbooks/mu-jenkins/Berksfile +0 -14
  209. data/cookbooks/mu-jenkins/CHANGELOG.md +0 -13
  210. data/cookbooks/mu-jenkins/LICENSE +0 -37
  211. data/cookbooks/mu-jenkins/README.md +0 -105
  212. data/cookbooks/mu-jenkins/attributes/default.rb +0 -42
  213. data/cookbooks/mu-jenkins/files/default/cleanup_deploy_config.xml +0 -73
  214. data/cookbooks/mu-jenkins/files/default/deploy_config.xml +0 -44
  215. data/cookbooks/mu-jenkins/metadata.rb +0 -21
  216. data/cookbooks/mu-jenkins/recipes/default.rb +0 -195
  217. data/cookbooks/mu-jenkins/recipes/node-ssh-config.rb +0 -54
  218. data/cookbooks/mu-jenkins/recipes/public_key.rb +0 -24
  219. data/cookbooks/mu-jenkins/templates/default/example_job.config.xml.erb +0 -24
  220. data/cookbooks/mu-jenkins/templates/default/org.jvnet.hudson.plugins.SSHBuildWrapper.xml.erb +0 -14
  221. data/cookbooks/mu-jenkins/templates/default/ssh_config.erb +0 -6
  222. data/cookbooks/nagios/Berksfile +0 -11
  223. data/cookbooks/nagios/CHANGELOG.md +0 -589
  224. data/cookbooks/nagios/CONTRIBUTING.md +0 -11
  225. data/cookbooks/nagios/LICENSE +0 -37
  226. data/cookbooks/nagios/README.md +0 -328
  227. data/cookbooks/nagios/TESTING.md +0 -2
  228. data/cookbooks/nagios/attributes/config.rb +0 -171
  229. data/cookbooks/nagios/attributes/default.rb +0 -228
  230. data/cookbooks/nagios/chefignore +0 -102
  231. data/cookbooks/nagios/definitions/command.rb +0 -33
  232. data/cookbooks/nagios/definitions/contact.rb +0 -33
  233. data/cookbooks/nagios/definitions/contactgroup.rb +0 -33
  234. data/cookbooks/nagios/definitions/host.rb +0 -33
  235. data/cookbooks/nagios/definitions/hostdependency.rb +0 -33
  236. data/cookbooks/nagios/definitions/hostescalation.rb +0 -34
  237. data/cookbooks/nagios/definitions/hostgroup.rb +0 -33
  238. data/cookbooks/nagios/definitions/nagios_conf.rb +0 -38
  239. data/cookbooks/nagios/definitions/resource.rb +0 -33
  240. data/cookbooks/nagios/definitions/service.rb +0 -33
  241. data/cookbooks/nagios/definitions/servicedependency.rb +0 -33
  242. data/cookbooks/nagios/definitions/serviceescalation.rb +0 -34
  243. data/cookbooks/nagios/definitions/servicegroup.rb +0 -33
  244. data/cookbooks/nagios/definitions/timeperiod.rb +0 -33
  245. data/cookbooks/nagios/libraries/base.rb +0 -314
  246. data/cookbooks/nagios/libraries/command.rb +0 -91
  247. data/cookbooks/nagios/libraries/contact.rb +0 -230
  248. data/cookbooks/nagios/libraries/contactgroup.rb +0 -112
  249. data/cookbooks/nagios/libraries/custom_option.rb +0 -36
  250. data/cookbooks/nagios/libraries/data_bag_helper.rb +0 -23
  251. data/cookbooks/nagios/libraries/default.rb +0 -90
  252. data/cookbooks/nagios/libraries/host.rb +0 -412
  253. data/cookbooks/nagios/libraries/hostdependency.rb +0 -181
  254. data/cookbooks/nagios/libraries/hostescalation.rb +0 -173
  255. data/cookbooks/nagios/libraries/hostgroup.rb +0 -119
  256. data/cookbooks/nagios/libraries/nagios.rb +0 -282
  257. data/cookbooks/nagios/libraries/resource.rb +0 -59
  258. data/cookbooks/nagios/libraries/service.rb +0 -455
  259. data/cookbooks/nagios/libraries/servicedependency.rb +0 -215
  260. data/cookbooks/nagios/libraries/serviceescalation.rb +0 -195
  261. data/cookbooks/nagios/libraries/servicegroup.rb +0 -144
  262. data/cookbooks/nagios/libraries/timeperiod.rb +0 -160
  263. data/cookbooks/nagios/libraries/users_helper.rb +0 -54
  264. data/cookbooks/nagios/metadata.rb +0 -25
  265. data/cookbooks/nagios/recipes/_load_databag_config.rb +0 -153
  266. data/cookbooks/nagios/recipes/_load_default_config.rb +0 -241
  267. data/cookbooks/nagios/recipes/apache.rb +0 -48
  268. data/cookbooks/nagios/recipes/default.rb +0 -204
  269. data/cookbooks/nagios/recipes/nginx.rb +0 -82
  270. data/cookbooks/nagios/recipes/pagerduty.rb +0 -143
  271. data/cookbooks/nagios/recipes/server_package.rb +0 -40
  272. data/cookbooks/nagios/recipes/server_source.rb +0 -164
  273. data/cookbooks/nagios/templates/default/apache2.conf.erb +0 -96
  274. data/cookbooks/nagios/templates/default/cgi.cfg.erb +0 -266
  275. data/cookbooks/nagios/templates/default/commands.cfg.erb +0 -13
  276. data/cookbooks/nagios/templates/default/contacts.cfg.erb +0 -37
  277. data/cookbooks/nagios/templates/default/hostgroups.cfg.erb +0 -25
  278. data/cookbooks/nagios/templates/default/hosts.cfg.erb +0 -15
  279. data/cookbooks/nagios/templates/default/htpasswd.users.erb +0 -6
  280. data/cookbooks/nagios/templates/default/nagios.cfg.erb +0 -22
  281. data/cookbooks/nagios/templates/default/nginx.conf.erb +0 -62
  282. data/cookbooks/nagios/templates/default/pagerduty.cgi.erb +0 -185
  283. data/cookbooks/nagios/templates/default/resource.cfg.erb +0 -27
  284. data/cookbooks/nagios/templates/default/servicedependencies.cfg.erb +0 -15
  285. data/cookbooks/nagios/templates/default/servicegroups.cfg.erb +0 -14
  286. data/cookbooks/nagios/templates/default/services.cfg.erb +0 -14
  287. data/cookbooks/nagios/templates/default/templates.cfg.erb +0 -31
  288. data/cookbooks/nagios/templates/default/timeperiods.cfg.erb +0 -13
  289. data/extras/image-generators/aws/centos6.yaml +0 -18
  290. data/modules/mu/defaults/google_images.yaml +0 -16
  291. data/roles/mu-master-jenkins.json +0 -24
@@ -19,38 +19,22 @@ module MU
19
19
  class AWS
20
20
  # A database as configured in {MU::Config::BasketofKittens::databases}
21
21
  class Database < MU::Cloud::Database
22
- @deploy = nil
23
- @config = nil
24
- attr_reader :mu_name
25
- attr_reader :cloud_id
26
- attr_reader :config
27
- attr_reader :groomer
28
-
29
- @cloudformation_data = {}
30
- attr_reader :cloudformation_data
31
-
32
- # @param mommacat [MU::MommaCat]: A {MU::Mommacat} object containing the deploy of which this resource is/will be a member.
33
- # @param kitten_cfg [Hash]: The fully parsed and resolved {MU::Config} resource descriptor as defined in {MU::Config::BasketofKittens::databases}
34
- def initialize(mommacat: nil, kitten_cfg: nil, mu_name: nil, cloud_id: nil)
35
- @deploy = mommacat
36
- @config = MU::Config.manxify(kitten_cfg)
37
- @cloud_id ||= cloud_id
38
- # @mu_name = mu_name ? mu_name : @deploy.getResourceName(@config["name"])
22
+
23
+ # Initialize this cloud resource object. Calling +super+ will invoke the initializer defined under {MU::Cloud}, which should set the attribtues listed in {MU::Cloud::PUBLIC_ATTRS} as well as applicable dependency shortcuts, like +@vpc+, for us.
24
+ # @param args [Hash]: Hash of named arguments passed via Ruby's double-splat
25
+ def initialize(**args)
26
+ super
39
27
  @config["groomer"] = MU::Config.defaultGroomer unless @config["groomer"]
40
28
  @groomclass = MU::Groomer.loadGroomer(@config["groomer"])
41
29
 
42
- if !mu_name.nil?
43
- @mu_name = mu_name
44
- else
45
- @mu_name ||=
46
- if @config and @config['engine'] and @config["engine"].match(/^sqlserver/)
47
- @deploy.getResourceName(@config["name"], max_length: 15)
48
- else
49
- @deploy.getResourceName(@config["name"], max_length: 63)
50
- end
30
+ @mu_name ||=
31
+ if @config and @config['engine'] and @config["engine"].match(/^sqlserver/)
32
+ @deploy.getResourceName(@config["name"], max_length: 15)
33
+ else
34
+ @deploy.getResourceName(@config["name"], max_length: 63)
35
+ end
51
36
 
52
- @mu_name.gsub(/(--|-$)/i, "").gsub(/(_)/, "-").gsub!(/^[^a-z]/i, "")
53
- end
37
+ @mu_name.gsub(/(--|-$)/i, "").gsub(/(_)/, "-").gsub!(/^[^a-z]/i, "")
54
38
  end
55
39
 
56
40
  # Called automatically by {MU::Deploy#createResources}
@@ -189,8 +173,8 @@ module MU
189
173
  def self.find(cloud_id: nil, region: MU.curRegion, tag_key: "Name", tag_value: nil, credentials: nil, flags: {})
190
174
  map = {}
191
175
  if cloud_id
192
- db = MU::Cloud::AWS::Database.getDatabaseById(cloud_id, region: region, credentials: credentials)
193
- map[cloud_id] = db if db
176
+ resp = MU::Cloud::AWS::Database.getDatabaseById(cloud_id, region: region, credentials: credentials)
177
+ map[cloud_id] = resp if resp
194
178
  end
195
179
 
196
180
  if tag_value
@@ -312,6 +296,7 @@ module MU
312
296
 
313
297
  if %w{existing_snapshot new_snapshot}.include?(@config["creation_style"])
314
298
  config[:db_snapshot_identifier] = @config["snapshot_id"]
299
+ config[:db_cluster_identifier] = @config["cluster_identifier"] if @config["add_cluster_node"]
315
300
  end
316
301
 
317
302
  if @config["creation_style"] == "point_in_time"
@@ -384,11 +369,11 @@ module MU
384
369
  MU::Cloud::AWS.rds(region: @config['region'], credentials: @config['credentials']).wait_until(:db_instance_available, db_instance_identifier: @config['identifier']) do |waiter|
385
370
  # Does create_db_instance implement wait_until_available ?
386
371
  waiter.max_attempts = nil
387
- waiter.before_attempt do |attempts|
388
- MU.log "Waiting for RDS database #{@config['identifier']} to be ready..", MU::NOTICE if attempts % 10 == 0
372
+ waiter.before_attempt do |w_attempts|
373
+ MU.log "Waiting for RDS database #{@config['identifier']} to be ready..", MU::NOTICE if w_attempts % 10 == 0
389
374
  end
390
- waiter.before_wait do |attempts, resp|
391
- throw :success if resp.db_instances.first.db_instance_status == "available"
375
+ waiter.before_wait do |w_attempts, r|
376
+ throw :success if r.db_instances.first.db_instance_status == "available"
392
377
  throw :failure if Time.now - wait_start_time > 3600
393
378
  end
394
379
  end
@@ -453,11 +438,11 @@ module MU
453
438
  MU::Cloud::AWS.rds(region: @config['region'], credentials: @config['credentials']).wait_until(:db_instance_available, db_instance_identifier: @config['identifier']) do |waiter|
454
439
  # Does create_db_instance implement wait_until_available ?
455
440
  waiter.max_attempts = nil
456
- waiter.before_attempt do |attempts|
457
- MU.log "Waiting for RDS database #{@config['identifier'] } to be ready..", MU::NOTICE if attempts % 10 == 0
441
+ waiter.before_attempt do |w_attempts|
442
+ MU.log "Waiting for RDS database #{@config['identifier'] } to be ready..", MU::NOTICE if w_attempts % 10 == 0
458
443
  end
459
- waiter.before_wait do |attempts, resp|
460
- throw :success if resp.db_instances.first.db_instance_status == "available"
444
+ waiter.before_wait do |w_attempts, r|
445
+ throw :success if r.db_instances.first.db_instance_status == "available"
461
446
  throw :failure if Time.now - wait_start_time > 2400
462
447
  end
463
448
  end
@@ -532,6 +517,10 @@ module MU
532
517
  cluster_config_struct[:use_latest_restorable_time] = true if @config["restore_time"] == "latest"
533
518
  end
534
519
 
520
+ if @config['cloudwatch_logs']
521
+ cluster_config_struct[:enable_cloudwatch_logs_exports ] = @config['cloudwatch_logs']
522
+ end
523
+
535
524
  attempts = 0
536
525
  begin
537
526
  resp =
@@ -655,8 +644,8 @@ module MU
655
644
  }
656
645
 
657
646
  @config['vpc'] = {
658
- "vpc_id" => vpc_id,
659
- "subnets" => mu_subnets
647
+ "vpc_id" => vpc_id,
648
+ "subnets" => mu_subnets
660
649
  }
661
650
  # Default VPC has only public subnets by default so setting publicly_accessible = true
662
651
  @config["publicly_accessible"] = true
@@ -798,7 +787,15 @@ module MU
798
787
 
799
788
  # Called automatically by {MU::Deploy#createResources}
800
789
  def groom
801
- unless @config["create_cluster"]
790
+ if @config["create_cluster"]
791
+ @config['cluster_node_count'] ||= 1
792
+ if @config['cluster_mode'] == "serverless"
793
+ MU::Cloud::AWS.rds(region: @config['region'], credentials: @config['credentials']).modify_current_db_cluster_capacity(
794
+ db_cluster_identifier: @cloud_id,
795
+ capacity: @config['cluster_node_count']
796
+ )
797
+ end
798
+ else
802
799
  database = MU::Cloud::AWS::Database.getDatabaseById(@config['identifier'], region: @config['region'], credentials: @config['credentials'])
803
800
 
804
801
  # Run SQL on deploy
@@ -1428,18 +1425,31 @@ module MU
1428
1425
  }
1429
1426
  }
1430
1427
 
1428
+
1431
1429
  schema = {
1432
1430
  "db_parameter_group_parameters" => rds_parameters_primitive,
1433
1431
  "cluster_parameter_group_parameters" => rds_parameters_primitive,
1432
+ "parameter_group_family" => {
1433
+ "type" => "String",
1434
+ "description" => "An RDS parameter group family. See also https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_WorkingWithParamGroups.html"
1435
+ },
1434
1436
  "cluster_mode" => {
1435
1437
  "type" => "string",
1436
1438
  "description" => "The DB engine mode of the DB cluster",
1437
1439
  "enum" => ["provisioned", "serverless", "parallelquery", "global"],
1438
1440
  "default" => "provisioned"
1439
1441
  },
1442
+ "cloudwatch_logs" => {
1443
+ "type" => "array",
1444
+ "default" => ["error"],
1445
+ "items" => {
1446
+ "type" => "string",
1447
+ "enum" => ["error", "general", "audit", "slow_query"],
1448
+ }
1449
+ },
1440
1450
  "serverless_scaling" => {
1441
1451
  "type" => "object",
1442
- "descriptions" => "Scaling configuration for a +serverless+ Aurora cluster",
1452
+ "description" => "Scaling configuration for a +serverless+ Aurora cluster",
1443
1453
  "default" => {
1444
1454
  "auto_pause" => false,
1445
1455
  "min_capacity" => 2,
@@ -1505,10 +1515,45 @@ module MU
1505
1515
  def self.validateConfig(db, configurator)
1506
1516
  ok = true
1507
1517
 
1518
+ if db['creation_style'] == "existing_snapshot" and
1519
+ !db['create_cluster'] and
1520
+ db['identifier'] and db['identifier'].match(/:cluster-snapshot:/)
1521
+ MU.log "Database #{db['name']}: Existing snapshot #{db['identifier']} looks like a cluster snapshot, but create_cluster is not set. Add 'create_cluster: true' if you're building an RDS cluster.", MU::ERR
1522
+ ok = false
1523
+ end
1524
+
1525
+ pgroup_families = []
1526
+ engines = {}
1527
+
1528
+ marker = nil
1529
+ begin
1530
+ resp = MU::Cloud::AWS.rds(credentials: db['credentials'], region: db['region']).describe_db_engine_versions(marker: marker)
1531
+ marker = resp.marker
1532
+
1533
+ if resp and resp.db_engine_versions
1534
+ resp.db_engine_versions.each { |version|
1535
+ engines[version.engine] ||= {
1536
+ "versions" => [],
1537
+ "families" => []
1538
+ }
1539
+ engines[version.engine]['versions'] << version.engine_version
1540
+ engines[version.engine]['families'] << version.db_parameter_group_family
1541
+
1542
+ }
1543
+ engines.keys.each { |engine|
1544
+ engines[engine]["versions"].uniq!
1545
+ engines[engine]["families"].uniq!
1546
+ }
1547
+
1548
+ else
1549
+ MU.log "Failed to get list of valid RDS engine versions in #{db['region']}, proceeding without proper validation", MU::WARN
1550
+ end
1551
+ end while !marker.nil?
1552
+
1508
1553
  if db['create_cluster'] or db['engine'] == "aurora" or db["member_of_cluster"]
1509
1554
  case db['engine']
1510
1555
  when "mysql", "aurora", "aurora-mysql"
1511
- if db["engine_version"] == "5.6" or db["cluster_mode"] == "serverless"
1556
+ if db["engine_version"].match(/^5\.6/) or db["cluster_mode"] == "serverless"
1512
1557
  db["engine"] = "aurora"
1513
1558
  else
1514
1559
  db["engine"] = "aurora-mysql"
@@ -1517,10 +1562,40 @@ module MU
1517
1562
  db["engine"] = "aurora-postgresql"
1518
1563
  else
1519
1564
  ok = false
1520
- MU.log "Requested a clustered database, but engine #{db['engine']} is not supported for clustering", MU::ERR
1565
+ MU.log "Database #{db['name']}: Requested a clustered database, but engine #{db['engine']} is not supported for clustering", MU::ERR
1521
1566
  end
1522
1567
  end
1523
1568
 
1569
+ if db['engine'].match(/^aurora/) and !db['create_cluster'] and !db['add_cluster_node']
1570
+ MU.log "Database #{db['name']}: #{db['engine']} looks like a cluster engine, but create_cluster is not set. Add 'create_cluster: true' if you're building an RDS cluster.", MU::ERR
1571
+ ok = false
1572
+ end
1573
+
1574
+ if engines.size > 0
1575
+ if !engines[db['engine']]
1576
+ MU.log "RDS engine #{db['engine']} is not supported in #{db['region']}", MU::ERR, details: engines.keys.sort
1577
+ ok = false
1578
+ else
1579
+ if db["engine_version"] and
1580
+ engines[db['engine']]['versions'].size > 0 and
1581
+ !engines[db['engine']]['versions'].include?(db['engine_version']) and
1582
+ !engines[db['engine']]['versions'].grep(/^#{Regexp.quote(db["engine_version"])}.+/)
1583
+ MU.log "RDS engine '#{db['engine']}' version '#{db['engine_version']}' is not supported in #{db['region']}", MU::ERR, details: { "Known-good versions:" => engines[db['engine']]['versions'].uniq.sort }
1584
+ ok = false
1585
+ end
1586
+ if db["parameter_group_family"] and
1587
+ engines[db['engine']]['families'].size > 0 and
1588
+ !engines[db['engine']]['families'].include?(db['parameter_group_family'])
1589
+ MU.log "RDS engine '#{db['engine']}' parameter group family '#{db['parameter_group_family']}' is not supported in #{db['region']}", MU::ERR, details: { "Valid parameter families:" => engines[db['engine']]['families'].uniq.sort }
1590
+ ok = false
1591
+ end
1592
+ end
1593
+ end
1594
+
1595
+ if db['parameter_group_family'] and pgroup_families.size > 0 and
1596
+ !pgroup_families.include?(db['parameter_group_family'])
1597
+ end
1598
+
1524
1599
  db["license_model"] ||=
1525
1600
  if ["postgres", "postgresql", "aurora-postgresql"].include?(db["engine"])
1526
1601
  "postgresql-license"
@@ -1605,7 +1680,7 @@ module MU
1605
1680
  end
1606
1681
 
1607
1682
  if db["vpc"]
1608
- if db["vpc"]["subnet_pref"] == "all_public" and !db['publicly_accessible']
1683
+ if db["vpc"]["subnet_pref"] == "all_public" and !db['publicly_accessible'] and (db["vpc"]['subnets'].nil? or db["vpc"]['subnets'].empty?)
1609
1684
  MU.log "Setting publicly_accessible to true on database '#{db['name']}', since deploying into public subnets.", MU::WARN
1610
1685
  db['publicly_accessible'] = true
1611
1686
  elsif db["vpc"]["subnet_pref"] == "all_private" and db['publicly_accessible']
@@ -19,22 +19,11 @@ module MU
19
19
  # A DNS Zone as configured in {MU::Config::BasketofKittens::dnszones}
20
20
  class DNSZone < MU::Cloud::DNSZone
21
21
 
22
- @config = nil
23
- attr_reader :mu_name
24
- attr_reader :cloud_id
25
- attr_reader :config
26
-
27
- @cloudformation_data = {}
28
- attr_reader :cloudformation_data
29
-
30
- # @param mommacat [MU::MommaCat]: A {MU::Mommacat} object containing the deploy of which this resource is/will be a member.
31
- # @param kitten_cfg [Hash]: The fully parsed and resolved {MU::Config} resource descriptor as defined in {MU::Config::BasketofKittens::dnszones}
32
- def initialize(mommacat: nil, kitten_cfg: nil, mu_name: nil, cloud_id: nil)
33
- @deploy = mommacat
34
- @config = MU::Config.manxify(kitten_cfg)
35
- unless @mu_name
36
- @mu_name = mu_name ? mu_name : @deploy.getResourceName(@config["name"])
37
- end
22
+ # Initialize this cloud resource object. Calling +super+ will invoke the initializer defined under {MU::Cloud}, which should set the attribtues listed in {MU::Cloud::PUBLIC_ATTRS} as well as applicable dependency shortcuts, like +@vpc+, for us.
23
+ # @param args [Hash]: Hash of named arguments passed via Ruby's double-splat
24
+ def initialize(**args)
25
+ super
26
+ @mu_name ||= @deploy.getResourceName(@config["name"])
38
27
 
39
28
  MU.setVar("curRegion", @config['region']) if !@config['region'].nil?
40
29
  end
@@ -399,8 +388,8 @@ module MU
399
388
  if !alias_zone.nil?
400
389
  target_zone = "/hostedzone/"+alias_zone if !alias_zone.match(/^\/hostedzone\//)
401
390
  else
402
- MU::Cloud::AWS.listRegions.each { |region|
403
- MU::Cloud::AWS.elb(region: region).describe_load_balancers.load_balancer_descriptions.each { |elb|
391
+ MU::Cloud::AWS.listRegions.each { |r|
392
+ MU::Cloud::AWS.elb(region: r).describe_load_balancers.load_balancer_descriptions.each { |elb|
404
393
  elb_dns = elb.dns_name.downcase
405
394
  elb_dns.chomp!(".")
406
395
  if target_name == elb_dns
@@ -3,21 +3,11 @@ module MU
3
3
  class AWS
4
4
  # An API as configured in {MU::Config::BasketofKittens::endpoints}
5
5
  class Endpoint < MU::Cloud::Endpoint
6
- @deploy = nil
7
- @config = nil
8
- attr_reader :mu_name
9
- attr_reader :config
10
- attr_reader :cloud_id
11
-
12
- @cloudformation_data = {}
13
- attr_reader :cloudformation_data
14
-
15
- # @param mommacat [MU::MommaCat]: A {MU::Mommacat} object containing the deploy of which this resource is/will be a member.
16
- # @param kitten_cfg [Hash]: The fully parsed and resolved {MU::Config} resource descriptor as defined in {MU::Config::BasketofKittens::endpoints}
17
- def initialize(mommacat: nil, kitten_cfg: nil, mu_name: nil, cloud_id: nil)
18
- @deploy = mommacat
19
- @config = MU::Config.manxify(kitten_cfg)
20
- @cloud_id ||= cloud_id
6
+
7
+ # Initialize this cloud resource object. Calling +super+ will invoke the initializer defined under {MU::Cloud}, which should set the attribtues listed in {MU::Cloud::PUBLIC_ATTRS} as well as applicable dependency shortcuts, like +@vpc+, for us.
8
+ # @param args [Hash]: Hash of named arguments passed via Ruby's double-splat
9
+ def initialize(**args)
10
+ super
21
11
  @mu_name ||= @deploy.getResourceName(@config["name"])
22
12
  end
23
13
 
@@ -18,30 +18,19 @@ module MU
18
18
  class AWS
19
19
  # A firewall ruleset as configured in {MU::Config::BasketofKittens::firewall_rules}
20
20
  class FirewallRule < MU::Cloud::FirewallRule
21
+ require "mu/clouds/aws/vpc"
21
22
 
22
- @deploy = nil
23
- @config = nil
24
23
  @admin_sgs = Hash.new
25
24
  @admin_sg_semaphore = Mutex.new
26
25
 
27
- attr_reader :mu_name
28
- attr_reader :config
29
- attr_reader :cloud_id
30
-
31
- # @param mommacat [MU::MommaCat]: A {MU::Mommacat} object containing the deploy of which this resource is/will be a member.
32
- # @param kitten_cfg [Hash]: The fully parsed and resolved {MU::Config} resource descriptor as defined in {MU::Config::BasketofKittens::firewall_rules}
33
- def initialize(mommacat: nil, kitten_cfg: nil, mu_name: nil, cloud_id: nil)
34
- @deploy = mommacat
35
- @config = MU::Config.manxify(kitten_cfg)
36
- @cloud_id ||= cloud_id
37
- if !mu_name.nil?
38
- @mu_name = mu_name
26
+ # Initialize this cloud resource object. Calling +super+ will invoke the initializer defined under {MU::Cloud}, which should set the attribtues listed in {MU::Cloud::PUBLIC_ATTRS} as well as applicable dependency shortcuts, like +@vpc+, for us.
27
+ # @param args [Hash]: Hash of named arguments passed via Ruby's double-splat
28
+ def initialize(**args)
29
+ super
30
+ if !@vpc.nil?
31
+ @mu_name ||= @deploy.getResourceName(@config['name'], need_unique_string: true)
39
32
  else
40
- if !@vpc.nil?
41
- @mu_name = @deploy.getResourceName(@config['name'], need_unique_string: true)
42
- else
43
- @mu_name = @deploy.getResourceName(@config['name'])
44
- end
33
+ @mu_name ||= @deploy.getResourceName(@config['name'])
45
34
  end
46
35
 
47
36
  end
@@ -86,7 +75,7 @@ module MU
86
75
  retry
87
76
  end
88
77
 
89
- MU::MommaCat.createStandardTags(secgroup.group_id, region: @config['region'], credentials: @config['credentials'])
78
+ MU::Cloud::AWS.createStandardTags(secgroup.group_id, region: @config['region'], credentials: @config['credentials'])
90
79
  MU::MommaCat.createTag(secgroup.group_id, "Name", groupname, region: @config['region'], credentials: @config['credentials'])
91
80
 
92
81
  if @config['optional_tags']
@@ -170,7 +159,6 @@ module MU
170
159
  else
171
160
  rule["port_range"] = port_range
172
161
  end
173
- rule["description"] = comment if comment
174
162
  ec2_rule = convertToEc2([rule])
175
163
 
176
164
  begin
@@ -212,32 +200,27 @@ module MU
212
200
  end
213
201
 
214
202
  # Locate an existing security group or groups and return an array containing matching AWS resource descriptors for those that match.
215
- # @param cloud_id [String]: The cloud provider's identifier for this resource.
216
- # @param region [String]: The cloud provider region
217
- # @param tag_key [String]: A tag key to search.
218
- # @param tag_value [String]: The value of the tag specified by tag_key to match when searching by tag.
219
- # @param flags [Hash]: Optional flags
220
203
  # @return [Array<Hash<String,OpenStruct>>]: The cloud provider's complete descriptions of matching FirewallRules
221
- def self.find(cloud_id: nil, region: MU.curRegion, tag_key: "Name", tag_value: nil, credentials: nil, flags: {})
204
+ def self.find(**args)
222
205
 
223
- if !cloud_id.nil? and !cloud_id.empty?
206
+ if !args[:cloud_id].nil? and !args[:cloud_id].empty?
224
207
  begin
225
- resp = MU::Cloud::AWS.ec2(region: region, credentials: credentials).describe_security_groups(group_ids: [cloud_id])
226
- return {cloud_id => resp.data.security_groups.first}
208
+ resp = MU::Cloud::AWS.ec2(region: args[:region], credentials: args[:credentials]).describe_security_groups(group_ids: [args[:cloud_id]])
209
+ return {args[:cloud_id] => resp.data.security_groups.first}
227
210
  rescue ArgumentError => e
228
- MU.log "Attempting to load #{cloud_id}: #{e.inspect}", MU::WARN, details: caller
211
+ MU.log "Attempting to load #{args[:cloud_id]}: #{e.inspect}", MU::WARN, details: caller
229
212
  return {}
230
213
  rescue Aws::EC2::Errors::InvalidGroupNotFound => e
231
- MU.log "Attempting to load #{cloud_id}: #{e.inspect}", MU::DEBUG, details: caller
214
+ MU.log "Attempting to load #{args[:cloud_id]}: #{e.inspect}", MU::DEBUG, details: caller
232
215
  return {}
233
216
  end
234
217
  end
235
218
 
236
219
  map = {}
237
- if !tag_key.nil? and !tag_value.nil?
238
- resp = MU::Cloud::AWS.ec2(region: region, credentials: credentials).describe_security_groups(
220
+ if !args[:tag_key].nil? and !args[:tag_value].nil?
221
+ resp = MU::Cloud::AWS.ec2(region: args[:region], credentials: args[:credentials]).describe_security_groups(
239
222
  filters: [
240
- {name: "tag:#{tag_key}", values: [tag_value]}
223
+ {name: "tag:#{args[:tag_key]}", values: [args[:tag_value]]}
241
224
  ]
242
225
  )
243
226
  if !resp.nil?
@@ -269,19 +252,26 @@ module MU
269
252
  # @param region [String]: The cloud provider region
270
253
  # @return [void]
271
254
  def self.cleanup(noop: false, ignoremaster: false, region: MU.curRegion, credentials: nil, flags: {})
272
- tagfilters = [
255
+ filters = nil
256
+ if flags and flags["vpc_id"]
257
+ filters = [
258
+ {name: "vpc-id", values: [flags["vpc_id"]]}
259
+ ]
260
+ else
261
+ filters = [
273
262
  {name: "tag:MU-ID", values: [MU.deploy_id]}
274
- ]
275
- if !ignoremaster
276
- tagfilters << {name: "tag:MU-MASTER-IP", values: [MU.mu_public_ip]}
263
+ ]
264
+ if !ignoremaster
265
+ filters << {name: "tag:MU-MASTER-IP", values: [MU.mu_public_ip]}
266
+ end
277
267
  end
278
268
 
279
269
  # Some services create sneaky rogue ENIs which then block removal of
280
270
  # associated security groups. Find them and fry them.
281
- MU::Cloud::AWS::VPC.purge_interfaces(noop, tagfilters, region: region, credentials: credentials)
271
+ MU::Cloud::AWS::VPC.purge_interfaces(noop, filters, region: region, credentials: credentials)
282
272
 
283
273
  resp = MU::Cloud::AWS.ec2(credentials: credentials, region: region).describe_security_groups(
284
- filters: tagfilters
274
+ filters: filters
285
275
  )
286
276
 
287
277
  resp.data.security_groups.each { |sg|
@@ -361,11 +351,14 @@ module MU
361
351
  }
362
352
 
363
353
  resp.data.security_groups.each { |sg|
354
+ next if sg.group_name == "default"
364
355
  MU.log "Removing EC2 Security Group #{sg.group_name}"
365
356
 
366
357
  retries = 0
367
358
  begin
368
359
  MU::Cloud::AWS.ec2(credentials: credentials, region: region).delete_security_group(group_id: sg.group_id) if !noop
360
+ rescue Aws::EC2::Errors::CannotDelete => e
361
+ MU.log e.message, MU::WARN
369
362
  rescue Aws::EC2::Errors::InvalidGroupNotFound
370
363
  MU.log "EC2 Security Group #{sg.group_name} disappeared before I could delete it!", MU::WARN
371
364
  rescue Aws::EC2::Errors::DependencyViolation, Aws::EC2::Errors::InvalidGroupInUse
@@ -488,28 +481,109 @@ module MU
488
481
  end
489
482
 
490
483
  ec2_rules = convertToEc2(rules)
484
+ ext_permissions = MU.structToHash(cloud_desc.ip_permissions)
485
+
486
+ # Purge any old rules that we're sure we created (check the comment)
487
+ # but which are no longer configured.
488
+ ext_permissions.each { |ext_rule|
489
+ haverule = false
490
+ ec2_rules.each { |rule|
491
+ if rule[:from_port] == ext_rule[:from_port] and
492
+ rule[:to_port] == ext_rule[:to_port] and
493
+ rule[:ip_protocol] == ext_rule[:ip_protocol]
494
+ haverule = true
495
+ break
496
+ end
497
+ }
498
+ next if haverule
499
+
500
+ mu_comments = false
501
+ (ext_rule[:user_id_group_pairs] + ext_rule[:ip_ranges]).each { |entry|
502
+ if entry[:description] == "Added by Mu"
503
+ mu_comments = true
504
+ else
505
+ mu_comments = false
506
+ break
507
+ end
508
+ }
509
+
510
+ if mu_comments
511
+ ext_rule.keys.each { |k|
512
+ if ext_rule[k].nil? or ext_rule[k] == []
513
+ ext_rule.delete(k)
514
+ end
515
+ }
516
+ MU.log "Removing unconfigured rule in #{@mu_name}", MU::WARN, details: ext_rule
517
+ MU::Cloud::AWS.ec2(region: @config['region'], credentials: @config['credentials']).revoke_security_group_ingress(
518
+ group_id: @cloud_id,
519
+ ip_permissions: [ext_rule]
520
+ )
521
+ end
522
+
523
+ }
491
524
 
492
525
  # Creating an empty security group is ok, so don't freak out if we get
493
526
  # a null rule list.
494
527
  if !ec2_rules.nil?
495
528
  ec2_rules.uniq!
496
- MU.log "Setting rules in Security Group #{@mu_name} (#{@cloud_id})", details: ec2_rules
497
529
  retries = 0
498
- if rules != nil
499
- MU.log "Rules for EC2 Security Group #{@mu_name} (#{@cloud_id}): #{ec2_rules}", MU::DEBUG
530
+ ec2_rules.each { |rule|
531
+ haverule = nil
532
+ different = false
533
+ ext_permissions.each { |ext_rule|
534
+ if rule[:from_port] == ext_rule[:from_port] and
535
+ rule[:to_port] == ext_rule[:to_port] and
536
+ rule[:ip_protocol] == ext_rule[:ip_protocol]
537
+ haverule = ext_rule
538
+ ext_rule.keys.each { |k|
539
+ if ext_rule[k].nil? or ext_rule[k] == []
540
+ haverule.delete(k)
541
+ end
542
+ different = true if rule[k] != ext_rule[k]
543
+ }
544
+ break
545
+ end
546
+ }
547
+ if haverule and !different
548
+ MU.log "Security Group rule already up-to-date in #{@mu_name}", MU::DEBUG, details: rule
549
+ next
550
+ end
551
+
552
+ MU.log "Setting #{ingress ? "ingress" : "egress"} rule in Security Group #{@mu_name} (#{@cloud_id})", MU::NOTICE, details: rule
500
553
  begin
554
+
501
555
  if ingress
556
+ if haverule
557
+ begin
558
+ MU::Cloud::AWS.ec2(region: @config['region'], credentials: @config['credentials']).revoke_security_group_ingress(
559
+ group_id: @cloud_id,
560
+ ip_permissions: [haverule]
561
+ )
562
+ rescue Aws::EC2::Errors::InvalidPermissionNotFound => e
563
+ end
564
+ end
502
565
  MU::Cloud::AWS.ec2(region: @config['region'], credentials: @config['credentials']).authorize_security_group_ingress(
503
- group_id: @cloud_id,
504
- ip_permissions: ec2_rules
566
+ group_id: @cloud_id,
567
+ ip_permissions: [rule]
505
568
  )
506
569
  end
570
+
507
571
  if egress
572
+ if haverule
573
+ begin
574
+ MU::Cloud::AWS.ec2(region: @config['region'], credentials: @config['credentials']).revoke_security_group_egress(
575
+ group_id: @cloud_id,
576
+ ip_permissions: [haverule]
577
+ )
578
+ rescue Aws::EC2::Errors::InvalidPermissionNotFound => e
579
+ end
580
+ end
508
581
  MU::Cloud::AWS.ec2(region: @config['region'], credentials: @config['credentials']).authorize_security_group_egress(
509
- group_id: @cloud_id,
510
- ip_permissions: ec2_rules
582
+ group_id: @cloud_id,
583
+ ip_permissions: [rule]
511
584
  )
512
585
  end
586
+
513
587
  rescue Aws::EC2::Errors::InvalidGroupNotFound => e
514
588
  MU.log "#{@mu_name} (#{@cloud_id}) does not yet exist", MU::WARN
515
589
  retries = retries + 1
@@ -520,9 +594,9 @@ module MU
520
594
  raise MuError, "#{@mu_name} does not exist", e.backtrace
521
595
  end
522
596
  rescue Aws::EC2::Errors::InvalidPermissionDuplicate => e
523
- MU.log "Attempt to add duplicate rule to #{@mu_name}", MU::DEBUG, details: ec2_rules
597
+ MU.log "Attempt to add duplicate rule to #{@mu_name}", MU::DEBUG, details: rule
524
598
  end
525
- end
599
+ }
526
600
  end
527
601
 
528
602
  end
@@ -538,6 +612,8 @@ module MU
538
612
 
539
613
  rules.each { |rule|
540
614
  ec2_rule = {}
615
+ rule["comment"] ||= "Added by Mu"
616
+
541
617
 
542
618
  rule['proto'] ||= "tcp"
543
619
  ec2_rule[:ip_protocol] = rule['proto']
@@ -564,9 +640,9 @@ module MU
564
640
  end
565
641
 
566
642
  if (!defined? rule['hosts'] or !rule['hosts'].is_a?(Array)) and
567
- (!defined? rule['sgs'] or !rule['sgs'].is_a?(Array)) and
568
- (!defined? rule['lbs'] or !rule['lbs'].is_a?(Array))
569
- raise MuError, "One of 'hosts', 'sgs', or 'lbs' in rules provided to createEc2SG must be an array."
643
+ (!defined? rule['sgs'] or !rule['sgs'].is_a?(Array)) and
644
+ (!defined? rule['lbs'] or !rule['lbs'].is_a?(Array))
645
+ rule['hosts'] = ["0.0.0.0/0"]
570
646
  end
571
647
  ec2_rule[:ip_ranges] = []
572
648
  ec2_rule[:user_id_group_pairs] = []
@@ -576,11 +652,7 @@ module MU
576
652
  rule['hosts'].each { |cidr|
577
653
  next if cidr.nil? # XXX where is that coming from?
578
654
  cidr = cidr + "/32" if cidr.match(/^\d+\.\d+\.\d+\.\d+$/)
579
- if rule['description']
580
- ec2_rule[:ip_ranges] << {cidr_ip: cidr, description: rule['description']}
581
- else
582
- ec2_rule[:ip_ranges] << {cidr_ip: cidr}
583
- end
655
+ ec2_rule[:ip_ranges] << {cidr_ip: cidr, description: rule['comment']}
584
656
  }
585
657
  end
586
658
 
@@ -627,25 +699,25 @@ module MU
627
699
  rule['sgs'].uniq!
628
700
  rule['sgs'].each { |sg_name|
629
701
  dependencies # Make sure our cache is fresh
630
- if sg_name == @config['name']
631
- sg = self
702
+ sg = @deploy.findLitterMate(type: "firewall_rule", name: sg_name) if @deploy
703
+ sg ||= if sg_name == @config['name']
704
+ self
632
705
  elsif @dependencies.has_key?("firewall_rule") and
633
706
  @dependencies["firewall_rule"].has_key?(sg_name)
634
- sg = @dependencies["firewall_rule"][sg_name]
635
- else
636
- if sg_name.match(/^sg-/)
637
- found_sgs = MU::MommaCat.findStray("AWS", "firewall_rule", cloud_id: sg_name, region: @config['region'], calling_deploy: @deploy, dummy_ok: true)
638
- else
639
- found_sgs = MU::MommaCat.findStray("AWS", "firewall_rule", name: sg_name, region: @config['region'], deploy_id: MU.deploy_id, calling_deploy: @deploy)
640
- end
641
- if found_sgs.nil? or found_sgs.size == 0
642
- raise MuError, "Attempted to reference non-existent Security Group #{sg_name} while building #{@mu_name}"
643
- end
644
- sg = found_sgs.first
707
+ @dependencies["firewall_rule"][sg_name]
708
+ elsif sg_name.match(/^sg-/)
709
+ found_sgs = MU::MommaCat.findStray("AWS", "firewall_rule", cloud_id: sg_name, region: @config['region'], calling_deploy: @deploy, dummy_ok: true)
710
+ found_sgs.first if found_sgs
645
711
  end
712
+
713
+ if sg.nil?
714
+ raise MuError, "FirewallRule #{@config['name']} referenced security group '#{sg_name}' in a rule, but I can't find it anywhere!"
715
+ end
716
+
646
717
  ec2_rule[:user_id_group_pairs] << {
647
718
  user_id: MU.account_number,
648
- group_id: sg.cloud_id
719
+ group_id: sg.cloud_id,
720
+ description: rule['comment']
649
721
  }
650
722
  }
651
723
  end