cloud-mu 2.1.0beta → 3.0.0beta

Sign up to get free protection for your applications and to get access to all the features.
Files changed (291) hide show
  1. checksums.yaml +5 -5
  2. data/Berksfile +4 -5
  3. data/Berksfile.lock +179 -0
  4. data/README.md +1 -6
  5. data/ansible/roles/geerlingguy.firewall/templates/firewall.bash.j2 +0 -0
  6. data/ansible/roles/mu-installer/README.md +33 -0
  7. data/ansible/roles/mu-installer/defaults/main.yml +2 -0
  8. data/ansible/roles/mu-installer/handlers/main.yml +2 -0
  9. data/ansible/roles/mu-installer/meta/main.yml +60 -0
  10. data/ansible/roles/mu-installer/tasks/main.yml +13 -0
  11. data/ansible/roles/mu-installer/tests/inventory +2 -0
  12. data/ansible/roles/mu-installer/tests/test.yml +5 -0
  13. data/ansible/roles/mu-installer/vars/main.yml +2 -0
  14. data/bin/mu-adopt +125 -0
  15. data/bin/mu-aws-setup +4 -4
  16. data/bin/mu-azure-setup +265 -0
  17. data/bin/mu-azure-tests +43 -0
  18. data/bin/mu-cleanup +20 -8
  19. data/bin/mu-configure +224 -98
  20. data/bin/mu-deploy +8 -3
  21. data/bin/mu-gcp-setup +16 -8
  22. data/bin/mu-gen-docs +92 -8
  23. data/bin/mu-load-config.rb +52 -12
  24. data/bin/mu-momma-cat +36 -0
  25. data/bin/mu-node-manage +34 -27
  26. data/bin/mu-self-update +2 -2
  27. data/bin/mu-ssh +12 -8
  28. data/bin/mu-upload-chef-artifacts +11 -4
  29. data/bin/mu-user-manage +3 -0
  30. data/cloud-mu.gemspec +8 -11
  31. data/cookbooks/firewall/libraries/helpers_iptables.rb +2 -2
  32. data/cookbooks/firewall/metadata.json +1 -1
  33. data/cookbooks/firewall/recipes/default.rb +5 -9
  34. data/cookbooks/mu-firewall/attributes/default.rb +2 -0
  35. data/cookbooks/mu-firewall/metadata.rb +1 -1
  36. data/cookbooks/mu-glusterfs/templates/default/mu-gluster-client.erb +0 -0
  37. data/cookbooks/mu-master/Berksfile +2 -2
  38. data/cookbooks/mu-master/files/default/check_mem.pl +0 -0
  39. data/cookbooks/mu-master/files/default/cloudamatic.png +0 -0
  40. data/cookbooks/mu-master/metadata.rb +5 -4
  41. data/cookbooks/mu-master/recipes/389ds.rb +1 -1
  42. data/cookbooks/mu-master/recipes/basepackages.rb +30 -10
  43. data/cookbooks/mu-master/recipes/default.rb +59 -7
  44. data/cookbooks/mu-master/recipes/firewall-holes.rb +1 -1
  45. data/cookbooks/mu-master/recipes/init.rb +65 -47
  46. data/cookbooks/mu-master/recipes/{eks-kubectl.rb → kubectl.rb} +4 -10
  47. data/cookbooks/mu-master/recipes/sssd.rb +2 -1
  48. data/cookbooks/mu-master/recipes/update_nagios_only.rb +6 -6
  49. data/cookbooks/mu-master/templates/default/web_app.conf.erb +2 -2
  50. data/cookbooks/mu-master/templates/mods/ldap.conf.erb +4 -0
  51. data/cookbooks/mu-php54/Berksfile +1 -2
  52. data/cookbooks/mu-php54/metadata.rb +4 -5
  53. data/cookbooks/mu-php54/recipes/default.rb +1 -1
  54. data/cookbooks/mu-splunk/templates/default/splunk-init.erb +0 -0
  55. data/cookbooks/mu-tools/Berksfile +3 -2
  56. data/cookbooks/mu-tools/files/default/Mu_CA.pem +33 -0
  57. data/cookbooks/mu-tools/libraries/helper.rb +20 -8
  58. data/cookbooks/mu-tools/metadata.rb +5 -2
  59. data/cookbooks/mu-tools/recipes/apply_security.rb +2 -3
  60. data/cookbooks/mu-tools/recipes/eks.rb +1 -1
  61. data/cookbooks/mu-tools/recipes/gcloud.rb +5 -30
  62. data/cookbooks/mu-tools/recipes/nagios.rb +1 -1
  63. data/cookbooks/mu-tools/recipes/rsyslog.rb +1 -0
  64. data/cookbooks/mu-tools/recipes/selinux.rb +19 -0
  65. data/cookbooks/mu-tools/recipes/split_var_partitions.rb +0 -1
  66. data/cookbooks/mu-tools/recipes/windows-client.rb +256 -122
  67. data/cookbooks/mu-tools/resources/disk.rb +3 -1
  68. data/cookbooks/mu-tools/templates/amazon/sshd_config.erb +1 -1
  69. data/cookbooks/mu-tools/templates/default/etc_hosts.erb +1 -1
  70. data/cookbooks/mu-tools/templates/default/{kubeconfig.erb → kubeconfig-eks.erb} +0 -0
  71. data/cookbooks/mu-tools/templates/default/kubeconfig-gke.erb +27 -0
  72. data/cookbooks/mu-tools/templates/windows-10/sshd_config.erb +137 -0
  73. data/cookbooks/mu-utility/recipes/nat.rb +4 -0
  74. data/extras/alpha.png +0 -0
  75. data/extras/beta.png +0 -0
  76. data/extras/clean-stock-amis +2 -2
  77. data/extras/generate-stock-images +131 -0
  78. data/extras/git-fix-permissions-hook +0 -0
  79. data/extras/image-generators/AWS/centos6.yaml +17 -0
  80. data/extras/image-generators/{aws → AWS}/centos7-govcloud.yaml +0 -0
  81. data/extras/image-generators/{aws → AWS}/centos7.yaml +0 -0
  82. data/extras/image-generators/{aws → AWS}/rhel7.yaml +0 -0
  83. data/extras/image-generators/{aws → AWS}/win2k12.yaml +0 -0
  84. data/extras/image-generators/{aws → AWS}/win2k16.yaml +0 -0
  85. data/extras/image-generators/{aws → AWS}/windows.yaml +0 -0
  86. data/extras/image-generators/{gcp → Google}/centos6.yaml +1 -0
  87. data/extras/image-generators/Google/centos7.yaml +18 -0
  88. data/extras/python_rpm/build.sh +0 -0
  89. data/extras/release.png +0 -0
  90. data/extras/ruby_rpm/build.sh +0 -0
  91. data/extras/ruby_rpm/muby.spec +1 -1
  92. data/install/README.md +43 -5
  93. data/install/deprecated-bash-library.sh +0 -0
  94. data/install/installer +1 -1
  95. data/install/jenkinskeys.rb +0 -0
  96. data/install/mu-master.yaml +55 -0
  97. data/modules/mommacat.ru +41 -7
  98. data/modules/mu.rb +444 -149
  99. data/modules/mu/adoption.rb +500 -0
  100. data/modules/mu/cleanup.rb +235 -158
  101. data/modules/mu/cloud.rb +675 -138
  102. data/modules/mu/clouds/aws.rb +156 -24
  103. data/modules/mu/clouds/aws/alarm.rb +4 -14
  104. data/modules/mu/clouds/aws/bucket.rb +60 -18
  105. data/modules/mu/clouds/aws/cache_cluster.rb +8 -20
  106. data/modules/mu/clouds/aws/collection.rb +12 -22
  107. data/modules/mu/clouds/aws/container_cluster.rb +209 -118
  108. data/modules/mu/clouds/aws/database.rb +120 -45
  109. data/modules/mu/clouds/aws/dnszone.rb +7 -18
  110. data/modules/mu/clouds/aws/endpoint.rb +5 -15
  111. data/modules/mu/clouds/aws/firewall_rule.rb +144 -72
  112. data/modules/mu/clouds/aws/folder.rb +4 -11
  113. data/modules/mu/clouds/aws/function.rb +6 -16
  114. data/modules/mu/clouds/aws/group.rb +4 -12
  115. data/modules/mu/clouds/aws/habitat.rb +11 -13
  116. data/modules/mu/clouds/aws/loadbalancer.rb +40 -28
  117. data/modules/mu/clouds/aws/log.rb +5 -13
  118. data/modules/mu/clouds/aws/msg_queue.rb +9 -24
  119. data/modules/mu/clouds/aws/nosqldb.rb +4 -12
  120. data/modules/mu/clouds/aws/notifier.rb +6 -13
  121. data/modules/mu/clouds/aws/role.rb +69 -40
  122. data/modules/mu/clouds/aws/search_domain.rb +17 -20
  123. data/modules/mu/clouds/aws/server.rb +184 -94
  124. data/modules/mu/clouds/aws/server_pool.rb +33 -38
  125. data/modules/mu/clouds/aws/storage_pool.rb +5 -12
  126. data/modules/mu/clouds/aws/user.rb +59 -33
  127. data/modules/mu/clouds/aws/userdata/linux.erb +18 -30
  128. data/modules/mu/clouds/aws/userdata/windows.erb +9 -9
  129. data/modules/mu/clouds/aws/vpc.rb +214 -145
  130. data/modules/mu/clouds/azure.rb +978 -44
  131. data/modules/mu/clouds/azure/container_cluster.rb +413 -0
  132. data/modules/mu/clouds/azure/firewall_rule.rb +500 -0
  133. data/modules/mu/clouds/azure/habitat.rb +167 -0
  134. data/modules/mu/clouds/azure/loadbalancer.rb +205 -0
  135. data/modules/mu/clouds/azure/role.rb +211 -0
  136. data/modules/mu/clouds/azure/server.rb +810 -0
  137. data/modules/mu/clouds/azure/user.rb +257 -0
  138. data/modules/mu/clouds/azure/userdata/README.md +4 -0
  139. data/modules/mu/clouds/azure/userdata/linux.erb +137 -0
  140. data/modules/mu/clouds/azure/userdata/windows.erb +275 -0
  141. data/modules/mu/clouds/azure/vpc.rb +782 -0
  142. data/modules/mu/clouds/cloudformation.rb +12 -9
  143. data/modules/mu/clouds/cloudformation/firewall_rule.rb +5 -13
  144. data/modules/mu/clouds/cloudformation/server.rb +10 -1
  145. data/modules/mu/clouds/cloudformation/server_pool.rb +1 -0
  146. data/modules/mu/clouds/cloudformation/vpc.rb +0 -2
  147. data/modules/mu/clouds/google.rb +554 -117
  148. data/modules/mu/clouds/google/bucket.rb +173 -32
  149. data/modules/mu/clouds/google/container_cluster.rb +1112 -157
  150. data/modules/mu/clouds/google/database.rb +24 -47
  151. data/modules/mu/clouds/google/firewall_rule.rb +344 -89
  152. data/modules/mu/clouds/google/folder.rb +156 -79
  153. data/modules/mu/clouds/google/group.rb +272 -82
  154. data/modules/mu/clouds/google/habitat.rb +177 -52
  155. data/modules/mu/clouds/google/loadbalancer.rb +9 -34
  156. data/modules/mu/clouds/google/role.rb +1211 -0
  157. data/modules/mu/clouds/google/server.rb +491 -227
  158. data/modules/mu/clouds/google/server_pool.rb +233 -48
  159. data/modules/mu/clouds/google/user.rb +479 -125
  160. data/modules/mu/clouds/google/userdata/linux.erb +3 -3
  161. data/modules/mu/clouds/google/userdata/windows.erb +9 -9
  162. data/modules/mu/clouds/google/vpc.rb +381 -223
  163. data/modules/mu/config.rb +689 -214
  164. data/modules/mu/config/bucket.rb +1 -1
  165. data/modules/mu/config/cache_cluster.rb +1 -1
  166. data/modules/mu/config/cache_cluster.yml +0 -4
  167. data/modules/mu/config/container_cluster.rb +18 -9
  168. data/modules/mu/config/database.rb +6 -23
  169. data/modules/mu/config/firewall_rule.rb +9 -15
  170. data/modules/mu/config/folder.rb +22 -21
  171. data/modules/mu/config/habitat.rb +22 -21
  172. data/modules/mu/config/loadbalancer.rb +2 -2
  173. data/modules/mu/config/role.rb +9 -40
  174. data/modules/mu/config/server.rb +26 -5
  175. data/modules/mu/config/server_pool.rb +1 -1
  176. data/modules/mu/config/storage_pool.rb +2 -2
  177. data/modules/mu/config/user.rb +4 -0
  178. data/modules/mu/config/vpc.rb +350 -110
  179. data/modules/mu/defaults/{amazon_images.yaml → AWS.yaml} +37 -39
  180. data/modules/mu/defaults/Azure.yaml +17 -0
  181. data/modules/mu/defaults/Google.yaml +24 -0
  182. data/modules/mu/defaults/README.md +1 -1
  183. data/modules/mu/deploy.rb +168 -125
  184. data/modules/mu/groomer.rb +2 -1
  185. data/modules/mu/groomers/ansible.rb +104 -32
  186. data/modules/mu/groomers/chef.rb +96 -44
  187. data/modules/mu/kittens.rb +20602 -0
  188. data/modules/mu/logger.rb +38 -11
  189. data/modules/mu/master.rb +90 -8
  190. data/modules/mu/master/chef.rb +2 -3
  191. data/modules/mu/master/ldap.rb +0 -1
  192. data/modules/mu/master/ssl.rb +250 -0
  193. data/modules/mu/mommacat.rb +917 -513
  194. data/modules/scratchpad.erb +1 -1
  195. data/modules/tests/super_complex_bok.yml +0 -0
  196. data/modules/tests/super_simple_bok.yml +0 -0
  197. data/roles/mu-master.json +2 -1
  198. data/spec/azure_creds +5 -0
  199. data/spec/mu.yaml +56 -0
  200. data/spec/mu/clouds/azure_spec.rb +164 -27
  201. data/spec/spec_helper.rb +5 -0
  202. data/test/clean_up.py +0 -0
  203. data/test/exec_inspec.py +0 -0
  204. data/test/exec_mu_install.py +0 -0
  205. data/test/exec_retry.py +0 -0
  206. data/test/smoke_test.rb +0 -0
  207. metadata +90 -118
  208. data/cookbooks/mu-jenkins/Berksfile +0 -14
  209. data/cookbooks/mu-jenkins/CHANGELOG.md +0 -13
  210. data/cookbooks/mu-jenkins/LICENSE +0 -37
  211. data/cookbooks/mu-jenkins/README.md +0 -105
  212. data/cookbooks/mu-jenkins/attributes/default.rb +0 -42
  213. data/cookbooks/mu-jenkins/files/default/cleanup_deploy_config.xml +0 -73
  214. data/cookbooks/mu-jenkins/files/default/deploy_config.xml +0 -44
  215. data/cookbooks/mu-jenkins/metadata.rb +0 -21
  216. data/cookbooks/mu-jenkins/recipes/default.rb +0 -195
  217. data/cookbooks/mu-jenkins/recipes/node-ssh-config.rb +0 -54
  218. data/cookbooks/mu-jenkins/recipes/public_key.rb +0 -24
  219. data/cookbooks/mu-jenkins/templates/default/example_job.config.xml.erb +0 -24
  220. data/cookbooks/mu-jenkins/templates/default/org.jvnet.hudson.plugins.SSHBuildWrapper.xml.erb +0 -14
  221. data/cookbooks/mu-jenkins/templates/default/ssh_config.erb +0 -6
  222. data/cookbooks/nagios/Berksfile +0 -11
  223. data/cookbooks/nagios/CHANGELOG.md +0 -589
  224. data/cookbooks/nagios/CONTRIBUTING.md +0 -11
  225. data/cookbooks/nagios/LICENSE +0 -37
  226. data/cookbooks/nagios/README.md +0 -328
  227. data/cookbooks/nagios/TESTING.md +0 -2
  228. data/cookbooks/nagios/attributes/config.rb +0 -171
  229. data/cookbooks/nagios/attributes/default.rb +0 -228
  230. data/cookbooks/nagios/chefignore +0 -102
  231. data/cookbooks/nagios/definitions/command.rb +0 -33
  232. data/cookbooks/nagios/definitions/contact.rb +0 -33
  233. data/cookbooks/nagios/definitions/contactgroup.rb +0 -33
  234. data/cookbooks/nagios/definitions/host.rb +0 -33
  235. data/cookbooks/nagios/definitions/hostdependency.rb +0 -33
  236. data/cookbooks/nagios/definitions/hostescalation.rb +0 -34
  237. data/cookbooks/nagios/definitions/hostgroup.rb +0 -33
  238. data/cookbooks/nagios/definitions/nagios_conf.rb +0 -38
  239. data/cookbooks/nagios/definitions/resource.rb +0 -33
  240. data/cookbooks/nagios/definitions/service.rb +0 -33
  241. data/cookbooks/nagios/definitions/servicedependency.rb +0 -33
  242. data/cookbooks/nagios/definitions/serviceescalation.rb +0 -34
  243. data/cookbooks/nagios/definitions/servicegroup.rb +0 -33
  244. data/cookbooks/nagios/definitions/timeperiod.rb +0 -33
  245. data/cookbooks/nagios/libraries/base.rb +0 -314
  246. data/cookbooks/nagios/libraries/command.rb +0 -91
  247. data/cookbooks/nagios/libraries/contact.rb +0 -230
  248. data/cookbooks/nagios/libraries/contactgroup.rb +0 -112
  249. data/cookbooks/nagios/libraries/custom_option.rb +0 -36
  250. data/cookbooks/nagios/libraries/data_bag_helper.rb +0 -23
  251. data/cookbooks/nagios/libraries/default.rb +0 -90
  252. data/cookbooks/nagios/libraries/host.rb +0 -412
  253. data/cookbooks/nagios/libraries/hostdependency.rb +0 -181
  254. data/cookbooks/nagios/libraries/hostescalation.rb +0 -173
  255. data/cookbooks/nagios/libraries/hostgroup.rb +0 -119
  256. data/cookbooks/nagios/libraries/nagios.rb +0 -282
  257. data/cookbooks/nagios/libraries/resource.rb +0 -59
  258. data/cookbooks/nagios/libraries/service.rb +0 -455
  259. data/cookbooks/nagios/libraries/servicedependency.rb +0 -215
  260. data/cookbooks/nagios/libraries/serviceescalation.rb +0 -195
  261. data/cookbooks/nagios/libraries/servicegroup.rb +0 -144
  262. data/cookbooks/nagios/libraries/timeperiod.rb +0 -160
  263. data/cookbooks/nagios/libraries/users_helper.rb +0 -54
  264. data/cookbooks/nagios/metadata.rb +0 -25
  265. data/cookbooks/nagios/recipes/_load_databag_config.rb +0 -153
  266. data/cookbooks/nagios/recipes/_load_default_config.rb +0 -241
  267. data/cookbooks/nagios/recipes/apache.rb +0 -48
  268. data/cookbooks/nagios/recipes/default.rb +0 -204
  269. data/cookbooks/nagios/recipes/nginx.rb +0 -82
  270. data/cookbooks/nagios/recipes/pagerduty.rb +0 -143
  271. data/cookbooks/nagios/recipes/server_package.rb +0 -40
  272. data/cookbooks/nagios/recipes/server_source.rb +0 -164
  273. data/cookbooks/nagios/templates/default/apache2.conf.erb +0 -96
  274. data/cookbooks/nagios/templates/default/cgi.cfg.erb +0 -266
  275. data/cookbooks/nagios/templates/default/commands.cfg.erb +0 -13
  276. data/cookbooks/nagios/templates/default/contacts.cfg.erb +0 -37
  277. data/cookbooks/nagios/templates/default/hostgroups.cfg.erb +0 -25
  278. data/cookbooks/nagios/templates/default/hosts.cfg.erb +0 -15
  279. data/cookbooks/nagios/templates/default/htpasswd.users.erb +0 -6
  280. data/cookbooks/nagios/templates/default/nagios.cfg.erb +0 -22
  281. data/cookbooks/nagios/templates/default/nginx.conf.erb +0 -62
  282. data/cookbooks/nagios/templates/default/pagerduty.cgi.erb +0 -185
  283. data/cookbooks/nagios/templates/default/resource.cfg.erb +0 -27
  284. data/cookbooks/nagios/templates/default/servicedependencies.cfg.erb +0 -15
  285. data/cookbooks/nagios/templates/default/servicegroups.cfg.erb +0 -14
  286. data/cookbooks/nagios/templates/default/services.cfg.erb +0 -14
  287. data/cookbooks/nagios/templates/default/templates.cfg.erb +0 -31
  288. data/cookbooks/nagios/templates/default/timeperiods.cfg.erb +0 -13
  289. data/extras/image-generators/aws/centos6.yaml +0 -18
  290. data/modules/mu/defaults/google_images.yaml +0 -16
  291. data/roles/mu-master-jenkins.json +0 -24
@@ -28,6 +28,24 @@ module MU
28
28
 
29
29
  @@creds_loaded = {}
30
30
 
31
+ # Module used by {MU::Cloud} to insert additional instance methods into
32
+ # instantiated resources in this cloud layer.
33
+ module AdditionalResourceMethods
34
+ end
35
+
36
+ # A hook that is always called just before any of the instance method of
37
+ # our resource implementations gets invoked, so that we can ensure that
38
+ # repetitive setup tasks (like resolving +:resource_group+ for Azure
39
+ # resources) have always been done.
40
+ # @param cloudobj [MU::Cloud]
41
+ # @param deploy [MU::MommaCat]
42
+ def self.resourceInitHook(cloudobj, deploy)
43
+ class << self
44
+ attr_reader :cloudformation_data
45
+ end
46
+ cloudobj.instance_variable_set(:@cloudformation_data, {})
47
+ end
48
+
31
49
  # Load some credentials for using the AWS API
32
50
  # @param name [String]: The name of the mu.yaml AWS credential set to use. If not specified, will use the default credentials, and set the global Aws.config credentials to those.
33
51
  # @return [Aws::Credentials]
@@ -110,7 +128,7 @@ module MU
110
128
  else
111
129
  MU.log "AWS credentials vault:item #{cred_cfg["credentials"]} specified, but is missing access_key or access_secret elements", MU::WARN
112
130
  end
113
- rescue MU::Groomer::Chef::MuNoSuchSecret
131
+ rescue MU::Groomer::MuNoSuchSecret
114
132
  MU.log "AWS credentials vault:item #{cred_cfg["credentials"]} specified, but does not exist", MU::WARN
115
133
  end
116
134
  end
@@ -145,39 +163,99 @@ module MU
145
163
  # Given an AWS region, check the API to make sure it's a valid one
146
164
  # @param r [String]
147
165
  # @return [String]
148
- def self.validate_region(r)
149
- MU::Cloud::AWS.ec2(region: r).describe_availability_zones.availability_zones.first.region_name
166
+ def self.validate_region(r, credentials: nil)
167
+ begin
168
+ MU::Cloud::AWS.ec2(region: r, credentials: credentials).describe_availability_zones.availability_zones.first.region_name
169
+ rescue ::Aws::EC2::Errors::UnauthorizedOperation => e
170
+ MU.log "Got '#{e.message}' trying to validate region #{r} (hosted: #{hosted?.to_s})", MU::ERR, details: loadCredentials(credentials)
171
+ raise MuError, "Got '#{e.message}' trying to validate region #{r} with credentials #{credentials ? credentials : "<default>"} (hosted: #{hosted?.to_s})"
172
+ end
173
+ end
174
+
175
+ # Tag a resource with all of our standard identifying tags.
176
+ #
177
+ # @param resource [String]: The cloud provider identifier of the resource to tag
178
+ # @param region [String]: The cloud provider region
179
+ # @return [void]
180
+ def self.createStandardTags(resource = nil, region: MU.curRegion, credentials: nil)
181
+ tags = []
182
+ MU::MommaCat.listStandardTags.each_pair { |name, value|
183
+ if !value.nil?
184
+ tags << {key: name, value: value}
185
+ end
186
+ }
187
+ if MU::Cloud::CloudFormation.emitCloudFormation
188
+ return tags
189
+ end
190
+
191
+ attempts = 0
192
+ begin
193
+ MU::Cloud::AWS.ec2(region: region, credentials: credentials).create_tags(
194
+ resources: [resource],
195
+ tags: tags
196
+ )
197
+ rescue Aws::EC2::Errors::ServiceError => e
198
+ MU.log "Got #{e.inspect} tagging #{resource} in #{region}, will retry", MU::WARN, details: caller.concat(tags) if attempts > 1
199
+ if attempts < 5
200
+ attempts = attempts + 1
201
+ sleep 15
202
+ retry
203
+ else
204
+ raise e
205
+ end
206
+ end
207
+ MU.log "Created standard tags for resource #{resource}", MU::DEBUG, details: caller
208
+ end
209
+
210
+ # If we reside in this cloud, return the VPC in which we, the Mu Master, reside.
211
+ # @return [MU::Cloud::VPC]
212
+ def self.myVPCObj
213
+ return nil if !hosted?
214
+ instance = MU.myCloudDescriptor
215
+ return nil if !instance or !instance.vpc_id
216
+ vpc = MU::MommaCat.findStray("AWS", "vpc", cloud_id: instance.vpc_id, dummy_ok: true)
217
+ return nil if vpc.nil? or vpc.size == 0
218
+ vpc.first
150
219
  end
151
220
 
152
221
  # If we've configured AWS as a provider, or are simply hosted in AWS,
153
222
  # decide what our default region is.
154
- def self.myRegion
223
+ def self.myRegion(credentials = nil)
155
224
  return @@myRegion_var if @@myRegion_var
156
225
 
157
226
  if credConfig.nil? and !hosted? and !ENV['EC2_REGION']
158
227
  return nil
159
228
  end
160
229
 
161
-
162
230
  if $MU_CFG and $MU_CFG['aws']
163
231
  $MU_CFG['aws'].each_pair { |credset, cfg|
232
+ next if credentials and credset != credentials
164
233
  next if !cfg['region']
165
- if (cfg['default'] or !@@myRegion_var) and validate_region(cfg['region'])
234
+ if (cfg['default'] or !@@myRegion_var) and validate_region(cfg['region'], credentials: credset)
166
235
  @@myRegion_var = cfg['region']
167
- break if cfg['default']
236
+ break if cfg['default'] or credentials
168
237
  end
169
238
  }
170
239
  elsif ENV.has_key?("EC2_REGION") and !ENV['EC2_REGION'].empty? and
171
- validate_region(ENV['EC2_REGION'])
240
+ validate_region(ENV['EC2_REGION']) and
241
+ (
242
+ (ENV.has_key?("AWS_SECRET_ACCESS_KEY") and ENV.has_key?("AWS_SECRET_ACCESS_KEY") ) or
243
+ (Aws.config['access_key'] and Aws.config['access_secret'])
244
+ )
172
245
  # Make sure this string is valid by way of the API
173
246
  @@myRegion_var = ENV['EC2_REGION']
174
- else
247
+ end
248
+
249
+ if hosted? and !@@myRegion_var
175
250
  # hacky, but useful in a pinch (and if we're hosted in AWS)
176
251
  az_str = MU::Cloud::AWS.getAWSMetaData("placement/availability-zone")
177
252
  @@myRegion_var = az_str.sub(/[a-z]$/i, "") if az_str
178
253
  end
254
+
255
+ @@myRegion_var
179
256
  end
180
257
 
258
+
181
259
  # Is the region we're dealing with a GovCloud region?
182
260
  # @param region [String]: The region in question, defaults to the Mu Master's local region
183
261
  def self.isGovCloud?(region = myRegion)
@@ -247,9 +325,8 @@ module MU
247
325
  # @param region [String]: The region to search.
248
326
  # @return [Array<String>]: The Availability Zones in this region.
249
327
  def self.listAZs(region: MU.curRegion, account: nil, credentials: nil)
250
- if $MU_CFG and (!$MU_CFG['aws'] or !account_number)
251
- return []
252
- end
328
+ cfg = credConfig(credentials)
329
+ return [] if !cfg
253
330
  if !region.nil? and @@azs[region]
254
331
  return @@azs[region]
255
332
  end
@@ -265,6 +342,18 @@ module MU
265
342
  return @@azs[region]
266
343
  end
267
344
 
345
+ # Do cloud-specific deploy instantiation tasks, such as copying SSH keys
346
+ # around, sticking secrets in buckets, creating resource groups, etc
347
+ # @param deploy [MU::MommaCat]
348
+ def self.initDeploy(deploy)
349
+ end
350
+
351
+ # Purge cloud-specific deploy meta-artifacts (SSH keys, resource groups,
352
+ # etc)
353
+ # @param deploy_id [MU::MommaCat]
354
+ def self.cleanDeploy(deploy_id, credentials: nil, noop: false)
355
+ end
356
+
268
357
  # Plant a Mu deploy secret into a storage bucket somewhere for so our kittens can consume it
269
358
  # @param deploy_id [String]: The deploy for which we're writing the secret
270
359
  # @param value [String]: The contents of the secret
@@ -346,6 +435,14 @@ module MU
346
435
  instance_id = open("http://169.254.169.254/latest/meta-data/instance-id").read
347
436
  if !instance_id.nil? and instance_id.size > 0
348
437
  @@is_in_aws = true
438
+ region = getAWSMetaData("placement/availability-zone").sub(/[a-z]$/i, "")
439
+ begin
440
+ validate_region(region)
441
+ rescue MuError
442
+ @@creds_loaded.delete("#default")
443
+ @@is_in_aws = false
444
+ false
445
+ end
349
446
  return true
350
447
  end
351
448
  end
@@ -384,6 +481,16 @@ module MU
384
481
  sample
385
482
  end
386
483
 
484
+ # Return what we think of as a cloud object's habitat. In AWS, this means
485
+ # the +account_number+ in which it's resident. If this is not applicable,
486
+ # such as for a {Habitat} or {Folder}, returns nil.
487
+ # @param cloudobj [MU::Cloud::AWS]: The resource from which to extract the habitat id
488
+ # @return [String,nil]
489
+ def self.habitat(cloudobj, nolookup: false, deploy: nil)
490
+ cloudobj.respond_to?(:account_number) ? cloudobj.account_number : nil
491
+ end
492
+
493
+
387
494
  @@my_acct_num = nil
388
495
  @@my_hosted_cfg = nil
389
496
  @@acct_to_profile_map = {}
@@ -415,8 +522,29 @@ module MU
415
522
  # @param credentials [String]
416
523
  # @return [String]
417
524
  def self.adminBucketName(credentials = nil)
418
- #XXX find a default if this particular account doesn't have a log_bucket_name configured
419
525
  cfg = credConfig(credentials)
526
+ return nil if !cfg
527
+ if !cfg['log_bucket_name']
528
+ cfg['log_bucket_name'] = $MU_CFG['hostname']
529
+ MU.log "No AWS log bucket defined for credentials #{credentials}, attempting to use default of #{cfg['log_bucket_name']}", MU::WARN
530
+ end
531
+ resp = MU::Cloud::AWS.s3(credentials: credentials).list_buckets
532
+ found = false
533
+ resp.buckets.each { |b|
534
+ if b.name == cfg['log_bucket_name']
535
+ found = true
536
+ break
537
+ end
538
+ }
539
+ if !found
540
+ MU.log "Attempting to create log bucket #{cfg['log_bucket_name']} for credentials #{credentials}", MU::WARN
541
+ begin
542
+ resp = MU::Cloud::AWS.s3(credentials: credentials).create_bucket(bucket: cfg['log_bucket_name'], acl: "private")
543
+ rescue Aws::S3::Errors::BucketAlreadyExists => e
544
+ raise MuError, "AWS credentials #{credentials} need a log bucket, and the name #{cfg['log_bucket_name']} is unavailable. Use mu-configure to edit credentials '#{credentials}' or 'hostname'"
545
+ end
546
+ end
547
+
420
548
  cfg['log_bucket_name']
421
549
  end
422
550
 
@@ -425,7 +553,8 @@ module MU
425
553
  # @param credentials [String]
426
554
  # @return [String]
427
555
  def self.adminBucketUrl(credentials = nil)
428
- "s3://"+adminBucketName+"/"
556
+ return nil if !credConfig(credentials)
557
+ "s3://"+adminBucketName(credentials)+"/"
429
558
  end
430
559
 
431
560
  # Return the $MU_CFG data associated with a particular profile/name/set of
@@ -439,7 +568,9 @@ module MU
439
568
  # on a machine hosted in AWS, *and* that machine has an IAM profile,
440
569
  # fake it with those credentials and hope for the best.
441
570
  if !$MU_CFG['aws'] or !$MU_CFG['aws'].is_a?(Hash) or $MU_CFG['aws'].size == 0
442
- return @@my_hosted_cfg if @@my_hosted_cfg
571
+ if @@my_hosted_cfg
572
+ return name_only ? "#default" : @@my_hosted_cfg
573
+ end
443
574
 
444
575
  if hosted?
445
576
  begin
@@ -464,9 +595,9 @@ module MU
464
595
  end
465
596
 
466
597
  if name.nil?
467
- $MU_CFG['aws'].each_pair { |name, cfg|
598
+ $MU_CFG['aws'].each_pair { |set, cfg|
468
599
  if cfg['default']
469
- return name_only ? name : cfg
600
+ return name_only ? set : cfg
470
601
  end
471
602
  }
472
603
  else
@@ -496,7 +627,6 @@ module MU
496
627
  cfg['account_number'] = acct_num.to_s
497
628
  @@acct_to_profile_map[name.to_s] = cfg
498
629
  return name_only ? name.to_s : cfg
499
- return cfg
500
630
  end
501
631
  }
502
632
  end
@@ -1026,10 +1156,14 @@ module MU
1026
1156
  # @return [void]
1027
1157
  def self.openFirewallForClients
1028
1158
  MU::Cloud.loadCloudType("AWS", :FirewallRule)
1029
- if File.exists?(Etc.getpwuid(Process.uid).dir+"/.chef/knife.rb")
1030
- ::Chef::Config.from_file(Etc.getpwuid(Process.uid).dir+"/.chef/knife.rb")
1159
+ begin
1160
+ if File.exist?(Etc.getpwuid(Process.uid).dir+"/.chef/knife.rb")
1161
+ ::Chef::Config.from_file(Etc.getpwuid(Process.uid).dir+"/.chef/knife.rb")
1162
+ end
1163
+ ::Chef::Config[:environment] = MU.environment
1164
+ rescue LoadError
1165
+ # XXX why is Chef here
1031
1166
  end
1032
- ::Chef::Config[:environment] = MU.environment
1033
1167
 
1034
1168
  # This is the set of (TCP) ports we're opening to clients. We assume that
1035
1169
  # we can and and remove these without impacting anything a human has
@@ -1218,8 +1352,6 @@ module MU
1218
1352
 
1219
1353
  MU.log "Initializing #{api} object with credentials #{credentials}", MU::DEBUG, details: params
1220
1354
  @api = Object.const_get("Aws::#{api}::Client").new(params)
1221
-
1222
- @api
1223
1355
  end
1224
1356
 
1225
1357
  @instance_cache = {}
@@ -1239,7 +1371,7 @@ module MU
1239
1371
  retval = @api.method(method_sym).call
1240
1372
  end
1241
1373
  return retval
1242
- rescue Aws::EC2::Errors::InternalError, Aws::EC2::Errors::RequestLimitExceeded, Aws::EC2::Errors::Unavailable, Aws::Route53::Errors::Throttling, Aws::ElasticLoadBalancing::Errors::HttpFailureException, Aws::EC2::Errors::Http503Error, Aws::AutoScaling::Errors::Http503Error, Aws::AutoScaling::Errors::InternalFailure, Aws::AutoScaling::Errors::ServiceUnavailable, Aws::Route53::Errors::ServiceUnavailable, Aws::ElasticLoadBalancing::Errors::Throttling, Aws::RDS::Errors::ClientUnavailable, Aws::Waiters::Errors::UnexpectedError, Aws::ElasticLoadBalancing::Errors::ServiceUnavailable, Aws::ElasticLoadBalancingV2::Errors::Throttling, Seahorse::Client::NetworkingError, Aws::IAM::Errors::Throttling, Aws::EFS::Errors::ThrottlingException, Aws::Pricing::Errors::ThrottlingException, Aws::APIGateway::Errors::TooManyRequestsException, Aws::ECS::Errors::ThrottlingException => e
1374
+ rescue Aws::EC2::Errors::InternalError, Aws::EC2::Errors::RequestLimitExceeded, Aws::EC2::Errors::Unavailable, Aws::Route53::Errors::Throttling, Aws::ElasticLoadBalancing::Errors::HttpFailureException, Aws::EC2::Errors::Http503Error, Aws::AutoScaling::Errors::Http503Error, Aws::AutoScaling::Errors::InternalFailure, Aws::AutoScaling::Errors::ServiceUnavailable, Aws::Route53::Errors::ServiceUnavailable, Aws::ElasticLoadBalancing::Errors::Throttling, Aws::RDS::Errors::ClientUnavailable, Aws::Waiters::Errors::UnexpectedError, Aws::ElasticLoadBalancing::Errors::ServiceUnavailable, Aws::ElasticLoadBalancingV2::Errors::Throttling, Seahorse::Client::NetworkingError, Aws::IAM::Errors::Throttling, Aws::EFS::Errors::ThrottlingException, Aws::Pricing::Errors::ThrottlingException, Aws::APIGateway::Errors::TooManyRequestsException, Aws::ECS::Errors::ThrottlingException, Net::ReadTimeout, Faraday::TimeoutError => e
1243
1375
  if e.class.name == "Seahorse::Client::NetworkingError" and e.message.match(/Name or service not known/)
1244
1376
  MU.log e.inspect, MU::ERR
1245
1377
  raise e
@@ -17,21 +17,11 @@ module MU
17
17
  class AWS
18
18
  # A alarm as configured in {MU::Config::BasketofKittens::alarms}
19
19
  class Alarm < MU::Cloud::Alarm
20
- @deploy = nil
21
- @config = nil
22
- attr_reader :mu_name
23
- attr_reader :config
24
- attr_reader :cloud_id
25
20
 
26
- @cloudformation_data = {}
27
- attr_reader :cloudformation_data
28
-
29
- # @param mommacat [MU::MommaCat]: A {MU::Mommacat} object containing the deploy of which this resource is/will be a member.
30
- # @param kitten_cfg [Hash]: The fully parsed and resolved {MU::Config} resource descriptor as defined in {MU::Config::BasketofKittens::alarms}
31
- def initialize(mommacat: nil, kitten_cfg: nil, mu_name: nil, cloud_id: nil)
32
- @deploy = mommacat
33
- @config = MU::Config.manxify(kitten_cfg)
34
- @cloud_id ||= cloud_id
21
+ # Initialize this cloud resource object. Calling +super+ will invoke the initializer defined under {MU::Cloud}, which should set the attribtues listed in {MU::Cloud::PUBLIC_ATTRS} as well as applicable dependency shortcuts, like +@vpc+, for us.
22
+ # @param args [Hash]: Hash of named arguments passed via Ruby's double-splat
23
+ def initialize(**args)
24
+ super
35
25
  @mu_name ||= @deploy.getResourceName(@config["name"])
36
26
  end
37
27
 
@@ -17,22 +17,14 @@ module MU
17
17
  class AWS
18
18
  # Support for AWS S3
19
19
  class Bucket < MU::Cloud::Bucket
20
- @deploy = nil
21
- @config = nil
22
20
 
23
21
  @@region_cache = {}
24
22
  @@region_cache_semaphore = Mutex.new
25
23
 
26
- attr_reader :mu_name
27
- attr_reader :config
28
- attr_reader :cloud_id
29
-
30
- # @param mommacat [MU::MommaCat]: A {MU::Mommacat} object containing the deploy of which this resource is/will be a member.
31
- # @param kitten_cfg [Hash]: The fully parsed and resolved {MU::Config} resource descriptor as defined in {MU::Config::BasketofKittens::logs}
32
- def initialize(mommacat: nil, kitten_cfg: nil, mu_name: nil, cloud_id: nil)
33
- @deploy = mommacat
34
- @config = MU::Config.manxify(kitten_cfg)
35
- @cloud_id ||= cloud_id
24
+ # Initialize this cloud resource object. Calling +super+ will invoke the initializer defined under {MU::Cloud}, which should set the attribtues listed in {MU::Cloud::PUBLIC_ATTRS} as well as applicable dependency shortcuts, like +@vpc+, for us.
25
+ # @param args [Hash]: Hash of named arguments passed via Ruby's double-splat
26
+ def initialize(**args)
27
+ super
36
28
  @mu_name ||= @deploy.getResourceName(@config["name"])
37
29
  end
38
30
 
@@ -145,6 +137,51 @@ module MU
145
137
  end
146
138
  end
147
139
 
140
+ # Upload a file to a bucket.
141
+ # @param url [String]: Target URL, of the form s3://bucket/folder/file
142
+ # @param acl [String]: Canned ACL permission to assign to the object we upload
143
+ # @param file [String]: Path to a local file to write to our target location. One of +file+ or +data+ must be specified.
144
+ # @param data [String]: Data to write to our target location. One of +file+ or +data+ must be specified.
145
+ def self.upload(url, acl: "private", file: nil, data: nil, credentials: nil, region: nil)
146
+ if (!file or file.empty?) and !data
147
+ raise MuError, "Must specify a file or some data to upload to bucket #{s3_url}"
148
+ end
149
+
150
+ if file and !file.empty?
151
+ if !File.exist?(file) or !File.readable?(file)
152
+ raise MuError, "Unable to read #{file} for upload to #{url}"
153
+ else
154
+ data = File.read(file)
155
+ end
156
+ end
157
+
158
+ url.match(/^(?:s3:\/\/)([^\/:]+?)[\/:]\/?(.+)?/)
159
+ bucket = Regexp.last_match[1]
160
+ path = Regexp.last_match[2]
161
+ if !path
162
+ if !file
163
+ raise MuError, "Unable to determine upload path from url #{url}"
164
+ end
165
+ end
166
+
167
+ begin
168
+ puts data
169
+ puts acl
170
+ puts bucket
171
+ puts path
172
+ MU.log "Writing #{path} to S3 bucket #{bucket}"
173
+ MU::Cloud::AWS.s3(region: region, credentials: credentials).put_object(
174
+ acl: acl,
175
+ bucket: bucket,
176
+ key: path,
177
+ body: data
178
+ )
179
+ rescue Aws::S3::Errors => e
180
+ raise MuError, "Got #{e.inspect} trying to write #{path} to #{bucket} (region: #{region}, credentials: #{credentials})"
181
+ end
182
+
183
+ end
184
+
148
185
  # Does this resource type exist as a global (cloud-wide) artifact, or
149
186
  # is it localized to a region/zone?
150
187
  # @return [Boolean]
@@ -172,13 +209,18 @@ module MU
172
209
  if @@region_cache[bucket.name]
173
210
  next if @@region_cache[bucket.name] != region
174
211
  else
175
- location = MU::Cloud::AWS.s3(credentials: credentials, region: region).get_bucket_location(bucket: bucket.name).location_constraint
176
-
177
- if location.nil? or location.empty?
178
- @@region_cache[bucket.name] = region
179
- else
180
- @@region_cache[bucket.name] = location
212
+ begin
213
+ location = MU::Cloud::AWS.s3(credentials: credentials, region: region).get_bucket_location(bucket: bucket.name).location_constraint
214
+ if location.nil? or location.empty?
215
+ @@region_cache[bucket.name] = region
216
+ else
217
+ @@region_cache[bucket.name] = location
218
+ end
219
+ rescue Aws::S3::Errors::AccessDenied => e
220
+ # this is routine- we saw a bucket that's not our business
221
+ next
181
222
  end
223
+
182
224
  end
183
225
  }
184
226
 
@@ -17,23 +17,11 @@ module MU
17
17
  class AWS
18
18
  # A cache cluster as configured in {MU::Config::BasketofKittens::cache_clusters}
19
19
  class CacheCluster < MU::Cloud::CacheCluster
20
- @deploy = nil
21
- @config = nil
22
- attr_reader :mu_name
23
- attr_reader :cloud_id
24
- attr_reader :config
25
-
26
- @cloudformation_data = {}
27
- attr_reader :cloudformation_data
28
-
29
- # @param mommacat [MU::MommaCat]: A {MU::Mommacat} object containing the deploy of which this resource is/will be a member.
30
- # @param kitten_cfg [Hash]: The fully parsed and resolved {MU::Config} resource descriptor as defined in {MU::Config::BasketofKittens::cache_clusters}
31
- def initialize(mommacat: nil, kitten_cfg: nil, mu_name: nil, cloud_id: nil)
32
- @deploy = mommacat
33
- @config = MU::Config.manxify(kitten_cfg)
34
- @cloud_id ||= cloud_id
35
- # @mu_name = mu_name ? mu_name : @deploy.getResourceName(@config["name"])
36
20
 
21
+ # Initialize this cloud resource object. Calling +super+ will invoke the initializer defined under {MU::Cloud}, which should set the attribtues listed in {MU::Cloud::PUBLIC_ATTRS} as well as applicable dependency shortcuts, like +@vpc+, for us.
22
+ # @param args [Hash]: Hash of named arguments passed via Ruby's double-splat
23
+ def initialize(**args)
24
+ super
37
25
  @mu_name ||=
38
26
  if @config["create_replication_group"]
39
27
  @deploy.getResourceName(@config["name"], max_length: 16, need_unique_string: true)
@@ -194,8 +182,8 @@ module MU
194
182
  waiter.before_attempt do |attempts|
195
183
  MU.log "Waiting for cache replication group #{@config['identifier']} to become available", MU::NOTICE if attempts % 5 == 0
196
184
  end
197
- waiter.before_wait do |attempts, resp|
198
- throw :success if resp.replication_groups.first.status == "available"
185
+ waiter.before_wait do |attempts, r|
186
+ throw :success if r.replication_groups.first.status == "available"
199
187
  throw :failure if Time.now - wait_start_time > 1800
200
188
  end
201
189
  end
@@ -251,8 +239,8 @@ module MU
251
239
  waiter.before_attempt do |attempts|
252
240
  MU.log "Waiting for cache cluster #{@config['identifier']} to become available", MU::NOTICE if attempts % 5 == 0
253
241
  end
254
- waiter.before_wait do |attempts, resp|
255
- throw :success if resp.cache_clusters.first.cache_cluster_status == "available"
242
+ waiter.before_wait do |attempts, r|
243
+ throw :success if r.cache_clusters.first.cache_cluster_status == "available"
256
244
  throw :failure if Time.now - wait_start_time > 1800
257
245
  end
258
246
  end