cloud-mu 1.9.0.pre.beta
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/Berksfile +56 -0
- data/Berksfile.lock +250 -0
- data/Jenkinsfile +184 -0
- data/LICENSE.md +37 -0
- data/README.md +26 -0
- data/bin/mu-aws-setup +376 -0
- data/bin/mu-cleanup +68 -0
- data/bin/mu-configure +1133 -0
- data/bin/mu-deploy +166 -0
- data/bin/mu-firewall-allow-clients +30 -0
- data/bin/mu-gcp-setup +200 -0
- data/bin/mu-gen-docs +34 -0
- data/bin/mu-gen-env +42 -0
- data/bin/mu-load-config.rb +158 -0
- data/bin/mu-node-manage +683 -0
- data/bin/mu-self-update +228 -0
- data/bin/mu-ssh +23 -0
- data/bin/mu-tunnel-nagios +144 -0
- data/bin/mu-upload-chef-artifacts +757 -0
- data/bin/mu-user-manage +275 -0
- data/cookbooks/awscli/LICENSE +37 -0
- data/cookbooks/awscli/README.md +58 -0
- data/cookbooks/awscli/attributes/default.rb +1 -0
- data/cookbooks/awscli/libraries/instance_metadata.rb +21 -0
- data/cookbooks/awscli/metadata.rb +20 -0
- data/cookbooks/awscli/recipes/default.rb +56 -0
- data/cookbooks/awscli/templates/default/config.erb +18 -0
- data/cookbooks/mu-activedirectory/CHANGELOG.md +13 -0
- data/cookbooks/mu-activedirectory/LICENSE +37 -0
- data/cookbooks/mu-activedirectory/README.md +6 -0
- data/cookbooks/mu-activedirectory/attributes/default.rb +98 -0
- data/cookbooks/mu-activedirectory/files/default/password-auth +32 -0
- data/cookbooks/mu-activedirectory/files/default/sshd_pol.pp +0 -0
- data/cookbooks/mu-activedirectory/files/default/sshd_pol.te +32 -0
- data/cookbooks/mu-activedirectory/files/default/syslogd_oddjobd.pp +0 -0
- data/cookbooks/mu-activedirectory/files/default/syslogd_oddjobd.te +10 -0
- data/cookbooks/mu-activedirectory/files/default/system-auth +34 -0
- data/cookbooks/mu-activedirectory/files/default/winbindpol.pp +0 -0
- data/cookbooks/mu-activedirectory/files/default/winbindpol.te +37 -0
- data/cookbooks/mu-activedirectory/libraries/config.rb +106 -0
- data/cookbooks/mu-activedirectory/libraries/helper.rb +86 -0
- data/cookbooks/mu-activedirectory/metadata.rb +17 -0
- data/cookbooks/mu-activedirectory/providers/domain.rb +152 -0
- data/cookbooks/mu-activedirectory/providers/domain_controller.rb +89 -0
- data/cookbooks/mu-activedirectory/providers/domain_node.rb +275 -0
- data/cookbooks/mu-activedirectory/recipes/default.rb +8 -0
- data/cookbooks/mu-activedirectory/recipes/domain-controller.rb +44 -0
- data/cookbooks/mu-activedirectory/recipes/domain-node.rb +50 -0
- data/cookbooks/mu-activedirectory/recipes/domain.rb +43 -0
- data/cookbooks/mu-activedirectory/recipes/sssd.rb +185 -0
- data/cookbooks/mu-activedirectory/resources/domain.rb +25 -0
- data/cookbooks/mu-activedirectory/resources/domain_controller.rb +25 -0
- data/cookbooks/mu-activedirectory/resources/domain_node.rb +20 -0
- data/cookbooks/mu-activedirectory/templates/default/dhclient-eth0.conf.erb +4 -0
- data/cookbooks/mu-activedirectory/templates/default/interface +0 -0
- data/cookbooks/mu-activedirectory/templates/default/krb5.conf.erb +23 -0
- data/cookbooks/mu-activedirectory/templates/default/ntp.conf.erb +56 -0
- data/cookbooks/mu-activedirectory/templates/default/smb.conf.erb +33 -0
- data/cookbooks/mu-activedirectory/templates/default/sssd.conf.erb +60 -0
- data/cookbooks/mu-activedirectory/templates/windows/Backup.xml.erb +20 -0
- data/cookbooks/mu-activedirectory/templates/windows/bkupInfo.xml.erb +1 -0
- data/cookbooks/mu-activedirectory/templates/windows/gpreprt.xml.erb +198 -0
- data/cookbooks/mu-activedirectory/templates/windows/gptmpl.inf.erb +12 -0
- data/cookbooks/mu-activedirectory/templates/windows/manifest.xml.erb +1 -0
- data/cookbooks/mu-firewall/CHANGELOG.md +11 -0
- data/cookbooks/mu-firewall/LICENSE +37 -0
- data/cookbooks/mu-firewall/README.md +5 -0
- data/cookbooks/mu-firewall/attributes/default.rb +3 -0
- data/cookbooks/mu-firewall/metadata.rb +16 -0
- data/cookbooks/mu-firewall/recipes/default.rb +10 -0
- data/cookbooks/mu-glusterfs/CHANGELOG.md +13 -0
- data/cookbooks/mu-glusterfs/LICENSE +37 -0
- data/cookbooks/mu-glusterfs/README.md +5 -0
- data/cookbooks/mu-glusterfs/attributes/default.rb +34 -0
- data/cookbooks/mu-glusterfs/metadata.rb +17 -0
- data/cookbooks/mu-glusterfs/recipes/client.rb +62 -0
- data/cookbooks/mu-glusterfs/recipes/default.rb +16 -0
- data/cookbooks/mu-glusterfs/recipes/samba.rb +57 -0
- data/cookbooks/mu-glusterfs/recipes/server.rb +200 -0
- data/cookbooks/mu-glusterfs/templates/default/mu-gluster-client.erb +71 -0
- data/cookbooks/mu-glusterfs/templates/default/smb.conf.erb +14 -0
- data/cookbooks/mu-jenkins/CHANGELOG.md +13 -0
- data/cookbooks/mu-jenkins/LICENSE +37 -0
- data/cookbooks/mu-jenkins/README.md +105 -0
- data/cookbooks/mu-jenkins/attributes/default.rb +42 -0
- data/cookbooks/mu-jenkins/files/default/cleanup_deploy_config.xml +73 -0
- data/cookbooks/mu-jenkins/files/default/deploy_config.xml +44 -0
- data/cookbooks/mu-jenkins/metadata.rb +21 -0
- data/cookbooks/mu-jenkins/recipes/default.rb +195 -0
- data/cookbooks/mu-jenkins/recipes/node-ssh-config.rb +54 -0
- data/cookbooks/mu-jenkins/recipes/public_key.rb +24 -0
- data/cookbooks/mu-jenkins/templates/default/example_job.config.xml.erb +24 -0
- data/cookbooks/mu-jenkins/templates/default/org.jvnet.hudson.plugins.SSHBuildWrapper.xml.erb +14 -0
- data/cookbooks/mu-jenkins/templates/default/ssh_config.erb +6 -0
- data/cookbooks/mu-master/CHANGELOG.md +13 -0
- data/cookbooks/mu-master/LICENSE +37 -0
- data/cookbooks/mu-master/README.md +6 -0
- data/cookbooks/mu-master/attributes/default.rb +95 -0
- data/cookbooks/mu-master/files/default/0-mu-log-server.conf +19 -0
- data/cookbooks/mu-master/files/default/addRSA.ldif +8 -0
- data/cookbooks/mu-master/files/default/check_mem.pl +197 -0
- data/cookbooks/mu-master/files/default/cloudamatic.png +0 -0
- data/cookbooks/mu-master/files/default/dirsrv_admin.pp +0 -0
- data/cookbooks/mu-master/files/default/dirsrv_admin.te +13 -0
- data/cookbooks/mu-master/files/default/nagios_selinux.pp +0 -0
- data/cookbooks/mu-master/files/default/nagios_selinux.te +51 -0
- data/cookbooks/mu-master/files/default/nagios_selinux_7.pp +0 -0
- data/cookbooks/mu-master/files/default/nagios_selinux_7.te +17 -0
- data/cookbooks/mu-master/files/default/pam_sshd +18 -0
- data/cookbooks/mu-master/files/default/ssl_enable.ldif +18 -0
- data/cookbooks/mu-master/files/default/syslogd_oddjobd.pp +0 -0
- data/cookbooks/mu-master/files/default/syslogd_oddjobd.te +10 -0
- data/cookbooks/mu-master/files/default/vimrc +19 -0
- data/cookbooks/mu-master/libraries/mu.rb +29 -0
- data/cookbooks/mu-master/metadata.rb +30 -0
- data/cookbooks/mu-master/providers/user.rb +41 -0
- data/cookbooks/mu-master/recipes/389ds.rb +164 -0
- data/cookbooks/mu-master/recipes/basepackages.rb +58 -0
- data/cookbooks/mu-master/recipes/caching_nameserver.rb +37 -0
- data/cookbooks/mu-master/recipes/default.rb +451 -0
- data/cookbooks/mu-master/recipes/eks-kubectl.rb +41 -0
- data/cookbooks/mu-master/recipes/firewall-holes.rb +70 -0
- data/cookbooks/mu-master/recipes/init.rb +542 -0
- data/cookbooks/mu-master/recipes/ssl-certs.rb +109 -0
- data/cookbooks/mu-master/recipes/sssd.rb +89 -0
- data/cookbooks/mu-master/recipes/update_nagios_only.rb +242 -0
- data/cookbooks/mu-master/recipes/vault.rb +111 -0
- data/cookbooks/mu-master/resources/user.rb +19 -0
- data/cookbooks/mu-master/templates/default/389-directory-setup.inf.erb +28 -0
- data/cookbooks/mu-master/templates/default/chef-server.rb.erb +18 -0
- data/cookbooks/mu-master/templates/default/dhclient-eth0.conf.erb +9 -0
- data/cookbooks/mu-master/templates/default/mu-momma-cat.erb +149 -0
- data/cookbooks/mu-master/templates/default/mu.rc.erb +9 -0
- data/cookbooks/mu-master/templates/default/openssl.cnf.erb +354 -0
- data/cookbooks/mu-master/templates/default/sssd.conf.erb +44 -0
- data/cookbooks/mu-master/templates/default/web_app.conf.erb +90 -0
- data/cookbooks/mu-mongo/CHANGELOG.md +13 -0
- data/cookbooks/mu-mongo/LICENSE +37 -0
- data/cookbooks/mu-mongo/README.md +5 -0
- data/cookbooks/mu-mongo/attributes/default.rb +22 -0
- data/cookbooks/mu-mongo/files/default/keyfile +16 -0
- data/cookbooks/mu-mongo/files/default/remove_nodes.js +5 -0
- data/cookbooks/mu-mongo/metadata.rb +17 -0
- data/cookbooks/mu-mongo/recipes/default.rb +149 -0
- data/cookbooks/mu-mongo/recipes/yum-update-rule.rb +18 -0
- data/cookbooks/mu-mongo/templates/default/mongo_create_openfema_db.js.erb +2 -0
- data/cookbooks/mu-mongo/templates/default/mongo_init.js.erb +1 -0
- data/cookbooks/mu-mongo/templates/default/mongo_logrotate.erb +14 -0
- data/cookbooks/mu-mongo/templates/default/mongo_replset_addnodes.js.erb +6 -0
- data/cookbooks/mu-mongo/templates/default/replset_init.js.erb +2 -0
- data/cookbooks/mu-openvpn/CHANGELOG.md +13 -0
- data/cookbooks/mu-openvpn/LICENSE +37 -0
- data/cookbooks/mu-openvpn/README.md +6 -0
- data/cookbooks/mu-openvpn/attributes/default.rb +119 -0
- data/cookbooks/mu-openvpn/metadata.rb +18 -0
- data/cookbooks/mu-openvpn/recipes/default.rb +108 -0
- data/cookbooks/mu-openvpn/templates/default/users.json.erb +42 -0
- data/cookbooks/mu-php54/CHANGELOG.md +12 -0
- data/cookbooks/mu-php54/LICENSE +37 -0
- data/cookbooks/mu-php54/README.md +0 -0
- data/cookbooks/mu-php54/files/centos/php.ini +1802 -0
- data/cookbooks/mu-php54/files/ubuntu/php.ini +1870 -0
- data/cookbooks/mu-php54/metadata.rb +21 -0
- data/cookbooks/mu-php54/recipes/default.rb +97 -0
- data/cookbooks/mu-splunk/CHANGELOG.md +37 -0
- data/cookbooks/mu-splunk/LICENSE +37 -0
- data/cookbooks/mu-splunk/README.md +451 -0
- data/cookbooks/mu-splunk/attributes/default.rb +95 -0
- data/cookbooks/mu-splunk/attributes/upgrade.rb +49 -0
- data/cookbooks/mu-splunk/definitions/splunk_installer.rb +103 -0
- data/cookbooks/mu-splunk/files/default/splunk-nocheck +10 -0
- data/cookbooks/mu-splunk/libraries/helpers.rb +72 -0
- data/cookbooks/mu-splunk/libraries/splunk_app_provider.rb +156 -0
- data/cookbooks/mu-splunk/libraries/splunk_app_resource.rb +43 -0
- data/cookbooks/mu-splunk/metadata.json +30 -0
- data/cookbooks/mu-splunk/metadata.rb +17 -0
- data/cookbooks/mu-splunk/recipes/client.rb +143 -0
- data/cookbooks/mu-splunk/recipes/default.rb +31 -0
- data/cookbooks/mu-splunk/recipes/disabled.rb +41 -0
- data/cookbooks/mu-splunk/recipes/install_forwarder.rb +23 -0
- data/cookbooks/mu-splunk/recipes/install_server.rb +23 -0
- data/cookbooks/mu-splunk/recipes/server.rb +53 -0
- data/cookbooks/mu-splunk/recipes/service.rb +95 -0
- data/cookbooks/mu-splunk/recipes/setup_auth.rb +49 -0
- data/cookbooks/mu-splunk/recipes/setup_ssl.rb +63 -0
- data/cookbooks/mu-splunk/recipes/upgrade.rb +94 -0
- data/cookbooks/mu-splunk/recipes/user.rb +34 -0
- data/cookbooks/mu-splunk/templates/default/base_logs_unix_inputs.conf.erb +26 -0
- data/cookbooks/mu-splunk/templates/default/inputs.conf.erb +13 -0
- data/cookbooks/mu-splunk/templates/default/outputs.conf.erb +9 -0
- data/cookbooks/mu-splunk/templates/default/splunk-init.erb +74 -0
- data/cookbooks/mu-splunk/templates/default/system-web.conf.erb +7 -0
- data/cookbooks/mu-tools/CHANGELOG.md +12 -0
- data/cookbooks/mu-tools/LICENSE +37 -0
- data/cookbooks/mu-tools/README.md +188 -0
- data/cookbooks/mu-tools/attributes/default.rb +142 -0
- data/cookbooks/mu-tools/attributes/ebs_rolling_snapshots.rb +3 -0
- data/cookbooks/mu-tools/files/amazon/etc/freshclam.conf +235 -0
- data/cookbooks/mu-tools/files/centos/CentOS-Base.repo +52 -0
- data/cookbooks/mu-tools/files/centos/etc/bashrc +93 -0
- data/cookbooks/mu-tools/files/centos/etc/freshclam.conf +235 -0
- data/cookbooks/mu-tools/files/centos/etc/login.defs +72 -0
- data/cookbooks/mu-tools/files/centos/etc/profile +77 -0
- data/cookbooks/mu-tools/files/centos/etc/security/limits.conf +57 -0
- data/cookbooks/mu-tools/files/centos/etc/sysconfig/init +19 -0
- data/cookbooks/mu-tools/files/centos/etc/sysctl.conf +82 -0
- data/cookbooks/mu-tools/files/centos-6/README_MU +0 -0
- data/cookbooks/mu-tools/files/centos-6/etc/audit/stig.rules +173 -0
- data/cookbooks/mu-tools/files/centos-6/etc/bashrc +90 -0
- data/cookbooks/mu-tools/files/centos-6/etc/login.defs +70 -0
- data/cookbooks/mu-tools/files/centos-6/etc/pam.d/su +12 -0
- data/cookbooks/mu-tools/files/centos-6/etc/profile +83 -0
- data/cookbooks/mu-tools/files/centos-6/etc/securetty +12 -0
- data/cookbooks/mu-tools/files/centos-6/etc/sysconfig/init +30 -0
- data/cookbooks/mu-tools/files/centos-6/etc/sysctl.conf +40 -0
- data/cookbooks/mu-tools/files/default/Mu_CA.pem +34 -0
- data/cookbooks/mu-tools/files/default/PSWindowsUpdate.zip +0 -0
- data/cookbooks/mu-tools/files/default/ebs_snapshots.py +123 -0
- data/cookbooks/mu-tools/files/default/etc/BANNER +0 -0
- data/cookbooks/mu-tools/files/default/etc/BANNER-FEDERAL +19 -0
- data/cookbooks/mu-tools/files/default/gpo_no_uac.zip +0 -0
- data/cookbooks/mu-tools/files/default/mypol.pp +0 -0
- data/cookbooks/mu-tools/files/default/mypol.te +37 -0
- data/cookbooks/mu-tools/files/default/nrpe_c7.pp +0 -0
- data/cookbooks/mu-tools/files/default/nrpe_c7.te +31 -0
- data/cookbooks/mu-tools/files/default/nrpe_check_disk.pp +0 -0
- data/cookbooks/mu-tools/files/default/nrpe_check_disk.te +11 -0
- data/cookbooks/mu-tools/files/default/nrpe_disk.pp +0 -0
- data/cookbooks/mu-tools/files/default/nrpe_disk.te +10 -0
- data/cookbooks/mu-tools/files/default/nrpe_file.pp +0 -0
- data/cookbooks/mu-tools/files/default/nrpe_file.te +31 -0
- data/cookbooks/mu-tools/files/default/ntrights +0 -0
- data/cookbooks/mu-tools/files/default/serverclass.conf +18 -0
- data/cookbooks/mu-tools/files/default/splunk-apps/base_logs_unix/local/app.conf +1 -0
- data/cookbooks/mu-tools/files/default/splunk-apps/base_logs_unix/local/inputs.conf +13 -0
- data/cookbooks/mu-tools/files/default/splunk-apps/base_logs_windows/local/app.conf +1 -0
- data/cookbooks/mu-tools/files/default/splunk-apps/base_logs_windows/local/inputs.conf +8 -0
- data/cookbooks/mu-tools/files/default/sshd_pol.pp +0 -0
- data/cookbooks/mu-tools/files/default/sshd_pol.te +32 -0
- data/cookbooks/mu-tools/files/redhat/etc/bashrc +93 -0
- data/cookbooks/mu-tools/files/redhat/etc/freshclam.conf +235 -0
- data/cookbooks/mu-tools/files/redhat/etc/login.defs +72 -0
- data/cookbooks/mu-tools/files/redhat/etc/profile +77 -0
- data/cookbooks/mu-tools/files/redhat/etc/security/limits.conf +57 -0
- data/cookbooks/mu-tools/files/redhat/etc/sysconfig/init +19 -0
- data/cookbooks/mu-tools/files/redhat/etc/sysctl.conf +82 -0
- data/cookbooks/mu-tools/files/redhat-6/README_MU +0 -0
- data/cookbooks/mu-tools/files/redhat-6/etc/audit/stig.rules +173 -0
- data/cookbooks/mu-tools/files/redhat-6/etc/bashrc +90 -0
- data/cookbooks/mu-tools/files/redhat-6/etc/login.defs +70 -0
- data/cookbooks/mu-tools/files/redhat-6/etc/pam.d/su +12 -0
- data/cookbooks/mu-tools/files/redhat-6/etc/profile +83 -0
- data/cookbooks/mu-tools/files/redhat-6/etc/securetty +12 -0
- data/cookbooks/mu-tools/files/redhat-6/etc/sysconfig/init +30 -0
- data/cookbooks/mu-tools/files/redhat-6/etc/sysctl.conf +40 -0
- data/cookbooks/mu-tools/files/redhat-7.1/etc/freshclam.conf +235 -0
- data/cookbooks/mu-tools/files/ubuntu-12.04/etc/bash.bashrc +64 -0
- data/cookbooks/mu-tools/files/ubuntu-12.04/etc/common-session +30 -0
- data/cookbooks/mu-tools/files/ubuntu-12.04/etc/login.defs +338 -0
- data/cookbooks/mu-tools/files/ubuntu-12.04/etc/profile +30 -0
- data/cookbooks/mu-tools/files/ubuntu-12.04/etc/security/limits.conf +56 -0
- data/cookbooks/mu-tools/files/ubuntu-12.04/etc/sysctl.conf +60 -0
- data/cookbooks/mu-tools/libraries/helper.rb +292 -0
- data/cookbooks/mu-tools/metadata.rb +28 -0
- data/cookbooks/mu-tools/recipes/add_admin_ssh_keys.rb +35 -0
- data/cookbooks/mu-tools/recipes/apply_security.rb +440 -0
- data/cookbooks/mu-tools/recipes/aws_api.rb +23 -0
- data/cookbooks/mu-tools/recipes/base_repositories.rb +31 -0
- data/cookbooks/mu-tools/recipes/cisbenchmark.rb +59 -0
- data/cookbooks/mu-tools/recipes/clamav.rb +53 -0
- data/cookbooks/mu-tools/recipes/cloudinit.rb +58 -0
- data/cookbooks/mu-tools/recipes/configure_oracle_tools.rb +81 -0
- data/cookbooks/mu-tools/recipes/disable-requiretty.rb +22 -0
- data/cookbooks/mu-tools/recipes/ebs_rolling_snapshots.rb +75 -0
- data/cookbooks/mu-tools/recipes/efs.rb +70 -0
- data/cookbooks/mu-tools/recipes/eks.rb +160 -0
- data/cookbooks/mu-tools/recipes/gcloud.rb +98 -0
- data/cookbooks/mu-tools/recipes/google_api.rb +25 -0
- data/cookbooks/mu-tools/recipes/maldet.rb +67 -0
- data/cookbooks/mu-tools/recipes/nagios.rb +19 -0
- data/cookbooks/mu-tools/recipes/newclient.rb +23 -0
- data/cookbooks/mu-tools/recipes/nrpe.rb +115 -0
- data/cookbooks/mu-tools/recipes/python_pip.rb +35 -0
- data/cookbooks/mu-tools/recipes/retrieve_application.rb +51 -0
- data/cookbooks/mu-tools/recipes/rsyslog.rb +65 -0
- data/cookbooks/mu-tools/recipes/set_local_fw.rb +57 -0
- data/cookbooks/mu-tools/recipes/set_mu_hostname.rb +81 -0
- data/cookbooks/mu-tools/recipes/split_var_partitions.rb +86 -0
- data/cookbooks/mu-tools/recipes/splunk-client.rb +69 -0
- data/cookbooks/mu-tools/recipes/splunk-server.rb +104 -0
- data/cookbooks/mu-tools/recipes/store_inspec_attr.rb +8 -0
- data/cookbooks/mu-tools/recipes/updates.rb +96 -0
- data/cookbooks/mu-tools/recipes/windows-client.rb +202 -0
- data/cookbooks/mu-tools/resources/aws_windows.rb +33 -0
- data/cookbooks/mu-tools/resources/disk.rb +88 -0
- data/cookbooks/mu-tools/resources/mommacat_request.rb +11 -0
- data/cookbooks/mu-tools/resources/scheduled_tasks.rb +29 -0
- data/cookbooks/mu-tools/resources/sshd_service.rb +45 -0
- data/cookbooks/mu-tools/resources/windows_users.rb +242 -0
- data/cookbooks/mu-tools/templates/amazon/sshd_config.erb +168 -0
- data/cookbooks/mu-tools/templates/centos-6/sshd_config.erb +212 -0
- data/cookbooks/mu-tools/templates/centos-7/sshd_config.erb +215 -0
- data/cookbooks/mu-tools/templates/default/0-mu-log-client.conf.erb +13 -0
- data/cookbooks/mu-tools/templates/default/conf.maldet.erb +137 -0
- data/cookbooks/mu-tools/templates/default/etc_hosts.erb +30 -0
- data/cookbooks/mu-tools/templates/default/etc_pamd_password-auth.erb +14 -0
- data/cookbooks/mu-tools/templates/default/etc_pamd_system-auth.erb +14 -0
- data/cookbooks/mu-tools/templates/default/etc_sysconfig_network.erb +12 -0
- data/cookbooks/mu-tools/templates/default/kubeconfig.erb +29 -0
- data/cookbooks/mu-tools/templates/default/kubelet.service.erb +35 -0
- data/cookbooks/mu-tools/templates/default/maldet_scanall.sh.erb +15 -0
- data/cookbooks/mu-tools/templates/default/nrpe.cfg.erb +233 -0
- data/cookbooks/mu-tools/templates/redhat-6/sshd_config.erb +213 -0
- data/cookbooks/mu-tools/templates/redhat-7/sshd_config.erb +215 -0
- data/cookbooks/mu-tools/templates/ubuntu-12.04/sshd_config.erb +146 -0
- data/cookbooks/mu-tools/templates/ubuntu-14.04/sshd_config.erb +145 -0
- data/cookbooks/mu-tools/templates/windows/Backup.xml.erb +20 -0
- data/cookbooks/mu-tools/templates/windows/bkupInfo.xml.erb +1 -0
- data/cookbooks/mu-tools/templates/windows/gpreprt.xml.erb +214 -0
- data/cookbooks/mu-tools/templates/windows/gptmpl.inf.erb +12 -0
- data/cookbooks/mu-tools/templates/windows/manifest.xml.erb +1 -0
- data/cookbooks/mu-tools/templates/windows/set_ad_dns_scheduled_task.ps1.erb +6 -0
- data/cookbooks/mu-tools/templates/windows/sshd_config.erb +136 -0
- data/cookbooks/mu-utility/CHANGELOG.md +12 -0
- data/cookbooks/mu-utility/LICENSE +37 -0
- data/cookbooks/mu-utility/README.md +6 -0
- data/cookbooks/mu-utility/attributes/default.rb +1 -0
- data/cookbooks/mu-utility/libraries/matchers.rb +21 -0
- data/cookbooks/mu-utility/metadata.rb +16 -0
- data/cookbooks/mu-utility/recipes/apt.rb +23 -0
- data/cookbooks/mu-utility/recipes/cleanup_image_helper.rb +118 -0
- data/cookbooks/mu-utility/recipes/iptables.rb +26 -0
- data/cookbooks/mu-utility/recipes/luks.rb +18 -0
- data/cookbooks/mu-utility/recipes/nat.rb +104 -0
- data/cookbooks/mu-utility/recipes/php.rb +33 -0
- data/cookbooks/mu-utility/recipes/rdp_gateway.rb +83 -0
- data/cookbooks/mu-utility/recipes/remi.rb +44 -0
- data/cookbooks/mu-utility/recipes/vim.rb +26 -0
- data/cookbooks/mu-utility/recipes/windows_basics.rb +37 -0
- data/cookbooks/mu-utility/recipes/zip.rb +26 -0
- data/cookbooks/mu-utility/templates/default/BundleConfig.xml.erb +34 -0
- data/cookbooks/mu-utility/templates/default/config.xml.erb +60 -0
- data/cookbooks/nagios/Berksfile +8 -0
- data/cookbooks/nagios/CHANGELOG.md +589 -0
- data/cookbooks/nagios/CONTRIBUTING.md +11 -0
- data/cookbooks/nagios/LICENSE +37 -0
- data/cookbooks/nagios/README.md +328 -0
- data/cookbooks/nagios/TESTING.md +2 -0
- data/cookbooks/nagios/attributes/config.rb +171 -0
- data/cookbooks/nagios/attributes/default.rb +228 -0
- data/cookbooks/nagios/chefignore +102 -0
- data/cookbooks/nagios/definitions/command.rb +33 -0
- data/cookbooks/nagios/definitions/contact.rb +33 -0
- data/cookbooks/nagios/definitions/contactgroup.rb +33 -0
- data/cookbooks/nagios/definitions/host.rb +33 -0
- data/cookbooks/nagios/definitions/hostdependency.rb +33 -0
- data/cookbooks/nagios/definitions/hostescalation.rb +34 -0
- data/cookbooks/nagios/definitions/hostgroup.rb +33 -0
- data/cookbooks/nagios/definitions/nagios_conf.rb +38 -0
- data/cookbooks/nagios/definitions/resource.rb +33 -0
- data/cookbooks/nagios/definitions/service.rb +33 -0
- data/cookbooks/nagios/definitions/servicedependency.rb +33 -0
- data/cookbooks/nagios/definitions/serviceescalation.rb +34 -0
- data/cookbooks/nagios/definitions/servicegroup.rb +33 -0
- data/cookbooks/nagios/definitions/timeperiod.rb +33 -0
- data/cookbooks/nagios/libraries/base.rb +314 -0
- data/cookbooks/nagios/libraries/command.rb +91 -0
- data/cookbooks/nagios/libraries/contact.rb +230 -0
- data/cookbooks/nagios/libraries/contactgroup.rb +112 -0
- data/cookbooks/nagios/libraries/custom_option.rb +36 -0
- data/cookbooks/nagios/libraries/data_bag_helper.rb +23 -0
- data/cookbooks/nagios/libraries/default.rb +90 -0
- data/cookbooks/nagios/libraries/host.rb +412 -0
- data/cookbooks/nagios/libraries/hostdependency.rb +181 -0
- data/cookbooks/nagios/libraries/hostescalation.rb +173 -0
- data/cookbooks/nagios/libraries/hostgroup.rb +119 -0
- data/cookbooks/nagios/libraries/nagios.rb +282 -0
- data/cookbooks/nagios/libraries/resource.rb +59 -0
- data/cookbooks/nagios/libraries/service.rb +455 -0
- data/cookbooks/nagios/libraries/servicedependency.rb +215 -0
- data/cookbooks/nagios/libraries/serviceescalation.rb +195 -0
- data/cookbooks/nagios/libraries/servicegroup.rb +144 -0
- data/cookbooks/nagios/libraries/timeperiod.rb +160 -0
- data/cookbooks/nagios/libraries/users_helper.rb +54 -0
- data/cookbooks/nagios/metadata.rb +25 -0
- data/cookbooks/nagios/recipes/_load_databag_config.rb +153 -0
- data/cookbooks/nagios/recipes/_load_default_config.rb +241 -0
- data/cookbooks/nagios/recipes/apache.rb +48 -0
- data/cookbooks/nagios/recipes/default.rb +204 -0
- data/cookbooks/nagios/recipes/nginx.rb +82 -0
- data/cookbooks/nagios/recipes/pagerduty.rb +143 -0
- data/cookbooks/nagios/recipes/server_package.rb +40 -0
- data/cookbooks/nagios/recipes/server_source.rb +164 -0
- data/cookbooks/nagios/templates/default/apache2.conf.erb +96 -0
- data/cookbooks/nagios/templates/default/cgi.cfg.erb +266 -0
- data/cookbooks/nagios/templates/default/commands.cfg.erb +13 -0
- data/cookbooks/nagios/templates/default/contacts.cfg.erb +37 -0
- data/cookbooks/nagios/templates/default/hostgroups.cfg.erb +25 -0
- data/cookbooks/nagios/templates/default/hosts.cfg.erb +15 -0
- data/cookbooks/nagios/templates/default/htpasswd.users.erb +6 -0
- data/cookbooks/nagios/templates/default/nagios.cfg.erb +22 -0
- data/cookbooks/nagios/templates/default/nginx.conf.erb +62 -0
- data/cookbooks/nagios/templates/default/pagerduty.cgi.erb +185 -0
- data/cookbooks/nagios/templates/default/resource.cfg.erb +27 -0
- data/cookbooks/nagios/templates/default/servicedependencies.cfg.erb +15 -0
- data/cookbooks/nagios/templates/default/servicegroups.cfg.erb +14 -0
- data/cookbooks/nagios/templates/default/services.cfg.erb +14 -0
- data/cookbooks/nagios/templates/default/templates.cfg.erb +31 -0
- data/cookbooks/nagios/templates/default/timeperiods.cfg.erb +13 -0
- data/cookbooks/s3fs/CHANGELOG.md +13 -0
- data/cookbooks/s3fs/LICENSE +37 -0
- data/cookbooks/s3fs/README.md +6 -0
- data/cookbooks/s3fs/attributes/default.rb +15 -0
- data/cookbooks/s3fs/files/default/fuse-2.9.3.zip +0 -0
- data/cookbooks/s3fs/metadata.rb +16 -0
- data/cookbooks/s3fs/recipes/default.rb +91 -0
- data/data_bags/demo/app.json +7 -0
- data/data_bags/nagios_services/chef.json +6 -0
- data/data_bags/nagios_services/linux_diskspace.json +5 -0
- data/data_bags/nagios_services/momma_cat.json +6 -0
- data/data_bags/nagios_services/mu-master-memory.json +5 -0
- data/data_bags/nagios_services/nagios_ui.json +6 -0
- data/data_bags/nagios_services/node_ssh.json +6 -0
- data/data_bags/nagios_services/ssh.json +6 -0
- data/demo/lambda_test.yaml +29 -0
- data/environments/DEV.json +8 -0
- data/environments/PROD.json +8 -0
- data/environments/dev.json +8 -0
- data/environments/development.json +8 -0
- data/environments/prod.json +8 -0
- data/extras/README.md +1 -0
- data/extras/admin-role-binding.yaml +16 -0
- data/extras/admin-user.yaml +6 -0
- data/extras/aws-auth-cm.yaml.erb +12 -0
- data/extras/clean-stock-amis +48 -0
- data/extras/git-fix-permissions-hook +12 -0
- data/extras/gitlab-eks-helper.sh.erb +20 -0
- data/extras/image-generators/README.md +2 -0
- data/extras/image-generators/aws/centos6.yaml +18 -0
- data/extras/image-generators/aws/centos7-govcloud.yaml +24 -0
- data/extras/image-generators/aws/centos7.yaml +17 -0
- data/extras/image-generators/aws/rhel7.yaml +17 -0
- data/extras/image-generators/aws/win2k12.yaml +16 -0
- data/extras/image-generators/aws/win2k16.yaml +16 -0
- data/extras/image-generators/aws/windows.yaml +18 -0
- data/extras/image-generators/gcp/centos6.yaml +17 -0
- data/extras/lambda_waf_domain_blacklist.py +103 -0
- data/extras/platform_berksfile_base +50 -0
- data/extras/ruby_rpm/build.sh +17 -0
- data/extras/ruby_rpm/muby.spec +44 -0
- data/extras/vault_tools/README.md +6 -0
- data/extras/vault_tools/export_vaults.sh +3 -0
- data/extras/vault_tools/recreate_vaults.sh +5 -0
- data/extras/vault_tools/test_vaults.sh +5 -0
- data/install/README.md +8 -0
- data/install/cfn_create_mu_master.json +1034 -0
- data/install/chef-server.rb.erb +19 -0
- data/install/deprecated-bash-library.sh +1891 -0
- data/install/images/Usage.png +0 -0
- data/install/installer +71 -0
- data/install/jenkinskeys.rb +8 -0
- data/install/user-dot-murc.erb +14 -0
- data/modules/html.erb +19 -0
- data/modules/mommacat.ru +426 -0
- data/modules/mu/cleanup.rb +339 -0
- data/modules/mu/cloud.rb +1446 -0
- data/modules/mu/clouds/README.md +201 -0
- data/modules/mu/clouds/aws/alarm.rb +319 -0
- data/modules/mu/clouds/aws/cache_cluster.rb +1010 -0
- data/modules/mu/clouds/aws/collection.rb +373 -0
- data/modules/mu/clouds/aws/container_cluster.rb +667 -0
- data/modules/mu/clouds/aws/database.rb +1836 -0
- data/modules/mu/clouds/aws/dnszone.rb +911 -0
- data/modules/mu/clouds/aws/firewall_rule.rb +641 -0
- data/modules/mu/clouds/aws/folder.rb +92 -0
- data/modules/mu/clouds/aws/function.rb +349 -0
- data/modules/mu/clouds/aws/group.rb +251 -0
- data/modules/mu/clouds/aws/loadbalancer.rb +888 -0
- data/modules/mu/clouds/aws/log.rb +363 -0
- data/modules/mu/clouds/aws/msg_queue.rb +480 -0
- data/modules/mu/clouds/aws/notification.rb +139 -0
- data/modules/mu/clouds/aws/role.rb +656 -0
- data/modules/mu/clouds/aws/search_domain.rb +646 -0
- data/modules/mu/clouds/aws/server.rb +2294 -0
- data/modules/mu/clouds/aws/server_pool.rb +1388 -0
- data/modules/mu/clouds/aws/storage_pool.rb +495 -0
- data/modules/mu/clouds/aws/user.rb +382 -0
- data/modules/mu/clouds/aws/userdata/README.md +4 -0
- data/modules/mu/clouds/aws/userdata/linux.erb +179 -0
- data/modules/mu/clouds/aws/userdata/windows.erb +278 -0
- data/modules/mu/clouds/aws/vpc.rb +1943 -0
- data/modules/mu/clouds/aws.rb +1009 -0
- data/modules/mu/clouds/cloudformation/alarm.rb +146 -0
- data/modules/mu/clouds/cloudformation/cache_cluster.rb +167 -0
- data/modules/mu/clouds/cloudformation/collection.rb +117 -0
- data/modules/mu/clouds/cloudformation/database.rb +278 -0
- data/modules/mu/clouds/cloudformation/dnszone.rb +274 -0
- data/modules/mu/clouds/cloudformation/firewall_rule.rb +308 -0
- data/modules/mu/clouds/cloudformation/loadbalancer.rb +193 -0
- data/modules/mu/clouds/cloudformation/log.rb +170 -0
- data/modules/mu/clouds/cloudformation/server.rb +370 -0
- data/modules/mu/clouds/cloudformation/server_pool.rb +279 -0
- data/modules/mu/clouds/cloudformation/vpc.rb +322 -0
- data/modules/mu/clouds/cloudformation.rb +733 -0
- data/modules/mu/clouds/docker.rb +30 -0
- data/modules/mu/clouds/google/container_cluster.rb +290 -0
- data/modules/mu/clouds/google/database.rb +152 -0
- data/modules/mu/clouds/google/firewall_rule.rb +267 -0
- data/modules/mu/clouds/google/group.rb +164 -0
- data/modules/mu/clouds/google/loadbalancer.rb +479 -0
- data/modules/mu/clouds/google/server.rb +1510 -0
- data/modules/mu/clouds/google/server_pool.rb +274 -0
- data/modules/mu/clouds/google/user.rb +266 -0
- data/modules/mu/clouds/google/userdata/README.md +4 -0
- data/modules/mu/clouds/google/userdata/linux.erb +137 -0
- data/modules/mu/clouds/google/userdata/windows.erb +275 -0
- data/modules/mu/clouds/google/vpc.rb +890 -0
- data/modules/mu/clouds/google.rb +811 -0
- data/modules/mu/config/README.md +11 -0
- data/modules/mu/config/alarm.rb +271 -0
- data/modules/mu/config/cache_cluster.rb +172 -0
- data/modules/mu/config/collection.rb +87 -0
- data/modules/mu/config/container_cluster.rb +103 -0
- data/modules/mu/config/container_cluster.yml +36 -0
- data/modules/mu/config/database.rb +458 -0
- data/modules/mu/config/database.yml +26 -0
- data/modules/mu/config/dnszone.rb +327 -0
- data/modules/mu/config/firewall_rule.rb +118 -0
- data/modules/mu/config/folder.rb +70 -0
- data/modules/mu/config/function.rb +140 -0
- data/modules/mu/config/group.rb +64 -0
- data/modules/mu/config/loadbalancer.rb +482 -0
- data/modules/mu/config/log.rb +47 -0
- data/modules/mu/config/log.yml +6 -0
- data/modules/mu/config/msg_queue.rb +47 -0
- data/modules/mu/config/msg_queue.yml +9 -0
- data/modules/mu/config/notification.rb +44 -0
- data/modules/mu/config/project.rb +71 -0
- data/modules/mu/config/role.rb +102 -0
- data/modules/mu/config/search_domain.rb +61 -0
- data/modules/mu/config/search_domain.yml +25 -0
- data/modules/mu/config/server.rb +587 -0
- data/modules/mu/config/server.yml +8 -0
- data/modules/mu/config/server_pool.rb +216 -0
- data/modules/mu/config/server_pool.yml +71 -0
- data/modules/mu/config/storage_pool.rb +145 -0
- data/modules/mu/config/user.rb +78 -0
- data/modules/mu/config/vpc.rb +743 -0
- data/modules/mu/config/vpc.yml +6 -0
- data/modules/mu/config.rb +2000 -0
- data/modules/mu/defaults/README.md +2 -0
- data/modules/mu/defaults/amazon_images.yaml +121 -0
- data/modules/mu/defaults/google_images.yaml +16 -0
- data/modules/mu/deploy.rb +686 -0
- data/modules/mu/groomer.rb +123 -0
- data/modules/mu/groomers/README.md +58 -0
- data/modules/mu/groomers/chef.rb +1024 -0
- data/modules/mu/kittens.rb +11319 -0
- data/modules/mu/logger.rb +208 -0
- data/modules/mu/master/README.md +27 -0
- data/modules/mu/master/chef.rb +471 -0
- data/modules/mu/master/ldap.rb +1005 -0
- data/modules/mu/master.rb +415 -0
- data/modules/mu/mommacat.rb +2703 -0
- data/modules/mu-load-config.rb +1 -0
- data/modules/mu.rb +724 -0
- data/modules/scratchpad.erb +1 -0
- data/modules/tests/super_complex_bok.yml +41 -0
- data/modules/tests/super_simple_bok.yml +40 -0
- data/mu.gemspec +62 -0
- data/roles/demo-dbservice-configure.json +19 -0
- data/roles/demo-portal-configure.json +19 -0
- data/roles/mu-master-jenkins.json +24 -0
- data/roles/mu-master-nagios-only.json +13 -0
- data/roles/mu-master.json +12 -0
- data/roles/mu-node.json +19 -0
- data/roles/mu-splunk-server.json +13 -0
- data/roles/mu-splunk.json +13 -0
- data/test/clean_up.py +25 -0
- data/test/demo-test-profile/README.md +3 -0
- data/test/demo-test-profile/controls/flask.rb +84 -0
- data/test/demo-test-profile/inspec.lock +7 -0
- data/test/demo-test-profile/inspec.yml +11 -0
- data/test/etco-test-profile/README.md +3 -0
- data/test/etco-test-profile/controls/all-in-one.rb +182 -0
- data/test/etco-test-profile/inspec.lock +7 -0
- data/test/etco-test-profile/inspec.yml +11 -0
- data/test/exec_inspec.py +246 -0
- data/test/exec_mu_install.py +241 -0
- data/test/exec_retry.py +44 -0
- data/test/mu-master-test/README.md +3 -0
- data/test/mu-master-test/controls/all_in_one.rb +557 -0
- data/test/mu-master-test/inspec.lock +3 -0
- data/test/mu-master-test/inspec.yml +11 -0
- data/test/mu-tools-test/README.md +3 -0
- data/test/mu-tools-test/controls/base.rb +265 -0
- data/test/mu-tools-test/inspec.lock +3 -0
- data/test/mu-tools-test/inspec.yml +8 -0
- data/test/simple-server-php-test/README.md +3 -0
- data/test/simple-server-php-test/controls/apachephp.rb +25 -0
- data/test/simple-server-php-test/controls/example.rb +19 -0
- data/test/simple-server-php-test/inspec.lock +7 -0
- data/test/simple-server-php-test/inspec.yml +12 -0
- data/test/simple-server-rails-test/README.md +3 -0
- data/test/simple-server-rails-test/controls/rails.rb +188 -0
- data/test/simple-server-rails-test/inspec.lock +7 -0
- data/test/simple-server-rails-test/inspec.yml +11 -0
- data/test/simple-windows-test/README.md +3 -0
- data/test/simple-windows-test/controls/windows.rb +20 -0
- data/test/simple-windows-test/inspec.lock +7 -0
- data/test/simple-windows-test/inspec.yml +11 -0
- data/test/smoke_test.rb +75 -0
- data/test/wordpress-test/README.md +3 -0
- data/test/wordpress-test/controls/wordpress.rb +97 -0
- data/test/wordpress-test/inspec.lock +7 -0
- data/test/wordpress-test/inspec.yml +11 -0
- metadata +979 -0
@@ -0,0 +1,1836 @@
|
|
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
|
+
autoload :Net, 'net/ssh/gateway'
|
16
|
+
|
17
|
+
module MU
|
18
|
+
class Cloud
|
19
|
+
class AWS
|
20
|
+
# A database as configured in {MU::Config::BasketofKittens::databases}
|
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"])
|
39
|
+
@config["groomer"] = MU::Config.defaultGroomer unless @config["groomer"]
|
40
|
+
@groomclass = MU::Groomer.loadGroomer(@config["groomer"])
|
41
|
+
|
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
|
51
|
+
|
52
|
+
@mu_name.gsub(/(--|-$)/i, "").gsub(/(_)/, "-").gsub!(/^[^a-z]/i, "")
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
# Called automatically by {MU::Deploy#createResources}
|
57
|
+
# @return [String]: The cloud provider's identifier for this database instance.
|
58
|
+
def create
|
59
|
+
# RDS is picky, we can't just use our regular node names for things like
|
60
|
+
# the default schema or username. And it varies from engine to engine.
|
61
|
+
basename = @config["name"]+@deploy.timestamp+MU.seed.downcase
|
62
|
+
basename.gsub!(/[^a-z0-9]/i, "")
|
63
|
+
@config["db_name"] = MU::Cloud::AWS::Database.getName(basename, type: "dbname", config: @config)
|
64
|
+
@config['master_user'] = MU::Cloud::AWS::Database.getName(basename, type: "dbuser", config: @config) unless @config['master_user']
|
65
|
+
|
66
|
+
# Lets make sure automatic backups are enabled when DB instance is deployed in Multi-AZ so failover actually works. Maybe default to 1 instead?
|
67
|
+
if @config['multi_az_on_create'] or @config['multi_az_on_deploy'] or @config["create_cluster"]
|
68
|
+
if @config["backup_retention_period"].nil? or @config["backup_retention_period"] == 0
|
69
|
+
@config["backup_retention_period"] = 35
|
70
|
+
MU.log "Multi-AZ deployment specified but backup retention period disabled or set to 0. Changing to #{@config["backup_retention_period"]} ", MU::WARN
|
71
|
+
end
|
72
|
+
|
73
|
+
if @config["preferred_backup_window"].nil?
|
74
|
+
@config["preferred_backup_window"] = "05:00-05:30"
|
75
|
+
MU.log "Multi-AZ deployment specified but no backup window specified. Changing to #{@config["preferred_backup_window"]} ", MU::WARN
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
@config["snapshot_id"] =
|
80
|
+
if @config["creation_style"] == "existing_snapshot"
|
81
|
+
getExistingSnapshot ? getExistingSnapshot : createNewSnapshot
|
82
|
+
elsif @config["creation_style"] == "new_snapshot"
|
83
|
+
createNewSnapshot
|
84
|
+
end
|
85
|
+
|
86
|
+
@config['source_identifier'] = @config['identifier'] if @config["creation_style"] == "point_in_time"
|
87
|
+
@config['identifier'] = @mu_name unless @config["creation_style"] == "existing"
|
88
|
+
@config["subnet_group_name"] = @mu_name
|
89
|
+
MU.log "Using the database identifier #{@config['identifier']}"
|
90
|
+
|
91
|
+
|
92
|
+
if @config["create_cluster"]
|
93
|
+
getPassword
|
94
|
+
createSubnetGroup
|
95
|
+
|
96
|
+
if @config.has_key?("parameter_group_family")
|
97
|
+
@config["parameter_group_name"] = @config['identifier']
|
98
|
+
createDBClusterParameterGroup
|
99
|
+
end
|
100
|
+
|
101
|
+
@cloud_id = createDbCluster
|
102
|
+
elsif @config["add_cluster_node"]
|
103
|
+
cluster = nil
|
104
|
+
rr = @config["member_of_cluster"]
|
105
|
+
cluster = @deploy.findLitterMate(type: "database", name: rr['db_name']) if rr['db_name']
|
106
|
+
|
107
|
+
if cluster.nil?
|
108
|
+
tag_key, tag_value = rr['tag'].split(/=/, 2) if !rr['tag'].nil?
|
109
|
+
found = MU::MommaCat.findStray(
|
110
|
+
rr['cloud'],
|
111
|
+
"database",
|
112
|
+
deploy_id: rr["deploy_id"],
|
113
|
+
cloud_id: rr["db_id"],
|
114
|
+
tag_key: tag_key,
|
115
|
+
tag_value: tag_value,
|
116
|
+
region: rr["region"],
|
117
|
+
dummy_ok: true
|
118
|
+
)
|
119
|
+
cluster = found.first if found.size == 1
|
120
|
+
end
|
121
|
+
|
122
|
+
raise MuError, "Couldn't resolve cluster node reference to a unique live Database in #{@mu_name}" if cluster.nil? || cluster.cloud_id.nil?
|
123
|
+
@config['cluster_identifier'] = cluster.cloud_id.downcase
|
124
|
+
# We're overriding @config["subnet_group_name"] because we need each cluster member to use the cluster's subnet group instead of a unique subnet group
|
125
|
+
@config["subnet_group_name"] = @config['cluster_identifier']
|
126
|
+
@config["creation_style"] = "new" if @config["creation_style"] != "new"
|
127
|
+
|
128
|
+
if @config.has_key?("parameter_group_family")
|
129
|
+
@config["parameter_group_name"] = @config['identifier']
|
130
|
+
createDBParameterGroup
|
131
|
+
end
|
132
|
+
|
133
|
+
@cloud_id = createDb
|
134
|
+
else
|
135
|
+
source_db = nil
|
136
|
+
if @config['read_replica_of']
|
137
|
+
rr = @config['read_replica_of']
|
138
|
+
source_db = @deploy.findLitterMate(type: "database", name: rr['db_name']) if rr['db_name']
|
139
|
+
|
140
|
+
if source_db.nil?
|
141
|
+
tag_key, tag_value = rr['tag'].split(/=/, 2) if !rr['tag'].nil?
|
142
|
+
found = MU::MommaCat.findStray(
|
143
|
+
rr['cloud'],
|
144
|
+
"database",
|
145
|
+
deploy_id: rr["deploy_id"],
|
146
|
+
cloud_id: rr["db_id"],
|
147
|
+
tag_key: tag_key,
|
148
|
+
tag_value: tag_value,
|
149
|
+
region: rr["region"],
|
150
|
+
dummy_ok: true
|
151
|
+
)
|
152
|
+
source_db = found.first if found.size == 1
|
153
|
+
end
|
154
|
+
|
155
|
+
raise MuError, "Couldn't resolve read replica reference to a unique live Database in #{@mu_name}" if source_db.nil? or source_db.cloud_id.nil?
|
156
|
+
@config['source_identifier'] = source_db.cloud_id
|
157
|
+
end
|
158
|
+
|
159
|
+
getPassword
|
160
|
+
if source_db.nil? or @config['region'] != source_db.config['region']
|
161
|
+
createSubnetGroup
|
162
|
+
else
|
163
|
+
MU.log "Note: Read Replicas automatically reside in the same subnet group as the source database, if they're both in the same region. This replica may not land in the VPC you intended.", MU::WARN
|
164
|
+
end
|
165
|
+
|
166
|
+
if @config.has_key?("parameter_group_family")
|
167
|
+
@config["parameter_group_name"] = @config['identifier']
|
168
|
+
createDBParameterGroup
|
169
|
+
end
|
170
|
+
|
171
|
+
@cloud_id = createDb
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
# Canonical Amazon Resource Number for this resource
|
176
|
+
# @return [String]
|
177
|
+
def arn
|
178
|
+
cloud_desc.db_instance_arn
|
179
|
+
end
|
180
|
+
|
181
|
+
|
182
|
+
# Locate an existing Database or Databases and return an array containing matching AWS resource descriptors for those that match.
|
183
|
+
# @param cloud_id [String]: The cloud provider's identifier for this resource.
|
184
|
+
# @param region [String]: The cloud provider region
|
185
|
+
# @param tag_key [String]: A tag key to search.
|
186
|
+
# @param tag_value [String]: The value of the tag specified by tag_key to match when searching by tag.
|
187
|
+
# @param flags [Hash]: Optional flags
|
188
|
+
# @return [Array<Hash<String,OpenStruct>>]: The cloud provider's complete descriptions of matching Databases
|
189
|
+
def self.find(cloud_id: nil, region: MU.curRegion, tag_key: "Name", tag_value: nil, flags: {})
|
190
|
+
map = {}
|
191
|
+
if cloud_id
|
192
|
+
db = MU::Cloud::AWS::Database.getDatabaseById(cloud_id, region: region)
|
193
|
+
map[cloud_id] = db if db
|
194
|
+
end
|
195
|
+
|
196
|
+
if tag_value
|
197
|
+
MU::Cloud::AWS.rds(region).describe_db_instances.db_instances.each { |db|
|
198
|
+
resp = MU::Cloud::AWS.rds(region).list_tags_for_resource(
|
199
|
+
resource_name: MU::Cloud::AWS::Database.getARN(db.db_instance_identifier, "db", "rds", region: region)
|
200
|
+
)
|
201
|
+
if resp && resp.tag_list && !resp.tag_list.empty?
|
202
|
+
resp.tag_list.each { |tag|
|
203
|
+
map[db.db_instance_identifier] = db if tag.key == tag_key and tag.value == tag_value
|
204
|
+
}
|
205
|
+
end
|
206
|
+
}
|
207
|
+
end
|
208
|
+
|
209
|
+
return map
|
210
|
+
end
|
211
|
+
|
212
|
+
# Construct an Amazon Resource Name for an RDS resource. The RDS API is
|
213
|
+
# peculiar, and we often need this identifier in order to do things that
|
214
|
+
# the other APIs can do with shorthand.
|
215
|
+
# @param resource [String]: The name of the resource
|
216
|
+
# @param resource_type [String]: The type of the resource (one of `db, es, og, pg, ri, secgrp, snapshot, subgrp`)
|
217
|
+
# @param client_type [String]: The name of the client (eg. elasticache, rds, ec2, s3)
|
218
|
+
# @param region [String]: The region in which the resource resides.
|
219
|
+
# @param account_number [String]: The account in which the resource resides.
|
220
|
+
# @return [String]
|
221
|
+
def self.getARN(resource, resource_type, client_type, region: MU.curRegion, account_number: MU.account_number)
|
222
|
+
aws_str = MU::Cloud::AWS.isGovCloud?(region) ? "aws-us-gov" : "aws"
|
223
|
+
"arn:#{aws_str}:#{client_type}:#{region}:#{account_number}:#{resource_type}:#{resource}"
|
224
|
+
end
|
225
|
+
|
226
|
+
# Construct all our tags.
|
227
|
+
# @return [Array]: All our standard tags and any custom tags.
|
228
|
+
def allTags
|
229
|
+
tags = []
|
230
|
+
MU::MommaCat.listStandardTags.each_pair { |name, value|
|
231
|
+
tags << {key: name, value: value}
|
232
|
+
}
|
233
|
+
|
234
|
+
if @config['optional_tags']
|
235
|
+
MU::MommaCat.listOptionalTags.each_pair { |name, value|
|
236
|
+
tags << {key: name, value: value}
|
237
|
+
}
|
238
|
+
end
|
239
|
+
|
240
|
+
if @config['tags']
|
241
|
+
@config['tags'].each { |tag|
|
242
|
+
tags << {key: tag['key'], value: tag['value']}
|
243
|
+
}
|
244
|
+
end
|
245
|
+
|
246
|
+
return tags
|
247
|
+
end
|
248
|
+
|
249
|
+
# Add our standard tag set to an Amazon RDS resource.
|
250
|
+
# @param resource [String]: The name of the resource
|
251
|
+
# @param resource_type [String]: The type of the resource (one of `db, es, og, pg, ri, secgrp, snapshot, subgrp`)
|
252
|
+
# @param region [String]: The cloud provider region
|
253
|
+
def addStandardTags(resource, resource_type, region: MU.curRegion)
|
254
|
+
MU.log "Adding tags to RDS resource #{resource}: #{allTags}"
|
255
|
+
MU::Cloud::AWS.rds(region).add_tags_to_resource(
|
256
|
+
resource_name: MU::Cloud::AWS::Database.getARN(resource, resource_type, "rds", region: region),
|
257
|
+
tags: allTags
|
258
|
+
)
|
259
|
+
end
|
260
|
+
|
261
|
+
# Getting the password for the master user, and saving it in a database / cluster specif vault
|
262
|
+
def getPassword
|
263
|
+
if @config['password'].nil?
|
264
|
+
if @config['auth_vault'] && !@config['auth_vault'].empty?
|
265
|
+
@config['password'] = @groomclass.getSecret(
|
266
|
+
vault: @config['auth_vault']['vault'],
|
267
|
+
item: @config['auth_vault']['item'],
|
268
|
+
field: @config['auth_vault']['password_field']
|
269
|
+
)
|
270
|
+
else
|
271
|
+
# Should we use random instead?
|
272
|
+
@config['password'] = Password.pronounceable(10..12)
|
273
|
+
end
|
274
|
+
end
|
275
|
+
|
276
|
+
creds = {
|
277
|
+
"username" => @config["master_user"],
|
278
|
+
"password" => @config["password"]
|
279
|
+
}
|
280
|
+
@groomclass.saveSecret(vault: @mu_name, item: "database_credentials", data: creds)
|
281
|
+
end
|
282
|
+
|
283
|
+
# Create the database described in this instance
|
284
|
+
# @return [String]: The cloud provider's identifier for this database instance.
|
285
|
+
def createDb
|
286
|
+
# Shared configuration elements between most database creation styles
|
287
|
+
config = {
|
288
|
+
db_instance_identifier: @config['identifier'],
|
289
|
+
db_instance_class: @config["size"],
|
290
|
+
engine: @config["engine"],
|
291
|
+
auto_minor_version_upgrade: @config["auto_minor_version_upgrade"],
|
292
|
+
license_model: @config["license_model"],
|
293
|
+
db_subnet_group_name: @config["subnet_group_name"],
|
294
|
+
publicly_accessible: @config["publicly_accessible"],
|
295
|
+
copy_tags_to_snapshot: true,
|
296
|
+
tags: allTags
|
297
|
+
}
|
298
|
+
|
299
|
+
unless @config["add_cluster_node"]
|
300
|
+
config[:storage_type] = @config["storage_type"]
|
301
|
+
config[:port] = @config["port"] if @config["port"]
|
302
|
+
config[:iops] = @config["iops"] if @config['storage_type'] == "io1"
|
303
|
+
config[:multi_az] = @config['multi_az_on_create']
|
304
|
+
end
|
305
|
+
|
306
|
+
if @config["creation_style"] == "new"
|
307
|
+
unless @config["add_cluster_node"]
|
308
|
+
config[:preferred_backup_window] = @config["preferred_backup_window"]
|
309
|
+
config[:backup_retention_period] = @config["backup_retention_period"]
|
310
|
+
config[:storage_encrypted] = @config["storage_encrypted"]
|
311
|
+
config[:allocated_storage] = @config["storage"]
|
312
|
+
config[:db_name] = @config["db_name"]
|
313
|
+
config[:master_username] = @config['master_user']
|
314
|
+
config[:master_user_password] = @config['password']
|
315
|
+
config[:vpc_security_group_ids] = @config["vpc_security_group_ids"]
|
316
|
+
end
|
317
|
+
|
318
|
+
config[:engine_version] = @config["engine_version"]
|
319
|
+
config[:preferred_maintenance_window] = @config["preferred_maintenance_window"] if @config["preferred_maintenance_window"]
|
320
|
+
config[:db_parameter_group_name] = @config["parameter_group_name"] if @config["parameter_group_name"]
|
321
|
+
config[:db_cluster_identifier] = @config["cluster_identifier"] if @config["add_cluster_node"]
|
322
|
+
end
|
323
|
+
|
324
|
+
if %w{existing_snapshot new_snapshot}.include?(@config["creation_style"])
|
325
|
+
config[:db_snapshot_identifier] = @config["snapshot_id"]
|
326
|
+
end
|
327
|
+
|
328
|
+
if @config["creation_style"] == "point_in_time"
|
329
|
+
point_in_time_config = config
|
330
|
+
point_in_time_config.delete(:db_instance_identifier)
|
331
|
+
point_in_time_config[:source_db_instance_identifier] = @config['source_identifier']
|
332
|
+
point_in_time_config[:target_db_instance_identifier] = @config['identifier']
|
333
|
+
point_in_time_config[:restore_time] = @config['restore_time'] unless @config["restore_time"] == "latest"
|
334
|
+
point_in_time_config[:use_latest_restorable_time] = true if @config['restore_time'] == "latest"
|
335
|
+
end
|
336
|
+
|
337
|
+
if @config["read_replica_of"] || @config["create_read_replica"]
|
338
|
+
srcdb = @config['source_identifier']
|
339
|
+
if @config["read_replica_of"]["region"] and @config['region'] != @config["read_replica_of"]["region"]
|
340
|
+
srcdb = MU::Cloud::AWS::Database.getARN(@config['source_identifier'], "db", "rds", region: @config["read_replica_of"]["region"])
|
341
|
+
end
|
342
|
+
read_replica_struct = {
|
343
|
+
db_instance_identifier: @config['identifier'],
|
344
|
+
source_db_instance_identifier: srcdb,
|
345
|
+
db_instance_class: @config["size"],
|
346
|
+
auto_minor_version_upgrade: @config["auto_minor_version_upgrade"],
|
347
|
+
publicly_accessible: @config["publicly_accessible"],
|
348
|
+
tags: allTags,
|
349
|
+
db_subnet_group_name: @config["subnet_group_name"],
|
350
|
+
storage_type: @config["storage_type"]
|
351
|
+
}
|
352
|
+
|
353
|
+
read_replica_struct[:port] = @config["port"] if @config["port"]
|
354
|
+
read_replica_struct[:iops] = @config["iops"] if @config['storage_type'] == "io1"
|
355
|
+
end
|
356
|
+
|
357
|
+
# Creating DB instance
|
358
|
+
attempts = 0
|
359
|
+
|
360
|
+
begin
|
361
|
+
if %w{existing_snapshot new_snapshot}.include?(@config["creation_style"])
|
362
|
+
MU.log "Creating database instance #{@config['identifier']} from snapshot #{@config["snapshot_id"]}"
|
363
|
+
resp = MU::Cloud::AWS.rds(@config['region']).restore_db_instance_from_db_snapshot(config)
|
364
|
+
elsif @config["creation_style"] == "point_in_time"
|
365
|
+
MU.log "Creating database instance #{@config['identifier']} based on point in time backup #{@config['restore_time']} of #{@config['source_identifier']}"
|
366
|
+
resp = MU::Cloud::AWS.rds(@config['region']).restore_db_instance_to_point_in_time(point_in_time_config)
|
367
|
+
elsif @config["read_replica_of"]
|
368
|
+
MU.log "Creating read replica database instance #{@config['identifier']} for #{@config['source_identifier']}"
|
369
|
+
begin
|
370
|
+
resp = MU::Cloud::AWS.rds(@config['region']).create_db_instance_read_replica(read_replica_struct)
|
371
|
+
rescue Aws::RDS::Errors::DBSubnetGroupNotAllowedFault => e
|
372
|
+
MU.log "Being forced to use source database's subnet group: #{e.message}", MU::WARN
|
373
|
+
read_replica_struct.delete(:db_subnet_group_name)
|
374
|
+
resp = MU::Cloud::AWS.rds(@config['region']).create_db_instance_read_replica(read_replica_struct)
|
375
|
+
end
|
376
|
+
elsif @config["creation_style"] == "new"
|
377
|
+
MU.log "Creating database instance #{@config['identifier']}"
|
378
|
+
resp = MU::Cloud::AWS.rds(@config['region']).create_db_instance(config)
|
379
|
+
end
|
380
|
+
rescue Aws::RDS::Errors::InvalidParameterValue => e
|
381
|
+
if attempts < 5
|
382
|
+
MU.log "Got #{e.inspect} creating #{@config['identifier']}, will retry a few times in case of transient errors.", MU::WARN
|
383
|
+
attempts += 1
|
384
|
+
sleep 10
|
385
|
+
retry
|
386
|
+
else
|
387
|
+
raise MuError, "Exhausted retries trying to create database instance #{@config['identifier']}: e.inspect"
|
388
|
+
end
|
389
|
+
end
|
390
|
+
|
391
|
+
wait_start_time = Time.now
|
392
|
+
retries = 0
|
393
|
+
|
394
|
+
begin
|
395
|
+
MU::Cloud::AWS.rds(@config['region']).wait_until(:db_instance_available, db_instance_identifier: @config['identifier']) do |waiter|
|
396
|
+
# Does create_db_instance implement wait_until_available ?
|
397
|
+
waiter.max_attempts = nil
|
398
|
+
waiter.before_attempt do |attempts|
|
399
|
+
MU.log "Waiting for RDS database #{@config['identifier']} to be ready..", MU::NOTICE if attempts % 10 == 0
|
400
|
+
end
|
401
|
+
waiter.before_wait do |attempts, resp|
|
402
|
+
throw :success if resp.db_instances.first.db_instance_status == "available"
|
403
|
+
throw :failure if Time.now - wait_start_time > 3600
|
404
|
+
end
|
405
|
+
end
|
406
|
+
rescue Aws::Waiters::Errors::TooManyAttemptsError => e
|
407
|
+
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
|
408
|
+
wait_start_time = Time.now
|
409
|
+
retries += 1
|
410
|
+
retry
|
411
|
+
end
|
412
|
+
|
413
|
+
database = MU::Cloud::AWS::Database.getDatabaseById(@config['identifier'], region: @config['region'])
|
414
|
+
MU::Cloud::AWS::DNSZone.genericMuDNSEntry(name: database.db_instance_identifier, target: "#{database.endpoint.address}.", cloudclass: MU::Cloud::Database, sync_wait: @config['dns_sync_wait'])
|
415
|
+
MU.log "Database #{@config['name']} is at #{database.endpoint.address}", MU::SUMMARY
|
416
|
+
MU.log "knife vault show #{@config['auth_vault']['vault']} #{@config['auth_vault']['item']} for Database #{@config['name']} credentials", MU::SUMMARY
|
417
|
+
|
418
|
+
# If referencing an existing DB, insert this deploy's DB security group so it can access db
|
419
|
+
if @config["creation_style"] == 'existing'
|
420
|
+
vpc_sg_ids = []
|
421
|
+
database.vpc_security_groups.each { |vpc_sg|
|
422
|
+
vpc_sg_ids << vpc_sg.vpc_security_group_id
|
423
|
+
}
|
424
|
+
|
425
|
+
localdeploy_rule = @deploy.findLitterMate(type: "firewall_rule", name: "database"+@config['name'])
|
426
|
+
if localdeploy_rule.nil?
|
427
|
+
raise MU::MuError, "Database #{@config['name']} failed to find its generic security group 'database#{@config['name']}'"
|
428
|
+
end
|
429
|
+
MU.log "Found this deploy's DB security group: #{localdeploy_rule.cloud_id}", MU::DEBUG
|
430
|
+
vpc_sg_ids << localdeploy_rule.cloud_id
|
431
|
+
mod_config = Hash.new
|
432
|
+
mod_config[:vpc_security_group_ids] = vpc_sg_ids
|
433
|
+
mod_config[:db_instance_identifier] = @config["identifier"]
|
434
|
+
|
435
|
+
MU::Cloud::AWS.rds(@config['region']).modify_db_instance(mod_config)
|
436
|
+
MU.log "Modified database #{@config['identifier']} with new security groups: #{mod_config}", MU::NOTICE
|
437
|
+
end
|
438
|
+
|
439
|
+
# When creating from a snapshot, some of the create arguments aren't
|
440
|
+
# applicable- but we can apply them after the fact with a modify.
|
441
|
+
if %w{existing_snapshot new_snapshot point_in_time}.include?(@config["creation_style"]) or @config["read_replica_of"]
|
442
|
+
mod_config = Hash.new
|
443
|
+
if !@config["read_replica_of"]
|
444
|
+
mod_config[:preferred_backup_window] = @config["preferred_backup_window"]
|
445
|
+
mod_config[:backup_retention_period] = @config["backup_retention_period"]
|
446
|
+
mod_config[:engine_version] = @config["engine_version"]
|
447
|
+
mod_config[:allow_major_version_upgrade] = @config["allow_major_version_upgrade"] if @config['allow_major_version_upgrade']
|
448
|
+
mod_config[:db_parameter_group_name] = @config["parameter_group_name"] if @config["parameter_group_name"]
|
449
|
+
mod_config[:master_user_password] = @config['password']
|
450
|
+
mod_config[:allocated_storage] = @config["storage"] if @config["storage"]
|
451
|
+
end
|
452
|
+
mod_config[:db_instance_identifier] = database.db_instance_identifier
|
453
|
+
mod_config[:preferred_maintenance_window] = @config["preferred_maintenance_window"] if @config["preferred_maintenance_window"]
|
454
|
+
mod_config[:vpc_security_group_ids] = @config["vpc_security_group_ids"]
|
455
|
+
mod_config[:apply_immediately] = true
|
456
|
+
|
457
|
+
MU::Cloud::AWS.rds(@config['region']).modify_db_instance(mod_config)
|
458
|
+
wait_start_time = Time.now
|
459
|
+
retries = 0
|
460
|
+
|
461
|
+
begin
|
462
|
+
MU::Cloud::AWS.rds(@config['region']).wait_until(:db_instance_available, db_instance_identifier: @config['identifier']) do |waiter|
|
463
|
+
# Does create_db_instance implement wait_until_available ?
|
464
|
+
waiter.max_attempts = nil
|
465
|
+
waiter.before_attempt do |attempts|
|
466
|
+
MU.log "Waiting for RDS database #{@config['identifier'] } to be ready..", MU::NOTICE if attempts % 10 == 0
|
467
|
+
end
|
468
|
+
waiter.before_wait do |attempts, resp|
|
469
|
+
throw :success if resp.db_instances.first.db_instance_status == "available"
|
470
|
+
throw :failure if Time.now - wait_start_time > 2400
|
471
|
+
end
|
472
|
+
end
|
473
|
+
rescue Aws::Waiters::Errors::TooManyAttemptsError => e
|
474
|
+
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
|
475
|
+
wait_start_time = Time.now
|
476
|
+
retries += 1
|
477
|
+
retry
|
478
|
+
end
|
479
|
+
end
|
480
|
+
|
481
|
+
# Maybe wait for DB instance to be in available state. DB should still be writeable at this state
|
482
|
+
if @config['allow_major_version_upgrade'] && @config["creation_style"] == "new"
|
483
|
+
MU.log "Setting major database version upgrade on #{@config['identifier']}'"
|
484
|
+
MU::Cloud::AWS.rds(@config['region']).modify_db_instance(
|
485
|
+
db_instance_identifier: @config['identifier'],
|
486
|
+
apply_immediately: true,
|
487
|
+
allow_major_version_upgrade: true
|
488
|
+
)
|
489
|
+
end
|
490
|
+
|
491
|
+
MU.log "Database #{@config['identifier']} is ready to use"
|
492
|
+
return database.db_instance_identifier
|
493
|
+
end
|
494
|
+
|
495
|
+
# Create the database cluster described in this instance
|
496
|
+
# @return [String]: The cloud provider's identifier for this database cluster.
|
497
|
+
def createDbCluster
|
498
|
+
cluster_config_struct = {
|
499
|
+
db_cluster_identifier: @config['identifier'],
|
500
|
+
# downcasing @config["subnet_group_name"] becuase the API is choking on upper case.
|
501
|
+
db_subnet_group_name: @config["subnet_group_name"].downcase,
|
502
|
+
vpc_security_group_ids: @config["vpc_security_group_ids"],
|
503
|
+
tags: allTags
|
504
|
+
}
|
505
|
+
cluster_config_struct[:port] = @config["port"] if @config["port"]
|
506
|
+
|
507
|
+
if %w{existing_snapshot new_snapshot}.include?(@config["creation_style"])
|
508
|
+
cluster_config_struct[:snapshot_identifier] = @config["snapshot_id"]
|
509
|
+
cluster_config_struct[:engine] = @config["engine"]
|
510
|
+
cluster_config_struct[:engine_version] = @config["engine_version"]
|
511
|
+
cluster_config_struct[:database_name] = @config["db_name"]
|
512
|
+
end
|
513
|
+
|
514
|
+
if @config["creation_style"] == "new"
|
515
|
+
cluster_config_struct[:backup_retention_period] = @config["backup_retention_period"]
|
516
|
+
cluster_config_struct[:database_name] = @config["db_name"]
|
517
|
+
cluster_config_struct[:db_cluster_parameter_group_name] = @config["parameter_group_name"]
|
518
|
+
cluster_config_struct[:engine] = @config["engine"]
|
519
|
+
cluster_config_struct[:engine_version] = @config["engine_version"]
|
520
|
+
cluster_config_struct[:master_username] = @config["master_user"]
|
521
|
+
cluster_config_struct[:master_user_password] = @config["password"]
|
522
|
+
cluster_config_struct[:preferred_backup_window] = @config["preferred_backup_window"]
|
523
|
+
cluster_config_struct[:preferred_maintenance_window] = @config["preferred_maintenance_window"]
|
524
|
+
end
|
525
|
+
|
526
|
+
if @config["creation_style"] == "point_in_time"
|
527
|
+
cluster_config_struct[:source_db_cluster_identifier] = @config["source_identifier"]
|
528
|
+
cluster_config_struct[:restore_to_time] = @config["restore_time"] unless @config["restore_time"] == "latest"
|
529
|
+
cluster_config_struct[:use_latest_restorable_time] = true if @config["restore_time"] == "latest"
|
530
|
+
end
|
531
|
+
|
532
|
+
attempts = 0
|
533
|
+
begin
|
534
|
+
resp =
|
535
|
+
if @config["creation_style"] == "new"
|
536
|
+
MU.log "Creating new database cluster #{@config['identifier']}"
|
537
|
+
MU::Cloud::AWS.rds(@config['region']).create_db_cluster(cluster_config_struct)
|
538
|
+
elsif %w{existing_snapshot new_snapshot}.include?(@config["creation_style"])
|
539
|
+
MU.log "Creating new database cluster #{@config['identifier']} from snapshot #{@config["snapshot_id"]}"
|
540
|
+
MU::Cloud::AWS.rds(@config['region']).restore_db_cluster_from_snapshot(cluster_config_struct)
|
541
|
+
elsif @config["creation_style"] == "point_in_time"
|
542
|
+
MU.log "Creating new database cluster #{@config['identifier']} from point in time backup #{@config["restore_time"]} of #{@config["source_identifier"]}"
|
543
|
+
MU::Cloud::AWS.rds(@config['region']).restore_db_cluster_to_point_in_time(cluster_config_struct)
|
544
|
+
end
|
545
|
+
rescue Aws::RDS::Errors::InvalidParameterValue => e
|
546
|
+
if attempts < 5
|
547
|
+
MU.log "Got #{e.inspect} while creating database cluster #{@config['identifier']}, will retry a few times in case of transient errors.", MU::WARN
|
548
|
+
attempts += 1
|
549
|
+
sleep 10
|
550
|
+
retry
|
551
|
+
else
|
552
|
+
raise MuError, "Exhausted retries trying to create database cluster #{@config['identifier']}", MU::ERR, details: e.inspect
|
553
|
+
end
|
554
|
+
end
|
555
|
+
|
556
|
+
attempts = 0
|
557
|
+
loop do
|
558
|
+
MU.log "Waiting for #{@config['identifier']} to become available", MU::NOTICE if attempts % 5 == 0
|
559
|
+
attempts += 1
|
560
|
+
cluster = MU::Cloud::AWS::Database.getDatabaseClusterById(@config['identifier'], region: @config['region'])
|
561
|
+
break unless cluster.status != "available"
|
562
|
+
sleep 30
|
563
|
+
end
|
564
|
+
|
565
|
+
if %w{existing_snapshot new_snapshot point_in_time}.include?(@config["creation_style"])
|
566
|
+
modify_db_cluster_struct = {
|
567
|
+
db_cluster_identifier: @config['identifier'],
|
568
|
+
apply_immediately: true,
|
569
|
+
backup_retention_period: @config["backup_retention_period"],
|
570
|
+
db_cluster_parameter_group_name: @config["parameter_group_name"],
|
571
|
+
master_user_password: @config["password"],
|
572
|
+
preferred_backup_window: @config["preferred_backup_window"]
|
573
|
+
}
|
574
|
+
|
575
|
+
modify_db_cluster_struct[:preferred_maintenance_window] = @config["preferred_maintenance_window"] if @config["preferred_maintenance_window"]
|
576
|
+
MU::Cloud::AWS.rds(@config['region']).modify_db_cluster(modify_db_cluster_struct)
|
577
|
+
|
578
|
+
attempts = 0
|
579
|
+
loop do
|
580
|
+
MU.log "Waiting for #{@config['identifier']} to become available", MU::NOTICE if attempts % 5 == 0
|
581
|
+
attempts += 1
|
582
|
+
cluster = MU::Cloud::AWS::Database.getDatabaseClusterById(@config['identifier'], region: @config['region'])
|
583
|
+
break unless cluster.status != "available"
|
584
|
+
sleep 30
|
585
|
+
end
|
586
|
+
end
|
587
|
+
|
588
|
+
cluster = MU::Cloud::AWS::Database.getDatabaseClusterById(@config['identifier'], region: @config['region'])
|
589
|
+
MU::Cloud::AWS::DNSZone.genericMuDNSEntry(name: cluster.db_cluster_identifier, target: "#{cluster.endpoint}.", cloudclass: MU::Cloud::Database, sync_wait: @config['dns_sync_wait'])
|
590
|
+
return cluster.db_cluster_identifier
|
591
|
+
end
|
592
|
+
|
593
|
+
# Create a subnet group for a database.
|
594
|
+
def createSubnetGroup
|
595
|
+
# Finding subnets, creating security groups/adding holes, create subnet group
|
596
|
+
subnet_ids = []
|
597
|
+
vpc_id = nil
|
598
|
+
if @config['vpc'] and !@config['vpc'].empty?
|
599
|
+
raise MuError, "Didn't find the VPC specified in #{@config["vpc"]}" unless @vpc
|
600
|
+
|
601
|
+
vpc_id = @vpc.cloud_id
|
602
|
+
# Getting subnet IDs
|
603
|
+
subnets =
|
604
|
+
if @config["vpc"]["subnets"].empty?
|
605
|
+
@vpc.subnets
|
606
|
+
else
|
607
|
+
subnet_objects= []
|
608
|
+
@config["vpc"]["subnets"].each { |subnet|
|
609
|
+
sobj = @vpc.getSubnet(cloud_id: subnet["subnet_id"], name: subnet["subnet_name"])
|
610
|
+
if sobj.nil?
|
611
|
+
MU.log "Got nil result from @vpc.getSubnet(cloud_id: #{subnet["subnet_id"]}, name: #{subnet["subnet_name"]})", MU::WARN
|
612
|
+
else
|
613
|
+
subnet_objects << sobj
|
614
|
+
end
|
615
|
+
}
|
616
|
+
subnet_objects
|
617
|
+
end
|
618
|
+
|
619
|
+
subnets.each{ |subnet|
|
620
|
+
next if subnet.nil?
|
621
|
+
if @config["publicly_accessible"]
|
622
|
+
subnet_ids << subnet.cloud_id if !subnet.private?
|
623
|
+
elsif !@config["publicly_accessible"]
|
624
|
+
subnet_ids << subnet.cloud_id if subnet.private?
|
625
|
+
end
|
626
|
+
}
|
627
|
+
else
|
628
|
+
# If we didn't specify a VPC try to figure out if the account has a default VPC
|
629
|
+
vpc_id = nil
|
630
|
+
subnets = []
|
631
|
+
MU::Cloud::AWS.ec2(@config['region']).describe_vpcs.vpcs.each { |vpc|
|
632
|
+
if vpc.is_default
|
633
|
+
vpc_id = vpc.vpc_id
|
634
|
+
subnets = MU::Cloud::AWS.ec2(@config['region']).describe_subnets(
|
635
|
+
filters: [
|
636
|
+
{
|
637
|
+
name: "vpc-id",
|
638
|
+
values: [vpc_id]
|
639
|
+
}
|
640
|
+
]
|
641
|
+
).subnets
|
642
|
+
break
|
643
|
+
end
|
644
|
+
}
|
645
|
+
|
646
|
+
if !subnets.empty?
|
647
|
+
mu_subnets = []
|
648
|
+
subnets.each { |subnet|
|
649
|
+
subnet_ids << subnet.subnet_id
|
650
|
+
mu_subnets << {"subnet_id" => subnet.subnet_id}
|
651
|
+
}
|
652
|
+
|
653
|
+
@config['vpc'] = {
|
654
|
+
"vpc_id" => vpc_id,
|
655
|
+
"subnets" => mu_subnets
|
656
|
+
}
|
657
|
+
# Default VPC has only public subnets by default so setting publicly_accessible = true
|
658
|
+
@config["publicly_accessible"] = true
|
659
|
+
using_default_vpc = true
|
660
|
+
MU.log "Using default VPC for cache cluster #{@config['identifier']}"
|
661
|
+
end
|
662
|
+
end
|
663
|
+
|
664
|
+
if @config['creation_style'] == "existing"
|
665
|
+
srcdb = MU::Cloud::AWS.rds(@config['region']).describe_db_instances(
|
666
|
+
db_instance_identifier: @config['identifier']
|
667
|
+
)
|
668
|
+
srcdb_vpc = srcdb.db_instances.first.db_subnet_group.vpc_id
|
669
|
+
if srcdb_vpc != vpc_id
|
670
|
+
MU.log "#{self} is deploying into #{vpc_id}, but our source database, #{@config['identifier']}, is in #{srcdb_vpc}", MU::ERR
|
671
|
+
raise MuError, "Can't use 'existing' to deploy into a different VPC from the source database; try 'new_snapshot' instead"
|
672
|
+
end
|
673
|
+
end
|
674
|
+
|
675
|
+
if subnet_ids.empty?
|
676
|
+
raise MuError, "Couldn't find subnets in #{@vpc} to add to #{@config["subnet_group_name"]}. Make sure the subnets are valid and publicly_accessible is set correctly"
|
677
|
+
else
|
678
|
+
# Create subnet group
|
679
|
+
resp = MU::Cloud::AWS.rds(@config['region']).create_db_subnet_group(
|
680
|
+
db_subnet_group_name: @config["subnet_group_name"],
|
681
|
+
db_subnet_group_description: @config["subnet_group_name"],
|
682
|
+
subnet_ids: subnet_ids,
|
683
|
+
tags: allTags
|
684
|
+
)
|
685
|
+
@config["subnet_group_name"] = resp.db_subnet_group.db_subnet_group_name
|
686
|
+
|
687
|
+
if @dependencies.has_key?('firewall_rule')
|
688
|
+
@config["vpc_security_group_ids"] = []
|
689
|
+
@dependencies['firewall_rule'].values.each { |sg|
|
690
|
+
@config["vpc_security_group_ids"] << sg.cloud_id
|
691
|
+
}
|
692
|
+
end
|
693
|
+
end
|
694
|
+
|
695
|
+
# Find NAT and create holes in security groups.
|
696
|
+
if @config["vpc"]["nat_host_name"] || @config["vpc"]["nat_host_id"] || @config["vpc"]["nat_host_tag"] || @config["vpc"]["nat_host_ip"]
|
697
|
+
nat = @nat
|
698
|
+
if nat.is_a?(Struct) && nat.nat_gateway_id && nat.nat_gateway_id.start_with?("nat-")
|
699
|
+
MU.log "Using NAT Gateway, not modifying security groups"
|
700
|
+
else
|
701
|
+
nat_name, nat_conf, nat_deploydata = @nat.describe
|
702
|
+
@deploy.kittens['firewall_rules'].each_pair { |name, acl|
|
703
|
+
# 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.
|
704
|
+
if acl.config["admin"]
|
705
|
+
acl.addRule([nat_deploydata["private_ip_address"]], proto: "tcp")
|
706
|
+
acl.addRule([nat_deploydata["private_ip_address"]], proto: "udp")
|
707
|
+
break
|
708
|
+
end
|
709
|
+
}
|
710
|
+
end
|
711
|
+
end
|
712
|
+
end
|
713
|
+
|
714
|
+
# Create a database cluster parameter group.
|
715
|
+
def createDBClusterParameterGroup
|
716
|
+
MU.log "Creating a cluster parameter group #{@config["parameter_group_name"]}"
|
717
|
+
|
718
|
+
MU::Cloud::AWS.rds(@config['region']).create_db_cluster_parameter_group(
|
719
|
+
db_cluster_parameter_group_name: @config["parameter_group_name"],
|
720
|
+
db_parameter_group_family: @config["parameter_group_family"],
|
721
|
+
description: "Parameter group for #{@config["parameter_group_family"]}",
|
722
|
+
tags: allTags
|
723
|
+
)
|
724
|
+
|
725
|
+
if @config["cluster_parameter_group_parameters"] && !@config["cluster_parameter_group_parameters"].empty?
|
726
|
+
params = []
|
727
|
+
@config["cluster_parameter_group_parameters"].each { |item|
|
728
|
+
params << {parameter_name: item['name'], parameter_value: item['value'], apply_method: item['apply_method']}
|
729
|
+
}
|
730
|
+
|
731
|
+
MU.log "Modifiying cluster parameter group #{@config["parameter_group_name"]}"
|
732
|
+
MU::Cloud::AWS.rds(@config['region']).modify_db_cluster_parameter_group(
|
733
|
+
db_cluster_parameter_group_name: @config["parameter_group_name"],
|
734
|
+
parameters: params
|
735
|
+
)
|
736
|
+
end
|
737
|
+
end
|
738
|
+
|
739
|
+
# Create a database parameter group.
|
740
|
+
def createDBParameterGroup
|
741
|
+
MU.log "Creating a database parameter group #{@config["parameter_group_name"]}"
|
742
|
+
MU::Cloud::AWS.rds(@config['region']).create_db_parameter_group(
|
743
|
+
db_parameter_group_name: @config["parameter_group_name"],
|
744
|
+
db_parameter_group_family: @config["parameter_group_family"],
|
745
|
+
description: "Parameter group for #{@config["parameter_group_family"]}",
|
746
|
+
tags: allTags
|
747
|
+
)
|
748
|
+
|
749
|
+
if @config["db_parameter_group_parameters"] && !@config["db_parameter_group_parameters"].empty?
|
750
|
+
params = []
|
751
|
+
@config["db_parameter_group_parameters"].each { |item|
|
752
|
+
params << {parameter_name: item['name'], parameter_value: item['value'], apply_method: item['apply_method']}
|
753
|
+
}
|
754
|
+
|
755
|
+
MU.log "Modifiying database parameter group #{@config["parameter_group_name"]}"
|
756
|
+
MU::Cloud::AWS.rds(@config['region']).modify_db_parameter_group(
|
757
|
+
db_parameter_group_name: @config["parameter_group_name"],
|
758
|
+
parameters: params
|
759
|
+
)
|
760
|
+
end
|
761
|
+
end
|
762
|
+
|
763
|
+
# Retrieve a complete description of a database cluster parameter group.
|
764
|
+
# @param param_group_id [String]: The cloud provider's identifier for this parameter group.
|
765
|
+
# @param region [String]: The cloud provider region
|
766
|
+
# @return [OpenStruct]
|
767
|
+
def self.getDBClusterParameterGroup(param_group_id, region: MU.curRegion)
|
768
|
+
MU::Cloud::AWS.rds(region).describe_db_cluster_parameter_groups(db_cluster_parameter_group_name: param_group_id).db_cluster_parameter_groups.first
|
769
|
+
# rescue DBClusterParameterGroupNotFound => e
|
770
|
+
# Of course the API will return DBParameterGroupNotFound instead of the documented DBClusterParameterGroupNotFound error.
|
771
|
+
rescue Aws::RDS::Errors::DBParameterGroupNotFound => e
|
772
|
+
#we're fine returning nil
|
773
|
+
end
|
774
|
+
|
775
|
+
# Retrieve a complete description of a database parameter group.
|
776
|
+
# @param param_group_id [String]: The cloud provider's identifier for this parameter group.
|
777
|
+
# @param region [String]: The cloud provider region
|
778
|
+
# @return [OpenStruct]
|
779
|
+
def self.getDBParameterGroup(param_group_id, region: MU.curRegion)
|
780
|
+
MU::Cloud::AWS.rds(region).describe_db_parameter_groups(db_parameter_group_name: param_group_id).db_parameter_groups.first
|
781
|
+
rescue Aws::RDS::Errors::DBParameterGroupNotFound => e
|
782
|
+
#we're fine returning nil
|
783
|
+
end
|
784
|
+
|
785
|
+
# Retrieve a complete description of a database subnet group.
|
786
|
+
# @param subnet_id [String]: The cloud provider's identifier for this subnet group.
|
787
|
+
# @param region [String]: The cloud provider region
|
788
|
+
# @return [OpenStruct]
|
789
|
+
def self.getSubnetGroup(subnet_id, region: MU.curRegion)
|
790
|
+
MU::Cloud::AWS.rds(region).describe_db_subnet_groups(db_subnet_group_name: subnet_id).db_subnet_groups.first
|
791
|
+
rescue Aws::RDS::Errors::DBSubnetGroupNotFoundFault => e
|
792
|
+
#we're fine returning nil
|
793
|
+
end
|
794
|
+
|
795
|
+
# Called automatically by {MU::Deploy#createResources}
|
796
|
+
def groom
|
797
|
+
unless @config["create_cluster"]
|
798
|
+
database = MU::Cloud::AWS::Database.getDatabaseById(@config['identifier'], region: @config['region'])
|
799
|
+
|
800
|
+
# Run SQL on deploy
|
801
|
+
if @config['run_sql_on_deploy']
|
802
|
+
MU.log "Running initial SQL commands on #{@config['name']}", details: @config['run_sql_on_deploy']
|
803
|
+
|
804
|
+
# check if DB is private or public
|
805
|
+
if !database.publicly_accessible
|
806
|
+
# This doesn't necessarily mean what we think it does. publicly_accessible = true means resolve to public address.
|
807
|
+
# publicly_accessible can still be set to true even when only private subnets are included in the subnet group. We try to solve this during creation.
|
808
|
+
is_private = true
|
809
|
+
else
|
810
|
+
is_private = false
|
811
|
+
end
|
812
|
+
|
813
|
+
#Setting up connection params
|
814
|
+
ssh_keydir = Etc.getpwuid(Process.uid).dir+"/.ssh"
|
815
|
+
keypairname, ssh_private_key, ssh_public_key = @deploy.SSHKey
|
816
|
+
if is_private and @vpc
|
817
|
+
if @config['vpc']['nat_host_name']
|
818
|
+
begin
|
819
|
+
proxy_cmd = "ssh -q -o StrictHostKeyChecking=no -W %h:%p #{nat_ssh_user}@#{nat_host_name}"
|
820
|
+
gateway = Net::SSH::Gateway.new(
|
821
|
+
@config['vpc']['nat_host_name'],
|
822
|
+
@config['vpc']['nat_ssh_user'],
|
823
|
+
:keys => [ssh_keydir+"/"+keypairname],
|
824
|
+
:keys_only => true,
|
825
|
+
:auth_methods => ['publickey'],
|
826
|
+
# :verbose => :info
|
827
|
+
)
|
828
|
+
port = gateway.open(database.endpoint.address, database.endpoint.port)
|
829
|
+
address = "127.0.0.1"
|
830
|
+
MU.log "Tunneling #{@config['engine']} connection through #{nat_host_name} via local port #{port}", MU::DEBUG
|
831
|
+
rescue IOError => e
|
832
|
+
MU.log "Got #{e.inspect} while connecting to #{@config['identifier']} through NAT #{nat_host_name}", MU::ERR
|
833
|
+
end
|
834
|
+
else
|
835
|
+
MU.log "Can't run initial SQL commands! Database #{@config['identifier']} is not publicly accessible, but we have no NAT host for connecting to it", MU::WARN, details: @config['run_sql_on_deploy']
|
836
|
+
end
|
837
|
+
else
|
838
|
+
port = database.endpoint.port
|
839
|
+
address = database.endpoint.address
|
840
|
+
end
|
841
|
+
|
842
|
+
# Running SQL on deploy
|
843
|
+
if @config['engine'] == "postgres"
|
844
|
+
autoload :PG, 'pg'
|
845
|
+
begin
|
846
|
+
conn = PG::Connection.new(
|
847
|
+
:host => address,
|
848
|
+
:port => port,
|
849
|
+
:user => @config['master_user'],
|
850
|
+
:dbname => database.db_name,
|
851
|
+
:password => @config['password']
|
852
|
+
)
|
853
|
+
@config['run_sql_on_deploy'].each { |cmd|
|
854
|
+
MU.log "Running #{cmd} on database #{@config['name']}"
|
855
|
+
conn.exec(cmd)
|
856
|
+
}
|
857
|
+
conn.finish
|
858
|
+
rescue PG::Error => e
|
859
|
+
MU.log "Failed to run initial SQL commands on #{@config['name']} via #{address}:#{port}: #{e.inspect}", MU::WARN, details: conn
|
860
|
+
end
|
861
|
+
elsif @config['engine'] == "mysql"
|
862
|
+
autoload :Mysql, 'mysql'
|
863
|
+
MU.log "Initiating mysql connection to #{address}:#{port} as #{@config['master_user']}"
|
864
|
+
conn = Mysql.new(address, @config['master_user'], @config['password'], "mysql", port)
|
865
|
+
@config['run_sql_on_deploy'].each { |cmd|
|
866
|
+
MU.log "Running #{cmd} on database #{@config['name']}"
|
867
|
+
conn.query(cmd)
|
868
|
+
}
|
869
|
+
conn.close
|
870
|
+
end
|
871
|
+
|
872
|
+
# close the SQL on deploy sessions
|
873
|
+
if is_private
|
874
|
+
begin
|
875
|
+
gateway.close(port)
|
876
|
+
rescue IOError => e
|
877
|
+
MU.log "Failed to close ssh session to NAT after running sql_on_deploy", MU::ERR, details: e.inspect
|
878
|
+
end
|
879
|
+
end
|
880
|
+
end
|
881
|
+
|
882
|
+
# set multi-az on deploy
|
883
|
+
if @config['multi_az_on_deploy']
|
884
|
+
if !database.multi_az
|
885
|
+
MU.log "Setting multi-az on #{@config['identifier']}"
|
886
|
+
attempts = 0
|
887
|
+
begin
|
888
|
+
MU::Cloud::AWS.rds(@config['region']).modify_db_instance(
|
889
|
+
db_instance_identifier: @config['identifier'],
|
890
|
+
apply_immediately: true,
|
891
|
+
multi_az: true
|
892
|
+
)
|
893
|
+
rescue Aws::RDS::Errors::InvalidParameterValue, Aws::RDS::Errors::InvalidDBInstanceState => e
|
894
|
+
if attempts < 15
|
895
|
+
MU.log "Got #{e.inspect} while setting Multi-AZ on #{@config['identifier']}, retrying."
|
896
|
+
attempts += 1
|
897
|
+
sleep 15
|
898
|
+
retry
|
899
|
+
else
|
900
|
+
MU.log "Couldn't set Multi-AZ on #{@config['identifier']} after several retries, giving up. #{e.inspect}", MU::ERR
|
901
|
+
end
|
902
|
+
end
|
903
|
+
end
|
904
|
+
end
|
905
|
+
end
|
906
|
+
end
|
907
|
+
|
908
|
+
# Generate database user, database identifier, database name based on engine-specific constraints
|
909
|
+
# @return [String]: Name
|
910
|
+
def self.getName(basename, type: 'dbname', config: nil)
|
911
|
+
if type == 'dbname'
|
912
|
+
# Apply engine-specific db name constraints
|
913
|
+
if config["engine"].match(/^oracle/)
|
914
|
+
(MU.seed.downcase+config["name"])[0..7]
|
915
|
+
elsif config["engine"].match(/^sqlserver/)
|
916
|
+
nil
|
917
|
+
elsif config["engine"].match(/^mysql/)
|
918
|
+
basename[0..63]
|
919
|
+
elsif config["engine"].match(/^aurora/)
|
920
|
+
(MU.seed.downcase+config["name"])[0..7]
|
921
|
+
else
|
922
|
+
basename
|
923
|
+
end
|
924
|
+
elsif type == 'dbuser'
|
925
|
+
# Apply engine-specific master username constraints
|
926
|
+
if config["engine"].match(/^oracle/)
|
927
|
+
basename[0..29].gsub(/[^a-z0-9]/i, "")
|
928
|
+
elsif config["engine"].match(/^sqlserver/)
|
929
|
+
basename[0..127].gsub(/[^a-z0-9]/i, "")
|
930
|
+
elsif config["engine"].match(/^mysql/)
|
931
|
+
basename[0..15].gsub(/[^a-z0-9]/i, "")
|
932
|
+
elsif config["engine"].match(/^aurora/)
|
933
|
+
basename[0..15].gsub(/[^a-z0-9]/i, "")
|
934
|
+
else
|
935
|
+
basename.gsub(/[^a-z0-9]/i, "")
|
936
|
+
end
|
937
|
+
end
|
938
|
+
end
|
939
|
+
|
940
|
+
# Permit a host to connect to the given database instance.
|
941
|
+
# @param cidr [String]: The CIDR-formatted IP address or block to allow access.
|
942
|
+
# @return [void]
|
943
|
+
def allowHost(cidr)
|
944
|
+
# If we're an old, Classic-style database with RDS-specific
|
945
|
+
# authorization, punch holes in that.
|
946
|
+
if !cloud_desc.db_security_groups.empty?
|
947
|
+
cloud_desc.db_security_groups.each { |rds_sg|
|
948
|
+
begin
|
949
|
+
MU::Cloud::AWS.rds(@config['region']).authorize_db_security_group_ingress(
|
950
|
+
db_security_group_name: rds_sg.db_security_group_name,
|
951
|
+
cidrip: cidr
|
952
|
+
)
|
953
|
+
rescue Aws::RDS::Errors::AuthorizationAlreadyExists => e
|
954
|
+
MU.log "CIDR #{cidr} already in database instance #{@cloud_id} security group", MU::WARN
|
955
|
+
end
|
956
|
+
}
|
957
|
+
end
|
958
|
+
|
959
|
+
# Otherwise go get our generic EC2 ruleset and punch a hole in it
|
960
|
+
if @dependencies.has_key?('firewall_rule')
|
961
|
+
@dependencies['firewall_rule'].values.each { |sg|
|
962
|
+
sg.addRule([cidr], proto: "tcp", port: cloud_desc.endpoint.port)
|
963
|
+
break
|
964
|
+
}
|
965
|
+
end
|
966
|
+
end
|
967
|
+
|
968
|
+
# Retrieve the complete cloud provider description of a database instance.
|
969
|
+
# @param db_id [String]: The cloud provider's identifier for this database.
|
970
|
+
# @param region [String]: The cloud provider region
|
971
|
+
# @return [OpenStruct]
|
972
|
+
def self.getDatabaseById(db_id, region: MU.curRegion)
|
973
|
+
raise MuError, "You must provide a db_id" if db_id.nil?
|
974
|
+
MU::Cloud::AWS.rds(region).describe_db_instances(db_instance_identifier: db_id).db_instances.first
|
975
|
+
rescue Aws::RDS::Errors::DBInstanceNotFound => e
|
976
|
+
# We're fine with this returning nil when searching for a database instance the doesn't exist.
|
977
|
+
end
|
978
|
+
|
979
|
+
# Retrieve the complete cloud provider description of a database cluster.
|
980
|
+
# @param db_cluster_id [String]: The cloud provider's identifier for this database cluster.
|
981
|
+
# @param region [String]: The cloud provider region
|
982
|
+
# @return [OpenStruct]
|
983
|
+
def self.getDatabaseClusterById(db_cluster_id, region: MU.curRegion)
|
984
|
+
MU::Cloud::AWS.rds(region).describe_db_clusters(db_cluster_identifier: db_cluster_id).db_clusters.first
|
985
|
+
rescue Aws::RDS::Errors::DBClusterNotFoundFault => e
|
986
|
+
# We're fine with this returning nil when searching for a database cluster the doesn't exist.
|
987
|
+
end
|
988
|
+
|
989
|
+
# Register a description of this database instance with this deployment's metadata.
|
990
|
+
# Register read replicas as separate instances, while we're
|
991
|
+
# at it.
|
992
|
+
def notify
|
993
|
+
my_dbs = [@config]
|
994
|
+
if @config['read_replica']
|
995
|
+
@config['read_replica']['creation_style'] = "read_replica"
|
996
|
+
@config['read_replica']['password'] = @config["password"]
|
997
|
+
my_dbs << @config['read_replica']
|
998
|
+
end
|
999
|
+
|
1000
|
+
deploy_struct = {}
|
1001
|
+
my_dbs.each { |db|
|
1002
|
+
deploy_struct =
|
1003
|
+
if db["create_cluster"]
|
1004
|
+
db["identifier"] = @mu_name.downcase if db["identifier"].nil?
|
1005
|
+
cluster = MU::Cloud::AWS::Database.getDatabaseClusterById(db["identifier"], region: db['region'])
|
1006
|
+
# 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.
|
1007
|
+
if db['dns_records']
|
1008
|
+
db['dns_records'].each { |dnsrec|
|
1009
|
+
dnsrec['name'] = cluster.db_cluster_identifier if !dnsrec.has_key?('name')
|
1010
|
+
dnsrec['name'] = "#{dnsrec['name']}.#{MU.environment.downcase}" if dnsrec["append_environment_name"] && !dnsrec['name'].match(/\.#{MU.environment.downcase}$/)
|
1011
|
+
}
|
1012
|
+
end
|
1013
|
+
# XXX this should be a call to @deploy.nameKitten
|
1014
|
+
MU::Cloud::AWS::DNSZone.createRecordsFromConfig(db['dns_records'], target: cluster.endpoint)
|
1015
|
+
|
1016
|
+
vpc_sg_ids = []
|
1017
|
+
cluster.vpc_security_groups.each { |vpc_sg|
|
1018
|
+
vpc_sg_ids << vpc_sg.vpc_security_group_id
|
1019
|
+
}
|
1020
|
+
|
1021
|
+
{
|
1022
|
+
"allocated_storage" => cluster.allocated_storage,
|
1023
|
+
"parameter_group" => cluster.db_cluster_parameter_group,
|
1024
|
+
"subnet_group" => cluster.db_subnet_group,
|
1025
|
+
"identifier" => cluster.db_cluster_identifier,
|
1026
|
+
"region" => db['region'],
|
1027
|
+
"engine" => cluster.engine,
|
1028
|
+
"engine_version" => cluster.engine_version,
|
1029
|
+
"backup_retention_period" => cluster.backup_retention_period,
|
1030
|
+
"preferred_backup_window" => cluster.preferred_backup_window,
|
1031
|
+
"preferred_maintenance_window" => cluster.preferred_maintenance_window,
|
1032
|
+
"endpoint" => cluster.endpoint,
|
1033
|
+
"port" => cluster.port,
|
1034
|
+
"username" => cluster.master_username,
|
1035
|
+
"vpc_sgs" => vpc_sg_ids,
|
1036
|
+
"azs" => cluster.availability_zones,
|
1037
|
+
"vault_name" => cluster.db_cluster_identifier.upcase,
|
1038
|
+
"vault_item" => "database_credentials",
|
1039
|
+
"password_field" => "password",
|
1040
|
+
"create_style" => db['creation_style'],
|
1041
|
+
"db_name" => cluster.database_name,
|
1042
|
+
"db_cluster_members" => cluster.db_cluster_members
|
1043
|
+
}
|
1044
|
+
else
|
1045
|
+
db["identifier"] = @mu_name.downcase if db["identifier"].nil? # Is this still valid if we have read replicas?
|
1046
|
+
database = MU::Cloud::AWS::Database.getDatabaseById(db["identifier"], region: db['region'])
|
1047
|
+
# 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.
|
1048
|
+
unless db["add_cluster_node"]
|
1049
|
+
# It isn't necessarily clear what we should do with DNS records of cluster members. Probably need to expose this to the BoK somehow.
|
1050
|
+
if db['dns_records']
|
1051
|
+
db['dns_records'].each { |dnsrec|
|
1052
|
+
dnsrec['name'] = database.db_instance_identifier if !dnsrec.has_key?('name')
|
1053
|
+
dnsrec['name'] = "#{dnsrec['name']}.#{MU.environment.downcase}" if dnsrec["append_environment_name"] && !dnsrec['name'].match(/\.#{MU.environment.downcase}$/)
|
1054
|
+
}
|
1055
|
+
# XXX this should be a call to @deploy.nameKitten
|
1056
|
+
MU::Cloud::AWS::DNSZone.createRecordsFromConfig(db['dns_records'], target: database.endpoint.address)
|
1057
|
+
end
|
1058
|
+
end
|
1059
|
+
|
1060
|
+
database = cloud_desc
|
1061
|
+
|
1062
|
+
vpc_sg_ids = Array.new
|
1063
|
+
database.vpc_security_groups.each { |vpc_sg|
|
1064
|
+
vpc_sg_ids << vpc_sg.vpc_security_group_id
|
1065
|
+
}
|
1066
|
+
|
1067
|
+
rds_sg_ids = Array.new
|
1068
|
+
database.db_security_groups.each { |rds_sg|
|
1069
|
+
rds_sg_ids << rds_sg.db_security_group_name
|
1070
|
+
}
|
1071
|
+
|
1072
|
+
subnet_ids = []
|
1073
|
+
if database.db_subnet_group and database.db_subnet_group.subnets
|
1074
|
+
database.db_subnet_group.subnets.each { |subnet|
|
1075
|
+
subnet_ids << subnet.subnet_identifier
|
1076
|
+
}
|
1077
|
+
end
|
1078
|
+
|
1079
|
+
{
|
1080
|
+
"identifier" => database.db_instance_identifier,
|
1081
|
+
"region" => db['region'],
|
1082
|
+
"engine" => database.engine,
|
1083
|
+
"engine_version" => database.engine_version,
|
1084
|
+
"backup_retention_period" => database.backup_retention_period,
|
1085
|
+
"preferred_backup_window" => database.preferred_backup_window,
|
1086
|
+
"preferred_maintenance_window" => database.preferred_maintenance_window,
|
1087
|
+
"auto_minor_version_upgrade" => database.auto_minor_version_upgrade,
|
1088
|
+
"storage_encrypted" => database.storage_encrypted,
|
1089
|
+
"endpoint" => database.endpoint.address,
|
1090
|
+
"port" => database.endpoint.port,
|
1091
|
+
"username" => database.master_username,
|
1092
|
+
"rds_sgs" => rds_sg_ids,
|
1093
|
+
"vpc_sgs" => vpc_sg_ids,
|
1094
|
+
"az" => database.availability_zone,
|
1095
|
+
"vault_name" => database.db_instance_identifier.upcase,
|
1096
|
+
"vault_item" => "database_credentials",
|
1097
|
+
"password_field" => "password",
|
1098
|
+
"create_style" => db['creation_style'],
|
1099
|
+
"db_name" => database.db_name,
|
1100
|
+
"multi_az" => database.multi_az,
|
1101
|
+
"publicly_accessible" => database.publicly_accessible,
|
1102
|
+
"ca_certificate_identifier" => database.ca_certificate_identifier,
|
1103
|
+
"subnets" => subnet_ids,
|
1104
|
+
"read_replica_source_db" => database.read_replica_source_db_instance_identifier,
|
1105
|
+
"read_replica_instance_identifiers" => database.read_replica_db_instance_identifiers,
|
1106
|
+
"cluster_identifier" => database.db_cluster_identifier,
|
1107
|
+
"size" => database.db_instance_class,
|
1108
|
+
"storage" => database.allocated_storage
|
1109
|
+
}
|
1110
|
+
end
|
1111
|
+
MU.log "Deploy structure is now #{deploy_struct}", MU::DEBUG
|
1112
|
+
}
|
1113
|
+
|
1114
|
+
raise MuError, "Can't find any deployment metadata" if deploy_struct.empty?
|
1115
|
+
return deploy_struct
|
1116
|
+
end
|
1117
|
+
|
1118
|
+
# Generate a snapshot from the database described in this instance.
|
1119
|
+
# @return [String]: The cloud provider's identifier for the snapshot.
|
1120
|
+
def createNewSnapshot
|
1121
|
+
snap_id = @deploy.getResourceName(@config["name"]) + Time.new.strftime("%M%S").to_s
|
1122
|
+
|
1123
|
+
attempts = 0
|
1124
|
+
begin
|
1125
|
+
snapshot =
|
1126
|
+
if @config["create_cluster"]
|
1127
|
+
MU::Cloud::AWS.rds(@config['region']).create_db_cluster_snapshot(
|
1128
|
+
db_cluster_snapshot_identifier: snap_id,
|
1129
|
+
db_cluster_identifier: @config["identifier"],
|
1130
|
+
tags: allTags
|
1131
|
+
)
|
1132
|
+
else
|
1133
|
+
MU::Cloud::AWS.rds(@config['region']).create_db_snapshot(
|
1134
|
+
db_snapshot_identifier: snap_id,
|
1135
|
+
db_instance_identifier: @config["identifier"],
|
1136
|
+
tags: allTags
|
1137
|
+
)
|
1138
|
+
end
|
1139
|
+
rescue Aws::RDS::Errors::InvalidDBInstanceState, Aws::RDS::Errors::InvalidDBClusterStateFault => e
|
1140
|
+
raise MuError, e.inspect if attempts >= 10
|
1141
|
+
attempts += 1
|
1142
|
+
sleep 60
|
1143
|
+
retry
|
1144
|
+
end
|
1145
|
+
|
1146
|
+
attempts = 0
|
1147
|
+
loop do
|
1148
|
+
MU.log "Waiting for RDS snapshot of #{@config["identifier"]} to be ready...", MU::NOTICE if attempts % 20 == 0
|
1149
|
+
MU.log "Waiting for RDS snapshot of #{@config["identifier"]} to be ready...", MU::DEBUG
|
1150
|
+
snapshot_resp =
|
1151
|
+
if @config["create_cluster"]
|
1152
|
+
MU::Cloud::AWS.rds(@config['region']).describe_db_cluster_snapshots(db_cluster_snapshot_identifier: snap_id)
|
1153
|
+
else
|
1154
|
+
MU::Cloud::AWS.rds(@config['region']).describe_db_snapshots(db_snapshot_identifier: snap_id)
|
1155
|
+
end
|
1156
|
+
|
1157
|
+
if @config["create_cluster"]
|
1158
|
+
break unless snapshot_resp.db_cluster_snapshots.first.status != "available"
|
1159
|
+
else
|
1160
|
+
break unless snapshot_resp.db_snapshots.first.status != "available"
|
1161
|
+
end
|
1162
|
+
attempts += 1
|
1163
|
+
sleep 15
|
1164
|
+
end
|
1165
|
+
|
1166
|
+
return snap_id
|
1167
|
+
end
|
1168
|
+
|
1169
|
+
# Fetch the latest snapshot of the database described in this instance.
|
1170
|
+
# @return [String]: The cloud provider's identifier for the snapshot.
|
1171
|
+
def getExistingSnapshot
|
1172
|
+
resp =
|
1173
|
+
if @config["create_cluster"]
|
1174
|
+
MU::Cloud::AWS.rds(@config['region']).describe_db_cluster_snapshots(db_cluster_snapshot_identifier: @config["identifier"])
|
1175
|
+
else
|
1176
|
+
MU::Cloud::AWS.rds(@config['region']).describe_db_snapshots(db_snapshot_identifier: @config["identifier"])
|
1177
|
+
end
|
1178
|
+
|
1179
|
+
snapshots = @config["create_cluster"] ? resp.db_cluster_snapshots : resp.db_snapshots
|
1180
|
+
|
1181
|
+
if snapshots.empty?
|
1182
|
+
nil
|
1183
|
+
else
|
1184
|
+
sorted_snapshots = snapshots.sort_by { |snap| snap.snapshot_create_time }
|
1185
|
+
@config["create_cluster"] ? sorted_snapshots.last.db_cluster_snapshot_identifier : sorted_snapshots.last.db_snapshot_identifier
|
1186
|
+
end
|
1187
|
+
end
|
1188
|
+
|
1189
|
+
# Called by {MU::Cleanup}. Locates resources that were created by the
|
1190
|
+
# currently-loaded deployment, and purges them.
|
1191
|
+
# @param noop [Boolean]: If true, will only print what would be done
|
1192
|
+
# @param ignoremaster [Boolean]: If true, will remove resources not flagged as originating from this Mu server
|
1193
|
+
# @param region [String]: The cloud provider region in which to operate
|
1194
|
+
# @return [void]
|
1195
|
+
def self.cleanup(skipsnapshots: false, noop: false, ignoremaster: false, region: MU.curRegion, flags: {})
|
1196
|
+
resp = MU::Cloud::AWS.rds(region).describe_db_instances
|
1197
|
+
threads = []
|
1198
|
+
|
1199
|
+
resp.db_instances.each { |db|
|
1200
|
+
db_id = db.db_instance_identifier
|
1201
|
+
arn = MU::Cloud::AWS::Database.getARN(db.db_instance_identifier, "db", "rds", region: region)
|
1202
|
+
tags = MU::Cloud::AWS.rds(region).list_tags_for_resource(resource_name: arn).tag_list
|
1203
|
+
|
1204
|
+
found_muid = false
|
1205
|
+
found_master = false
|
1206
|
+
tags.each { |tag|
|
1207
|
+
found_muid = true if tag.key == "MU-ID" && tag.value == MU.deploy_id
|
1208
|
+
found_master = true if tag.key == "MU-MASTER-IP" && tag.value == MU.mu_public_ip
|
1209
|
+
}
|
1210
|
+
next if !found_muid
|
1211
|
+
|
1212
|
+
delete =
|
1213
|
+
if ignoremaster && found_muid
|
1214
|
+
true
|
1215
|
+
elsif !ignoremaster && found_muid && found_master
|
1216
|
+
true
|
1217
|
+
else
|
1218
|
+
false
|
1219
|
+
end
|
1220
|
+
|
1221
|
+
if delete
|
1222
|
+
parent_thread_id = Thread.current.object_id
|
1223
|
+
threads << Thread.new(db) { |mydb|
|
1224
|
+
MU.dupGlobals(parent_thread_id)
|
1225
|
+
Thread.abort_on_exception = true
|
1226
|
+
MU::Cloud::AWS::Database.terminate_rds_instance(mydb, noop: noop, skipsnapshots: skipsnapshots, region: region, deploy_id: MU.deploy_id, cloud_id: db.db_instance_identifier, mu_name: db.db_instance_identifier.upcase)
|
1227
|
+
}
|
1228
|
+
end
|
1229
|
+
}
|
1230
|
+
|
1231
|
+
# Wait for all of the databases to finish cleanup before proceeding
|
1232
|
+
threads.each { |t|
|
1233
|
+
t.join
|
1234
|
+
}
|
1235
|
+
|
1236
|
+
# Cleanup database clusters
|
1237
|
+
threads = []
|
1238
|
+
resp = MU::Cloud::AWS.rds(region).describe_db_clusters
|
1239
|
+
resp.db_clusters.each { |cluster|
|
1240
|
+
cluster_id = cluster.db_cluster_identifier
|
1241
|
+
arn = MU::Cloud::AWS::Database.getARN(cluster_id, "cluster", "rds", region: region)
|
1242
|
+
tags = MU::Cloud::AWS.rds(region).list_tags_for_resource(resource_name: arn).tag_list
|
1243
|
+
|
1244
|
+
found_muid = false
|
1245
|
+
found_master = false
|
1246
|
+
tags.each { |tag|
|
1247
|
+
found_muid = true if tag.key == "MU-ID" && tag.value == MU.deploy_id
|
1248
|
+
found_master = true if tag.key == "MU-MASTER-IP" && tag.value == MU.mu_public_ip
|
1249
|
+
}
|
1250
|
+
next if !found_muid
|
1251
|
+
|
1252
|
+
delete =
|
1253
|
+
if ignoremaster && found_muid
|
1254
|
+
true
|
1255
|
+
elsif !ignoremaster && found_muid && found_master
|
1256
|
+
true
|
1257
|
+
else
|
1258
|
+
false
|
1259
|
+
end
|
1260
|
+
|
1261
|
+
if delete
|
1262
|
+
parent_thread_id = Thread.current.object_id
|
1263
|
+
threads << Thread.new(cluster) { |mydbcluster|
|
1264
|
+
MU.dupGlobals(parent_thread_id)
|
1265
|
+
Thread.abort_on_exception = true
|
1266
|
+
MU::Cloud::AWS::Database.terminate_rds_cluster(mydbcluster, noop: noop, skipsnapshots: skipsnapshots, region: region, deploy_id: MU.deploy_id, cloud_id: cluster_id, mu_name: cluster_id.upcase)
|
1267
|
+
}
|
1268
|
+
end
|
1269
|
+
}
|
1270
|
+
|
1271
|
+
# Wait for all of the database clusters to finish cleanup before proceeding
|
1272
|
+
threads.each { |t|
|
1273
|
+
t.join
|
1274
|
+
}
|
1275
|
+
|
1276
|
+
threads = []
|
1277
|
+
# Cleanup database subnet group
|
1278
|
+
MU::Cloud::AWS.rds(region).describe_db_subnet_groups.db_subnet_groups.each { |sub_group|
|
1279
|
+
sub_group_id = sub_group.db_subnet_group_name
|
1280
|
+
arn = MU::Cloud::AWS::Database.getARN(sub_group_id, "subgrp", "rds", region: region)
|
1281
|
+
tags = MU::Cloud::AWS.rds(region).list_tags_for_resource(resource_name: arn).tag_list
|
1282
|
+
|
1283
|
+
found_muid = false
|
1284
|
+
found_master = false
|
1285
|
+
tags.each { |tag|
|
1286
|
+
found_muid = true if tag.key == "MU-ID" && tag.value == MU.deploy_id
|
1287
|
+
found_master = true if tag.key == "MU-MASTER-IP" && tag.value == MU.mu_public_ip
|
1288
|
+
}
|
1289
|
+
next if !found_muid
|
1290
|
+
|
1291
|
+
delete =
|
1292
|
+
if ignoremaster && found_muid
|
1293
|
+
true
|
1294
|
+
elsif !ignoremaster && found_muid && found_master
|
1295
|
+
true
|
1296
|
+
else
|
1297
|
+
false
|
1298
|
+
end
|
1299
|
+
|
1300
|
+
if delete
|
1301
|
+
parent_thread_id = Thread.current.object_id
|
1302
|
+
threads << Thread.new(sub_group) { |mysubgroup|
|
1303
|
+
MU.dupGlobals(parent_thread_id)
|
1304
|
+
Thread.abort_on_exception = true
|
1305
|
+
MU::Cloud::AWS::Database.delete_subnet_group(sub_group_id, region: region) unless noop
|
1306
|
+
}
|
1307
|
+
end
|
1308
|
+
}
|
1309
|
+
|
1310
|
+
# Cleanup database parameter group
|
1311
|
+
MU::Cloud::AWS.rds(region).describe_db_parameter_groups.db_parameter_groups.each { |param_group|
|
1312
|
+
param_group_id = param_group.db_parameter_group_name
|
1313
|
+
arn = MU::Cloud::AWS::Database.getARN(param_group_id, "pg", "rds", region: region)
|
1314
|
+
tags = MU::Cloud::AWS.rds(region).list_tags_for_resource(resource_name: arn).tag_list
|
1315
|
+
|
1316
|
+
found_muid = false
|
1317
|
+
found_master = false
|
1318
|
+
tags.each { |tag|
|
1319
|
+
found_muid = true if tag.key == "MU-ID" && tag.value == MU.deploy_id
|
1320
|
+
found_master = true if tag.key == "MU-MASTER-IP" && tag.value == MU.mu_public_ip
|
1321
|
+
}
|
1322
|
+
next if !found_muid
|
1323
|
+
|
1324
|
+
delete =
|
1325
|
+
if ignoremaster && found_muid
|
1326
|
+
true
|
1327
|
+
elsif !ignoremaster && found_muid && found_master
|
1328
|
+
true
|
1329
|
+
else
|
1330
|
+
false
|
1331
|
+
end
|
1332
|
+
|
1333
|
+
if delete
|
1334
|
+
parent_thread_id = Thread.current.object_id
|
1335
|
+
threads << Thread.new(param_group) { |myparamgroup|
|
1336
|
+
MU.dupGlobals(parent_thread_id)
|
1337
|
+
Thread.abort_on_exception = true
|
1338
|
+
MU::Cloud::AWS::Database.delete_db_parameter_group(param_group_id, region: region) unless noop
|
1339
|
+
}
|
1340
|
+
end
|
1341
|
+
}
|
1342
|
+
|
1343
|
+
# Cleanup database cluster parameter group
|
1344
|
+
MU::Cloud::AWS.rds(region).describe_db_cluster_parameter_groups.db_cluster_parameter_groups.each { |param_group|
|
1345
|
+
param_group_id = param_group.db_cluster_parameter_group_name
|
1346
|
+
arn = MU::Cloud::AWS::Database.getARN(param_group_id, "cluster-pg", "rds", region: region)
|
1347
|
+
tags = MU::Cloud::AWS.rds(region).list_tags_for_resource(resource_name: arn).tag_list
|
1348
|
+
|
1349
|
+
found_muid = false
|
1350
|
+
found_master = false
|
1351
|
+
tags.each { |tag|
|
1352
|
+
found_muid = true if tag.key == "MU-ID" && tag.value == MU.deploy_id
|
1353
|
+
found_master = true if tag.key == "MU-MASTER-IP" && tag.value == MU.mu_public_ip
|
1354
|
+
}
|
1355
|
+
next if !found_muid
|
1356
|
+
|
1357
|
+
delete =
|
1358
|
+
if ignoremaster && found_muid
|
1359
|
+
true
|
1360
|
+
elsif !ignoremaster && found_muid && found_master
|
1361
|
+
true
|
1362
|
+
else
|
1363
|
+
false
|
1364
|
+
end
|
1365
|
+
|
1366
|
+
if delete
|
1367
|
+
parent_thread_id = Thread.current.object_id
|
1368
|
+
threads << Thread.new(param_group) { |myparamgroup|
|
1369
|
+
MU.dupGlobals(parent_thread_id)
|
1370
|
+
Thread.abort_on_exception = true
|
1371
|
+
MU::Cloud::AWS::Database.delete_db_cluster_parameter_group(param_group_id, region: region) unless noop
|
1372
|
+
}
|
1373
|
+
end
|
1374
|
+
}
|
1375
|
+
|
1376
|
+
# Wait for all of the databases subnet/parameter groups to finish cleanup before proceeding
|
1377
|
+
threads.each { |t|
|
1378
|
+
t.join
|
1379
|
+
}
|
1380
|
+
end
|
1381
|
+
|
1382
|
+
# Cloud-specific configuration properties.
|
1383
|
+
# @param config [MU::Config]: The calling MU::Config object
|
1384
|
+
# @return [Array<Array,Hash>]: List of required fields, and json-schema Hash of cloud-specific configuration parameters for this resource
|
1385
|
+
def self.schema(config)
|
1386
|
+
toplevel_required = []
|
1387
|
+
rds_parameters_primitive = {
|
1388
|
+
"type" => "array",
|
1389
|
+
"minItems" => 1,
|
1390
|
+
"items" => {
|
1391
|
+
"description" => "The database parameter group parameter to change and when to apply the change.",
|
1392
|
+
"type" => "object",
|
1393
|
+
"title" => "Database Parameter",
|
1394
|
+
"required" => ["name", "value"],
|
1395
|
+
"additionalProperties" => false,
|
1396
|
+
"properties" => {
|
1397
|
+
"name" => {
|
1398
|
+
"type" => "string"
|
1399
|
+
},
|
1400
|
+
"value" => {
|
1401
|
+
"type" => "string"
|
1402
|
+
},
|
1403
|
+
"apply_method" => {
|
1404
|
+
"enum" => ["pending-reboot", "immediate"],
|
1405
|
+
"default" => "immediate",
|
1406
|
+
"type" => "string"
|
1407
|
+
}
|
1408
|
+
}
|
1409
|
+
}
|
1410
|
+
}
|
1411
|
+
|
1412
|
+
schema = {
|
1413
|
+
"db_parameter_group_parameters" => rds_parameters_primitive,
|
1414
|
+
"cluster_parameter_group_parameters" => rds_parameters_primitive,
|
1415
|
+
"license_model" => {
|
1416
|
+
"type" => "string",
|
1417
|
+
"enum" => ["license-included", "bring-your-own-license", "general-public-license", "postgresql-license"]
|
1418
|
+
},
|
1419
|
+
"ingress_rules" => {
|
1420
|
+
"items" => {
|
1421
|
+
"properties" => {
|
1422
|
+
"sgs" => {
|
1423
|
+
"type" => "array",
|
1424
|
+
"items" => {
|
1425
|
+
"description" => "Other AWS Security Groups; resources that are associated with this group will have this rule applied to their traffic",
|
1426
|
+
"type" => "string"
|
1427
|
+
}
|
1428
|
+
},
|
1429
|
+
"lbs" => {
|
1430
|
+
"type" => "array",
|
1431
|
+
"items" => {
|
1432
|
+
"description" => "AWS Load Balancers which will have this rule applied to their traffic",
|
1433
|
+
"type" => "string"
|
1434
|
+
}
|
1435
|
+
}
|
1436
|
+
}
|
1437
|
+
}
|
1438
|
+
}
|
1439
|
+
}
|
1440
|
+
[toplevel_required, schema]
|
1441
|
+
end
|
1442
|
+
|
1443
|
+
# Cloud-specific pre-processing of {MU::Config::BasketofKittens::databases}, bare and unvalidated.
|
1444
|
+
# @param db [Hash]: The resource to process and validate
|
1445
|
+
# @param configurator [MU::Config]: The overall deployment configurator of which this resource is a member
|
1446
|
+
# @return [Boolean]: True if validation succeeded, False otherwise
|
1447
|
+
def self.validateConfig(db, configurator)
|
1448
|
+
ok = true
|
1449
|
+
|
1450
|
+
db_cluster_engines = %w{aurora}
|
1451
|
+
db["create_cluster"] =
|
1452
|
+
if db_cluster_engines.include?(db["engine"])
|
1453
|
+
true
|
1454
|
+
else
|
1455
|
+
false
|
1456
|
+
end
|
1457
|
+
|
1458
|
+
db["license_model"] ||=
|
1459
|
+
if db["engine"] == "postgres"
|
1460
|
+
"postgresql-license"
|
1461
|
+
elsif db["engine"] == "mysql"
|
1462
|
+
"general-public-license"
|
1463
|
+
else
|
1464
|
+
"license-included"
|
1465
|
+
end
|
1466
|
+
|
1467
|
+
if db["create_read_replica"] or db['read_replica_of']
|
1468
|
+
if db["engine"] != "postgres" and db["engine"] != "mysql"
|
1469
|
+
MU.log "Read replica(s) database instances only supported for postgres and mysql. #{db["engine"]} not supported.", MU::ERR
|
1470
|
+
ok = false
|
1471
|
+
end
|
1472
|
+
end
|
1473
|
+
|
1474
|
+
if db["creation_style"] == "existing"
|
1475
|
+
begin
|
1476
|
+
MU::Cloud::AWS.rds(db['region']).describe_db_instances(
|
1477
|
+
db_instance_identifier: db['identifier']
|
1478
|
+
)
|
1479
|
+
rescue Aws::RDS::Errors::DBInstanceNotFound => e
|
1480
|
+
MU.log "Source database #{db['identifier']} was specified for #{db['name']}, but no such database exists in #{db['region']}", MU::ERR
|
1481
|
+
ok = false
|
1482
|
+
end
|
1483
|
+
end
|
1484
|
+
|
1485
|
+
if !db['password'].nil? and (db['password'].length < 8 or db['password'].match(/[\/\\@\s]/))
|
1486
|
+
MU.log "Database password '#{db['password']}' doesn't meet RDS requirements. Must be > 8 chars and have only ASCII characters other than /, @, \", or [space].", MU::ERR
|
1487
|
+
ok = false
|
1488
|
+
end
|
1489
|
+
if db["multi_az_on_create"] and db["multi_az_on_deploy"]
|
1490
|
+
MU.log "Both of multi_az_on_create and multi_az_on_deploy cannot be true", MU::ERR
|
1491
|
+
ok = false
|
1492
|
+
end
|
1493
|
+
if db.has_key?("db_parameter_group_parameters") || db.has_key?("cluster_parameter_group_parameters")
|
1494
|
+
if db["parameter_group_family"].nil?
|
1495
|
+
MU.log "parameter_group_family must be set when setting db_parameter_group_parameters", MU::ERR
|
1496
|
+
ok = false
|
1497
|
+
end
|
1498
|
+
end
|
1499
|
+
# Adding rules for Database instance storage. This varies depending on storage type and database type.
|
1500
|
+
if !db["storage"].nil? and (db["storage_type"] == "standard" or db["storage_type"] == "gp2")
|
1501
|
+
if db["engine"] == "postgres" or db["engine"] == "mysql"
|
1502
|
+
if !(5..6144).include? db["storage"]
|
1503
|
+
MU.log "Database storage size is set to #{db["storage"]}. #{db["engine"]} only supports storage sizes between 5 to 6144 GB for #{db["storage_type"]} volume types", MU::ERR
|
1504
|
+
ok = false
|
1505
|
+
end
|
1506
|
+
elsif %w{oracle-se1 oracle-se oracle-ee}.include? db["engine"]
|
1507
|
+
if !(10..6144).include? db["storage"]
|
1508
|
+
MU.log "Database storage size is set to #{db["storage"]}. #{db["engine"]} only supports storage sizes between 10 to 6144 GB for #{db["storage_type"]} volume types", MU::ERR
|
1509
|
+
ok = false
|
1510
|
+
end
|
1511
|
+
elsif %w{sqlserver-ex sqlserver-web}.include? db["engine"]
|
1512
|
+
if !(20..4096).include? db["storage"]
|
1513
|
+
MU.log "Database storage size is set to #{db["storage"]}. #{db["engine"]} only supports storage sizes between 20 to 4096 GB for #{db["storage_type"]} volume types", MU::ERR
|
1514
|
+
ok = false
|
1515
|
+
end
|
1516
|
+
elsif %w{sqlserver-ee sqlserver-se}.include? db["engine"]
|
1517
|
+
if !(200..4096).include? db["storage"]
|
1518
|
+
MU.log "Database storage size is set to #{db["storage"]}. #{db["engine"]} only supports storage sizes between 200 to 4096 GB for #{db["storage_type"]} volume types", MU::ERR
|
1519
|
+
ok = false
|
1520
|
+
end
|
1521
|
+
end
|
1522
|
+
elsif db["storage_type"] == "io1"
|
1523
|
+
if %w{postgres mysql oracle-se1 oracle-se oracle-ee}.include? db["engine"]
|
1524
|
+
if !(100..6144).include? db["storage"]
|
1525
|
+
MU.log "Database storage size is set to #{db["storage"]}. #{db["engine"]} only supports storage sizes between 100 to 6144 GB for #{db["storage_type"]} volume types", MU::ERR
|
1526
|
+
ok = false
|
1527
|
+
end
|
1528
|
+
elsif %w{sqlserver-ex sqlserver-web}.include? db["engine"]
|
1529
|
+
if !(100..4096).include? db["storage"]
|
1530
|
+
MU.log "Database storage size is set to #{db["storage"]}. #{db["engine"]} only supports storage sizes between 100 to 4096 GB for #{db["storage_type"]} volume types", MU::ERR
|
1531
|
+
ok = false
|
1532
|
+
end
|
1533
|
+
elsif %w{sqlserver-ee sqlserver-se}.include? db["engine"]
|
1534
|
+
if !(200..4096).include? db["storage"]
|
1535
|
+
MU.log "Database storage size is set to #{db["storage"]}. #{db["engine"]} only supports storage sizes between 200 to 4096 GB #{db["storage_type"]} volume types", MU::ERR
|
1536
|
+
ok = false
|
1537
|
+
end
|
1538
|
+
end
|
1539
|
+
end
|
1540
|
+
|
1541
|
+
if db["vpc"]
|
1542
|
+
if db["vpc"]["subnet_pref"] == "all_public" and !db['publicly_accessible']
|
1543
|
+
MU.log "Setting publicly_accessible to true on database '#{db['name']}', since deploying into public subnets.", MU::WARN
|
1544
|
+
db['publicly_accessible'] = true
|
1545
|
+
elsif db["vpc"]["subnet_pref"] == "all_private" and db['publicly_accessible']
|
1546
|
+
MU.log "Setting publicly_accessible to false on database '#{db['name']}', since deploying into private subnets.", MU::NOTICE
|
1547
|
+
db['publicly_accessible'] = false
|
1548
|
+
end
|
1549
|
+
end
|
1550
|
+
|
1551
|
+
ok
|
1552
|
+
end
|
1553
|
+
|
1554
|
+
private
|
1555
|
+
|
1556
|
+
# Remove an RDS database and associated artifacts
|
1557
|
+
# @param db [OpenStruct]: The cloud provider's description of the database artifact
|
1558
|
+
# @return [void]
|
1559
|
+
def self.terminate_rds_instance(db, noop: false, skipsnapshots: false, region: MU.curRegion, deploy_id: MU.deploy_id, mu_name: nil, cloud_id: nil)
|
1560
|
+
raise MuError, "terminate_rds_instance requires a non-nil database descriptor" if db.nil?
|
1561
|
+
db_id = db.db_instance_identifier
|
1562
|
+
|
1563
|
+
database_obj = MU::MommaCat.findStray(
|
1564
|
+
"AWS",
|
1565
|
+
"database",
|
1566
|
+
region: region,
|
1567
|
+
deploy_id: deploy_id,
|
1568
|
+
cloud_id: cloud_id,
|
1569
|
+
mu_name: mu_name
|
1570
|
+
).first
|
1571
|
+
|
1572
|
+
subnet_group = nil
|
1573
|
+
begin
|
1574
|
+
subnet_group = db.db_subnet_group.db_subnet_group_name if db.db_subnet_group
|
1575
|
+
rescue NoMethodError
|
1576
|
+
# ignorable for non-VPC databases
|
1577
|
+
end
|
1578
|
+
|
1579
|
+
rdssecgroups = Array.new
|
1580
|
+
begin
|
1581
|
+
secgroup = MU::Cloud::AWS.rds(region).describe_db_security_groups(db_security_group_name: db_id)
|
1582
|
+
rescue Aws::RDS::Errors::DBSecurityGroupNotFound
|
1583
|
+
# this is normal in VPC world
|
1584
|
+
end
|
1585
|
+
|
1586
|
+
rdssecgroups << db_id if !secgroup.nil?
|
1587
|
+
parameter_group = db.db_parameter_groups.first.db_parameter_group_name
|
1588
|
+
|
1589
|
+
# We can use an AWS waiter for this.
|
1590
|
+
unless db.db_instance_status == "available"
|
1591
|
+
loop do
|
1592
|
+
MU.log "Waiting for #{db_id} to be in a removable state...", MU::NOTICE
|
1593
|
+
db = MU::Cloud::AWS::Database.getDatabaseById(db_id, region: region)
|
1594
|
+
break unless %w{creating modifying backing-up}.include?(db.db_instance_status)
|
1595
|
+
sleep 60
|
1596
|
+
end
|
1597
|
+
end
|
1598
|
+
|
1599
|
+
MU::Cloud::AWS::DNSZone.genericMuDNSEntry(name: db_id, target: db.endpoint.address, cloudclass: MU::Cloud::Database, delete: true)
|
1600
|
+
|
1601
|
+
if %w{deleting deleted}.include?(db.db_instance_status)
|
1602
|
+
MU.log "#{db_id} has already been terminated", MU::WARN
|
1603
|
+
else
|
1604
|
+
def self.dbSkipSnap(db_id, region)
|
1605
|
+
# We're calling this several times so lets declare it once
|
1606
|
+
MU.log "Terminating #{db_id} (not saving final snapshot)"
|
1607
|
+
MU::Cloud::AWS.rds(region).delete_db_instance(db_instance_identifier: db_id, skip_final_snapshot: true)
|
1608
|
+
end
|
1609
|
+
|
1610
|
+
def self.dbCreateSnap(db_id, region)
|
1611
|
+
MU.log "Terminating #{db_id} (final snapshot: #{db_id}-mufinal)"
|
1612
|
+
MU::Cloud::AWS.rds(region).delete_db_instance(db_instance_identifier: db_id, final_db_snapshot_identifier: "#{db_id}-mufinal", skip_final_snapshot: false)
|
1613
|
+
end
|
1614
|
+
|
1615
|
+
if !noop
|
1616
|
+
retries = 0
|
1617
|
+
begin
|
1618
|
+
if db.db_cluster_identifier || db.read_replica_source_db_instance_identifier
|
1619
|
+
# make sure we don't create final snapshot for a database instance that is part of a cluster, or if it's a read replica database instance
|
1620
|
+
dbSkipSnap(db_id, region)
|
1621
|
+
else
|
1622
|
+
skipsnapshots ? dbSkipSnap(db_id, region) : dbCreateSnap(db_id, region)
|
1623
|
+
end
|
1624
|
+
rescue Aws::RDS::Errors::InvalidDBInstanceState => e
|
1625
|
+
if retries < 5
|
1626
|
+
MU.log "#{db_id} is not in a removable state, retrying several times #{e.inspect}", MU::WARN
|
1627
|
+
retries += 1
|
1628
|
+
sleep 30
|
1629
|
+
retry
|
1630
|
+
else
|
1631
|
+
MU.log "#{db_id} is not in a removable state after several retries, giving up. #{e.inspect}", MU::ERR
|
1632
|
+
end
|
1633
|
+
rescue Aws::RDS::Errors::DBSnapshotAlreadyExists
|
1634
|
+
dbSkipSnap(db_id, region)
|
1635
|
+
MU.log "Snapshot of #{db_id} already exists", MU::WARN
|
1636
|
+
rescue Aws::RDS::Errors::SnapshotQuotaExceeded
|
1637
|
+
dbSkipSnap(db_id, region)
|
1638
|
+
MU.log "Snapshot quota exceeded while deleting #{db_id}", MU::ERR
|
1639
|
+
end
|
1640
|
+
end
|
1641
|
+
end
|
1642
|
+
|
1643
|
+
begin
|
1644
|
+
attempts = 0
|
1645
|
+
loop do
|
1646
|
+
MU.log "Waiting for #{db_id} termination to complete", MU::NOTICE if attempts % 6 == 0
|
1647
|
+
del_db = MU::Cloud::AWS::Database.getDatabaseById(db_id, region: region)
|
1648
|
+
break if del_db.nil? || del_db.db_instance_status == "deleted"
|
1649
|
+
sleep 10
|
1650
|
+
attempts += 1
|
1651
|
+
end
|
1652
|
+
rescue Aws::RDS::Errors::DBInstanceNotFound
|
1653
|
+
# we are ok with this
|
1654
|
+
end
|
1655
|
+
|
1656
|
+
# RDS security groups can depend on EC2 security groups, do these last
|
1657
|
+
begin
|
1658
|
+
rdssecgroups.each { |sg|
|
1659
|
+
MU.log "Removing RDS Security Group #{sg}"
|
1660
|
+
MU::Cloud::AWS.rds(region).delete_db_security_group(db_security_group_name: sg) if !noop
|
1661
|
+
}
|
1662
|
+
rescue Aws::RDS::Errors::DBSecurityGroupNotFound
|
1663
|
+
MU.log "RDS Security Group #{sg} disappeared before we could remove it", MU::WARN
|
1664
|
+
end
|
1665
|
+
|
1666
|
+
# Cleanup the database vault
|
1667
|
+
grommer =
|
1668
|
+
if database_obj
|
1669
|
+
database_obj.config.has_key?("groomer") ? database_obj.config["groomer"] : MU::Config.defaultGroomer
|
1670
|
+
else
|
1671
|
+
MU::Config.defaultGroomer
|
1672
|
+
end
|
1673
|
+
|
1674
|
+
groomclass = MU::Groomer.loadGroomer(grommer)
|
1675
|
+
groomclass.deleteSecret(vault: db_id.upcase) if !noop
|
1676
|
+
MU.log "#{db_id} has been terminated"
|
1677
|
+
end
|
1678
|
+
|
1679
|
+
# Remove an RDS database cluster and associated artifacts
|
1680
|
+
# @param cluster [OpenStruct]: The cloud provider's description of the database artifact
|
1681
|
+
# @return [void]
|
1682
|
+
def self.terminate_rds_cluster(cluster, noop: false, skipsnapshots: false, region: MU.curRegion, deploy_id: MU.deploy_id, mu_name: nil, cloud_id: nil)
|
1683
|
+
raise MuError, "terminate_rds_cluster requires a non-nil database cluster descriptor" if cluster.nil?
|
1684
|
+
cluster_id = cluster.db_cluster_identifier
|
1685
|
+
|
1686
|
+
cluster_obj = MU::MommaCat.findStray(
|
1687
|
+
"AWS",
|
1688
|
+
"database",
|
1689
|
+
region: region,
|
1690
|
+
deploy_id: deploy_id,
|
1691
|
+
cloud_id: cloud_id,
|
1692
|
+
mu_name: mu_name
|
1693
|
+
).first
|
1694
|
+
|
1695
|
+
subnet_group = cluster.db_subnet_group
|
1696
|
+
cluster_parameter_group = cluster.db_cluster_parameter_group
|
1697
|
+
|
1698
|
+
# We can use an AWS waiter for this.
|
1699
|
+
unless cluster.status == "available"
|
1700
|
+
loop do
|
1701
|
+
MU.log "Waiting for #{cluster_id} to be in a removable state...", MU::NOTICE
|
1702
|
+
cluster = MU::Cloud::AWS::Database.getDatabaseClusterById(cluster_id, region: region)
|
1703
|
+
break unless %w{creating modifying backing-up}.include?(cluster.status)
|
1704
|
+
sleep 60
|
1705
|
+
end
|
1706
|
+
end
|
1707
|
+
|
1708
|
+
MU::Cloud::AWS::DNSZone.genericMuDNSEntry(name: cluster_id, target: cluster.endpoint, cloudclass: MU::Cloud::Database, delete: true)
|
1709
|
+
|
1710
|
+
if %w{deleting deleted}.include?(cluster.status)
|
1711
|
+
MU.log "#{cluster_id} has already been terminated", MU::WARN
|
1712
|
+
else
|
1713
|
+
unless noop
|
1714
|
+
def self.clusterSkipSnap(cluster_id, region)
|
1715
|
+
# We're calling this several times so lets declare it once
|
1716
|
+
MU.log "Terminating #{cluster_id}. Not saving final snapshot"
|
1717
|
+
MU::Cloud::AWS.rds(region).delete_db_cluster(db_cluster_identifier: cluster_id, skip_final_snapshot: true)
|
1718
|
+
end
|
1719
|
+
|
1720
|
+
def self.clusterCreateSnap(cluster_id, region)
|
1721
|
+
MU.log "Terminating #{cluster_id}. Saving final snapshot: #{cluster_id}-mufinal"
|
1722
|
+
MU::Cloud::AWS.rds(region).delete_db_cluster(db_cluster_identifier: cluster_id, skip_final_snapshot: false, final_db_snapshot_identifier: "#{cluster_id}-mufinal")
|
1723
|
+
end
|
1724
|
+
|
1725
|
+
retries = 0
|
1726
|
+
begin
|
1727
|
+
skipsnapshots ? clusterSkipSnap(cluster_id, region) : clusterCreateSnap(cluster_id, region)
|
1728
|
+
rescue Aws::RDS::Errors::InvalidDBClusterStateFault => e
|
1729
|
+
if retries < 5
|
1730
|
+
MU.log "#{cluster_id} is not in a removable state, retrying several times", MU::WARN
|
1731
|
+
retries += 1
|
1732
|
+
sleep 30
|
1733
|
+
retry
|
1734
|
+
else
|
1735
|
+
MU.log "#{cluster_id} is not in a removable state after several retries, giving up. #{e.inspect}", MU::ERR
|
1736
|
+
end
|
1737
|
+
rescue Aws::RDS::Errors::DBClusterSnapshotAlreadyExistsFault
|
1738
|
+
clusterSkipSnap(cluster_id, region)
|
1739
|
+
MU.log "Snapshot of #{cluster_id} already exists", MU::WARN
|
1740
|
+
rescue Aws::RDS::Errors::DBClusterQuotaExceeded
|
1741
|
+
clusterSkipSnap(cluster_id, region)
|
1742
|
+
MU.log "Snapshot quota exceeded while deleting #{cluster_id}", MU::ERR
|
1743
|
+
end
|
1744
|
+
end
|
1745
|
+
end
|
1746
|
+
|
1747
|
+
# We're wating until getDatabaseClusterById returns nil. This assumes the database cluster object doesn't linger around in "deleted" state for a while.
|
1748
|
+
loop do
|
1749
|
+
MU.log "Waiting for #{cluster_id} to terminate", MU::NOTICE
|
1750
|
+
cluster = MU::Cloud::AWS::Database.getDatabaseClusterById(cluster_id, region: region)
|
1751
|
+
break unless cluster
|
1752
|
+
sleep 30
|
1753
|
+
end
|
1754
|
+
|
1755
|
+
# Cleanup the cluster vault
|
1756
|
+
grommer =
|
1757
|
+
if cluster_obj
|
1758
|
+
cluster_obj.config.has_key?("groomer") ? cluster_obj.config["groomer"] : MU::Config.defaultGroomer
|
1759
|
+
else
|
1760
|
+
MU::Config.defaultGroomer
|
1761
|
+
end
|
1762
|
+
|
1763
|
+
groomclass = MU::Groomer.loadGroomer(grommer)
|
1764
|
+
groomclass.deleteSecret(vault: cluster_id.upcase) if !noop
|
1765
|
+
|
1766
|
+
MU.log "#{cluster_id} has been terminated"
|
1767
|
+
end
|
1768
|
+
|
1769
|
+
# Remove a database subnet group.
|
1770
|
+
# @param subnet_group_id [string]: The cloud provider's ID of the database subnet group.
|
1771
|
+
# @param region [String]: The cloud provider's region in which to operate.
|
1772
|
+
# @return [void]
|
1773
|
+
def self.delete_subnet_group(subnet_group_id, region: MU.curRegion)
|
1774
|
+
retries ||= 0
|
1775
|
+
MU.log "Deleting DB subnet group #{subnet_group_id}"
|
1776
|
+
MU::Cloud::AWS.rds(region).delete_db_subnet_group(db_subnet_group_name: subnet_group_id)
|
1777
|
+
rescue Aws::RDS::Errors::DBSubnetGroupNotFoundFault => e
|
1778
|
+
MU.log "DB subnet group #{subnet_group_id} disappeared before we could remove it", MU::WARN
|
1779
|
+
rescue Aws::RDS::Errors::InvalidDBSubnetGroupStateFault=> e
|
1780
|
+
if retries < 5
|
1781
|
+
MU.log "DB subnet group #{subnet_group_id} is not in a removable state, retrying", MU::WARN
|
1782
|
+
retries += 1
|
1783
|
+
sleep 30
|
1784
|
+
retry
|
1785
|
+
else
|
1786
|
+
MU.log "#{subnet_group_id} is not in a removable state after several retries, giving up. #{e.inspect}", MU::ERR
|
1787
|
+
end
|
1788
|
+
end
|
1789
|
+
|
1790
|
+
# Remove a database parameter group.
|
1791
|
+
# @param parameter_group_id [string]: The cloud provider's ID of the database parameter group.
|
1792
|
+
# @param region [String]: The cloud provider's region in which to operate.
|
1793
|
+
# @return [void]
|
1794
|
+
def self.delete_db_parameter_group(parameter_group_id, region: MU.curRegion)
|
1795
|
+
retries ||= 0
|
1796
|
+
MU.log "Deleting DB parameter group #{parameter_group_id}"
|
1797
|
+
MU::Cloud::AWS.rds(region).delete_db_parameter_group(db_parameter_group_name: parameter_group_id)
|
1798
|
+
rescue Aws::RDS::Errors::DBParameterGroupNotFound
|
1799
|
+
MU.log "DB parameter group #{parameter_group_id} disappeared before we could remove it", MU::WARN
|
1800
|
+
rescue Aws::RDS::Errors::InvalidDBParameterGroupState => e
|
1801
|
+
if retries < 5
|
1802
|
+
MU.log "DB parameter group #{parameter_group_id} is not in a removable state, retrying", MU::WARN
|
1803
|
+
retries += 1
|
1804
|
+
sleep 30
|
1805
|
+
retry
|
1806
|
+
else
|
1807
|
+
MU.log "DB parameter group #{parameter_group_id} is not in a removable state after several retries, giving up. #{e.inspect}", MU::ERR
|
1808
|
+
end
|
1809
|
+
end
|
1810
|
+
|
1811
|
+
# Remove a database cluster parameter group.
|
1812
|
+
# @param parameter_group_id [string]: The cloud provider's ID of the database cluster parameter group.
|
1813
|
+
# @param region [String]: The cloud provider's region in which to operate.
|
1814
|
+
# @return [void]
|
1815
|
+
def self.delete_db_cluster_parameter_group(parameter_group_id, region: MU.curRegion)
|
1816
|
+
retries ||= 0
|
1817
|
+
MU.log "Deleting cluster parameter group #{parameter_group_id}"
|
1818
|
+
MU::Cloud::AWS.rds(region).delete_db_cluster_parameter_group(db_cluster_parameter_group_name: parameter_group_id)
|
1819
|
+
# AWS API sucks. instead of returning the documented error DBClusterParameterGroupNotFoundFault it errors out with DBParameterGroupNotFound.
|
1820
|
+
rescue Aws::RDS::Errors::DBParameterGroupNotFound
|
1821
|
+
MU.log "Cluster parameter group #{parameter_group_id} disappeared before we could remove it", MU::WARN
|
1822
|
+
rescue Aws::RDS::Errors::InvalidDBParameterGroupState => e
|
1823
|
+
if retries < 5
|
1824
|
+
MU.log "Cluster parameter group #{parameter_group_id} is not in a removable state, retrying", MU::WARN
|
1825
|
+
retries += 1
|
1826
|
+
sleep 30
|
1827
|
+
retry
|
1828
|
+
else
|
1829
|
+
MU.log "Cluster parameter group #{parameter_group_id} is not in a removable state after several retries, giving up. #{e.inspect}", MU::ERR
|
1830
|
+
end
|
1831
|
+
end
|
1832
|
+
|
1833
|
+
end #class
|
1834
|
+
end #class
|
1835
|
+
end
|
1836
|
+
end #module
|