cloud-mu 3.1.2 → 3.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (201) hide show
  1. checksums.yaml +4 -4
  2. data/Dockerfile +15 -3
  3. data/ansible/roles/mu-windows/README.md +33 -0
  4. data/ansible/roles/mu-windows/defaults/main.yml +2 -0
  5. data/ansible/roles/mu-windows/files/LaunchConfig.json +9 -0
  6. data/ansible/roles/mu-windows/files/config.xml +76 -0
  7. data/ansible/roles/mu-windows/handlers/main.yml +2 -0
  8. data/ansible/roles/mu-windows/meta/main.yml +53 -0
  9. data/ansible/roles/mu-windows/tasks/main.yml +36 -0
  10. data/ansible/roles/mu-windows/tests/inventory +2 -0
  11. data/ansible/roles/mu-windows/tests/test.yml +5 -0
  12. data/ansible/roles/mu-windows/vars/main.yml +2 -0
  13. data/bin/mu-adopt +10 -13
  14. data/bin/mu-azure-tests +57 -0
  15. data/bin/mu-cleanup +2 -4
  16. data/bin/mu-configure +52 -0
  17. data/bin/mu-deploy +3 -3
  18. data/bin/mu-findstray-tests +25 -0
  19. data/bin/mu-gen-docs +2 -4
  20. data/bin/mu-load-config.rb +2 -3
  21. data/bin/mu-node-manage +15 -16
  22. data/bin/mu-run-tests +135 -37
  23. data/cloud-mu.gemspec +22 -20
  24. data/cookbooks/mu-activedirectory/resources/domain.rb +4 -4
  25. data/cookbooks/mu-activedirectory/resources/domain_controller.rb +4 -4
  26. data/cookbooks/mu-tools/libraries/helper.rb +3 -2
  27. data/cookbooks/mu-tools/libraries/monkey.rb +35 -0
  28. data/cookbooks/mu-tools/recipes/apply_security.rb +14 -14
  29. data/cookbooks/mu-tools/recipes/aws_api.rb +9 -0
  30. data/cookbooks/mu-tools/recipes/eks.rb +2 -2
  31. data/cookbooks/mu-tools/recipes/google_api.rb +2 -2
  32. data/cookbooks/mu-tools/recipes/selinux.rb +2 -1
  33. data/cookbooks/mu-tools/recipes/windows-client.rb +163 -164
  34. data/cookbooks/mu-tools/resources/disk.rb +1 -1
  35. data/cookbooks/mu-tools/resources/windows_users.rb +44 -43
  36. data/extras/clean-stock-amis +25 -19
  37. data/extras/generate-stock-images +1 -0
  38. data/extras/image-generators/AWS/win2k12.yaml +18 -13
  39. data/extras/image-generators/AWS/win2k16.yaml +18 -13
  40. data/extras/image-generators/AWS/win2k19.yaml +21 -0
  41. data/extras/image-generators/Google/centos6.yaml +1 -0
  42. data/extras/image-generators/Google/centos7.yaml +1 -1
  43. data/modules/mommacat.ru +6 -16
  44. data/modules/mu.rb +165 -111
  45. data/modules/mu/adoption.rb +401 -68
  46. data/modules/mu/cleanup.rb +199 -306
  47. data/modules/mu/cloud.rb +100 -1632
  48. data/modules/mu/cloud/database.rb +49 -0
  49. data/modules/mu/cloud/dnszone.rb +46 -0
  50. data/modules/mu/cloud/machine_images.rb +212 -0
  51. data/modules/mu/cloud/providers.rb +81 -0
  52. data/modules/mu/cloud/resource_base.rb +920 -0
  53. data/modules/mu/cloud/server.rb +40 -0
  54. data/modules/mu/cloud/server_pool.rb +1 -0
  55. data/modules/mu/cloud/ssh_sessions.rb +228 -0
  56. data/modules/mu/cloud/winrm_sessions.rb +237 -0
  57. data/modules/mu/cloud/wrappers.rb +165 -0
  58. data/modules/mu/config.rb +171 -1767
  59. data/modules/mu/config/alarm.rb +2 -6
  60. data/modules/mu/config/bucket.rb +4 -4
  61. data/modules/mu/config/cache_cluster.rb +1 -1
  62. data/modules/mu/config/collection.rb +4 -4
  63. data/modules/mu/config/container_cluster.rb +9 -4
  64. data/modules/mu/config/database.rb +83 -104
  65. data/modules/mu/config/database.yml +1 -2
  66. data/modules/mu/config/dnszone.rb +6 -6
  67. data/modules/mu/config/doc_helpers.rb +516 -0
  68. data/modules/mu/config/endpoint.rb +4 -4
  69. data/modules/mu/config/firewall_rule.rb +103 -4
  70. data/modules/mu/config/folder.rb +4 -4
  71. data/modules/mu/config/function.rb +3 -3
  72. data/modules/mu/config/group.rb +4 -4
  73. data/modules/mu/config/habitat.rb +4 -4
  74. data/modules/mu/config/loadbalancer.rb +60 -14
  75. data/modules/mu/config/log.rb +4 -4
  76. data/modules/mu/config/msg_queue.rb +4 -4
  77. data/modules/mu/config/nosqldb.rb +4 -4
  78. data/modules/mu/config/notifier.rb +3 -3
  79. data/modules/mu/config/ref.rb +365 -0
  80. data/modules/mu/config/role.rb +4 -4
  81. data/modules/mu/config/schema_helpers.rb +509 -0
  82. data/modules/mu/config/search_domain.rb +4 -4
  83. data/modules/mu/config/server.rb +97 -70
  84. data/modules/mu/config/server.yml +1 -0
  85. data/modules/mu/config/server_pool.rb +5 -9
  86. data/modules/mu/config/storage_pool.rb +1 -1
  87. data/modules/mu/config/tail.rb +200 -0
  88. data/modules/mu/config/user.rb +4 -4
  89. data/modules/mu/config/vpc.rb +70 -27
  90. data/modules/mu/config/vpc.yml +0 -1
  91. data/modules/mu/defaults/AWS.yaml +83 -60
  92. data/modules/mu/defaults/Azure.yaml +1 -0
  93. data/modules/mu/defaults/Google.yaml +3 -2
  94. data/modules/mu/deploy.rb +30 -26
  95. data/modules/mu/groomer.rb +17 -2
  96. data/modules/mu/groomers/ansible.rb +188 -41
  97. data/modules/mu/groomers/chef.rb +116 -55
  98. data/modules/mu/logger.rb +127 -148
  99. data/modules/mu/master.rb +389 -2
  100. data/modules/mu/master/chef.rb +3 -4
  101. data/modules/mu/master/ldap.rb +3 -3
  102. data/modules/mu/master/ssl.rb +12 -3
  103. data/modules/mu/mommacat.rb +217 -2612
  104. data/modules/mu/mommacat/daemon.rb +397 -0
  105. data/modules/mu/mommacat/naming.rb +473 -0
  106. data/modules/mu/mommacat/search.rb +495 -0
  107. data/modules/mu/mommacat/storage.rb +722 -0
  108. data/modules/mu/{clouds → providers}/README.md +1 -1
  109. data/modules/mu/{clouds → providers}/aws.rb +271 -112
  110. data/modules/mu/{clouds → providers}/aws/alarm.rb +5 -3
  111. data/modules/mu/{clouds → providers}/aws/bucket.rb +26 -22
  112. data/modules/mu/{clouds → providers}/aws/cache_cluster.rb +33 -67
  113. data/modules/mu/{clouds → providers}/aws/collection.rb +24 -23
  114. data/modules/mu/{clouds → providers}/aws/container_cluster.rb +681 -721
  115. data/modules/mu/providers/aws/database.rb +1744 -0
  116. data/modules/mu/{clouds → providers}/aws/dnszone.rb +64 -63
  117. data/modules/mu/{clouds → providers}/aws/endpoint.rb +22 -27
  118. data/modules/mu/{clouds → providers}/aws/firewall_rule.rb +214 -244
  119. data/modules/mu/{clouds → providers}/aws/folder.rb +7 -7
  120. data/modules/mu/{clouds → providers}/aws/function.rb +17 -22
  121. data/modules/mu/{clouds → providers}/aws/group.rb +23 -23
  122. data/modules/mu/{clouds → providers}/aws/habitat.rb +17 -14
  123. data/modules/mu/{clouds → providers}/aws/loadbalancer.rb +57 -48
  124. data/modules/mu/{clouds → providers}/aws/log.rb +15 -12
  125. data/modules/mu/{clouds → providers}/aws/msg_queue.rb +17 -16
  126. data/modules/mu/{clouds → providers}/aws/nosqldb.rb +18 -11
  127. data/modules/mu/{clouds → providers}/aws/notifier.rb +11 -6
  128. data/modules/mu/{clouds → providers}/aws/role.rb +112 -86
  129. data/modules/mu/{clouds → providers}/aws/search_domain.rb +39 -33
  130. data/modules/mu/{clouds → providers}/aws/server.rb +835 -1133
  131. data/modules/mu/{clouds → providers}/aws/server_pool.rb +56 -60
  132. data/modules/mu/{clouds → providers}/aws/storage_pool.rb +24 -42
  133. data/modules/mu/{clouds → providers}/aws/user.rb +21 -22
  134. data/modules/mu/{clouds → providers}/aws/userdata/README.md +0 -0
  135. data/modules/mu/{clouds → providers}/aws/userdata/linux.erb +0 -0
  136. data/modules/mu/{clouds → providers}/aws/userdata/windows.erb +2 -1
  137. data/modules/mu/{clouds → providers}/aws/vpc.rb +523 -929
  138. data/modules/mu/providers/aws/vpc_subnet.rb +286 -0
  139. data/modules/mu/{clouds → providers}/azure.rb +29 -9
  140. data/modules/mu/{clouds → providers}/azure/container_cluster.rb +3 -8
  141. data/modules/mu/{clouds → providers}/azure/firewall_rule.rb +18 -11
  142. data/modules/mu/{clouds → providers}/azure/habitat.rb +8 -6
  143. data/modules/mu/{clouds → providers}/azure/loadbalancer.rb +5 -5
  144. data/modules/mu/{clouds → providers}/azure/role.rb +8 -10
  145. data/modules/mu/{clouds → providers}/azure/server.rb +95 -48
  146. data/modules/mu/{clouds → providers}/azure/user.rb +6 -8
  147. data/modules/mu/{clouds → providers}/azure/userdata/README.md +0 -0
  148. data/modules/mu/{clouds → providers}/azure/userdata/linux.erb +0 -0
  149. data/modules/mu/{clouds → providers}/azure/userdata/windows.erb +0 -0
  150. data/modules/mu/{clouds → providers}/azure/vpc.rb +16 -21
  151. data/modules/mu/{clouds → providers}/cloudformation.rb +18 -7
  152. data/modules/mu/{clouds → providers}/cloudformation/alarm.rb +3 -3
  153. data/modules/mu/{clouds → providers}/cloudformation/cache_cluster.rb +3 -3
  154. data/modules/mu/{clouds → providers}/cloudformation/collection.rb +3 -3
  155. data/modules/mu/{clouds → providers}/cloudformation/database.rb +6 -17
  156. data/modules/mu/{clouds → providers}/cloudformation/dnszone.rb +3 -3
  157. data/modules/mu/{clouds → providers}/cloudformation/firewall_rule.rb +3 -3
  158. data/modules/mu/{clouds → providers}/cloudformation/loadbalancer.rb +3 -3
  159. data/modules/mu/{clouds → providers}/cloudformation/log.rb +3 -3
  160. data/modules/mu/{clouds → providers}/cloudformation/server.rb +7 -7
  161. data/modules/mu/{clouds → providers}/cloudformation/server_pool.rb +5 -5
  162. data/modules/mu/{clouds → providers}/cloudformation/vpc.rb +5 -7
  163. data/modules/mu/{clouds → providers}/docker.rb +0 -0
  164. data/modules/mu/{clouds → providers}/google.rb +67 -30
  165. data/modules/mu/{clouds → providers}/google/bucket.rb +13 -15
  166. data/modules/mu/{clouds → providers}/google/container_cluster.rb +84 -77
  167. data/modules/mu/{clouds → providers}/google/database.rb +10 -20
  168. data/modules/mu/{clouds → providers}/google/firewall_rule.rb +15 -14
  169. data/modules/mu/{clouds → providers}/google/folder.rb +20 -17
  170. data/modules/mu/{clouds → providers}/google/function.rb +139 -167
  171. data/modules/mu/{clouds → providers}/google/group.rb +29 -34
  172. data/modules/mu/{clouds → providers}/google/habitat.rb +21 -22
  173. data/modules/mu/{clouds → providers}/google/loadbalancer.rb +18 -20
  174. data/modules/mu/{clouds → providers}/google/role.rb +92 -58
  175. data/modules/mu/{clouds → providers}/google/server.rb +242 -155
  176. data/modules/mu/{clouds → providers}/google/server_pool.rb +25 -44
  177. data/modules/mu/{clouds → providers}/google/user.rb +95 -31
  178. data/modules/mu/{clouds → providers}/google/userdata/README.md +0 -0
  179. data/modules/mu/{clouds → providers}/google/userdata/linux.erb +0 -0
  180. data/modules/mu/{clouds → providers}/google/userdata/windows.erb +0 -0
  181. data/modules/mu/{clouds → providers}/google/vpc.rb +103 -79
  182. data/modules/tests/bucket.yml +4 -0
  183. data/modules/tests/centos6.yaml +11 -0
  184. data/modules/tests/centos7.yaml +11 -0
  185. data/modules/tests/centos8.yaml +12 -0
  186. data/modules/tests/ecs.yaml +23 -0
  187. data/modules/tests/includes-and-params.yaml +2 -1
  188. data/modules/tests/rds.yaml +108 -0
  189. data/modules/tests/regrooms/aws-iam.yaml +201 -0
  190. data/modules/tests/regrooms/bucket.yml +19 -0
  191. data/modules/tests/regrooms/rds.yaml +123 -0
  192. data/modules/tests/server-with-scrub-muisms.yaml +1 -0
  193. data/modules/tests/super_simple_bok.yml +1 -3
  194. data/modules/tests/win2k12.yaml +17 -5
  195. data/modules/tests/win2k16.yaml +25 -0
  196. data/modules/tests/win2k19.yaml +25 -0
  197. data/requirements.txt +1 -0
  198. data/spec/mu/clouds/azure_spec.rb +2 -2
  199. metadata +232 -154
  200. data/extras/image-generators/AWS/windows.yaml +0 -18
  201. data/modules/mu/clouds/aws/database.rb +0 -1985
@@ -25,13 +25,15 @@ module MU
25
25
  # Routines for removing cloud resources.
26
26
  class Cleanup
27
27
 
28
- home = Etc.getpwuid(Process.uid).dir
29
-
30
28
  @deploy_id = nil
31
29
  @noop = false
32
30
  @onlycloud = false
33
31
  @skipcloud = false
34
32
 
33
+ # Resource types, in the order in which we generally have to clean them up
34
+ # to disentangle them from one another.
35
+ TYPES_IN_ORDER = ["Collection", "Endpoint", "Function", "ServerPool", "ContainerCluster", "SearchDomain", "Server", "MsgQueue", "Database", "CacheCluster", "StoragePool", "LoadBalancer", "NoSQLDB", "FirewallRule", "Alarm", "Notifier", "Log", "VPC", "Role", "Group", "User", "Bucket", "DNSZone", "Collection"]
36
+
35
37
  # Purge all resources associated with a deployment.
36
38
  # @param deploy_id [String]: The identifier of the deployment to remove (typically seen in the MU-ID tag on a resource).
37
39
  # @param noop [Boolean]: Do not delete resources, merely list what would be deleted.
@@ -56,14 +58,7 @@ module MU
56
58
  @noop = true
57
59
  end
58
60
 
59
- if MU.mu_user != "mu"
60
- MU.setVar("dataDir", Etc.getpwnam(MU.mu_user).dir+"/.mu/var")
61
- else
62
- MU.setVar("dataDir", MU.mainDataDir)
63
- end
64
-
65
-
66
- types_in_order = ["Collection", "Endpoint", "Function", "ServerPool", "ContainerCluster", "SearchDomain", "Server", "MsgQueue", "Database", "CacheCluster", "StoragePool", "LoadBalancer", "NoSQLDB", "FirewallRule", "Alarm", "Notifier", "Log", "VPC", "Role", "Group", "User", "Bucket", "DNSZone", "Collection"]
61
+ MU.setVar("dataDir", (MU.mu_user == "mu" ? MU.mainDataDir : Etc.getpwnam(MU.mu_user).dir+"/.mu/var"))
67
62
 
68
63
  # Load up our deployment metadata
69
64
  if !mommacat.nil?
@@ -81,174 +76,27 @@ module MU
81
76
  MU.log "Searching for remnants of #{deploy_id}, though this may be an invalid MU-ID.", MU::WARN
82
77
  end
83
78
  @mommacat = MU::MommaCat.new(deploy_id, mu_user: MU.mu_user, delay_descriptor_load: true)
84
- rescue Exception => e
79
+ rescue StandardError => e
85
80
  MU.log "Can't load a deploy record for #{deploy_id} (#{e.inspect}), cleaning up resources by guesswork", MU::WARN, details: e.backtrace
86
81
  MU.setVar("deploy_id", deploy_id)
87
-
88
82
  end
89
83
  end
90
84
 
91
- regionsused = @mommacat.regionsUsed if @mommacat
92
- credsused = @mommacat.credsUsed if @mommacat
85
+ @regionsused = @mommacat.regionsUsed if @mommacat
86
+ @credsused = @mommacat.credsUsed if @mommacat
87
+ @habitatsused = @mommacat.habitatsUsed if @mommacat
93
88
 
94
89
  if !@skipcloud
95
- creds = {}
96
- MU::Cloud.availableClouds.each { |cloud|
97
- cloudclass = Object.const_get("MU").const_get("Cloud").const_get(cloud)
98
- if $MU_CFG[cloud.downcase] and $MU_CFG[cloud.downcase].size > 0
99
- creds[cloud] ||= {}
100
- cloudclass.listCredentials.each { |credset|
101
- next if credsets and credsets.size > 0 and !credsets.include?(credset)
102
- next if credsused and credsused.size > 0 and !credsused.include?(credset)
103
- MU.log "Will scan #{cloud} with credentials #{credset}"
104
- creds[cloud][credset] = cloudclass.listRegions(credentials: credset)
105
- }
106
- else
107
- if cloudclass.hosted?
108
- creds[cloud] ||= {}
109
- creds[cloud]["#default"] = cloudclass.listRegions
110
- end
111
- end
112
- }
90
+ creds = listUsedCredentials(credsets)
113
91
 
114
- parent_thread_id = Thread.current.object_id
115
- deleted_nodes = 0
116
92
  cloudthreads = []
117
- keyname = "deploy-#{MU.deploy_id}"
93
+
118
94
  had_failures = false
119
95
 
120
96
  creds.each_pair { |provider, credsets_outer|
121
97
  cloudthreads << Thread.new(provider, credsets_outer) { |cloud, credsets_inner|
122
- MU.dupGlobals(parent_thread_id)
123
98
  Thread.abort_on_exception = false
124
- cloudclass = Object.const_get("MU").const_get("Cloud").const_get(cloud)
125
- habitatclass = Object.const_get("MU").const_get("Cloud").const_get(cloud).const_get("Habitat")
126
- credsets_inner.each_pair { |credset, acct_regions|
127
- next if credsused and !credsused.include?(credset)
128
- global_vs_region_semaphore = Mutex.new
129
- global_done = {}
130
- habitats_done = {}
131
- regionthreads = []
132
- acct_regions.each { |r|
133
- if regionsused
134
- if regionsused.size > 0
135
- next if !regionsused.include?(r)
136
- else
137
- next if r != cloudclass.myRegion(credset)
138
- end
139
- end
140
- if regions and !regions.empty?
141
- next if !regions.include?(r)
142
- MU.log "Checking for #{cloud}/#{credset} resources from #{MU.deploy_id} in #{r}...", MU::NOTICE
143
- end
144
- regionthreads << Thread.new {
145
- MU.dupGlobals(parent_thread_id)
146
- Thread.abort_on_exception = false
147
- MU.setVar("curRegion", r)
148
- projects = []
149
- if habitats
150
- projects = habitats
151
- else
152
- if $MU_CFG and $MU_CFG[cloud.downcase] and
153
- $MU_CFG[cloud.downcase][credset] and
154
- $MU_CFG[cloud.downcase][credset]["project"]
155
- # XXX GCP credential schema needs an array for projects
156
- projects << $MU_CFG[cloud.downcase][credset]["project"]
157
- end
158
- begin
159
- projects.concat(cloudclass.listProjects(credset))
160
- rescue NoMethodError
161
- end
162
- end
163
-
164
- if projects == []
165
- projects << "" # dummy
166
- MU.log "Checking for #{cloud}/#{credset} resources from #{MU.deploy_id} in #{r}", MU::NOTICE
167
- end
168
- projects.uniq!
169
-
170
- # We do these in an order that unrolls dependent resources
171
- # sensibly, and we hit :Collection twice because AWS
172
- # CloudFormation sometimes fails internally.
173
- projectthreads = []
174
- projects.each { |project|
175
- next if !habitatclass.isLive?(project, credset)
176
- if habitats and !habitats.empty? and project != ""
177
- next if !habitats.include?(project)
178
- end
179
-
180
- projectthreads << Thread.new {
181
- MU.dupGlobals(parent_thread_id)
182
- MU.setVar("curRegion", r)
183
- Thread.abort_on_exception = false
184
- if project != ""
185
- MU.log "Checking for #{cloud}/#{credset} resources from #{MU.deploy_id} in #{r}, project #{project}", MU::NOTICE
186
- end
187
-
188
- MU.dupGlobals(parent_thread_id)
189
- flags = {
190
- "project" => project,
191
- "onlycloud" => @onlycloud,
192
- "skipsnapshots" => @skipsnapshots,
193
- }
194
- types_in_order.each { |t|
195
- shortclass, cfg_name, cfg_plural, classname = MU::Cloud.getResourceNames(t)
196
- begin
197
- skipme = false
198
- global_vs_region_semaphore.synchronize {
199
- MU::Cloud.loadCloudType(cloud, t)
200
- if Object.const_get("MU").const_get("Cloud").const_get(cloud).const_get(t).isGlobal?
201
- global_done[project] ||= []
202
- if !global_done[project].include?(t)
203
- global_done[project] << t
204
- flags['global'] = true
205
- else
206
- skipme = true
207
- end
208
- end
209
- }
210
- next if skipme
211
- rescue MU::Cloud::MuDefunctHabitat, MU::Cloud::MuCloudResourceNotImplemented => e
212
- next
213
- rescue MU::MuError, NoMethodError => e
214
- MU.log "While checking mu/clouds/#{cloud.downcase}/#{cloudclass.cfg_name} for global-ness in cleanup: "+e.message, MU::WARN
215
- next
216
- rescue ::Aws::EC2::Errors::AuthFailure, ::Google::Apis::ClientError => e
217
- MU.log e.message+" in "+r, MU::ERR
218
- next
219
- end
220
-
221
- begin
222
- if !self.call_cleanup(t, credset, cloud, flags, r)
223
- had_failures = true
224
- end
225
- rescue MU::Cloud::MuDefunctHabitat, MU::Cloud::MuCloudResourceNotImplemented => e
226
- next
227
- end
228
- }
229
- } # types_in_order.each { |t|
230
- } # projects.each { |project|
231
- projectthreads.each do |t|
232
- t.join
233
- end
234
-
235
- # XXX move to MU::AWS
236
- if cloud == "AWS"
237
- resp = MU::Cloud::AWS.ec2(region: r, credentials: credset).describe_key_pairs(
238
- filters: [{name: "key-name", values: [keyname]}]
239
- )
240
- resp.data.key_pairs.each { |keypair|
241
- MU.log "Deleting key pair #{keypair.key_name} from #{r}"
242
- MU::Cloud::AWS.ec2(region: r, credentials: credset).delete_key_pair(key_name: keypair.key_name) if !@noop
243
- }
244
- end
245
- } # regionthreads << Thread.new {
246
- } # acct_regions.each { |r|
247
- regionthreads.each do |t|
248
- t.join
249
- end
250
-
251
- } # credsets.each_pair { |credset, acct_regions|
99
+ cleanCloud(cloud, habitats, regions, credsets_inner)
252
100
  } # cloudthreads << Thread.new(provider, credsets) { |cloud, credsets_outer|
253
101
  cloudthreads.each do |t|
254
102
  t.join
@@ -260,24 +108,21 @@ module MU
260
108
  # once they're all done.
261
109
  creds.each_pair { |provider, credsets_inner|
262
110
  credsets_inner.keys.each { |credset|
263
- next if credsused and !credsused.include?(credset)
111
+ next if @credsused and !@credsused.include?(credset)
264
112
  ["Habitat", "Folder"].each { |t|
265
113
  flags = {
266
114
  "onlycloud" => @onlycloud,
267
115
  "skipsnapshots" => @skipsnapshots
268
116
  }
269
- if !self.call_cleanup(t, credset, provider, flags, nil)
117
+ if !call_cleanup(t, credset, provider, flags, nil)
270
118
  had_failures = true
271
119
  end
272
120
  }
273
121
  }
274
122
  }
275
123
 
276
- MU::Cloud::Google.removeDeploySecretsAndRoles(MU.deploy_id)
277
- # XXX port AWS equivalent behavior and add a MU::Cloud wrapper
278
-
279
124
  creds.each_pair { |provider, credsets_inner|
280
- cloudclass = Object.const_get("MU").const_get("Cloud").const_get(provider)
125
+ cloudclass = MU::Cloud.cloudClass(provider)
281
126
  credsets_inner.keys.each { |c|
282
127
  cloudclass.cleanDeploy(MU.deploy_id, credentials: c, noop: @noop)
283
128
  }
@@ -285,44 +130,16 @@ module MU
285
130
  end
286
131
 
287
132
  # Scrub any residual Chef records with matching tags
288
- if !@onlycloud and (@mommacat.nil? or @mommacat.numKittens(types: ["Server", "ServerPool"]) > 0) and !(Gem.paths and Gem.paths.home and !Dir.exist?("/opt/mu/lib"))
289
- begin
290
- MU::Groomer::Chef.loadChefLib
291
- if File.exist?(Etc.getpwuid(Process.uid).dir+"/.chef/knife.rb")
292
- Chef::Config.from_file(Etc.getpwuid(Process.uid).dir+"/.chef/knife.rb")
293
- end
294
- deadnodes = []
295
- Chef::Config[:environment] = MU.environment
296
- q = Chef::Search::Query.new
297
- begin
298
- q.search("node", "tags_MU-ID:#{MU.deploy_id}").each { |item|
299
- next if item.is_a?(Integer)
300
- item.each { |node|
301
- deadnodes << node.name
302
- }
303
- }
304
- rescue Net::HTTPServerException
305
- end
306
-
307
- begin
308
- q.search("node", "name:#{MU.deploy_id}-*").each { |item|
309
- next if item.is_a?(Integer)
310
- item.each { |node|
311
- deadnodes << node.name
312
- }
313
- }
314
- rescue Net::HTTPServerException
315
- end
316
- MU.log "Missed some Chef resources in node cleanup, purging now", MU::NOTICE if deadnodes.size > 0
317
- deadnodes.uniq.each { |node|
318
- MU::Groomer::Chef.cleanup(node, [], noop)
319
- }
320
- rescue LoadError
321
- end
133
+ if !@onlycloud and (@mommacat.nil? or @mommacat.numKittens(types: ["Server", "ServerPool"]) > 0) and !@noop
134
+ MU.supportedGroomers.each { |g|
135
+ groomer = MU::Groomer.loadGroomer(g)
136
+ groomer.cleanup(MU.deploy_id, @noop)
137
+ }
322
138
  end
323
139
 
324
140
  if had_failures
325
141
  MU.log "Had cleanup failures, exiting", MU::ERR
142
+ File.unlink("#{deploy_dir}/.cleanup") if !@noop
326
143
  exit 1
327
144
  end
328
145
 
@@ -330,134 +147,210 @@ module MU
330
147
  @mommacat.purge!
331
148
  end
332
149
 
333
- myhome = Etc.getpwuid(Process.uid).dir
334
- sshdir = "#{myhome}/.ssh"
335
- sshconf = "#{sshdir}/config"
336
- ssharchive = "#{sshdir}/archive"
337
-
338
- Dir.mkdir(sshdir, 0700) if !Dir.exist?(sshdir) and !@noop
339
- Dir.mkdir(ssharchive, 0700) if !Dir.exist?(ssharchive) and !@noop
150
+ if !@onlycloud
151
+ MU::Master.purgeDeployFromSSH(MU.deploy_id, noop: @noop)
152
+ end
340
153
 
341
- keyname = "deploy-#{MU.deploy_id}"
342
- if File.exist?("#{sshdir}/#{keyname}")
343
- MU.log "Moving #{sshdir}/#{keyname} to #{ssharchive}/#{keyname}"
344
- if !@noop
345
- File.rename("#{sshdir}/#{keyname}", "#{ssharchive}/#{keyname}")
346
- end
154
+ if !@noop and !@skipcloud and (@mommacat.nil? or @mommacat.numKittens(types: ["Server", "ServerPool"]) > 0)
155
+ # MU::Master.syncMonitoringConfig
347
156
  end
348
157
 
349
- if File.exist?(sshconf) and File.open(sshconf).read.match(/\/deploy\-#{MU.deploy_id}$/)
350
- MU.log "Expunging #{MU.deploy_id} from #{sshconf}"
351
- if !@noop
352
- FileUtils.copy(sshconf, "#{ssharchive}/config-#{MU.deploy_id}")
353
- File.open(sshconf, File::CREAT|File::RDWR, 0600) { |f|
354
- f.flock(File::LOCK_EX)
355
- newlines = Array.new
356
- delete_block = false
357
- f.readlines.each { |line|
358
- if line.match(/^Host #{MU.deploy_id}\-/)
359
- delete_block = true
360
- elsif line.match(/^Host /)
361
- delete_block = false
362
- end
363
- newlines << line if !delete_block
364
- }
365
- f.rewind
366
- f.truncate(0)
367
- f.puts(newlines)
368
- f.flush
369
- f.flock(File::LOCK_UN)
158
+ end
159
+
160
+ def self.listUsedCredentials(credsets)
161
+ creds = {}
162
+ MU::Cloud.availableClouds.each { |cloud|
163
+ cloudclass = MU::Cloud.cloudClass(cloud)
164
+ if $MU_CFG[cloud.downcase] and $MU_CFG[cloud.downcase].size > 0
165
+ creds[cloud] ||= {}
166
+ cloudclass.listCredentials.each { |credset|
167
+ next if credsets and credsets.size > 0 and !credsets.include?(credset)
168
+ next if @credsused and @credsused.size > 0 and !@credsused.include?(credset)
169
+ MU.log "Will scan #{cloud} with credentials #{credset}"
170
+ creds[cloud][credset] = cloudclass.listRegions(credentials: credset)
370
171
  }
172
+ else
173
+ if cloudclass.hosted?
174
+ creds[cloud] ||= {}
175
+ creds[cloud]["#default"] = cloudclass.listRegions
176
+ end
371
177
  end
372
- end
373
-
374
- # XXX refactor with above? They're similar, ish.
375
- hostsfile = "/etc/hosts"
376
- if File.open(hostsfile).read.match(/ #{MU.deploy_id}\-/)
377
- if Process.uid == 0
378
- MU.log "Expunging traces of #{MU.deploy_id} from #{hostsfile}"
379
- if !@noop
380
- FileUtils.copy(hostsfile, "#{hostsfile}.cleanup-#{deploy_id}")
381
- File.open(hostsfile, File::CREAT|File::RDWR, 0644) { |f|
382
- f.flock(File::LOCK_EX)
383
- newlines = Array.new
384
- f.readlines.each { |line|
385
- newlines << line if !line.match(/ #{MU.deploy_id}\-/)
386
- }
387
- f.rewind
388
- f.truncate(0)
389
- f.puts(newlines)
390
- f.flush
391
- f.flock(File::LOCK_UN)
392
- }
178
+ }
179
+ creds
180
+ end
181
+ private_class_method :listUsedCredentials
182
+
183
+ def self.cleanCloud(cloud, habitats, regions, credsets)
184
+ cloudclass = MU::Cloud.cloudClass(cloud)
185
+ credsets.each_pair { |credset, acct_regions|
186
+ next if @credsused and !@credsused.include?(credset)
187
+ global_vs_region_semaphore = Mutex.new
188
+ global_done = {}
189
+ regionthreads = []
190
+ acct_regions.each { |r|
191
+ if @regionsused
192
+ if @regionsused.size > 0
193
+ next if !@regionsused.include?(r)
194
+ else
195
+ next if r != cloudclass.myRegion(credset)
196
+ end
393
197
  end
394
- else
395
- MU.log "Residual /etc/hosts entries for #{MU.deploy_id} must be removed by root user", MU::WARN
198
+ if regions and !regions.empty?
199
+ next if !regions.include?(r)
200
+ MU.log "Checking for #{cloud}/#{credset} resources from #{MU.deploy_id} in #{r}...", MU::NOTICE
201
+ end
202
+ regionthreads << Thread.new {
203
+ Thread.abort_on_exception = false
204
+ MU.setVar("curRegion", r)
205
+ cleanRegion(cloud, credset, r, global_vs_region_semaphore, global_done, habitats)
206
+ } # regionthreads << Thread.new {
207
+ } # acct_regions.each { |r|
208
+ regionthreads.each do |t|
209
+ t.join
396
210
  end
397
- end
211
+ }
212
+ end
213
+ private_class_method :cleanCloud
398
214
 
399
- if !@noop and !@skipcloud
400
- if $MU_CFG['aws'] and $MU_CFG['aws']['account_number']
401
- MU::Cloud::AWS.s3(region: MU.myRegion).delete_object(
402
- bucket: MU.adminBucketName,
403
- key: "#{MU.deploy_id}-secret"
404
- )
405
- end
406
- if $MU_CFG['google'] and $MU_CFG['google']['project']
407
- begin
408
- MU::Cloud::Google.storage.delete_object(
409
- MU.adminBucketName,
410
- "#{MU.deploy_id}-secret"
411
- )
412
- rescue ::Google::Apis::ClientError => e
413
- raise e if !e.message.match(/^notFound: /)
414
- end
215
+ def self.cleanRegion(cloud, credset, region, global_vs_region_semaphore, global_done, habitats)
216
+ had_failures = false
217
+ cloudclass = MU::Cloud.cloudClass(cloud)
218
+ habitatclass = MU::Cloud.resourceClass(cloud, "Habitat")
219
+
220
+ projects = []
221
+ if habitats
222
+ projects = habitats
223
+ else
224
+ if $MU_CFG and $MU_CFG[cloud.downcase] and
225
+ $MU_CFG[cloud.downcase][credset] and
226
+ $MU_CFG[cloud.downcase][credset]["project"]
227
+ # XXX GCP credential schema needs an array for projects
228
+ projects << $MU_CFG[cloud.downcase][credset]["project"]
415
229
  end
416
- if MU.myCloud == "AWS"
417
- MU::Cloud::AWS.openFirewallForClients # XXX add the other clouds, or abstract
230
+ begin
231
+ projects.concat(cloudclass.listHabitats(credset, use_cache: false))
232
+ rescue NoMethodError
418
233
  end
419
234
  end
420
235
 
421
- if !@noop and !@skipcloud and (@mommacat.nil? or @mommacat.numKittens(types: ["Server", "ServerPool"]) > 0)
422
- # MU::MommaCat.syncMonitoringConfig
236
+ if projects == []
237
+ projects << "" # dummy
238
+ MU.log "Checking for #{cloud}/#{credset} resources from #{MU.deploy_id} in #{region}", MU::NOTICE
239
+ end
240
+ projects.uniq!
241
+
242
+ # We do these in an order that unrolls dependent resources
243
+ # sensibly, and we hit :Collection twice because AWS
244
+ # CloudFormation sometimes fails internally.
245
+ projectthreads = []
246
+ projects.each { |project|
247
+ if habitats and !habitats.empty? and project != ""
248
+ next if !habitats.include?(project)
249
+ end
250
+ if @habitatsused and !@habitatsused.empty? and project != ""
251
+ next if !@habitatsused.include?(project)
252
+ end
253
+ next if !habitatclass.isLive?(project, credset)
254
+
255
+ projectthreads << Thread.new {
256
+ Thread.abort_on_exception = false
257
+ if !cleanHabitat(cloud, credset, region, project, global_vs_region_semaphore, global_done)
258
+ had_failures = true
259
+ end
260
+ } # TYPES_IN_ORDER.each { |t|
261
+ } # projects.each { |project|
262
+ projectthreads.each do |t|
263
+ t.join
423
264
  end
424
265
 
266
+ had_failures
425
267
  end
268
+ private_class_method :cleanRegion
269
+
270
+ def self.cleanHabitat(cloud, credset, region, habitat, global_vs_region_semaphore, global_done)
271
+ had_failures = false
272
+ if habitat != ""
273
+ MU.log "Checking for #{cloud}/#{credset} resources from #{MU.deploy_id} in #{region}, habitat #{habitat}", MU::NOTICE
274
+ end
426
275
 
427
- private
276
+ flags = {
277
+ "habitat" => habitat,
278
+ "onlycloud" => @onlycloud,
279
+ "skipsnapshots" => @skipsnapshots,
280
+ }
281
+ TYPES_IN_ORDER.each { |t|
282
+ begin
283
+ skipme = false
284
+ global_vs_region_semaphore.synchronize {
285
+ if MU::Cloud.resourceClass(cloud, t).isGlobal?
286
+ global_done[habitat] ||= []
287
+ if !global_done[habitat].include?(t)
288
+ global_done[habitat] << t
289
+ flags['global'] = true
290
+ else
291
+ skipme = true
292
+ end
293
+ end
294
+ }
295
+ next if skipme
296
+ rescue MU::Cloud::MuDefunctHabitat, MU::Cloud::MuCloudResourceNotImplemented
297
+ next
298
+ rescue MU::MuError, NoMethodError => e
299
+ MU.log "While checking mu/providers/#{cloud.downcase}/#{cloudclass.cfg_name} for global-ness in cleanup: "+e.message, MU::WARN
300
+ next
301
+ rescue ::Aws::EC2::Errors::AuthFailure, ::Google::Apis::ClientError => e
302
+ MU.log e.message+" in "+region, MU::ERR
303
+ next
304
+ end
428
305
 
306
+ begin
307
+ if !call_cleanup(t, credset, cloud, flags, region)
308
+ had_failures = true
309
+ end
310
+ rescue MU::Cloud::MuDefunctHabitat, MU::Cloud::MuCloudResourceNotImplemented
311
+ next
312
+ end
313
+ }
314
+ had_failures = true
315
+ end
316
+ private_class_method :cleanHabitat
317
+
318
+ # Wrapper for dynamically invoking resource type cleanup methods.
319
+ # @param type [String]:
320
+ # @param credset [String]:
321
+ # @param provider [String]:
322
+ # @param flags [Hash]:
323
+ # @param region [String]:
429
324
  def self.call_cleanup(type, credset, provider, flags, region)
430
325
  if @mommacat.nil? or @mommacat.numKittens(types: [type]) > 0
431
326
  if @mommacat
327
+
432
328
  found = @mommacat.findLitterMate(type: type, return_all: true, credentials: credset)
433
- flags['known'] ||= []
434
- if found.is_a?(Array)
435
- found.each { |k|
436
- flags['known'] << k.cloud_id
437
- }
438
- elsif found and found.is_a?(Hash)
439
- flags['known'] << found['cloud_id']
440
- elsif found
441
- flags['known'] << found.cloud_id
329
+
330
+ if found
331
+ flags['known'] = if found.is_a?(Array)
332
+ found.map { |k| k.cloud_id }
333
+ elsif found.is_a?(Hash)
334
+ found.each_value.map { |k| k.cloud_id }
335
+ else
336
+ [found.cloud_id]
337
+ end
442
338
  end
443
339
  end
444
- # begin
445
- resclass = Object.const_get("MU").const_get("Cloud").const_get(type)
446
-
447
- resclass.cleanup(
448
- noop: @noop,
449
- ignoremaster: @ignoremaster,
450
- region: region,
451
- cloud: provider,
452
- flags: flags,
453
- credentials: credset
454
- )
455
- # rescue ::Seahorse::Client::NetworkingError => e
456
- # MU.log "Service not available in AWS region #{r}, skipping", MU::DEBUG, details: e.message
457
- # end
340
+
341
+ MU::Cloud.loadBaseType(type).cleanup(
342
+ noop: @noop,
343
+ ignoremaster: @ignoremaster,
344
+ region: region,
345
+ cloud: provider,
346
+ flags: flags,
347
+ credentials: credset
348
+ )
458
349
  else
459
350
  true
460
351
  end
461
352
  end
353
+ private_class_method :call_cleanup
354
+
462
355
  end #class
463
356
  end #module