cloud-mu 1.9.0.pre.beta

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 (618) hide show
  1. checksums.yaml +7 -0
  2. data/Berksfile +56 -0
  3. data/Berksfile.lock +250 -0
  4. data/Jenkinsfile +184 -0
  5. data/LICENSE.md +37 -0
  6. data/README.md +26 -0
  7. data/bin/mu-aws-setup +376 -0
  8. data/bin/mu-cleanup +68 -0
  9. data/bin/mu-configure +1133 -0
  10. data/bin/mu-deploy +166 -0
  11. data/bin/mu-firewall-allow-clients +30 -0
  12. data/bin/mu-gcp-setup +200 -0
  13. data/bin/mu-gen-docs +34 -0
  14. data/bin/mu-gen-env +42 -0
  15. data/bin/mu-load-config.rb +158 -0
  16. data/bin/mu-node-manage +683 -0
  17. data/bin/mu-self-update +228 -0
  18. data/bin/mu-ssh +23 -0
  19. data/bin/mu-tunnel-nagios +144 -0
  20. data/bin/mu-upload-chef-artifacts +757 -0
  21. data/bin/mu-user-manage +275 -0
  22. data/cookbooks/awscli/LICENSE +37 -0
  23. data/cookbooks/awscli/README.md +58 -0
  24. data/cookbooks/awscli/attributes/default.rb +1 -0
  25. data/cookbooks/awscli/libraries/instance_metadata.rb +21 -0
  26. data/cookbooks/awscli/metadata.rb +20 -0
  27. data/cookbooks/awscli/recipes/default.rb +56 -0
  28. data/cookbooks/awscli/templates/default/config.erb +18 -0
  29. data/cookbooks/mu-activedirectory/CHANGELOG.md +13 -0
  30. data/cookbooks/mu-activedirectory/LICENSE +37 -0
  31. data/cookbooks/mu-activedirectory/README.md +6 -0
  32. data/cookbooks/mu-activedirectory/attributes/default.rb +98 -0
  33. data/cookbooks/mu-activedirectory/files/default/password-auth +32 -0
  34. data/cookbooks/mu-activedirectory/files/default/sshd_pol.pp +0 -0
  35. data/cookbooks/mu-activedirectory/files/default/sshd_pol.te +32 -0
  36. data/cookbooks/mu-activedirectory/files/default/syslogd_oddjobd.pp +0 -0
  37. data/cookbooks/mu-activedirectory/files/default/syslogd_oddjobd.te +10 -0
  38. data/cookbooks/mu-activedirectory/files/default/system-auth +34 -0
  39. data/cookbooks/mu-activedirectory/files/default/winbindpol.pp +0 -0
  40. data/cookbooks/mu-activedirectory/files/default/winbindpol.te +37 -0
  41. data/cookbooks/mu-activedirectory/libraries/config.rb +106 -0
  42. data/cookbooks/mu-activedirectory/libraries/helper.rb +86 -0
  43. data/cookbooks/mu-activedirectory/metadata.rb +17 -0
  44. data/cookbooks/mu-activedirectory/providers/domain.rb +152 -0
  45. data/cookbooks/mu-activedirectory/providers/domain_controller.rb +89 -0
  46. data/cookbooks/mu-activedirectory/providers/domain_node.rb +275 -0
  47. data/cookbooks/mu-activedirectory/recipes/default.rb +8 -0
  48. data/cookbooks/mu-activedirectory/recipes/domain-controller.rb +44 -0
  49. data/cookbooks/mu-activedirectory/recipes/domain-node.rb +50 -0
  50. data/cookbooks/mu-activedirectory/recipes/domain.rb +43 -0
  51. data/cookbooks/mu-activedirectory/recipes/sssd.rb +185 -0
  52. data/cookbooks/mu-activedirectory/resources/domain.rb +25 -0
  53. data/cookbooks/mu-activedirectory/resources/domain_controller.rb +25 -0
  54. data/cookbooks/mu-activedirectory/resources/domain_node.rb +20 -0
  55. data/cookbooks/mu-activedirectory/templates/default/dhclient-eth0.conf.erb +4 -0
  56. data/cookbooks/mu-activedirectory/templates/default/interface +0 -0
  57. data/cookbooks/mu-activedirectory/templates/default/krb5.conf.erb +23 -0
  58. data/cookbooks/mu-activedirectory/templates/default/ntp.conf.erb +56 -0
  59. data/cookbooks/mu-activedirectory/templates/default/smb.conf.erb +33 -0
  60. data/cookbooks/mu-activedirectory/templates/default/sssd.conf.erb +60 -0
  61. data/cookbooks/mu-activedirectory/templates/windows/Backup.xml.erb +20 -0
  62. data/cookbooks/mu-activedirectory/templates/windows/bkupInfo.xml.erb +1 -0
  63. data/cookbooks/mu-activedirectory/templates/windows/gpreprt.xml.erb +198 -0
  64. data/cookbooks/mu-activedirectory/templates/windows/gptmpl.inf.erb +12 -0
  65. data/cookbooks/mu-activedirectory/templates/windows/manifest.xml.erb +1 -0
  66. data/cookbooks/mu-firewall/CHANGELOG.md +11 -0
  67. data/cookbooks/mu-firewall/LICENSE +37 -0
  68. data/cookbooks/mu-firewall/README.md +5 -0
  69. data/cookbooks/mu-firewall/attributes/default.rb +3 -0
  70. data/cookbooks/mu-firewall/metadata.rb +16 -0
  71. data/cookbooks/mu-firewall/recipes/default.rb +10 -0
  72. data/cookbooks/mu-glusterfs/CHANGELOG.md +13 -0
  73. data/cookbooks/mu-glusterfs/LICENSE +37 -0
  74. data/cookbooks/mu-glusterfs/README.md +5 -0
  75. data/cookbooks/mu-glusterfs/attributes/default.rb +34 -0
  76. data/cookbooks/mu-glusterfs/metadata.rb +17 -0
  77. data/cookbooks/mu-glusterfs/recipes/client.rb +62 -0
  78. data/cookbooks/mu-glusterfs/recipes/default.rb +16 -0
  79. data/cookbooks/mu-glusterfs/recipes/samba.rb +57 -0
  80. data/cookbooks/mu-glusterfs/recipes/server.rb +200 -0
  81. data/cookbooks/mu-glusterfs/templates/default/mu-gluster-client.erb +71 -0
  82. data/cookbooks/mu-glusterfs/templates/default/smb.conf.erb +14 -0
  83. data/cookbooks/mu-jenkins/CHANGELOG.md +13 -0
  84. data/cookbooks/mu-jenkins/LICENSE +37 -0
  85. data/cookbooks/mu-jenkins/README.md +105 -0
  86. data/cookbooks/mu-jenkins/attributes/default.rb +42 -0
  87. data/cookbooks/mu-jenkins/files/default/cleanup_deploy_config.xml +73 -0
  88. data/cookbooks/mu-jenkins/files/default/deploy_config.xml +44 -0
  89. data/cookbooks/mu-jenkins/metadata.rb +21 -0
  90. data/cookbooks/mu-jenkins/recipes/default.rb +195 -0
  91. data/cookbooks/mu-jenkins/recipes/node-ssh-config.rb +54 -0
  92. data/cookbooks/mu-jenkins/recipes/public_key.rb +24 -0
  93. data/cookbooks/mu-jenkins/templates/default/example_job.config.xml.erb +24 -0
  94. data/cookbooks/mu-jenkins/templates/default/org.jvnet.hudson.plugins.SSHBuildWrapper.xml.erb +14 -0
  95. data/cookbooks/mu-jenkins/templates/default/ssh_config.erb +6 -0
  96. data/cookbooks/mu-master/CHANGELOG.md +13 -0
  97. data/cookbooks/mu-master/LICENSE +37 -0
  98. data/cookbooks/mu-master/README.md +6 -0
  99. data/cookbooks/mu-master/attributes/default.rb +95 -0
  100. data/cookbooks/mu-master/files/default/0-mu-log-server.conf +19 -0
  101. data/cookbooks/mu-master/files/default/addRSA.ldif +8 -0
  102. data/cookbooks/mu-master/files/default/check_mem.pl +197 -0
  103. data/cookbooks/mu-master/files/default/cloudamatic.png +0 -0
  104. data/cookbooks/mu-master/files/default/dirsrv_admin.pp +0 -0
  105. data/cookbooks/mu-master/files/default/dirsrv_admin.te +13 -0
  106. data/cookbooks/mu-master/files/default/nagios_selinux.pp +0 -0
  107. data/cookbooks/mu-master/files/default/nagios_selinux.te +51 -0
  108. data/cookbooks/mu-master/files/default/nagios_selinux_7.pp +0 -0
  109. data/cookbooks/mu-master/files/default/nagios_selinux_7.te +17 -0
  110. data/cookbooks/mu-master/files/default/pam_sshd +18 -0
  111. data/cookbooks/mu-master/files/default/ssl_enable.ldif +18 -0
  112. data/cookbooks/mu-master/files/default/syslogd_oddjobd.pp +0 -0
  113. data/cookbooks/mu-master/files/default/syslogd_oddjobd.te +10 -0
  114. data/cookbooks/mu-master/files/default/vimrc +19 -0
  115. data/cookbooks/mu-master/libraries/mu.rb +29 -0
  116. data/cookbooks/mu-master/metadata.rb +30 -0
  117. data/cookbooks/mu-master/providers/user.rb +41 -0
  118. data/cookbooks/mu-master/recipes/389ds.rb +164 -0
  119. data/cookbooks/mu-master/recipes/basepackages.rb +58 -0
  120. data/cookbooks/mu-master/recipes/caching_nameserver.rb +37 -0
  121. data/cookbooks/mu-master/recipes/default.rb +451 -0
  122. data/cookbooks/mu-master/recipes/eks-kubectl.rb +41 -0
  123. data/cookbooks/mu-master/recipes/firewall-holes.rb +70 -0
  124. data/cookbooks/mu-master/recipes/init.rb +542 -0
  125. data/cookbooks/mu-master/recipes/ssl-certs.rb +109 -0
  126. data/cookbooks/mu-master/recipes/sssd.rb +89 -0
  127. data/cookbooks/mu-master/recipes/update_nagios_only.rb +242 -0
  128. data/cookbooks/mu-master/recipes/vault.rb +111 -0
  129. data/cookbooks/mu-master/resources/user.rb +19 -0
  130. data/cookbooks/mu-master/templates/default/389-directory-setup.inf.erb +28 -0
  131. data/cookbooks/mu-master/templates/default/chef-server.rb.erb +18 -0
  132. data/cookbooks/mu-master/templates/default/dhclient-eth0.conf.erb +9 -0
  133. data/cookbooks/mu-master/templates/default/mu-momma-cat.erb +149 -0
  134. data/cookbooks/mu-master/templates/default/mu.rc.erb +9 -0
  135. data/cookbooks/mu-master/templates/default/openssl.cnf.erb +354 -0
  136. data/cookbooks/mu-master/templates/default/sssd.conf.erb +44 -0
  137. data/cookbooks/mu-master/templates/default/web_app.conf.erb +90 -0
  138. data/cookbooks/mu-mongo/CHANGELOG.md +13 -0
  139. data/cookbooks/mu-mongo/LICENSE +37 -0
  140. data/cookbooks/mu-mongo/README.md +5 -0
  141. data/cookbooks/mu-mongo/attributes/default.rb +22 -0
  142. data/cookbooks/mu-mongo/files/default/keyfile +16 -0
  143. data/cookbooks/mu-mongo/files/default/remove_nodes.js +5 -0
  144. data/cookbooks/mu-mongo/metadata.rb +17 -0
  145. data/cookbooks/mu-mongo/recipes/default.rb +149 -0
  146. data/cookbooks/mu-mongo/recipes/yum-update-rule.rb +18 -0
  147. data/cookbooks/mu-mongo/templates/default/mongo_create_openfema_db.js.erb +2 -0
  148. data/cookbooks/mu-mongo/templates/default/mongo_init.js.erb +1 -0
  149. data/cookbooks/mu-mongo/templates/default/mongo_logrotate.erb +14 -0
  150. data/cookbooks/mu-mongo/templates/default/mongo_replset_addnodes.js.erb +6 -0
  151. data/cookbooks/mu-mongo/templates/default/replset_init.js.erb +2 -0
  152. data/cookbooks/mu-openvpn/CHANGELOG.md +13 -0
  153. data/cookbooks/mu-openvpn/LICENSE +37 -0
  154. data/cookbooks/mu-openvpn/README.md +6 -0
  155. data/cookbooks/mu-openvpn/attributes/default.rb +119 -0
  156. data/cookbooks/mu-openvpn/metadata.rb +18 -0
  157. data/cookbooks/mu-openvpn/recipes/default.rb +108 -0
  158. data/cookbooks/mu-openvpn/templates/default/users.json.erb +42 -0
  159. data/cookbooks/mu-php54/CHANGELOG.md +12 -0
  160. data/cookbooks/mu-php54/LICENSE +37 -0
  161. data/cookbooks/mu-php54/README.md +0 -0
  162. data/cookbooks/mu-php54/files/centos/php.ini +1802 -0
  163. data/cookbooks/mu-php54/files/ubuntu/php.ini +1870 -0
  164. data/cookbooks/mu-php54/metadata.rb +21 -0
  165. data/cookbooks/mu-php54/recipes/default.rb +97 -0
  166. data/cookbooks/mu-splunk/CHANGELOG.md +37 -0
  167. data/cookbooks/mu-splunk/LICENSE +37 -0
  168. data/cookbooks/mu-splunk/README.md +451 -0
  169. data/cookbooks/mu-splunk/attributes/default.rb +95 -0
  170. data/cookbooks/mu-splunk/attributes/upgrade.rb +49 -0
  171. data/cookbooks/mu-splunk/definitions/splunk_installer.rb +103 -0
  172. data/cookbooks/mu-splunk/files/default/splunk-nocheck +10 -0
  173. data/cookbooks/mu-splunk/libraries/helpers.rb +72 -0
  174. data/cookbooks/mu-splunk/libraries/splunk_app_provider.rb +156 -0
  175. data/cookbooks/mu-splunk/libraries/splunk_app_resource.rb +43 -0
  176. data/cookbooks/mu-splunk/metadata.json +30 -0
  177. data/cookbooks/mu-splunk/metadata.rb +17 -0
  178. data/cookbooks/mu-splunk/recipes/client.rb +143 -0
  179. data/cookbooks/mu-splunk/recipes/default.rb +31 -0
  180. data/cookbooks/mu-splunk/recipes/disabled.rb +41 -0
  181. data/cookbooks/mu-splunk/recipes/install_forwarder.rb +23 -0
  182. data/cookbooks/mu-splunk/recipes/install_server.rb +23 -0
  183. data/cookbooks/mu-splunk/recipes/server.rb +53 -0
  184. data/cookbooks/mu-splunk/recipes/service.rb +95 -0
  185. data/cookbooks/mu-splunk/recipes/setup_auth.rb +49 -0
  186. data/cookbooks/mu-splunk/recipes/setup_ssl.rb +63 -0
  187. data/cookbooks/mu-splunk/recipes/upgrade.rb +94 -0
  188. data/cookbooks/mu-splunk/recipes/user.rb +34 -0
  189. data/cookbooks/mu-splunk/templates/default/base_logs_unix_inputs.conf.erb +26 -0
  190. data/cookbooks/mu-splunk/templates/default/inputs.conf.erb +13 -0
  191. data/cookbooks/mu-splunk/templates/default/outputs.conf.erb +9 -0
  192. data/cookbooks/mu-splunk/templates/default/splunk-init.erb +74 -0
  193. data/cookbooks/mu-splunk/templates/default/system-web.conf.erb +7 -0
  194. data/cookbooks/mu-tools/CHANGELOG.md +12 -0
  195. data/cookbooks/mu-tools/LICENSE +37 -0
  196. data/cookbooks/mu-tools/README.md +188 -0
  197. data/cookbooks/mu-tools/attributes/default.rb +142 -0
  198. data/cookbooks/mu-tools/attributes/ebs_rolling_snapshots.rb +3 -0
  199. data/cookbooks/mu-tools/files/amazon/etc/freshclam.conf +235 -0
  200. data/cookbooks/mu-tools/files/centos/CentOS-Base.repo +52 -0
  201. data/cookbooks/mu-tools/files/centos/etc/bashrc +93 -0
  202. data/cookbooks/mu-tools/files/centos/etc/freshclam.conf +235 -0
  203. data/cookbooks/mu-tools/files/centos/etc/login.defs +72 -0
  204. data/cookbooks/mu-tools/files/centos/etc/profile +77 -0
  205. data/cookbooks/mu-tools/files/centos/etc/security/limits.conf +57 -0
  206. data/cookbooks/mu-tools/files/centos/etc/sysconfig/init +19 -0
  207. data/cookbooks/mu-tools/files/centos/etc/sysctl.conf +82 -0
  208. data/cookbooks/mu-tools/files/centos-6/README_MU +0 -0
  209. data/cookbooks/mu-tools/files/centos-6/etc/audit/stig.rules +173 -0
  210. data/cookbooks/mu-tools/files/centos-6/etc/bashrc +90 -0
  211. data/cookbooks/mu-tools/files/centos-6/etc/login.defs +70 -0
  212. data/cookbooks/mu-tools/files/centos-6/etc/pam.d/su +12 -0
  213. data/cookbooks/mu-tools/files/centos-6/etc/profile +83 -0
  214. data/cookbooks/mu-tools/files/centos-6/etc/securetty +12 -0
  215. data/cookbooks/mu-tools/files/centos-6/etc/sysconfig/init +30 -0
  216. data/cookbooks/mu-tools/files/centos-6/etc/sysctl.conf +40 -0
  217. data/cookbooks/mu-tools/files/default/Mu_CA.pem +34 -0
  218. data/cookbooks/mu-tools/files/default/PSWindowsUpdate.zip +0 -0
  219. data/cookbooks/mu-tools/files/default/ebs_snapshots.py +123 -0
  220. data/cookbooks/mu-tools/files/default/etc/BANNER +0 -0
  221. data/cookbooks/mu-tools/files/default/etc/BANNER-FEDERAL +19 -0
  222. data/cookbooks/mu-tools/files/default/gpo_no_uac.zip +0 -0
  223. data/cookbooks/mu-tools/files/default/mypol.pp +0 -0
  224. data/cookbooks/mu-tools/files/default/mypol.te +37 -0
  225. data/cookbooks/mu-tools/files/default/nrpe_c7.pp +0 -0
  226. data/cookbooks/mu-tools/files/default/nrpe_c7.te +31 -0
  227. data/cookbooks/mu-tools/files/default/nrpe_check_disk.pp +0 -0
  228. data/cookbooks/mu-tools/files/default/nrpe_check_disk.te +11 -0
  229. data/cookbooks/mu-tools/files/default/nrpe_disk.pp +0 -0
  230. data/cookbooks/mu-tools/files/default/nrpe_disk.te +10 -0
  231. data/cookbooks/mu-tools/files/default/nrpe_file.pp +0 -0
  232. data/cookbooks/mu-tools/files/default/nrpe_file.te +31 -0
  233. data/cookbooks/mu-tools/files/default/ntrights +0 -0
  234. data/cookbooks/mu-tools/files/default/serverclass.conf +18 -0
  235. data/cookbooks/mu-tools/files/default/splunk-apps/base_logs_unix/local/app.conf +1 -0
  236. data/cookbooks/mu-tools/files/default/splunk-apps/base_logs_unix/local/inputs.conf +13 -0
  237. data/cookbooks/mu-tools/files/default/splunk-apps/base_logs_windows/local/app.conf +1 -0
  238. data/cookbooks/mu-tools/files/default/splunk-apps/base_logs_windows/local/inputs.conf +8 -0
  239. data/cookbooks/mu-tools/files/default/sshd_pol.pp +0 -0
  240. data/cookbooks/mu-tools/files/default/sshd_pol.te +32 -0
  241. data/cookbooks/mu-tools/files/redhat/etc/bashrc +93 -0
  242. data/cookbooks/mu-tools/files/redhat/etc/freshclam.conf +235 -0
  243. data/cookbooks/mu-tools/files/redhat/etc/login.defs +72 -0
  244. data/cookbooks/mu-tools/files/redhat/etc/profile +77 -0
  245. data/cookbooks/mu-tools/files/redhat/etc/security/limits.conf +57 -0
  246. data/cookbooks/mu-tools/files/redhat/etc/sysconfig/init +19 -0
  247. data/cookbooks/mu-tools/files/redhat/etc/sysctl.conf +82 -0
  248. data/cookbooks/mu-tools/files/redhat-6/README_MU +0 -0
  249. data/cookbooks/mu-tools/files/redhat-6/etc/audit/stig.rules +173 -0
  250. data/cookbooks/mu-tools/files/redhat-6/etc/bashrc +90 -0
  251. data/cookbooks/mu-tools/files/redhat-6/etc/login.defs +70 -0
  252. data/cookbooks/mu-tools/files/redhat-6/etc/pam.d/su +12 -0
  253. data/cookbooks/mu-tools/files/redhat-6/etc/profile +83 -0
  254. data/cookbooks/mu-tools/files/redhat-6/etc/securetty +12 -0
  255. data/cookbooks/mu-tools/files/redhat-6/etc/sysconfig/init +30 -0
  256. data/cookbooks/mu-tools/files/redhat-6/etc/sysctl.conf +40 -0
  257. data/cookbooks/mu-tools/files/redhat-7.1/etc/freshclam.conf +235 -0
  258. data/cookbooks/mu-tools/files/ubuntu-12.04/etc/bash.bashrc +64 -0
  259. data/cookbooks/mu-tools/files/ubuntu-12.04/etc/common-session +30 -0
  260. data/cookbooks/mu-tools/files/ubuntu-12.04/etc/login.defs +338 -0
  261. data/cookbooks/mu-tools/files/ubuntu-12.04/etc/profile +30 -0
  262. data/cookbooks/mu-tools/files/ubuntu-12.04/etc/security/limits.conf +56 -0
  263. data/cookbooks/mu-tools/files/ubuntu-12.04/etc/sysctl.conf +60 -0
  264. data/cookbooks/mu-tools/libraries/helper.rb +292 -0
  265. data/cookbooks/mu-tools/metadata.rb +28 -0
  266. data/cookbooks/mu-tools/recipes/add_admin_ssh_keys.rb +35 -0
  267. data/cookbooks/mu-tools/recipes/apply_security.rb +440 -0
  268. data/cookbooks/mu-tools/recipes/aws_api.rb +23 -0
  269. data/cookbooks/mu-tools/recipes/base_repositories.rb +31 -0
  270. data/cookbooks/mu-tools/recipes/cisbenchmark.rb +59 -0
  271. data/cookbooks/mu-tools/recipes/clamav.rb +53 -0
  272. data/cookbooks/mu-tools/recipes/cloudinit.rb +58 -0
  273. data/cookbooks/mu-tools/recipes/configure_oracle_tools.rb +81 -0
  274. data/cookbooks/mu-tools/recipes/disable-requiretty.rb +22 -0
  275. data/cookbooks/mu-tools/recipes/ebs_rolling_snapshots.rb +75 -0
  276. data/cookbooks/mu-tools/recipes/efs.rb +70 -0
  277. data/cookbooks/mu-tools/recipes/eks.rb +160 -0
  278. data/cookbooks/mu-tools/recipes/gcloud.rb +98 -0
  279. data/cookbooks/mu-tools/recipes/google_api.rb +25 -0
  280. data/cookbooks/mu-tools/recipes/maldet.rb +67 -0
  281. data/cookbooks/mu-tools/recipes/nagios.rb +19 -0
  282. data/cookbooks/mu-tools/recipes/newclient.rb +23 -0
  283. data/cookbooks/mu-tools/recipes/nrpe.rb +115 -0
  284. data/cookbooks/mu-tools/recipes/python_pip.rb +35 -0
  285. data/cookbooks/mu-tools/recipes/retrieve_application.rb +51 -0
  286. data/cookbooks/mu-tools/recipes/rsyslog.rb +65 -0
  287. data/cookbooks/mu-tools/recipes/set_local_fw.rb +57 -0
  288. data/cookbooks/mu-tools/recipes/set_mu_hostname.rb +81 -0
  289. data/cookbooks/mu-tools/recipes/split_var_partitions.rb +86 -0
  290. data/cookbooks/mu-tools/recipes/splunk-client.rb +69 -0
  291. data/cookbooks/mu-tools/recipes/splunk-server.rb +104 -0
  292. data/cookbooks/mu-tools/recipes/store_inspec_attr.rb +8 -0
  293. data/cookbooks/mu-tools/recipes/updates.rb +96 -0
  294. data/cookbooks/mu-tools/recipes/windows-client.rb +202 -0
  295. data/cookbooks/mu-tools/resources/aws_windows.rb +33 -0
  296. data/cookbooks/mu-tools/resources/disk.rb +88 -0
  297. data/cookbooks/mu-tools/resources/mommacat_request.rb +11 -0
  298. data/cookbooks/mu-tools/resources/scheduled_tasks.rb +29 -0
  299. data/cookbooks/mu-tools/resources/sshd_service.rb +45 -0
  300. data/cookbooks/mu-tools/resources/windows_users.rb +242 -0
  301. data/cookbooks/mu-tools/templates/amazon/sshd_config.erb +168 -0
  302. data/cookbooks/mu-tools/templates/centos-6/sshd_config.erb +212 -0
  303. data/cookbooks/mu-tools/templates/centos-7/sshd_config.erb +215 -0
  304. data/cookbooks/mu-tools/templates/default/0-mu-log-client.conf.erb +13 -0
  305. data/cookbooks/mu-tools/templates/default/conf.maldet.erb +137 -0
  306. data/cookbooks/mu-tools/templates/default/etc_hosts.erb +30 -0
  307. data/cookbooks/mu-tools/templates/default/etc_pamd_password-auth.erb +14 -0
  308. data/cookbooks/mu-tools/templates/default/etc_pamd_system-auth.erb +14 -0
  309. data/cookbooks/mu-tools/templates/default/etc_sysconfig_network.erb +12 -0
  310. data/cookbooks/mu-tools/templates/default/kubeconfig.erb +29 -0
  311. data/cookbooks/mu-tools/templates/default/kubelet.service.erb +35 -0
  312. data/cookbooks/mu-tools/templates/default/maldet_scanall.sh.erb +15 -0
  313. data/cookbooks/mu-tools/templates/default/nrpe.cfg.erb +233 -0
  314. data/cookbooks/mu-tools/templates/redhat-6/sshd_config.erb +213 -0
  315. data/cookbooks/mu-tools/templates/redhat-7/sshd_config.erb +215 -0
  316. data/cookbooks/mu-tools/templates/ubuntu-12.04/sshd_config.erb +146 -0
  317. data/cookbooks/mu-tools/templates/ubuntu-14.04/sshd_config.erb +145 -0
  318. data/cookbooks/mu-tools/templates/windows/Backup.xml.erb +20 -0
  319. data/cookbooks/mu-tools/templates/windows/bkupInfo.xml.erb +1 -0
  320. data/cookbooks/mu-tools/templates/windows/gpreprt.xml.erb +214 -0
  321. data/cookbooks/mu-tools/templates/windows/gptmpl.inf.erb +12 -0
  322. data/cookbooks/mu-tools/templates/windows/manifest.xml.erb +1 -0
  323. data/cookbooks/mu-tools/templates/windows/set_ad_dns_scheduled_task.ps1.erb +6 -0
  324. data/cookbooks/mu-tools/templates/windows/sshd_config.erb +136 -0
  325. data/cookbooks/mu-utility/CHANGELOG.md +12 -0
  326. data/cookbooks/mu-utility/LICENSE +37 -0
  327. data/cookbooks/mu-utility/README.md +6 -0
  328. data/cookbooks/mu-utility/attributes/default.rb +1 -0
  329. data/cookbooks/mu-utility/libraries/matchers.rb +21 -0
  330. data/cookbooks/mu-utility/metadata.rb +16 -0
  331. data/cookbooks/mu-utility/recipes/apt.rb +23 -0
  332. data/cookbooks/mu-utility/recipes/cleanup_image_helper.rb +118 -0
  333. data/cookbooks/mu-utility/recipes/iptables.rb +26 -0
  334. data/cookbooks/mu-utility/recipes/luks.rb +18 -0
  335. data/cookbooks/mu-utility/recipes/nat.rb +104 -0
  336. data/cookbooks/mu-utility/recipes/php.rb +33 -0
  337. data/cookbooks/mu-utility/recipes/rdp_gateway.rb +83 -0
  338. data/cookbooks/mu-utility/recipes/remi.rb +44 -0
  339. data/cookbooks/mu-utility/recipes/vim.rb +26 -0
  340. data/cookbooks/mu-utility/recipes/windows_basics.rb +37 -0
  341. data/cookbooks/mu-utility/recipes/zip.rb +26 -0
  342. data/cookbooks/mu-utility/templates/default/BundleConfig.xml.erb +34 -0
  343. data/cookbooks/mu-utility/templates/default/config.xml.erb +60 -0
  344. data/cookbooks/nagios/Berksfile +8 -0
  345. data/cookbooks/nagios/CHANGELOG.md +589 -0
  346. data/cookbooks/nagios/CONTRIBUTING.md +11 -0
  347. data/cookbooks/nagios/LICENSE +37 -0
  348. data/cookbooks/nagios/README.md +328 -0
  349. data/cookbooks/nagios/TESTING.md +2 -0
  350. data/cookbooks/nagios/attributes/config.rb +171 -0
  351. data/cookbooks/nagios/attributes/default.rb +228 -0
  352. data/cookbooks/nagios/chefignore +102 -0
  353. data/cookbooks/nagios/definitions/command.rb +33 -0
  354. data/cookbooks/nagios/definitions/contact.rb +33 -0
  355. data/cookbooks/nagios/definitions/contactgroup.rb +33 -0
  356. data/cookbooks/nagios/definitions/host.rb +33 -0
  357. data/cookbooks/nagios/definitions/hostdependency.rb +33 -0
  358. data/cookbooks/nagios/definitions/hostescalation.rb +34 -0
  359. data/cookbooks/nagios/definitions/hostgroup.rb +33 -0
  360. data/cookbooks/nagios/definitions/nagios_conf.rb +38 -0
  361. data/cookbooks/nagios/definitions/resource.rb +33 -0
  362. data/cookbooks/nagios/definitions/service.rb +33 -0
  363. data/cookbooks/nagios/definitions/servicedependency.rb +33 -0
  364. data/cookbooks/nagios/definitions/serviceescalation.rb +34 -0
  365. data/cookbooks/nagios/definitions/servicegroup.rb +33 -0
  366. data/cookbooks/nagios/definitions/timeperiod.rb +33 -0
  367. data/cookbooks/nagios/libraries/base.rb +314 -0
  368. data/cookbooks/nagios/libraries/command.rb +91 -0
  369. data/cookbooks/nagios/libraries/contact.rb +230 -0
  370. data/cookbooks/nagios/libraries/contactgroup.rb +112 -0
  371. data/cookbooks/nagios/libraries/custom_option.rb +36 -0
  372. data/cookbooks/nagios/libraries/data_bag_helper.rb +23 -0
  373. data/cookbooks/nagios/libraries/default.rb +90 -0
  374. data/cookbooks/nagios/libraries/host.rb +412 -0
  375. data/cookbooks/nagios/libraries/hostdependency.rb +181 -0
  376. data/cookbooks/nagios/libraries/hostescalation.rb +173 -0
  377. data/cookbooks/nagios/libraries/hostgroup.rb +119 -0
  378. data/cookbooks/nagios/libraries/nagios.rb +282 -0
  379. data/cookbooks/nagios/libraries/resource.rb +59 -0
  380. data/cookbooks/nagios/libraries/service.rb +455 -0
  381. data/cookbooks/nagios/libraries/servicedependency.rb +215 -0
  382. data/cookbooks/nagios/libraries/serviceescalation.rb +195 -0
  383. data/cookbooks/nagios/libraries/servicegroup.rb +144 -0
  384. data/cookbooks/nagios/libraries/timeperiod.rb +160 -0
  385. data/cookbooks/nagios/libraries/users_helper.rb +54 -0
  386. data/cookbooks/nagios/metadata.rb +25 -0
  387. data/cookbooks/nagios/recipes/_load_databag_config.rb +153 -0
  388. data/cookbooks/nagios/recipes/_load_default_config.rb +241 -0
  389. data/cookbooks/nagios/recipes/apache.rb +48 -0
  390. data/cookbooks/nagios/recipes/default.rb +204 -0
  391. data/cookbooks/nagios/recipes/nginx.rb +82 -0
  392. data/cookbooks/nagios/recipes/pagerduty.rb +143 -0
  393. data/cookbooks/nagios/recipes/server_package.rb +40 -0
  394. data/cookbooks/nagios/recipes/server_source.rb +164 -0
  395. data/cookbooks/nagios/templates/default/apache2.conf.erb +96 -0
  396. data/cookbooks/nagios/templates/default/cgi.cfg.erb +266 -0
  397. data/cookbooks/nagios/templates/default/commands.cfg.erb +13 -0
  398. data/cookbooks/nagios/templates/default/contacts.cfg.erb +37 -0
  399. data/cookbooks/nagios/templates/default/hostgroups.cfg.erb +25 -0
  400. data/cookbooks/nagios/templates/default/hosts.cfg.erb +15 -0
  401. data/cookbooks/nagios/templates/default/htpasswd.users.erb +6 -0
  402. data/cookbooks/nagios/templates/default/nagios.cfg.erb +22 -0
  403. data/cookbooks/nagios/templates/default/nginx.conf.erb +62 -0
  404. data/cookbooks/nagios/templates/default/pagerduty.cgi.erb +185 -0
  405. data/cookbooks/nagios/templates/default/resource.cfg.erb +27 -0
  406. data/cookbooks/nagios/templates/default/servicedependencies.cfg.erb +15 -0
  407. data/cookbooks/nagios/templates/default/servicegroups.cfg.erb +14 -0
  408. data/cookbooks/nagios/templates/default/services.cfg.erb +14 -0
  409. data/cookbooks/nagios/templates/default/templates.cfg.erb +31 -0
  410. data/cookbooks/nagios/templates/default/timeperiods.cfg.erb +13 -0
  411. data/cookbooks/s3fs/CHANGELOG.md +13 -0
  412. data/cookbooks/s3fs/LICENSE +37 -0
  413. data/cookbooks/s3fs/README.md +6 -0
  414. data/cookbooks/s3fs/attributes/default.rb +15 -0
  415. data/cookbooks/s3fs/files/default/fuse-2.9.3.zip +0 -0
  416. data/cookbooks/s3fs/metadata.rb +16 -0
  417. data/cookbooks/s3fs/recipes/default.rb +91 -0
  418. data/data_bags/demo/app.json +7 -0
  419. data/data_bags/nagios_services/chef.json +6 -0
  420. data/data_bags/nagios_services/linux_diskspace.json +5 -0
  421. data/data_bags/nagios_services/momma_cat.json +6 -0
  422. data/data_bags/nagios_services/mu-master-memory.json +5 -0
  423. data/data_bags/nagios_services/nagios_ui.json +6 -0
  424. data/data_bags/nagios_services/node_ssh.json +6 -0
  425. data/data_bags/nagios_services/ssh.json +6 -0
  426. data/demo/lambda_test.yaml +29 -0
  427. data/environments/DEV.json +8 -0
  428. data/environments/PROD.json +8 -0
  429. data/environments/dev.json +8 -0
  430. data/environments/development.json +8 -0
  431. data/environments/prod.json +8 -0
  432. data/extras/README.md +1 -0
  433. data/extras/admin-role-binding.yaml +16 -0
  434. data/extras/admin-user.yaml +6 -0
  435. data/extras/aws-auth-cm.yaml.erb +12 -0
  436. data/extras/clean-stock-amis +48 -0
  437. data/extras/git-fix-permissions-hook +12 -0
  438. data/extras/gitlab-eks-helper.sh.erb +20 -0
  439. data/extras/image-generators/README.md +2 -0
  440. data/extras/image-generators/aws/centos6.yaml +18 -0
  441. data/extras/image-generators/aws/centos7-govcloud.yaml +24 -0
  442. data/extras/image-generators/aws/centos7.yaml +17 -0
  443. data/extras/image-generators/aws/rhel7.yaml +17 -0
  444. data/extras/image-generators/aws/win2k12.yaml +16 -0
  445. data/extras/image-generators/aws/win2k16.yaml +16 -0
  446. data/extras/image-generators/aws/windows.yaml +18 -0
  447. data/extras/image-generators/gcp/centos6.yaml +17 -0
  448. data/extras/lambda_waf_domain_blacklist.py +103 -0
  449. data/extras/platform_berksfile_base +50 -0
  450. data/extras/ruby_rpm/build.sh +17 -0
  451. data/extras/ruby_rpm/muby.spec +44 -0
  452. data/extras/vault_tools/README.md +6 -0
  453. data/extras/vault_tools/export_vaults.sh +3 -0
  454. data/extras/vault_tools/recreate_vaults.sh +5 -0
  455. data/extras/vault_tools/test_vaults.sh +5 -0
  456. data/install/README.md +8 -0
  457. data/install/cfn_create_mu_master.json +1034 -0
  458. data/install/chef-server.rb.erb +19 -0
  459. data/install/deprecated-bash-library.sh +1891 -0
  460. data/install/images/Usage.png +0 -0
  461. data/install/installer +71 -0
  462. data/install/jenkinskeys.rb +8 -0
  463. data/install/user-dot-murc.erb +14 -0
  464. data/modules/html.erb +19 -0
  465. data/modules/mommacat.ru +426 -0
  466. data/modules/mu/cleanup.rb +339 -0
  467. data/modules/mu/cloud.rb +1446 -0
  468. data/modules/mu/clouds/README.md +201 -0
  469. data/modules/mu/clouds/aws/alarm.rb +319 -0
  470. data/modules/mu/clouds/aws/cache_cluster.rb +1010 -0
  471. data/modules/mu/clouds/aws/collection.rb +373 -0
  472. data/modules/mu/clouds/aws/container_cluster.rb +667 -0
  473. data/modules/mu/clouds/aws/database.rb +1836 -0
  474. data/modules/mu/clouds/aws/dnszone.rb +911 -0
  475. data/modules/mu/clouds/aws/firewall_rule.rb +641 -0
  476. data/modules/mu/clouds/aws/folder.rb +92 -0
  477. data/modules/mu/clouds/aws/function.rb +349 -0
  478. data/modules/mu/clouds/aws/group.rb +251 -0
  479. data/modules/mu/clouds/aws/loadbalancer.rb +888 -0
  480. data/modules/mu/clouds/aws/log.rb +363 -0
  481. data/modules/mu/clouds/aws/msg_queue.rb +480 -0
  482. data/modules/mu/clouds/aws/notification.rb +139 -0
  483. data/modules/mu/clouds/aws/role.rb +656 -0
  484. data/modules/mu/clouds/aws/search_domain.rb +646 -0
  485. data/modules/mu/clouds/aws/server.rb +2294 -0
  486. data/modules/mu/clouds/aws/server_pool.rb +1388 -0
  487. data/modules/mu/clouds/aws/storage_pool.rb +495 -0
  488. data/modules/mu/clouds/aws/user.rb +382 -0
  489. data/modules/mu/clouds/aws/userdata/README.md +4 -0
  490. data/modules/mu/clouds/aws/userdata/linux.erb +179 -0
  491. data/modules/mu/clouds/aws/userdata/windows.erb +278 -0
  492. data/modules/mu/clouds/aws/vpc.rb +1943 -0
  493. data/modules/mu/clouds/aws.rb +1009 -0
  494. data/modules/mu/clouds/cloudformation/alarm.rb +146 -0
  495. data/modules/mu/clouds/cloudformation/cache_cluster.rb +167 -0
  496. data/modules/mu/clouds/cloudformation/collection.rb +117 -0
  497. data/modules/mu/clouds/cloudformation/database.rb +278 -0
  498. data/modules/mu/clouds/cloudformation/dnszone.rb +274 -0
  499. data/modules/mu/clouds/cloudformation/firewall_rule.rb +308 -0
  500. data/modules/mu/clouds/cloudformation/loadbalancer.rb +193 -0
  501. data/modules/mu/clouds/cloudformation/log.rb +170 -0
  502. data/modules/mu/clouds/cloudformation/server.rb +370 -0
  503. data/modules/mu/clouds/cloudformation/server_pool.rb +279 -0
  504. data/modules/mu/clouds/cloudformation/vpc.rb +322 -0
  505. data/modules/mu/clouds/cloudformation.rb +733 -0
  506. data/modules/mu/clouds/docker.rb +30 -0
  507. data/modules/mu/clouds/google/container_cluster.rb +290 -0
  508. data/modules/mu/clouds/google/database.rb +152 -0
  509. data/modules/mu/clouds/google/firewall_rule.rb +267 -0
  510. data/modules/mu/clouds/google/group.rb +164 -0
  511. data/modules/mu/clouds/google/loadbalancer.rb +479 -0
  512. data/modules/mu/clouds/google/server.rb +1510 -0
  513. data/modules/mu/clouds/google/server_pool.rb +274 -0
  514. data/modules/mu/clouds/google/user.rb +266 -0
  515. data/modules/mu/clouds/google/userdata/README.md +4 -0
  516. data/modules/mu/clouds/google/userdata/linux.erb +137 -0
  517. data/modules/mu/clouds/google/userdata/windows.erb +275 -0
  518. data/modules/mu/clouds/google/vpc.rb +890 -0
  519. data/modules/mu/clouds/google.rb +811 -0
  520. data/modules/mu/config/README.md +11 -0
  521. data/modules/mu/config/alarm.rb +271 -0
  522. data/modules/mu/config/cache_cluster.rb +172 -0
  523. data/modules/mu/config/collection.rb +87 -0
  524. data/modules/mu/config/container_cluster.rb +103 -0
  525. data/modules/mu/config/container_cluster.yml +36 -0
  526. data/modules/mu/config/database.rb +458 -0
  527. data/modules/mu/config/database.yml +26 -0
  528. data/modules/mu/config/dnszone.rb +327 -0
  529. data/modules/mu/config/firewall_rule.rb +118 -0
  530. data/modules/mu/config/folder.rb +70 -0
  531. data/modules/mu/config/function.rb +140 -0
  532. data/modules/mu/config/group.rb +64 -0
  533. data/modules/mu/config/loadbalancer.rb +482 -0
  534. data/modules/mu/config/log.rb +47 -0
  535. data/modules/mu/config/log.yml +6 -0
  536. data/modules/mu/config/msg_queue.rb +47 -0
  537. data/modules/mu/config/msg_queue.yml +9 -0
  538. data/modules/mu/config/notification.rb +44 -0
  539. data/modules/mu/config/project.rb +71 -0
  540. data/modules/mu/config/role.rb +102 -0
  541. data/modules/mu/config/search_domain.rb +61 -0
  542. data/modules/mu/config/search_domain.yml +25 -0
  543. data/modules/mu/config/server.rb +587 -0
  544. data/modules/mu/config/server.yml +8 -0
  545. data/modules/mu/config/server_pool.rb +216 -0
  546. data/modules/mu/config/server_pool.yml +71 -0
  547. data/modules/mu/config/storage_pool.rb +145 -0
  548. data/modules/mu/config/user.rb +78 -0
  549. data/modules/mu/config/vpc.rb +743 -0
  550. data/modules/mu/config/vpc.yml +6 -0
  551. data/modules/mu/config.rb +2000 -0
  552. data/modules/mu/defaults/README.md +2 -0
  553. data/modules/mu/defaults/amazon_images.yaml +121 -0
  554. data/modules/mu/defaults/google_images.yaml +16 -0
  555. data/modules/mu/deploy.rb +686 -0
  556. data/modules/mu/groomer.rb +123 -0
  557. data/modules/mu/groomers/README.md +58 -0
  558. data/modules/mu/groomers/chef.rb +1024 -0
  559. data/modules/mu/kittens.rb +11319 -0
  560. data/modules/mu/logger.rb +208 -0
  561. data/modules/mu/master/README.md +27 -0
  562. data/modules/mu/master/chef.rb +471 -0
  563. data/modules/mu/master/ldap.rb +1005 -0
  564. data/modules/mu/master.rb +415 -0
  565. data/modules/mu/mommacat.rb +2703 -0
  566. data/modules/mu-load-config.rb +1 -0
  567. data/modules/mu.rb +724 -0
  568. data/modules/scratchpad.erb +1 -0
  569. data/modules/tests/super_complex_bok.yml +41 -0
  570. data/modules/tests/super_simple_bok.yml +40 -0
  571. data/mu.gemspec +62 -0
  572. data/roles/demo-dbservice-configure.json +19 -0
  573. data/roles/demo-portal-configure.json +19 -0
  574. data/roles/mu-master-jenkins.json +24 -0
  575. data/roles/mu-master-nagios-only.json +13 -0
  576. data/roles/mu-master.json +12 -0
  577. data/roles/mu-node.json +19 -0
  578. data/roles/mu-splunk-server.json +13 -0
  579. data/roles/mu-splunk.json +13 -0
  580. data/test/clean_up.py +25 -0
  581. data/test/demo-test-profile/README.md +3 -0
  582. data/test/demo-test-profile/controls/flask.rb +84 -0
  583. data/test/demo-test-profile/inspec.lock +7 -0
  584. data/test/demo-test-profile/inspec.yml +11 -0
  585. data/test/etco-test-profile/README.md +3 -0
  586. data/test/etco-test-profile/controls/all-in-one.rb +182 -0
  587. data/test/etco-test-profile/inspec.lock +7 -0
  588. data/test/etco-test-profile/inspec.yml +11 -0
  589. data/test/exec_inspec.py +246 -0
  590. data/test/exec_mu_install.py +241 -0
  591. data/test/exec_retry.py +44 -0
  592. data/test/mu-master-test/README.md +3 -0
  593. data/test/mu-master-test/controls/all_in_one.rb +557 -0
  594. data/test/mu-master-test/inspec.lock +3 -0
  595. data/test/mu-master-test/inspec.yml +11 -0
  596. data/test/mu-tools-test/README.md +3 -0
  597. data/test/mu-tools-test/controls/base.rb +265 -0
  598. data/test/mu-tools-test/inspec.lock +3 -0
  599. data/test/mu-tools-test/inspec.yml +8 -0
  600. data/test/simple-server-php-test/README.md +3 -0
  601. data/test/simple-server-php-test/controls/apachephp.rb +25 -0
  602. data/test/simple-server-php-test/controls/example.rb +19 -0
  603. data/test/simple-server-php-test/inspec.lock +7 -0
  604. data/test/simple-server-php-test/inspec.yml +12 -0
  605. data/test/simple-server-rails-test/README.md +3 -0
  606. data/test/simple-server-rails-test/controls/rails.rb +188 -0
  607. data/test/simple-server-rails-test/inspec.lock +7 -0
  608. data/test/simple-server-rails-test/inspec.yml +11 -0
  609. data/test/simple-windows-test/README.md +3 -0
  610. data/test/simple-windows-test/controls/windows.rb +20 -0
  611. data/test/simple-windows-test/inspec.lock +7 -0
  612. data/test/simple-windows-test/inspec.yml +11 -0
  613. data/test/smoke_test.rb +75 -0
  614. data/test/wordpress-test/README.md +3 -0
  615. data/test/wordpress-test/controls/wordpress.rb +97 -0
  616. data/test/wordpress-test/inspec.lock +7 -0
  617. data/test/wordpress-test/inspec.yml +11 -0
  618. metadata +979 -0
@@ -0,0 +1,1010 @@
1
+ # Copyright:: Copyright (c) 2014 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 Cloud
17
+ class AWS
18
+ # A cache cluster as configured in {MU::Config::BasketofKittens::cache_clusters}
19
+ class CacheCluster < MU::Cloud::CacheCluster
20
+ @deploy = nil
21
+ @config = nil
22
+ attr_reader :mu_name
23
+ attr_reader :cloud_id
24
+ attr_reader :config
25
+
26
+ @cloudformation_data = {}
27
+ attr_reader :cloudformation_data
28
+
29
+ # @param mommacat [MU::MommaCat]: A {MU::Mommacat} object containing the deploy of which this resource is/will be a member.
30
+ # @param kitten_cfg [Hash]: The fully parsed and resolved {MU::Config} resource descriptor as defined in {MU::Config::BasketofKittens::cache_clusters}
31
+ def initialize(mommacat: nil, kitten_cfg: nil, mu_name: nil, cloud_id: nil)
32
+ @deploy = mommacat
33
+ @config = MU::Config.manxify(kitten_cfg)
34
+ @cloud_id ||= cloud_id
35
+ # @mu_name = mu_name ? mu_name : @deploy.getResourceName(@config["name"])
36
+
37
+ @mu_name ||=
38
+ if @config["create_replication_group"]
39
+ @deploy.getResourceName(@config["name"], max_length: 16, need_unique_string: true)
40
+ else
41
+ @deploy.getResourceName(@config["name"], max_length: 20, need_unique_string: true)
42
+ end
43
+
44
+ @mu_name.gsub!(/(--|-$)/i, "")
45
+ end
46
+
47
+ # Canonical Amazon Resource Number for this resource
48
+ # @return [String]
49
+ def arn
50
+ "arn:"+(MU::Cloud::AWS.isGovCloud?(@config["region"]) ? "aws-us-gov" : "aws")+":elasticache:"+@config['region']+":"+MU.account_number+":cluster/"+@cloud_id
51
+ end
52
+
53
+ # Locate an existing Cache Cluster or Cache Clusters and return an array containing matching AWS resource descriptors for those that match.
54
+ # @param cloud_id [String]: The cloud provider's identifier for this resource.
55
+ # @param region [String]: The cloud provider region.
56
+ # @param tag_key [String]: A tag key to search.
57
+ # @param tag_value [String]: The value of the tag specified by tag_key to match when searching by tag.
58
+ # @param flags [Hash]: Optional flags
59
+ # @return [Array<Hash<String,OpenStruct>>]: The cloud provider's complete descriptions of matching Cache Clusters.
60
+ def self.find(cloud_id: nil, region: MU.curRegion, tag_key: "Name", tag_value: nil, flags: {})
61
+ map = {}
62
+ if cloud_id
63
+ cache_cluster = MU::Cloud::AWS::CacheCluster.getCacheClusterById(cloud_id, region: region)
64
+ map[cloud_id] = cache_cluster if cache_cluster
65
+ end
66
+
67
+ if tag_value
68
+ MU::Cloud::AWS.elasticache(region).describe_cache_clusters.cache_clusters.each { |cc|
69
+ resp = MU::Cloud::AWS.elasticache(region).list_tags_for_resource(
70
+ resource_name: MU::Cloud::AWS::CacheCluster.getARN(cc.cache_cluster_id, "cluster", "elasticache", region: region)
71
+ )
72
+ if resp && resp.tag_list && !resp.tag_list.empty?
73
+ resp.tag_list.each { |tag|
74
+ map[cc.cache_cluster_id] = cc if tag.key == tag_key and tag.value == tag_value
75
+ }
76
+ end
77
+ }
78
+ end
79
+
80
+ return map
81
+ end
82
+
83
+ # Construct an Amazon Resource Name for an AWS resource.
84
+ # Some APIs require this identifier in order to do things that other APIs can do with shorthand.
85
+ # @param resource [String]: The name of the resource
86
+ # @param client_type [String]: The name of the client (eg. elasticache, rds, ec2, s3)
87
+ # @param resource_type [String]: The type of the resource
88
+ # @param region [String]: The region in which the resource resides.
89
+ # @param account_number [String]: The account in which the resource resides.
90
+ # @return [String]
91
+ def self.getARN(resource, resource_type, client_type, region: MU.curRegion, account_number: MU.account_number)
92
+ aws_str = MU::Cloud::AWS.isGovCloud?(region) ? "aws-us-gov" : "aws"
93
+ "arn:#{aws_str}:#{client_type}:#{region}:#{account_number}:#{resource_type}:#{resource}"
94
+ end
95
+
96
+ # Construct all our tags.
97
+ # @return [Array]: All our standard tags and any custom tags.
98
+ def allTags
99
+ tags = []
100
+ MU::MommaCat.listStandardTags.each_pair { |name, value|
101
+ tags << {key: name, value: value}
102
+ }
103
+
104
+ if @config['optional_tags']
105
+ MU::MommaCat.listOptionalTags.each_pair { |name, value|
106
+ tags << {key: name, value: value}
107
+ }
108
+ end
109
+
110
+ if @config['tags']
111
+ @config['tags'].each { |tag|
112
+ tags << {key: tag['key'], value: tag['value']}
113
+ }
114
+ end
115
+
116
+ return tags
117
+ end
118
+
119
+ # Add our standard tag set to an Amazon ElasticCache resource.
120
+ # @param resource [String]: The name of the resource
121
+ # @param resource_type [String]: The type of the resource
122
+ # @param region [String]: The cloud provider region
123
+ def addStandardTags(resource, resource_type, region: MU.curRegion)
124
+ MU.log "Adding tags to ElasticCache resource #{resource}"
125
+ MU::Cloud::AWS.elasticache(region).add_tags_to_resource(
126
+ resource_name: MU::Cloud::AWS::CacheCluster.getARN(resource, resource_type, "elasticache", region: region),
127
+ tags: allTags
128
+ )
129
+ end
130
+
131
+ # Called automatically by {MU::Deploy#createResources}
132
+ # @return [String]: The cloud provider's identifier for this cache cluster instance.
133
+ def create
134
+ @config["snapshot_id"] =
135
+ if @config["creation_style"] == "existing_snapshot"
136
+ getExistingSnapshot ? getExistingSnapshot : createNewSnapshot
137
+ elsif @config["creation_style"] == "new_snapshot"
138
+ createNewSnapshot
139
+ end
140
+
141
+ # Should we base all our resource names on @mu_name even though only the cache cluster / cache replication group identifiers are the isssue?
142
+ @config['identifier'] = @mu_name
143
+ @config["subnet_group_name"] = @mu_name
144
+ createSubnetGroup
145
+
146
+ # Shared configuration elements between cache clusters and cache replication groups
147
+ config_struct = {
148
+ cache_node_type: @config["size"],
149
+ engine: @config["engine"],
150
+ engine_version: @config["engine_version"],
151
+ cache_subnet_group_name: @config["subnet_group_name"],
152
+ preferred_maintenance_window: @config["preferred_maintenance_window"],
153
+ port: @config["port"],
154
+ auto_minor_version_upgrade: @config["auto_minor_version_upgrade"],
155
+ security_group_ids: @config["security_group_ids"],
156
+ tags: allTags
157
+ }
158
+
159
+ if @config["engine"] == "redis"
160
+ config_struct[:snapshot_name] = @config["snapshot_id"] if @config["snapshot_id"]
161
+ config_struct[:snapshot_arns] = @config["snapshot_arn"] if @config["snapshot_arn"]
162
+ config_struct[:snapshot_retention_limit] = @config["snapshot_retention_limit"] if @config["snapshot_retention_limit"]
163
+ config_struct[:snapshot_window] = @config["snapshot_window"] if @config["snapshot_window"]
164
+ end
165
+
166
+ if @config.has_key?("parameter_group_family")
167
+ # downcasing parameter_group_name because AWS downcases the name for us and we won't be able to find it.
168
+ # AWS downcases all resource names in ElastiCache for some reason,
169
+ # but other resources don't seem to be case sensitive when we try to retrieve them.
170
+ @config["parameter_group_name"] = @mu_name.downcase
171
+ createParameterGroup
172
+ config_struct[:cache_parameter_group_name] = @config["parameter_group_name"]
173
+ end
174
+
175
+ config_struct[:notification_topic_arn] = @config["notification_topic_arn"] if @config["notification_topic_arn"]
176
+
177
+ # Mu already cleans up our resources for us when we fail mid creation, so not doing begin/ensure to cleanup in case we fail.
178
+ if @config["create_replication_group"]
179
+ config_struct[:automatic_failover_enabled] = @config['automatic_failover']
180
+ config_struct[:replication_group_id] = @config['identifier']
181
+ config_struct[:replication_group_description] = @mu_name
182
+ config_struct[:num_cache_clusters] = @config["node_count"]
183
+ # config_struct[:primary_cluster_id] = @config["primary_cluster_id"]
184
+ # config_struct[:preferred_cache_cluster_a_zs] = @config["preferred_cache_cluster_azs"]
185
+
186
+ MU.log "Creating cache replication group #{@config['identifier']}"
187
+ resp = MU::Cloud::AWS.elasticache(@config['region']).create_replication_group(config_struct).replication_group
188
+
189
+ wait_start_time = Time.now
190
+ retries = 0
191
+ begin
192
+ MU::Cloud::AWS.elasticache(@config['region']).wait_until(:replication_group_available, replication_group_id: @config['identifier']) do |waiter|
193
+ waiter.max_attempts = nil
194
+ waiter.before_attempt do |attempts|
195
+ MU.log "Waiting for cache replication group #{@config['identifier']} to become available", MU::NOTICE if attempts % 5 == 0
196
+ end
197
+ waiter.before_wait do |attempts, resp|
198
+ throw :success if resp.replication_groups.first.status == "available"
199
+ throw :failure if Time.now - wait_start_time > 1800
200
+ end
201
+ end
202
+ rescue Aws::Waiters::Errors::TooManyAttemptsError => e
203
+ raise MuError, "Waited #{(Time.now - wait_start_time).round/60*(retries+1)} minutes for #{@config['identifier']} become available, giving up. #{e}" if retries > 2
204
+ wait_start_time = Time.now
205
+ retries += 1
206
+ retry
207
+ end
208
+
209
+ resp = MU::Cloud::AWS::CacheCluster.getCacheReplicationGroupById(@config['identifier'], region: @config['region'])
210
+
211
+ # We want to make sure the clusters in the cache replication group get our tags
212
+ resp.member_clusters.each { |member|
213
+ addStandardTags(member, "cluster", region: @config['region'])
214
+ }
215
+
216
+ MU::Cloud::AWS::DNSZone.genericMuDNSEntry(
217
+ name: resp.replication_group_id,
218
+ target: "#{resp.node_groups.first.primary_endpoint.address}.",
219
+ cloudclass: MU::Cloud::CacheCluster,
220
+ sync_wait: @config['dns_sync_wait']
221
+ )
222
+
223
+ resp.node_groups.first.node_group_members.each { |member|
224
+ MU::Cloud::AWS::DNSZone.genericMuDNSEntry(
225
+ name: member.cache_cluster_id,
226
+ target: "#{member.read_endpoint.address}.",
227
+ cloudclass: MU::Cloud::CacheCluster,
228
+ sync_wait: @config['dns_sync_wait']
229
+ )
230
+
231
+ }
232
+
233
+ MU.log "Cache replication group #{@config['identifier']} is ready to use"
234
+ @cloud_id = resp.replication_group_id
235
+ else
236
+ config_struct[:cache_cluster_id] = @config['identifier']
237
+ config_struct[:az_mode] = @config["az_mode"]
238
+ config_struct[:num_cache_nodes] = @config["node_count"]
239
+ # config_struct[:replication_group_id] = @config["replication_group_id"] if @config["replication_group_id"]
240
+ # config_struct[:preferred_availability_zone] = @config["preferred_availability_zone"] if @config["preferred_availability_zone"] && @config["az_mode"] == "single-az"
241
+ # config_struct[:preferred_availability_zones] = @config["preferred_availability_zones"] if @config["preferred_availability_zones"] && @config["az_mode"] == "cross-az"
242
+
243
+ MU.log "Creating cache cluster #{@config['identifier']}"
244
+ resp = MU::Cloud::AWS.elasticache(@config['region']).create_cache_cluster(config_struct).cache_cluster
245
+
246
+ wait_start_time = Time.now
247
+ retries = 0
248
+ begin
249
+ MU::Cloud::AWS.elasticache(@config['region']).wait_until(:cache_cluster_available, cache_cluster_id: @config['identifier']) do |waiter|
250
+ waiter.max_attempts = nil
251
+ waiter.before_attempt do |attempts|
252
+ MU.log "Waiting for cache cluster #{@config['identifier']} to become available", MU::NOTICE if attempts % 5 == 0
253
+ end
254
+ waiter.before_wait do |attempts, resp|
255
+ throw :success if resp.cache_clusters.first.cache_cluster_status == "available"
256
+ throw :failure if Time.now - wait_start_time > 1800
257
+ end
258
+ end
259
+ rescue Aws::Waiters::Errors::TooManyAttemptsError => e
260
+ raise MuError, "Waited #{(Time.now - wait_start_time).round/60*(retries+1)} minutes for #{@config['identifier']} to become available, giving up. #{e}" if retries > 2
261
+ wait_start_time = Time.now
262
+ retries += 1
263
+ retry
264
+ end
265
+
266
+ resp = MU::Cloud::AWS::CacheCluster.getCacheClusterById(@config['identifier'], region: @config['region'])
267
+ MU.log "Cache Cluster #{@config['identifier']} is ready to use"
268
+ @cloud_id = resp.cache_cluster_id
269
+ end
270
+ end
271
+
272
+ # Create a subnet group for a Cache Cluster with the given config.
273
+ def createSubnetGroup
274
+ subnet_ids = []
275
+
276
+ if @config["vpc"] && !@config["vpc"].empty?
277
+ raise MuError, "Didn't find the VPC specified in #{@config["vpc"]}" unless @vpc
278
+
279
+ vpc_id = @vpc.cloud_id
280
+
281
+ # Getting subnet IDs
282
+ if @config["vpc"]["subnets"].empty?
283
+ @vpc.subnets.each { |subnet|
284
+ subnet_ids << subnet.cloud_id
285
+ }
286
+ MU.log "No subnets specified for #{@config['identifier']}, adding all subnets in #{@vpc}", MU::DEBUG
287
+ else
288
+ @config["vpc"]["subnets"].each { |subnet|
289
+ subnet_obj = @vpc.getSubnet(cloud_id: subnet["subnet_id"].to_s, name: subnet["subnet_name"].to_s)
290
+ raise MuError, "Couldn't find a live subnet matching #{subnet} in #{@vpc} (#{@vpc.subnets})" if subnet_obj.nil?
291
+ subnet_ids << subnet_obj.cloud_id
292
+ }
293
+ end
294
+ else
295
+ # If we didn't specify a VPC try to figure out if the account has a default VPC
296
+ vpc_id = nil
297
+ subnets = []
298
+ MU::Cloud::AWS.ec2(@config['region']).describe_vpcs.vpcs.each { |vpc|
299
+ if vpc.is_default
300
+ vpc_id = vpc.vpc_id
301
+ subnets = MU::Cloud::AWS.ec2(@config['region']).describe_subnets(
302
+ filters: [
303
+ {
304
+ name: "vpc-id",
305
+ values: [vpc_id]
306
+ }
307
+ ]
308
+ ).subnets
309
+ break
310
+ end
311
+ }
312
+
313
+ if !subnets.empty?
314
+ mu_subnets = []
315
+ subnets.each { |subnet|
316
+ subnet_ids << subnet.subnet_id
317
+ mu_subnets << {"subnet_id" => subnet.subnet_id}
318
+ }
319
+
320
+ @config['vpc'] = {
321
+ "vpc_id" => vpc_id,
322
+ "subnets" => mu_subnets
323
+ }
324
+ using_default_vpc = true
325
+ MU.log "Using default VPC for cache cluster #{@config['identifier']}"
326
+ end
327
+ end
328
+
329
+ if subnet_ids.empty?
330
+ raise MuError, "Can't create subnet group #{@config["subnet_group_name"]} because I couldn't find a VPC or subnets"
331
+ else
332
+ MU.log "Creating subnet group #{@config["subnet_group_name"]} for cache cluster #{@config['identifier']}"
333
+
334
+ resp = MU::Cloud::AWS.elasticache(@config['region']).create_cache_subnet_group(
335
+ cache_subnet_group_name: @config["subnet_group_name"],
336
+ cache_subnet_group_description: @config["subnet_group_name"],
337
+ subnet_ids: subnet_ids
338
+ )
339
+
340
+ # Find NAT and create holes in security groups.
341
+ # Adding just for consistency, but do we really need this for cache clusters? I guess Nagios and such..
342
+ if @config["vpc"]["nat_host_name"] || @config["vpc"]["nat_host_id"] || @config["vpc"]["nat_host_tag"] || @config["vpc"]["nat_host_ip"]
343
+ nat = @nat
344
+ if nat.is_a?(Struct) && nat.nat_gateway_id && nat.nat_gateway_id.start_with?("nat-")
345
+ MU.log "Using NAT Gateway, not modifying security groups"
346
+ else
347
+ nat_name, nat_conf, nat_deploydata = @nat.describe
348
+ @deploy.kittens['firewall_rules'].each_pair { |name, acl|
349
+ # XXX if a user doesn't set up dependencies correctly, this can die horribly on a NAT that's still in mid-creation. Fix this... possibly in the config parser.
350
+ if acl.config["admin"]
351
+ acl.addRule([nat_deploydata["private_ip_address"]], proto: "tcp")
352
+ acl.addRule([nat_deploydata["private_ip_address"]], proto: "udp")
353
+ break
354
+ end
355
+ }
356
+ end
357
+ end
358
+
359
+ if @dependencies.has_key?('firewall_rule')
360
+ @config["security_group_ids"] = []
361
+ @dependencies['firewall_rule'].values.each { |sg|
362
+ @config["security_group_ids"] << sg.cloud_id
363
+ }
364
+ end
365
+ end
366
+ end
367
+
368
+ # Create a Cache Cluster parameter group.
369
+ def createParameterGroup
370
+ MU.log "Creating a cache cluster parameter group #{@config["parameter_group_name"]}"
371
+ resp = MU::Cloud::AWS.elasticache(@config['region']).create_cache_parameter_group(
372
+ cache_parameter_group_name: @config["parameter_group_name"],
373
+ cache_parameter_group_family: @config["parameter_group_family"],
374
+ description: "Parameter group for #{@config["parameter_group_family"]}"
375
+ )
376
+
377
+ if @config.has_key?("parameter_group_parameters") && !@config["parameter_group_parameters"].empty?
378
+ params = []
379
+ @config["parameter_group_parameters"].each { |item|
380
+ params << {parameter_name: item['name'], parameter_value: item['value']}
381
+ }
382
+
383
+ MU.log "Modifiying cache cluster parameter group #{@config["parameter_group_name"]}"
384
+ MU::Cloud::AWS.elasticache(@config['region']).modify_cache_parameter_group(
385
+ cache_parameter_group_name: @config["parameter_group_name"],
386
+ parameter_name_values: params
387
+ )
388
+ end
389
+ end
390
+
391
+ # Retrieve a Cache Cluster parameter group name of on existing parameter group.
392
+ # @return [String]: Cache Cluster parameter group name.
393
+ def getParameterGroup
394
+ MU::Cloud::AWS.elasticache(@config['region']).describe_cache_parameter_groups(
395
+ cache_parameter_group_name: @config["parameter_group_name"]
396
+ ).cache_parameter_groups.first.cache_parameter_group_name
397
+ end
398
+
399
+ # Called automatically by {MU::Deploy#createResources}
400
+ def groom
401
+ # Do we have anything to do here??
402
+ end
403
+
404
+ # Retrieve the complete cloud provider description of a cache cluster.
405
+ # @param cc_id [String]: The cloud provider's identifier for this cache cluster.
406
+ # @param region [String]: The cloud provider's region.
407
+ # @return [OpenStruct]
408
+ def self.getCacheClusterById(cc_id, region: MU.curRegion)
409
+ MU::Cloud::AWS.elasticache(region).describe_cache_clusters(cache_cluster_id: cc_id).cache_clusters.first
410
+ end
411
+
412
+ # Retrieve the complete cloud provider description of a cache replication group.
413
+ # @param repl_group_id [String]: The cloud provider's identifier for this cache replication group.
414
+ # @param region [String]: The cloud provider's region.
415
+ # @return [OpenStruct]
416
+ def self.getCacheReplicationGroupById(repl_group_id, region: MU.curRegion)
417
+ MU::Cloud::AWS.elasticache(region).describe_replication_groups(replication_group_id: repl_group_id).replication_groups.first
418
+ end
419
+
420
+ # Register a description of this cache cluster / cache replication group with this deployment's metadata.
421
+ def notify
422
+ ### TO DO: Flatten the replication group deployment metadata structure. It is probably waaaaaaay too nested.
423
+ if @config["create_replication_group"]
424
+ repl_group = MU::Cloud::AWS::CacheCluster.getCacheReplicationGroupById(@config['identifier'], region: @config['region'])
425
+ # DNS records for the "real" zone should always be registered as late as possible so override_existing only overwrites the records after the resource is ready to use.
426
+ if @config['dns_records']
427
+ @config['dns_records'].each { |dnsrec|
428
+ dnsrec['name'] = repl_group.node_groups.first.primary_endpoint.address.downcase if !dnsrec.has_key?('name')
429
+ dnsrec['name'] = "#{dnsrec['name']}.#{MU.environment.downcase}" if dnsrec["append_environment_name"] && !dnsrec['name'].match(/\.#{MU.environment.downcase}$/)
430
+ }
431
+ end
432
+ # XXX this should be a call to @deploy.nameKitten
433
+ MU::Cloud::AWS::DNSZone.createRecordsFromConfig(@config['dns_records'], target: repl_group.node_groups.first.primary_endpoint.address)
434
+
435
+ deploy_struct = {
436
+ "identifier" => repl_group.replication_group_id,
437
+ "create_style" => @config["create_style"],
438
+ "region" => @config["region"],
439
+ "members" => repl_group.member_clusters,
440
+ "automatic_failover" => repl_group.automatic_failover,
441
+ "snapshotting_cluster_id" => repl_group.snapshotting_cluster_id,
442
+ "primary_endpoint" => repl_group.node_groups.first.primary_endpoint.address,
443
+ "primary_port" => repl_group.node_groups.first.primary_endpoint.port
444
+ }
445
+
446
+ repl_group.member_clusters.each { |id|
447
+ cluster = MU::Cloud::AWS::CacheCluster.getCacheClusterById(id, region: @config['region'])
448
+
449
+ vpc_sg_ids = []
450
+ cluster.security_groups.each { |vpc_sg|
451
+ vpc_sg_ids << vpc_sg.security_group_id
452
+ }
453
+
454
+ cache_sg_ids = []
455
+ unless cluster.cache_security_groups.empty?
456
+ cluster.cache_security_groups.each { |cache_sg|
457
+ cache_sg_ids << cache_sg.security_group_id
458
+ }
459
+ end
460
+
461
+ deploy_struct[id] = {
462
+ "configuration_endpoint" => cluster.configuration_endpoint,
463
+ "cache_node_type" => cluster.cache_node_type,
464
+ "engine" => cluster.engine,
465
+ "engine_version" => cluster.engine_version,
466
+ "num_cache_nodes" => cluster.num_cache_nodes,
467
+ "preferred_maintenance_window" => cluster.preferred_maintenance_window,
468
+ "notification_configuration" => cluster.notification_configuration,
469
+ "cache_security_groups" => cache_sg_ids,
470
+ "cache_parameter_group" => cluster.cache_parameter_group.cache_parameter_group_name,
471
+ "cache_subnet_group_name" => cluster.cache_subnet_group_name,
472
+ "cache_nodes" => cluster.cache_nodes,
473
+ "auto_minor_version_upgrade" => cluster.auto_minor_version_upgrade,
474
+ "vpc_security_groups" => vpc_sg_ids,
475
+ "replication_group_id" => cluster.replication_group_id,
476
+ "snapshot_retention_limit" => cluster.snapshot_retention_limit,
477
+ "snapshot_window" => cluster.snapshot_window
478
+ }
479
+ }
480
+
481
+ repl_group.node_groups.first.node_group_members.each{ |member|
482
+ deploy_struct[member.cache_cluster_id]["cache_node_id"] = member.cache_node_id
483
+ deploy_struct[member.cache_cluster_id]["read_endpoint_address"] = member.read_endpoint.address
484
+ deploy_struct[member.cache_cluster_id]["read_endpoint_port"] = member.read_endpoint.port
485
+ deploy_struct[member.cache_cluster_id]["current_role"] = member.current_role
486
+ }
487
+ else
488
+ cluster = MU::Cloud::AWS::CacheCluster.getCacheClusterById(@config['identifier'], region: @config['region'])
489
+ vpc_sg_ids = []
490
+ cluster.security_groups.each { |vpc_sg|
491
+ vpc_sg_ids << vpc_sg.security_group_id
492
+ }
493
+
494
+ cache_sg_ids = []
495
+ unless cluster.cache_security_groups.empty?
496
+ cluster.cache_security_groups.each { |cache_sg|
497
+ cache_sg_ids << cache_sg.security_group_id
498
+ }
499
+ end
500
+
501
+ deploy_struct = {
502
+ "cache_node_type" => cluster.cache_node_type,
503
+ "engine" => cluster.engine,
504
+ "engine_version" => cluster.engine_version,
505
+ "num_cache_nodes" => cluster.num_cache_nodes,
506
+ "preferred_maintenance_window" => cluster.preferred_maintenance_window,
507
+ "notification_configuration" => cluster.notification_configuration,
508
+ "cache_security_groups" => cache_sg_ids,
509
+ "cache_parameter_group" => cluster.cache_parameter_group.cache_parameter_group_name,
510
+ "cache_subnet_group_name" => cluster.cache_subnet_group_name,
511
+ "cache_nodes" => cluster.cache_nodes,
512
+ "auto_minor_version_upgrade" => cluster.auto_minor_version_upgrade,
513
+ "vpc_security_groups" => vpc_sg_ids,
514
+ "replication_group_id" => cluster.replication_group_id,
515
+ "snapshot_retention_limit" => cluster.snapshot_retention_limit,
516
+ "snapshot_window" => cluster.snapshot_window
517
+ }
518
+ if !cluster.configuration_endpoint.nil?
519
+ deploy_struct["configuration_endpoint_address"] = cluster.configuration_endpoint.address
520
+ deploy_struct["configuration_endpoint_port"] = cluster.configuration_endpoint.port
521
+ end
522
+ end
523
+
524
+ return deploy_struct
525
+ end
526
+
527
+ # Generate a snapshot from the Cache Cluster described in this instance.
528
+ # @return [String]: The cloud provider's identifier for the snapshot.
529
+ def createNewSnapshot
530
+ snap_id = @deploy.getResourceName(@config["name"]) + Time.new.strftime("%M%S").to_s
531
+
532
+ attempts = 0
533
+ begin
534
+ snapshot = MU::Cloud::AWS.elasticache(@config['region']).create_snapshot(
535
+ cache_cluster_id: @config["identifier"],
536
+ snapshot_name: snap_id
537
+ )
538
+ rescue Aws::ElastiCache::Errors::InvalidCacheClusterState => e
539
+ if attempts < 10
540
+ MU.log "Tried to create snapshot for #{@config["identifier"]} but cache cluster is busy, retrying a few times"
541
+ attempts += 1
542
+ sleep 30
543
+ retry
544
+ else
545
+ raise MuError, "Failed to create snpashot for cache cluster #{@config["identifier"]}: #{e.inspect}"
546
+ end
547
+ end
548
+
549
+ attempts = 0
550
+ loop do
551
+ MU.log "Waiting for snapshot of cache cluster #{@config["identifier"]} to be ready...", MU::NOTICE if attempts % 20 == 0
552
+ MU.log "Waiting for snapshot of cache cluster #{@config["identifier"]} to be ready...", MU::DEBUG
553
+
554
+ snapshot_resp = MU::Cloud::AWS.elasticache(@config['region']).describe_snapshots(snapshot_name: snap_id)
555
+ attempts += 1
556
+ break unless snapshot_resp.snapshots.first.snapshot_status != "available"
557
+ sleep 15
558
+ end
559
+
560
+ return snap_id
561
+ end
562
+
563
+ # @return [String]: The cloud provider's identifier for the snapshot.
564
+ def getExistingSnapshot
565
+ MU::Cloud::AWS.elasticache(@config['region']).describe_snapshots(snapshot_name: @config["identifier"]).snapshots.first.snapshot_name
566
+ rescue NoMethodError
567
+ raise MuError, "Snapshot #{@config["identifier"]} doesn't exist, make sure you provided a valid snapshot ID/Name"
568
+ end
569
+
570
+ # Called by {MU::Cleanup}. Locates resources that were created by the currently-loaded deployment and purges them.
571
+ # @param noop [Boolean]: If true, will only print what would be done.
572
+ # @param ignoremaster [Boolean]: If true, will remove resources not flagged as originating from this Mu server.
573
+ # @param region [String]: The cloud provider's region in which to operate.
574
+ # @return [void]
575
+ def self.cleanup(skipsnapshots: false, noop: false, ignoremaster: false, region: MU.curRegion, flags: {})
576
+ all_clusters = MU::Cloud::AWS.elasticache(region).describe_cache_clusters
577
+ our_clusters = []
578
+ our_replication_group_ids = []
579
+
580
+ # Because we can't run list_tags_for_resource on a cache cluster that isn't in "available" state we're loading the deploy to make sure we have a cache cluster to cleanup.
581
+ # To ensure we don't miss cache clusters that have been terminated mid creation we'll load the 'original_config'. We might want to find a better approach for this.
582
+ deploy = MU::MommaCat.getLitter(MU.deploy_id)
583
+ if deploy.original_config && deploy.original_config.has_key?("cache_clusters") && !deploy.original_config["cache_clusters"].empty?
584
+
585
+ # The ElastiCache API and documentation are a mess, the replication group ARN resource_type is not documented, and is not easily guessable.
586
+ # So instead of searching for replication groups directly we'll get their IDs from the cache clusters.
587
+ all_clusters.cache_clusters.each { |cluster|
588
+ cluster_id = cluster.cache_cluster_id
589
+
590
+ # ElastiCache API is buggy... It will throw a CacheClusterNotFound if we run list_tags_for_resource on a cahe cluster that isn't in an "available" state.
591
+ if cluster.cache_cluster_status != "available"
592
+ if %w{deleting deleted}.include?(cluster.cache_cluster_status)
593
+ # The cahe cluster might not be ours so don't notify us about it.
594
+ next
595
+ else
596
+ # We can replace this with an AWS waiter.
597
+ loop do
598
+ MU.log "Waiting for #{cluster_id} to be in a removable state", MU::NOTICE
599
+ cluster = MU::Cloud::AWS::CacheCluster.getCacheClusterById(cluster_id, region: region)
600
+ break unless %w{creating modifying backing-up}.include?(cluster.cache_cluster_status)
601
+ sleep 60
602
+ end
603
+ end
604
+ end
605
+
606
+ arn = MU::Cloud::AWS::CacheCluster.getARN(cluster_id, "cluster", "elasticache", region: region)
607
+ attempts = 0
608
+
609
+ begin
610
+ tags = MU::Cloud::AWS.elasticache(region).list_tags_for_resource(resource_name: arn).tag_list
611
+ rescue Aws::ElastiCache::Errors::CacheClusterNotFound => e
612
+ if attempts < 10
613
+ MU.log "Can't get tags for #{cluster_id}, retrying a few times in case of a lagging resource", MU::WARN
614
+ MU.log "arn #{arn}", MU::WARN
615
+ attempts += 1
616
+ sleep 30
617
+ retry
618
+ else
619
+ raise MuError, "Failed to get tags for cache cluster #{cluster_id}, MU-ID #{MU.deploy_id}: #{e.inspect}"
620
+ end
621
+ end
622
+
623
+ found_muid = false
624
+ found_master = false
625
+ tags.each { |tag|
626
+ found_muid = true if tag.key == "MU-ID" && tag.value == MU.deploy_id
627
+ found_master = true if tag.key == "MU-MASTER-IP" && tag.value == MU.mu_public_ip
628
+ }
629
+ next if !found_muid
630
+
631
+ delete =
632
+ if ignoremaster && found_muid
633
+ true
634
+ elsif !ignoremaster && found_muid && found_master
635
+ true
636
+ else
637
+ false
638
+ end
639
+
640
+ if delete
641
+ cluster.replication_group_id ? our_replication_group_ids << cluster.replication_group_id : our_clusters << cluster
642
+ end
643
+ }
644
+
645
+ threads = []
646
+
647
+ # Make sure we have only uniqe replication group IDs
648
+ our_replication_group_ids = our_replication_group_ids.uniq
649
+ if !our_replication_group_ids.empty?
650
+ our_replication_group_ids.each { |group_id|
651
+ replication_group = MU::Cloud::AWS::CacheCluster.getCacheReplicationGroupById(group_id, region: region)
652
+ parent_thread_id = Thread.current.object_id
653
+ threads << Thread.new(replication_group) { |myrepl_group|
654
+ MU.dupGlobals(parent_thread_id)
655
+ Thread.abort_on_exception = true
656
+ MU::Cloud::AWS::CacheCluster.terminate_replication_group(myrepl_group, noop: noop, skipsnapshots: skipsnapshots, region: region, deploy_id: MU.deploy_id, cloud_id: myrepl_group.replication_group_id)
657
+ }
658
+ }
659
+ end
660
+
661
+ # Hmmmm. Do we need to have seperate thread groups for clusters and replication groups?
662
+ if !our_clusters.empty?
663
+ our_clusters.each { |cluster|
664
+ parent_thread_id = Thread.current.object_id
665
+ threads << Thread.new(cluster) { |mycluster|
666
+ MU.dupGlobals(parent_thread_id)
667
+ Thread.abort_on_exception = true
668
+ MU::Cloud::AWS::CacheCluster.terminate_cache_cluster(mycluster, noop: noop, skipsnapshots: skipsnapshots, region: region, deploy_id: MU.deploy_id, cloud_id: mycluster.cache_cluster_id)
669
+ }
670
+ }
671
+ end
672
+
673
+ # Wait for all of the cache cluster and replication groups to finish cleanup before proceeding
674
+ threads.each { |t|
675
+ t.join
676
+ }
677
+ end
678
+ end
679
+
680
+ # Cloud-specific configuration properties.
681
+ # @param config [MU::Config]: The calling MU::Config object
682
+ # @return [Array<Array,Hash>]: List of required fields, and json-schema Hash of cloud-specific configuration parameters for this resource
683
+ def self.schema(config)
684
+ toplevel_required = []
685
+ schema = {
686
+ "ingress_rules" => {
687
+ "items" => {
688
+ "properties" => {
689
+ "sgs" => {
690
+ "type" => "array",
691
+ "items" => {
692
+ "description" => "Other AWS Security Groups; resources that are associated with this group will have this rule applied to their traffic",
693
+ "type" => "string"
694
+ }
695
+ },
696
+ "lbs" => {
697
+ "type" => "array",
698
+ "items" => {
699
+ "description" => "AWS Load Balancers which will have this rule applied to their traffic",
700
+ "type" => "string"
701
+ }
702
+ }
703
+ }
704
+ }
705
+ }
706
+ }
707
+ [toplevel_required, schema]
708
+ end
709
+
710
+ # Cloud-specific pre-processing of {MU::Config::BasketofKittens::cache_clusters}, bare and unvalidated.
711
+ # @param cache [Hash]: The resource to process and validate
712
+ # @param configurator [MU::Config]: The overall deployment configurator of which this resource is a member
713
+ # @return [Boolean]: True if validation succeeded, False otherwise
714
+ def self.validateConfig(cache, configurator)
715
+ ok = true
716
+
717
+ if cluster.has_key?("parameter_group_parameters") && cache["parameter_group_family"].nil?
718
+ MU.log "parameter_group_family must be set when setting parameter_group_parameters", MU::ERR
719
+ ok = false
720
+ end
721
+ if cache["engine"] == "redis"
722
+ # We aren't required to create a cache replication group for a single redis cache cluster,
723
+ # however AWS console does exactly that, ss such we will follow that behavior.
724
+ if cache["node_count"] > 1
725
+ cache["create_replication_group"] = true
726
+ cache["automatic_failover"] = cache["multi_az"]
727
+ end
728
+
729
+ # Some instance types don't support snapshotting
730
+ if %w{cache.t2.micro cache.t2.small cache.t2.medium}.include?(cache["size"])
731
+ if cluster.has_key?("snapshot_retention_limit") || cluster.has_key?("snapshot_window")
732
+ MU.log "Can't set snapshot_retention_limit or snapshot_window on #{cache["size"]}", MU::ERR
733
+ ok = false
734
+ end
735
+ end
736
+ elsif cache["engine"] == "memcached"
737
+ cache["create_replication_group"] = false
738
+ cache["az_mode"] = cache["multi_az"] ? "cross-az" : "single-az"
739
+
740
+ if cache["node_count"] > 20
741
+ MU.log "#{cache['engine']} supports up to 20 nodes per cache cluster", MU::ERR
742
+ ok = false
743
+ end
744
+
745
+ # memcached doesn't support snapshots
746
+ if cluster.has_key?("snapshot_retention_limit") || cluster.has_key?("snapshot_window")
747
+ MU.log "Can't set snapshot_retention_limit or snapshot_window on #{cache["engine"]}", MU::ERR
748
+ ok = false
749
+ end
750
+ end
751
+
752
+ ok
753
+ end
754
+
755
+ private
756
+
757
+ # Remove a Cache Cluster and associated artifacts
758
+ # @param cluster [OpenStruct]: The cloud provider's description of the Cache Cluster artifact.
759
+ # @param noop [Boolean]: If true, will only print what would be done.
760
+ # @param skipsnapshots [Boolean]: If true, will not create a last snapshot before terminating the Cache Cluster.
761
+ # @param region [String]: The cloud provider's region in which to operate.
762
+ # @param cloud_id [String]: The cloud provider's identifier for this resource.
763
+ # @return [void]
764
+ def self.terminate_cache_cluster(cluster, noop: false, skipsnapshots: false, region: MU.curRegion, deploy_id: MU.deploy_id, mu_name: nil, cloud_id: nil)
765
+ raise MuError, "terminate_cache_cluster requires a non-nil cache cluster descriptor" if cluster.nil? || cluster.empty?
766
+
767
+ cluster_id = cluster.cache_cluster_id
768
+ subnet_group = cluster.cache_subnet_group_name
769
+ parameter_group = cluster.cache_parameter_group.cache_parameter_group_name
770
+
771
+ # hmmmmm we can use an AWS waiter for this...
772
+ unless cluster.cache_cluster_status == "available"
773
+ loop do
774
+ MU.log "Waiting for #{cluster_id} to be in a removable state...", MU::NOTICE
775
+ cluster = MU::Cloud::AWS::CacheCluster.getCacheClusterById(cluster_id, region: region)
776
+ break unless %w{creating modifying backing-up}.include?(cluster.cache_cluster_status)
777
+ sleep 60
778
+ end
779
+ end
780
+
781
+ # The API is broken, cluster.cache_nodes is returnning an empty array, and the only URL we can get is the config one with cluster.configuration_endpoint.address.
782
+ # MU::Cloud::AWS::DNSZone.genericMuDNSEntry(name: cluster_id, target: , cloudclass: MU::Cloud::CacheCluster, delete: true)
783
+
784
+ if %w{deleting deleted}.include?(cluster.cache_cluster_status)
785
+ MU.log "#{cluster_id} has already been terminated", MU::WARN
786
+ else
787
+ unless noop
788
+ def self.clusterSkipSnap(cluster_id, region)
789
+ # We're calling this several times so lets declare it once
790
+ MU.log "Terminating #{cluster_id}. Not saving final snapshot"
791
+ MU::Cloud::AWS.elasticache(region).delete_cache_cluster(cache_cluster_id: cluster_id)
792
+ end
793
+
794
+ def self.clusterCreateSnap(cluster_id, region)
795
+ MU.log "Terminating #{cluster_id}. Final snapshot name: #{cluster_id}-mufinal"
796
+ MU::Cloud::AWS.elasticache(region).delete_cache_cluster(cache_cluster_id: cluster_id, final_snapshot_identifier: "#{cluster_id}-MUfinal")
797
+ end
798
+
799
+ retries = 0
800
+ begin
801
+ if cluster.engine == "memcached"
802
+ clusterSkipSnap(cluster_id, region)
803
+ else
804
+ skipsnapshots ? clusterSkipSnap(cluster_id, region) : clusterCreateSnap(cluster_id, region)
805
+ end
806
+ rescue Aws::ElastiCache::Errors::InvalidCacheClusterState => e
807
+ if retries < 5
808
+ MU.log "#{cluster_id} is not in a removable state, retrying several times", MU::WARN
809
+ retries += 1
810
+ sleep 30
811
+ retry
812
+ else
813
+ MU.log "#{cluster_id} is not in a removable state after several retries, giving up. #{e.inspect}", MU::ERR
814
+ return
815
+ end
816
+ rescue Aws::ElastiCache::Errors::SnapshotAlreadyExistsFault
817
+ MU.log "Snapshot #{cluster_id}-MUfinal already exists", MU::WARN
818
+ clusterSkipSnap(cluster_id, region)
819
+ rescue Aws::ElastiCache::Errors::SnapshotQuotaExceededFault
820
+ MU.log "Snapshot quota exceeded while deleting #{cluster_id}", MU::ERR
821
+ clusterSkipSnap(cluster_id, region)
822
+ end
823
+
824
+ wait_start_time = Time.now
825
+ retries = 0
826
+ begin
827
+ MU::Cloud::AWS.elasticache(region).wait_until(:cache_cluster_deleted, cache_cluster_id: cluster_id) do |waiter|
828
+ waiter.max_attempts = nil
829
+ waiter.before_attempt do |attempts|
830
+ MU.log "Waiting for cache cluster #{cluster_id} to delete..", MU::NOTICE if attempts % 10 == 0
831
+ end
832
+ waiter.before_wait do |attempts, resp|
833
+ throw :success if resp.cache_clusters.first.cache_cluster_status == "deleted"
834
+ throw :failure if Time.now - wait_start_time > 1800
835
+ end
836
+ end
837
+ rescue Aws::Waiters::Errors::TooManyAttemptsError => e
838
+ raise MuError, "Waited for #{(Time.now - wait_start_time).round/60*(retries+1)} minutes for cache cluster to delete, giving up. #{e}" if retries > 2
839
+ wait_start_time = Time.now
840
+ retries += 1
841
+ retry
842
+ rescue Aws::Waiters::Errors::FailureStateError
843
+ MU.log "#{cluster_id} disappeared on us"
844
+ end
845
+ end
846
+ end
847
+
848
+ MU.log "#{cluster_id} has been terminated"
849
+
850
+ unless noop
851
+ MU::Cloud::AWS::CacheCluster.delete_subnet_group(subnet_group, region: region) if subnet_group
852
+ MU::Cloud::AWS::CacheCluster.delete_parameter_group(parameter_group, region: region) if parameter_group && !parameter_group.start_with?("default")
853
+ end
854
+ end
855
+
856
+ # Remove a Cache Cluster Replication Group and associated artifacts
857
+ # @param repl_group [OpenStruct]: The cloud provider's description of the Cache Cluster artifact.
858
+ # @param noop [Boolean]: If true, will only print what would be done.
859
+ # @param skipsnapshots [Boolean]: If true, will not create a last snapshot before terminating the Cache Cluster.
860
+ # @param region [String]: The cloud provider's region in which to operate.
861
+ # @param cloud_id [String]: The cloud provider's identifier for this resource.
862
+ # @return [void]
863
+ def self.terminate_replication_group(repl_group, noop: false, skipsnapshots: false, region: MU.curRegion, deploy_id: MU.deploy_id, mu_name: nil, cloud_id: nil)
864
+ raise MuError, "terminate_replication_group requires a non-nil cache replication group descriptor" if repl_group.nil? || repl_group.empty?
865
+
866
+ repl_group_id = repl_group.replication_group_id
867
+ # We're assuming that all clusters in this replication group where created in the same deployment so have the same subnet group, parameter group, etc...
868
+ cluster_id = repl_group.member_clusters.first
869
+ cluster = MU::Cloud::AWS::CacheCluster.getCacheClusterById(cluster_id, region: region)
870
+ subnet_group = cluster.cache_subnet_group_name
871
+ parameter_group = cluster.cache_parameter_group.cache_parameter_group_name
872
+
873
+ # hmmmmm we can use an AWS waiter for this...
874
+ unless repl_group.status == "available"
875
+ loop do
876
+ MU.log "Waiting for #{repl_group_id} to be in a removable state...", MU::NOTICE
877
+ repl_group = MU::Cloud::AWS::CacheCluster.getCacheReplicationGroupById(repl_group_id, region: region)
878
+ break unless %w{creating modifying backing-up}.include?(repl_group.status)
879
+ sleep 60
880
+ end
881
+ end
882
+
883
+ # What's the likelihood of having more than one node group? maybe iterate over node_groups instead of assuming there is only one?
884
+ MU::Cloud::AWS::DNSZone.genericMuDNSEntry(name: repl_group_id, target: repl_group.node_groups.first.primary_endpoint.address, cloudclass: MU::Cloud::CacheCluster, delete: true)
885
+ # Assuming we also created DNS records for each of our cluster's read endpoint.
886
+ repl_group.node_groups.first.node_group_members.each { |member|
887
+ MU::Cloud::AWS::DNSZone.genericMuDNSEntry(name: member.cache_cluster_id, target: member.read_endpoint.address, cloudclass: MU::Cloud::CacheCluster, delete: true)
888
+ }
889
+
890
+ if %w{deleting deleted}.include?(repl_group.status)
891
+ MU.log "#{repl_group_id} has already been terminated", MU::WARN
892
+ else
893
+ unless noop
894
+ def self.skipSnap(repl_group_id, region)
895
+ # We're calling this several times so lets declare it once
896
+ MU.log "Terminating #{repl_group_id}. Not saving final snapshot"
897
+ MU::Cloud::AWS.elasticache(region).delete_replication_group(
898
+ replication_group_id: repl_group_id,
899
+ retain_primary_cluster: false
900
+ )
901
+ end
902
+
903
+ def self.createSnap(repl_group_id, region)
904
+ MU.log "Terminating #{repl_group_id}. Final snapshot name: #{repl_group_id}-mufinal"
905
+ MU::Cloud::AWS.elasticache(region).delete_replication_group(
906
+ replication_group_id: repl_group_id,
907
+ retain_primary_cluster: false,
908
+ final_snapshot_identifier: "#{repl_group_id}-mufinal"
909
+ )
910
+ end
911
+
912
+ retries = 0
913
+ begin
914
+ skipsnapshots ? skipSnap(repl_group_id, region) : createSnap(repl_group_id, region)
915
+ rescue Aws::ElastiCache::Errors::InvalidReplicationGroupState => e
916
+ if retries < 5
917
+ MU.log "#{repl_group_id} is not in a removable state, retrying several times", MU::WARN
918
+ retries += 1
919
+ sleep 30
920
+ retry
921
+ else
922
+ MU.log "#{repl_group_id} is not in a removable state after several retries, giving up. #{e.inspect}", MU::ERR
923
+ return
924
+ end
925
+ rescue Aws::ElastiCache::Errors::SnapshotAlreadyExistsFault
926
+ MU.log "Snapshot #{repl_group_id}-MUfinal already exists", MU::WARN
927
+ skipSnap(repl_group_id, region)
928
+ rescue Aws::ElastiCache::Errors::SnapshotQuotaExceededFault
929
+ MU.log "Snapshot quota exceeded while deleting #{repl_group_id}", MU::ERR
930
+ skipSnap(repl_group_id, region)
931
+ end
932
+
933
+ wait_start_time = Time.now
934
+ retries = 0
935
+ begin
936
+ MU::Cloud::AWS.elasticache(region).wait_until(:replication_group_deleted, replication_group_id: repl_group_id) do |waiter|
937
+ waiter.max_attempts = nil
938
+ waiter.before_attempt do |attempts|
939
+ MU.log "Waiting for #{repl_group_id} to delete..", MU::NOTICE if attempts % 10 == 0
940
+ end
941
+ waiter.before_wait do |attempts, resp|
942
+ throw :success if resp.replication_groups.first.status == "deleted"
943
+ throw :failure if Time.now - wait_start_time > 1800
944
+ end
945
+ end
946
+ rescue Aws::Waiters::Errors::TooManyAttemptsError => e
947
+ raise MuError, "Waited for #{(Time.now - wait_start_time).round/60*(retries+1)} minutes for #{repl_group_id} to delete, giving up. #{e}" if retries > 2
948
+ wait_start_time = Time.now
949
+ retries += 1
950
+ retry
951
+ rescue Aws::Waiters::Errors::FailureStateError
952
+ MU.log "#{repl_group_id} disappeared on us"
953
+ end
954
+ end
955
+ end
956
+
957
+ MU.log "#{repl_group_id} has been terminated"
958
+ unless noop
959
+ MU::Cloud::AWS::CacheCluster.delete_subnet_group(subnet_group, region: region) if subnet_group
960
+ MU::Cloud::AWS::CacheCluster.delete_parameter_group(parameter_group, region: region) if parameter_group && !parameter_group.start_with?("default")
961
+ end
962
+ end
963
+
964
+ # Remove a Cache Cluster Subnet Group.
965
+ # @param subnet_group_id [string]: The cloud provider's ID of the cache cluster subnet group.
966
+ # @param region [String]: The cloud provider's region in which to operate.
967
+ # @return [void]
968
+ def self.delete_subnet_group(subnet_group_id, region: MU.curRegion)
969
+ retries ||= 0
970
+ MU.log "Deleting Subnet group #{subnet_group_id}"
971
+ MU::Cloud::AWS.elasticache(region).delete_cache_subnet_group(cache_subnet_group_name: subnet_group_id)
972
+ rescue Aws::ElastiCache::Errors::CacheSubnetGroupNotFoundFault
973
+ MU.log "Subnet group #{subnet_group_id} disappeared before we could remove it", MU::WARN
974
+ rescue Aws::ElastiCache::Errors::CacheSubnetGroupInUse => e
975
+ if retries < 5
976
+ MU.log "Subnet group #{subnet_group_id} is not in a removable state, retrying", MU::WARN
977
+ retries += 1
978
+ sleep 30
979
+ retry
980
+ else
981
+ MU.log "Subnet group #{subnet_group_id} is not in a removable state after several retries, giving up. #{e.inspect}", MU::ERR
982
+ end
983
+ end
984
+
985
+ # Remove a Cache Cluster Parameter Group.
986
+ # @param parameter_group_id [string]: The cloud provider's ID of the cache cluster parameter group.
987
+ # @param region [String]: The cloud provider's region in which to operate.
988
+ # @return [void]
989
+ def self.delete_parameter_group(parameter_group_id, region: MU.curRegion)
990
+ retries ||= 0
991
+ MU.log "Deleting parameter group #{parameter_group_id}"
992
+ MU::Cloud::AWS.elasticache(region).delete_cache_parameter_group(
993
+ cache_parameter_group_name: parameter_group_id
994
+ )
995
+ rescue Aws::ElastiCache::Errors::CacheParameterGroupNotFound
996
+ MU.log "Parameter group #{parameter_group_id} disappeared before we could remove it", MU::WARN
997
+ rescue Aws::ElastiCache::Errors::InvalidCacheParameterGroupState => e
998
+ if retries < 5
999
+ MU.log "Parameter group #{parameter_group_id} is not in a removable state, retrying", MU::WARN
1000
+ retries += 1
1001
+ sleep 30
1002
+ retry
1003
+ else
1004
+ MU.log "Parameter group #{parameter_group_id} is not in a removable state after several retries, giving up. #{e.inspect}", MU::ERR
1005
+ end
1006
+ end
1007
+ end
1008
+ end
1009
+ end
1010
+ end