cloud-mu 1.9.0.pre.beta → 2.0.0.pre.alpha

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 (114) hide show
  1. checksums.yaml +4 -4
  2. data/Berksfile +16 -54
  3. data/Berksfile.lock +14 -62
  4. data/bin/mu-aws-setup +131 -108
  5. data/bin/mu-configure +311 -74
  6. data/bin/mu-gcp-setup +84 -62
  7. data/bin/mu-load-config.rb +46 -2
  8. data/bin/mu-self-update +11 -9
  9. data/bin/mu-upload-chef-artifacts +4 -4
  10. data/{mu.gemspec → cloud-mu.gemspec} +2 -2
  11. data/cookbooks/awscli/Berksfile +8 -0
  12. data/cookbooks/mu-activedirectory/Berksfile +11 -0
  13. data/cookbooks/mu-firewall/Berksfile +9 -0
  14. data/cookbooks/mu-firewall/metadata.rb +1 -1
  15. data/cookbooks/mu-glusterfs/Berksfile +10 -0
  16. data/cookbooks/mu-jenkins/Berksfile +14 -0
  17. data/cookbooks/mu-master/Berksfile +23 -0
  18. data/cookbooks/mu-master/attributes/default.rb +1 -1
  19. data/cookbooks/mu-master/metadata.rb +2 -2
  20. data/cookbooks/mu-master/recipes/default.rb +1 -1
  21. data/cookbooks/mu-master/recipes/init.rb +7 -3
  22. data/cookbooks/mu-master/recipes/ssl-certs.rb +1 -0
  23. data/cookbooks/mu-mongo/Berksfile +10 -0
  24. data/cookbooks/mu-openvpn/Berksfile +11 -0
  25. data/cookbooks/mu-php54/Berksfile +13 -0
  26. data/cookbooks/mu-splunk/Berksfile +10 -0
  27. data/cookbooks/mu-tools/Berksfile +21 -0
  28. data/cookbooks/mu-tools/files/default/Mu_CA.pem +15 -15
  29. data/cookbooks/mu-utility/Berksfile +9 -0
  30. data/cookbooks/mu-utility/metadata.rb +2 -1
  31. data/cookbooks/nagios/Berksfile +7 -4
  32. data/cookbooks/s3fs/Berksfile +9 -0
  33. data/environments/dev.json +6 -6
  34. data/environments/prod.json +6 -6
  35. data/modules/mu.rb +20 -42
  36. data/modules/mu/cleanup.rb +102 -100
  37. data/modules/mu/cloud.rb +90 -28
  38. data/modules/mu/clouds/aws.rb +449 -218
  39. data/modules/mu/clouds/aws/alarm.rb +29 -17
  40. data/modules/mu/clouds/aws/cache_cluster.rb +78 -64
  41. data/modules/mu/clouds/aws/collection.rb +25 -18
  42. data/modules/mu/clouds/aws/container_cluster.rb +73 -66
  43. data/modules/mu/clouds/aws/database.rb +124 -116
  44. data/modules/mu/clouds/aws/dnszone.rb +27 -20
  45. data/modules/mu/clouds/aws/firewall_rule.rb +30 -22
  46. data/modules/mu/clouds/aws/folder.rb +18 -3
  47. data/modules/mu/clouds/aws/function.rb +77 -23
  48. data/modules/mu/clouds/aws/group.rb +19 -12
  49. data/modules/mu/clouds/aws/habitat.rb +153 -0
  50. data/modules/mu/clouds/aws/loadbalancer.rb +59 -52
  51. data/modules/mu/clouds/aws/log.rb +30 -23
  52. data/modules/mu/clouds/aws/msg_queue.rb +29 -20
  53. data/modules/mu/clouds/aws/notifier.rb +222 -0
  54. data/modules/mu/clouds/aws/role.rb +178 -90
  55. data/modules/mu/clouds/aws/search_domain.rb +40 -24
  56. data/modules/mu/clouds/aws/server.rb +169 -137
  57. data/modules/mu/clouds/aws/server_pool.rb +60 -83
  58. data/modules/mu/clouds/aws/storage_pool.rb +59 -31
  59. data/modules/mu/clouds/aws/user.rb +36 -27
  60. data/modules/mu/clouds/aws/userdata/linux.erb +101 -93
  61. data/modules/mu/clouds/aws/vpc.rb +250 -189
  62. data/modules/mu/clouds/azure.rb +132 -0
  63. data/modules/mu/clouds/cloudformation.rb +65 -1
  64. data/modules/mu/clouds/cloudformation/alarm.rb +8 -0
  65. data/modules/mu/clouds/cloudformation/cache_cluster.rb +7 -0
  66. data/modules/mu/clouds/cloudformation/collection.rb +7 -0
  67. data/modules/mu/clouds/cloudformation/database.rb +7 -0
  68. data/modules/mu/clouds/cloudformation/dnszone.rb +7 -0
  69. data/modules/mu/clouds/cloudformation/firewall_rule.rb +9 -2
  70. data/modules/mu/clouds/cloudformation/loadbalancer.rb +7 -0
  71. data/modules/mu/clouds/cloudformation/log.rb +7 -0
  72. data/modules/mu/clouds/cloudformation/server.rb +7 -0
  73. data/modules/mu/clouds/cloudformation/server_pool.rb +7 -0
  74. data/modules/mu/clouds/cloudformation/vpc.rb +7 -0
  75. data/modules/mu/clouds/google.rb +214 -110
  76. data/modules/mu/clouds/google/container_cluster.rb +42 -24
  77. data/modules/mu/clouds/google/database.rb +15 -6
  78. data/modules/mu/clouds/google/firewall_rule.rb +17 -25
  79. data/modules/mu/clouds/google/group.rb +13 -5
  80. data/modules/mu/clouds/google/habitat.rb +105 -0
  81. data/modules/mu/clouds/google/loadbalancer.rb +28 -20
  82. data/modules/mu/clouds/google/server.rb +93 -354
  83. data/modules/mu/clouds/google/server_pool.rb +18 -10
  84. data/modules/mu/clouds/google/user.rb +22 -14
  85. data/modules/mu/clouds/google/vpc.rb +97 -69
  86. data/modules/mu/config.rb +133 -38
  87. data/modules/mu/config/alarm.rb +25 -0
  88. data/modules/mu/config/cache_cluster.rb +5 -3
  89. data/modules/mu/config/cache_cluster.yml +23 -0
  90. data/modules/mu/config/database.rb +25 -16
  91. data/modules/mu/config/database.yml +3 -3
  92. data/modules/mu/config/function.rb +1 -2
  93. data/modules/mu/config/{project.rb → habitat.rb} +10 -10
  94. data/modules/mu/config/notifier.rb +85 -0
  95. data/modules/mu/config/notifier.yml +9 -0
  96. data/modules/mu/config/role.rb +1 -1
  97. data/modules/mu/config/search_domain.yml +2 -2
  98. data/modules/mu/config/server.rb +13 -1
  99. data/modules/mu/config/server.yml +3 -3
  100. data/modules/mu/config/server_pool.rb +3 -1
  101. data/modules/mu/config/storage_pool.rb +3 -1
  102. data/modules/mu/config/storage_pool.yml +19 -0
  103. data/modules/mu/config/vpc.rb +70 -8
  104. data/modules/mu/groomers/chef.rb +2 -3
  105. data/modules/mu/kittens.rb +500 -122
  106. data/modules/mu/master.rb +5 -5
  107. data/modules/mu/mommacat.rb +151 -91
  108. data/modules/tests/super_complex_bok.yml +12 -0
  109. data/modules/tests/super_simple_bok.yml +12 -0
  110. data/spec/mu/clouds/azure_spec.rb +82 -0
  111. data/spec/spec_helper.rb +105 -0
  112. metadata +26 -5
  113. data/modules/mu/clouds/aws/notification.rb +0 -139
  114. data/modules/mu/config/notification.rb +0 -44
@@ -39,14 +39,7 @@ module MU
39
39
  deploydata = describe[2]
40
40
  @config['availability_zone'] = deploydata['zone']
41
41
  else
42
- @mu_name ||=
43
- if @config and @config['engine'] and @config["engine"].match(/^sqlserver/)
44
- @deploy.getResourceName(@config["name"], max_length: 15)
45
- else
46
- @deploy.getResourceName(@config["name"], max_length: 63)
47
- end
48
-
49
- @mu_name.gsub(/(--|-$)/i, "").gsub(/(_)/, "-").gsub!(/^[^a-z]/i, "")
42
+ @mu_name ||= @deploy.getResourceName(@config["name"], max_length: 40)
50
43
  end
51
44
  end
52
45
 
@@ -64,6 +57,14 @@ module MU
64
57
 
65
58
  @config['availability_zone'] ||= MU::Cloud::Google.listAZs(@config['region']).sample
66
59
 
60
+ if @vpc.nil? and @config['vpc'] and @config['vpc']['vpc_name']
61
+ @vpc = @deploy.findLitterMate(name: @config['vpc']['vpc_name'], type: "vpcs")
62
+ end
63
+
64
+ if !@vpc
65
+ raise MuError, "ContainerCluster #{@config['name']} unable to locate its resident VPC from #{@config['vpc']}"
66
+ end
67
+
67
68
  subnet = nil
68
69
  @vpc.subnets.each { |s|
69
70
  if s.az == @config['region']
@@ -71,12 +72,14 @@ module MU
71
72
  break
72
73
  end
73
74
  }
74
-
75
+ puts @config['credentials']
75
76
  service_acct = MU::Cloud::Google::Server.createServiceAccount(
76
77
  @mu_name.downcase,
77
- project: @config['project']
78
+ @deploy,
79
+ project: @config['project'],
80
+ credentials: @config['credentials']
78
81
  )
79
- MU::Cloud::Google.grantDeploySecretAccess(service_acct.email)
82
+ MU::Cloud::Google.grantDeploySecretAccess(service_acct.email, credentials: @config['credentials'])
80
83
 
81
84
  @config['ssh_user'] ||= "mu"
82
85
 
@@ -118,7 +121,9 @@ module MU
118
121
  )
119
122
 
120
123
  MU.log "Creating GKE cluster #{@mu_name.downcase}", details: desc
121
- cluster = MU::Cloud::Google.container.create_cluster(
124
+ pp @vpc.subnets.map { |x| x.config['name'] }
125
+ pp requestobj
126
+ cluster = MU::Cloud::Google.container(credentials: @config['credentials']).create_cluster(
122
127
  @config['project'],
123
128
  @config['availability_zone'],
124
129
  requestobj
@@ -126,7 +131,7 @@ module MU
126
131
 
127
132
  resp = nil
128
133
  begin
129
- resp = MU::Cloud::Google.container.get_zone_cluster(@config["project"], @config['availability_zone'], @mu_name.downcase)
134
+ resp = MU::Cloud::Google.container(credentials: @config['credentials']).get_zone_cluster(@config["project"], @config['availability_zone'], @mu_name.downcase)
130
135
  sleep 30 if resp.status != "RUNNING"
131
136
  end while resp.nil? or resp.status != "RUNNING"
132
137
  # labelCluster # XXX need newer API release
@@ -142,14 +147,15 @@ module MU
142
147
  # @param tag_value [String]: The value of the tag specified by tag_key to match when searching by tag.
143
148
  # @param flags [Hash]: Optional flags
144
149
  # @return [Array<Hash<String,OpenStruct>>]: The cloud provider's complete descriptions of matching ContainerClusters
145
- def self.find(cloud_id: nil, region: MU.curRegion, tag_key: "Name", tag_value: nil, flags: {})
150
+ def self.find(cloud_id: nil, region: MU.curRegion, tag_key: "Name", tag_value: nil, flags: {}, credentials: nil)
151
+ flags["project"] ||= MU::Cloud::Google.defaultProject(credentials)
146
152
  end
147
153
 
148
154
  # Called automatically by {MU::Deploy#createResources}
149
155
  def groom
150
156
  deploydata = describe[2]
151
157
  @config['availability_zone'] ||= deploydata['zone']
152
- resp = MU::Cloud::Google.container.get_zone_cluster(@config["project"], @config['availability_zone'], @mu_name.downcase)
158
+ resp = MU::Cloud::Google.container(credentials: @config['credentials']).get_zone_cluster(@config["project"], @config['availability_zone'], @mu_name.downcase)
153
159
  # pp resp
154
160
 
155
161
  # labelCluster # XXX need newer API release
@@ -176,32 +182,44 @@ module MU
176
182
 
177
183
  # Register a description of this cluster instance with this deployment's metadata.
178
184
  def notify
179
- desc = MU.structToHash(MU::Cloud::Google.container.get_zone_cluster(@config["project"], @config['availability_zone'], @mu_name.downcase))
185
+ desc = MU.structToHash(MU::Cloud::Google.container(credentials: @config['credentials']).get_zone_cluster(@config["project"], @config['availability_zone'], @mu_name.downcase))
180
186
  desc["project"] = @config['project']
181
187
  desc["cloud_id"] = @cloud_id
182
188
  desc["mu_name"] = @mu_name.downcase
183
189
  desc
184
190
  end
185
191
 
192
+ # Does this resource type exist as a global (cloud-wide) artifact, or
193
+ # is it localized to a region/zone?
194
+ # @return [Boolean]
195
+ def self.isGlobal?
196
+ false
197
+ end
198
+
186
199
  # Called by {MU::Cleanup}. Locates resources that were created by the
187
200
  # currently-loaded deployment, and purges them.
188
201
  # @param noop [Boolean]: If true, will only print what would be done
189
202
  # @param ignoremaster [Boolean]: If true, will remove resources not flagged as originating from this Mu server
190
203
  # @param region [String]: The cloud provider region in which to operate
191
204
  # @return [void]
192
- def self.cleanup(skipsnapshots: false, noop: false, ignoremaster: false, region: MU.curRegion, flags: {})
193
- flags["project"] ||= MU::Cloud::Google.defaultProject
205
+ def self.cleanup(noop: false, ignoremaster: false, region: MU.curRegion, credentials: nil, flags: {})
206
+ skipsnapshots = flags["skipsnapshots"]
207
+
208
+ flags["project"] ||= MU::Cloud::Google.defaultProject(credentials)
194
209
  MU::Cloud::Google.listAZs(region).each { |az|
195
- found = MU::Cloud::Google.container.list_zone_clusters(flags["project"], az)
196
- #filter: "description eq #{MU.deploy_id}"
210
+ found = MU::Cloud::Google.container(credentials: credentials).list_zone_clusters(flags["project"], az)
197
211
  if found and found.clusters
198
212
  found.clusters.each { |cluster|
199
- next if !cluster.name.match(/^#{Regexp.quote(MU.deploy_id)}\-/i)
213
+
214
+ if !cluster.name.match(/^#{Regexp.quote(MU.deploy_id)}\-/i) and
215
+ cluster.resource_labels['mu-id'] != MU.deploy_id.downcase
216
+ next
217
+ end
200
218
  MU.log "Deleting GKE cluster #{cluster.name}"
201
219
  if !noop
202
- MU::Cloud::Google.container.delete_zone_cluster(flags["project"], az, cluster.name)
220
+ MU::Cloud::Google.container(credentials: credentials).delete_zone_cluster(flags["project"], az, cluster.name)
203
221
  begin
204
- MU::Cloud::Google.container.get_zone_cluster(flags["project"], az, cluster.name)
222
+ MU::Cloud::Google.container(credentials: credentials).get_zone_cluster(flags["project"], az, cluster.name)
205
223
  sleep 60
206
224
  rescue ::Google::Apis::ClientError => e
207
225
  if e.message.match(/is currently creating cluster/)
@@ -281,7 +299,7 @@ module MU
281
299
  labelset = MU::Cloud::Google.container(:SetLabelsRequest).new(
282
300
  resource_labels: labels
283
301
  )
284
- MU::Cloud::Google.container.resource_project_zone_cluster_labels(@config["project"], @config['availability_zone'], @mu_name.downcase, labelset)
302
+ MU::Cloud::Google.container(credentials: @config['credentials']).resource_project_zone_cluster_labels(@config["project"], @config['availability_zone'], @mu_name.downcase, labelset)
285
303
  end
286
304
 
287
305
  end #class
@@ -74,7 +74,7 @@ module MU
74
74
  instance_type: "CLOUD_SQL_INSTANCE" # TODO: READ_REPLICA_INSTANCE
75
75
  )
76
76
  pp instance_desc
77
- pp MU::Cloud::Google.sql.insert_instance(@config['project'], instance_desc)
77
+ pp MU::Cloud::Google.sql(credentials: @config['credentials']).insert_instance(@config['project'], instance_desc)
78
78
  end
79
79
 
80
80
  # Locate an existing Database or Databases and return an array containing matching GCP resource descriptors for those that match.
@@ -84,7 +84,8 @@ module MU
84
84
  # @param tag_value [String]: The value of the tag specified by tag_key to match when searching by tag.
85
85
  # @param flags [Hash]: Optional flags
86
86
  # @return [Array<Hash<String,OpenStruct>>]: The cloud provider's complete descriptions of matching Databases
87
- def self.find(cloud_id: nil, region: MU.curRegion, tag_key: "Name", tag_value: nil, flags: {})
87
+ def self.find(cloud_id: nil, region: MU.curRegion, tag_key: "Name", tag_value: nil, flags: {}, credentials: nil)
88
+ flags["project"] ||= MU::Cloud::Google.defaultProject(credentials)
88
89
  end
89
90
 
90
91
  # Called automatically by {MU::Deploy#createResources}
@@ -103,19 +104,27 @@ module MU
103
104
  def allowHost(cidr)
104
105
  end
105
106
 
107
+ # Does this resource type exist as a global (cloud-wide) artifact, or
108
+ # is it localized to a region/zone?
109
+ # @return [Boolean]
110
+ def self.isGlobal?
111
+ false
112
+ end
113
+
106
114
  # Called by {MU::Cleanup}. Locates resources that were created by the
107
115
  # currently-loaded deployment, and purges them.
108
116
  # @param noop [Boolean]: If true, will only print what would be done
109
117
  # @param ignoremaster [Boolean]: If true, will remove resources not flagged as originating from this Mu server
110
118
  # @param region [String]: The cloud provider region in which to operate
111
119
  # @return [void]
112
- def self.cleanup(skipsnapshots: false, noop: false, ignoremaster: false, region: MU.curRegion, flags: {})
113
- flags["project"] ||= MU::Cloud::Google.defaultProject
114
- instances = MU::Cloud::Google.sql.list_instances(flags['project'], filter: %Q{userLabels.mu-id:"#{MU.deploy_id.downcase}"})
120
+ def self.cleanup(noop: false, ignoremaster: false, region: MU.curRegion, credentials: nil, flags: {})
121
+ flags["project"] ||= MU::Cloud::Google.defaultProject(credentials)
122
+ skipsnapshots||= flags["skipsnapshots"]
123
+ instances = MU::Cloud::Google.sql(credentials: credentials).list_instances(flags['project'], filter: %Q{userLabels.mu-id:"#{MU.deploy_id.downcase}"})
115
124
  if instances and instances.items
116
125
  instances.items.each { |instance|
117
126
  MU.log "Deleting Cloud SQL instance #{instance.name}"
118
- MU::Cloud::Google.sql.delete_instance(flags['project'], instance.name) if !noop
127
+ MU::Cloud::Google.sql(credentials: credentials).delete_instance(flags['project'], instance.name) if !noop
119
128
  }
120
129
  end
121
130
  end
@@ -40,9 +40,9 @@ module MU
40
40
  @cloud_id ||= MU::Cloud::Google.nameStr(@mu_name+"-ingress-allow")
41
41
  else
42
42
  if !@vpc.nil?
43
- @mu_name = @deploy.getResourceName(@config['name'], need_unique_string: true)
43
+ @mu_name = @deploy.getResourceName(@config['name'], need_unique_string: true, max_length: 61)
44
44
  else
45
- @mu_name = @deploy.getResourceName(@config['name'])
45
+ @mu_name = @deploy.getResourceName(@config['name'], max_length: 61)
46
46
  end
47
47
  end
48
48
 
@@ -77,7 +77,7 @@ module MU
77
77
 
78
78
  ["ingress", "egress"].each { |dir|
79
79
  if rule[dir] or (dir == "ingress" and !rule.has_key?("egress"))
80
- setname = MU::Cloud::Google.nameStr(@mu_name+"-"+dir+"-"+(rule['deny'] ? "deny" : "allow"))
80
+ setname = @deploy.getResourceName(@mu_name+"-"+dir+"-"+(rule['deny'] ? "deny" : "allow"), max_length: 61).downcase
81
81
  @cloud_id ||= setname
82
82
  allrules[setname] ||= {
83
83
  :name => setname,
@@ -110,7 +110,7 @@ module MU
110
110
  threads << Thread.new {
111
111
  fwobj = MU::Cloud::Google.compute(:Firewall).new(fwdesc)
112
112
  MU.log "Creating firewall #{fwdesc[:name]} in project #{@config['project']}", details: fwobj
113
- resp = MU::Cloud::Google.compute.insert_firewall(@config['project'], fwobj)
113
+ resp = MU::Cloud::Google.compute(credentials: @config['credentials']).insert_firewall(@config['project'], fwobj)
114
114
  # XXX Check for empty (no hosts) sets
115
115
  # MU.log "Can't create empty firewalls in Google Cloud, skipping #{@mu_name}", MU::WARN
116
116
  }
@@ -155,11 +155,11 @@ module MU
155
155
  # @param tag_value [String]: The value of the tag specified by tag_key to match when searching by tag.
156
156
  # @param flags [Hash]: Optional flags
157
157
  # @return [Array<Hash<String,OpenStruct>>]: The cloud provider's complete descriptions of matching FirewallRules
158
- def self.find(cloud_id: nil, region: MU.curRegion, tag_key: "Name", tag_value: nil, flags: {})
159
- flags["project"] ||= MU::Cloud::Google.defaultProject
158
+ def self.find(cloud_id: nil, region: MU.curRegion, tag_key: "Name", tag_value: nil, flags: {}, credentials: nil)
159
+ flags["project"] ||= MU::Cloud::Google.defaultProject(credentials)
160
160
 
161
161
  found = {}
162
- resp = MU::Cloud::Google.compute.list_firewalls(flags["project"])
162
+ resp = MU::Cloud::Google.compute(credentials: credentials).list_firewalls(flags["project"])
163
163
  if resp and resp.items
164
164
  resp.items.each { |fw|
165
165
  next if !cloud_id.nil? and fw.name != cloud_id
@@ -169,15 +169,21 @@ module MU
169
169
  found
170
170
  end
171
171
 
172
+ # Does this resource type exist as a global (cloud-wide) artifact, or
173
+ # is it localized to a region/zone?
174
+ # @return [Boolean]
175
+ def self.isGlobal?
176
+ true
177
+ end
178
+
172
179
  # Remove all security groups (firewall rulesets) associated with the currently loaded deployment.
173
180
  # @param noop [Boolean]: If true, will only print what would be done
174
181
  # @param ignoremaster [Boolean]: If true, will remove resources not flagged as originating from this Mu server
175
182
  # @param region [String]: The cloud provider region
176
183
  # @return [void]
177
- def self.cleanup(noop: false, ignoremaster: false, region: MU.curRegion, flags: {})
178
- flags["project"] ||= MU::Cloud::Google.defaultProject
179
-
180
- MU::Cloud::Google.compute.delete(
184
+ def self.cleanup(noop: false, ignoremaster: false, region: MU.curRegion, credentials: nil, flags: {})
185
+ flags["project"] ||= MU::Cloud::Google.defaultProject(credentials)
186
+ MU::Cloud::Google.compute(credentials: credentials).delete(
181
187
  "firewall",
182
188
  flags["project"],
183
189
  nil,
@@ -247,20 +253,6 @@ module MU
247
253
 
248
254
  private
249
255
 
250
- ########################################################################
251
- # Manufacture an EC2 security group. The second parameter, rules, is an
252
- # "ingress_rules" structure parsed and validated by MU::Config.
253
- ########################################################################
254
- def setRules(rules, add_to_self: false, ingress: true, egress: false)
255
- end
256
-
257
- ########################################################################
258
- # Convert our config languages description of firewall rules into
259
- # Amazon's. This rule structure is as defined in MU::Config.
260
- ########################################################################
261
- def convertToEc2(rules)
262
- end
263
-
264
256
  end #class
265
257
  end #class
266
258
  end
@@ -49,12 +49,19 @@ module MU
49
49
  }
50
50
  end
51
51
 
52
+ # Does this resource type exist as a global (cloud-wide) artifact, or
53
+ # is it localized to a region/zone?
54
+ # @return [Boolean]
55
+ def self.isGlobal?
56
+ true
57
+ end
58
+
52
59
  # Remove all groups associated with the currently loaded deployment.
53
60
  # @param noop [Boolean]: If true, will only print what would be done
54
61
  # @param ignoremaster [Boolean]: If true, will remove resources not flagged as originating from this Mu server
55
62
  # @param region [String]: The cloud provider region
56
63
  # @return [void]
57
- def self.cleanup(noop: false, ignoremaster: false, region: MU.curRegion, flags: {})
64
+ def self.cleanup(noop: false, ignoremaster: false, region: MU.curRegion, credentials: nil, flags: {})
58
65
  end
59
66
 
60
67
  # Locate an existing group group.
@@ -62,7 +69,8 @@ module MU
62
69
  # @param region [String]: The cloud provider region.
63
70
  # @param flags [Hash]: Optional flags
64
71
  # @return [OpenStruct]: The cloud provider's complete descriptions of matching group group.
65
- def self.find(cloud_id: nil, region: MU.curRegion, flags: {})
72
+ def self.find(cloud_id: nil, region: MU.curRegion, credentials: nil, flags: {})
73
+ flags["project"] ||= MU::Cloud::Google.defaultProject(credentials)
66
74
  found = nil
67
75
  found
68
76
  end
@@ -113,7 +121,7 @@ module MU
113
121
 
114
122
  def bind_group
115
123
  bindings = []
116
- ext_policy = MU::Cloud::Google.resource_manager.get_project_iam_policy(
124
+ ext_policy = MU::Cloud::Google.resource_manager(credentials: @config['credentials']).get_project_iam_policy(
117
125
  @config['project']
118
126
  )
119
127
 
@@ -145,12 +153,12 @@ module MU
145
153
  MU.log "Adding group #{@config['name']} to Google Cloud project #{@config['project']}", details: @config['roles']
146
154
 
147
155
  begin
148
- MU::Cloud::Google.resource_manager.set_project_iam_policy(
156
+ MU::Cloud::Google.resource_manager(credentials: @config['credentials']).set_project_iam_policy(
149
157
  @config['project'],
150
158
  req_obj
151
159
  )
152
160
  rescue ::Google::Apis::ClientError => e
153
- if e.message.match(/does not exist/i) and !$MU_CFG['google']['masquerade_as']
161
+ if e.message.match(/does not exist/i) and !MU::Cloud::Google.credConfig(@config['credentials'])['masquerade_as']
154
162
  raise MuError, "Group #{@config['name']} does not exist, and we cannot create Google groups in non-GSuite environments.\nVisit https://groups.google.com to manage groups."
155
163
  end
156
164
  raise e
@@ -0,0 +1,105 @@
1
+ # Copyright:: Copyright (c) 2019 eGlobalTech, Inc., all rights reserved
2
+ #
3
+ # Licensed under the BSD-3 license (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License in the root of the project or at
6
+ #
7
+ # http://egt-labs.com/mu/LICENSE.html
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ module MU
16
+ class Cloud
17
+ class Google
18
+ # Creates an Google project as configured in {MU::Config::BasketofKittens::habitats}
19
+ class Habitat < MU::Cloud::Habitat
20
+ @deploy = nil
21
+ @config = nil
22
+
23
+ attr_reader :mu_name
24
+ attr_reader :config
25
+ attr_reader :cloud_id
26
+
27
+ # @param mommacat [MU::MommaCat]: A {MU::Mommacat} object containing the deploy of which this resource is/will be a member.
28
+ # @param kitten_cfg [Hash]: The fully parsed and resolved {MU::Config} resource descriptor as defined in {MU::Config::BasketofKittens::habitats}
29
+ def initialize(mommacat: nil, kitten_cfg: nil, mu_name: nil, cloud_id: nil)
30
+ @deploy = mommacat
31
+ @config = MU::Config.manxify(kitten_cfg)
32
+ @cloud_id ||= cloud_id
33
+ @mu_name ||= @deploy.getResourceName(@config["name"])
34
+ end
35
+
36
+ # Called automatically by {MU::Deploy#createResources}
37
+ def create
38
+ end
39
+
40
+ # Return the cloud descriptor for the Habitat
41
+ def cloud_desc
42
+ MU::Cloud::Google::Habitat.find(cloud_id: @cloud_id).values.first
43
+ end
44
+
45
+ # Canonical Amazon Resource Number for this resource
46
+ # @return [String]
47
+ def arn
48
+ nil
49
+ end
50
+
51
+ # Return the metadata for this project's configuration
52
+ # @return [Hash]
53
+ def notify
54
+ {
55
+ }
56
+ end
57
+
58
+ # Does this resource type exist as a global (cloud-wide) artifact, or
59
+ # is it localized to a region/zone?
60
+ # @return [Boolean]
61
+ def self.isGlobal?
62
+ true
63
+ end
64
+
65
+ # Remove all Google projects associated with the currently loaded deployment. Try to, anyway.
66
+ # @param noop [Boolean]: If true, will only print what would be done
67
+ # @param ignoremaster [Boolean]: If true, will remove resources not flagged as originating from this Mu server
68
+ # @param region [String]: The cloud provider region
69
+ # @return [void]
70
+ def self.cleanup(noop: false, ignoremaster: false, region: MU.curRegion, credentials: nil, flags: {})
71
+ end
72
+
73
+ # Locate an existing project
74
+ # @param cloud_id [String]: The cloud provider's identifier for this resource.
75
+ # @param region [String]: The cloud provider region.
76
+ # @param flags [Hash]: Optional flags
77
+ # @return [OpenStruct]: The cloud provider's complete descriptions of matching project
78
+ def self.find(cloud_id: nil, region: MU.curRegion, credentials: nil, flags: {})
79
+ {}
80
+ end
81
+
82
+ # Cloud-specific configuration properties.
83
+ # @param config [MU::Config]: The calling MU::Config object
84
+ # @return [Array<Array,Hash>]: List of required fields, and json-schema Hash of cloud-specific configuration parameters for this resource
85
+ def self.schema(config)
86
+ toplevel_required = []
87
+ schema = {
88
+ }
89
+ [toplevel_required, schema]
90
+ end
91
+
92
+ # Cloud-specific pre-processing of {MU::Config::BasketofKittens::habitats}, bare and unvalidated.
93
+ # @param habitat [Hash]: The resource to process and validate
94
+ # @param configurator [MU::Config]: The overall deployment configurator of which this resource is a member
95
+ # @return [Boolean]: True if validation succeeded, False otherwise
96
+ def self.validateConfig(habitat, configurator)
97
+ ok = true
98
+
99
+ ok
100
+ end
101
+
102
+ end
103
+ end
104
+ end
105
+ end
@@ -95,13 +95,13 @@ module MU
95
95
  end
96
96
  if @config['global']
97
97
  MU.log "Creating Global Forwarding Rule #{@mu_name}", MU::NOTICE, details: ruleobj
98
- resp = MU::Cloud::Google.compute.insert_global_forwarding_rule(
98
+ resp = MU::Cloud::Google.compute(credentials: @config['credentials']).insert_global_forwarding_rule(
99
99
  @config['project'],
100
100
  ruleobj
101
101
  )
102
102
  else
103
103
  MU.log "Creating regional Forwarding Rule #{@mu_name} in #{@config['region']}", MU::NOTICE, details: ruleobj
104
- resp = MU::Cloud::Google.compute.insert_forwarding_rule(
104
+ resp = MU::Cloud::Google.compute(credentials: @config['credentials']).insert_forwarding_rule(
105
105
  @config['project'],
106
106
  @config['region'],
107
107
  ruleobj
@@ -119,12 +119,12 @@ module MU
119
119
  # @return [Hash]
120
120
  def notify
121
121
  rules = {}
122
- resp = MU::Cloud::Google.compute.list_global_forwarding_rules(
122
+ resp = MU::Cloud::Google.compute(credentials: @config['credentials']).list_global_forwarding_rules(
123
123
  @config["project"],
124
124
  filter: "description eq #{@deploy.deploy_id}"
125
125
  )
126
126
  if resp.nil? or resp.items.nil? or resp.items.size == 0
127
- resp = MU::Cloud::Google.compute.list_forwarding_rules(
127
+ resp = MU::Cloud::Google.compute(credentials: @config['credentials']).list_forwarding_rules(
128
128
  @config["project"],
129
129
  @config['region'],
130
130
  filter: "description eq #{@deploy.deploy_id}"
@@ -147,17 +147,24 @@ module MU
147
147
  def registerNode(instance_id, targetgroups: nil)
148
148
  end
149
149
 
150
+ # Does this resource type exist as a global (cloud-wide) artifact, or
151
+ # is it localized to a region/zone?
152
+ # @return [Boolean]
153
+ def self.isGlobal?
154
+ true
155
+ end
156
+
150
157
  # Remove all load balancers associated with the currently loaded deployment.
151
158
  # @param noop [Boolean]: If true, will only print what would be done
152
159
  # @param ignoremaster [Boolean]: If true, will remove resources not flagged as originating from this Mu server
153
160
  # @param region [String]: The cloud provider region
154
161
  # @return [void]
155
- def self.cleanup(noop: false, ignoremaster: false, region: MU.curRegion, flags: {})
156
- flags["project"] ||= MU::Cloud::Google.defaultProject
162
+ def self.cleanup(noop: false, ignoremaster: false, region: nil, credentials: nil, flags: {})
163
+ flags["project"] ||= MU::Cloud::Google.defaultProject(credentials)
157
164
 
158
165
  if region
159
166
  ["forwarding_rule", "region_backend_service"].each { |type|
160
- MU::Cloud::Google.compute.delete(
167
+ MU::Cloud::Google.compute(credentials: credentials).delete(
161
168
  type,
162
169
  flags["project"],
163
170
  region,
@@ -168,7 +175,7 @@ module MU
168
175
 
169
176
  if flags['global']
170
177
  ["global_forwarding_rule", "target_http_proxy", "target_https_proxy", "url_map", "backend_service", "health_check", "http_health_check", "https_health_check"].each { |type|
171
- MU::Cloud::Google.compute.delete(
178
+ MU::Cloud::Google.compute(credentials: credentials).delete(
172
179
  type,
173
180
  flags["project"],
174
181
  noop
@@ -296,7 +303,8 @@ module MU
296
303
  # @param tag_value [String]: The value of the tag specified by tag_key to match when searching by tag.
297
304
  # @param flags [Hash]: Optional flags
298
305
  # @return [Array<Hash<String,OpenStruct>>]: The cloud provider's complete descriptions of matching LoadBalancers
299
- def self.find(cloud_id: nil, region: MU.curRegion, tag_key: "Name", tag_value: nil, flags: {})
306
+ def self.find(cloud_id: nil, region: MU.curRegion, tag_key: "Name", tag_value: nil, flags: {}, credentials: nil)
307
+ flags["project"] ||= MU::Cloud::Google.defaultProject(credentials)
300
308
  end
301
309
 
302
310
  private
@@ -312,7 +320,7 @@ module MU
312
320
  default_service: backend.self_link
313
321
  )
314
322
  MU.log "Creating url map #{tg['name']}", details: urlmap_obj
315
- urlmap = MU::Cloud::Google.compute.insert_url_map(
323
+ urlmap = MU::Cloud::Google.compute(credentials: @config['credentials']).insert_url_map(
316
324
  @config['project'],
317
325
  urlmap_obj
318
326
  )
@@ -326,20 +334,20 @@ module MU
326
334
  if tg['proto'] == "HTTP"
327
335
  target_obj = MU::Cloud::Google.compute(:TargetHttpProxy).new(desc)
328
336
  MU.log "Creating http target proxy #{tg['name']}", details: target_obj
329
- MU::Cloud::Google.compute.insert_target_http_proxy(
337
+ MU::Cloud::Google.compute(credentials: @config['credentials']).insert_target_http_proxy(
330
338
  @config['project'],
331
339
  target_obj
332
340
  )
333
341
  else
334
- certdata = @deploy.nodeSSLCerts(self, 2048)
342
+ certdata = @deploy.nodeSSLCerts(self, false, 2048)
335
343
  cert_pem = certdata[0].to_s+File.read("/etc/pki/Mu_CA.pem")
336
- gcpcert = MU::Cloud::Google.createSSLCertificate(@mu_name.downcase+"-"+tg['name'], cert_pem, certdata[1])
344
+ gcpcert = MU::Cloud::Google.createSSLCertificate(@mu_name.downcase+"-"+tg['name'], cert_pem, certdata[1], credentials: @config['credentials'])
337
345
 
338
346
  # TODO we need a method like MU::Cloud::AWS.findSSLCertificate, with option to hunt down an existing one
339
347
  desc[:ssl_certificates] = [gcpcert.self_link]
340
348
  target_obj = MU::Cloud::Google.compute(:TargetHttpsProxy).new(desc)
341
349
  MU.log "Creating https target proxy #{tg['name']}", details: target_obj
342
- MU::Cloud::Google.compute.insert_target_https_proxy(
350
+ MU::Cloud::Google.compute(credentials: @config['credentials']).insert_target_https_proxy(
343
351
  @config['project'],
344
352
  target_obj
345
353
  )
@@ -385,13 +393,13 @@ module MU
385
393
  backend_obj = MU::Cloud::Google.compute(:BackendService).new(desc)
386
394
  MU.log "Creating backend service #{MU::Cloud::Google.nameStr(@deploy.getResourceName(tg["name"]))}", details: backend_obj
387
395
  if @config['private'] and !@config['global']
388
- return MU::Cloud::Google.compute.insert_region_backend_service(
396
+ return MU::Cloud::Google.compute(credentials: @config['credentials']).insert_region_backend_service(
389
397
  @config['project'],
390
398
  @config['region'],
391
399
  backend_obj
392
400
  )
393
401
  else
394
- return MU::Cloud::Google.compute.insert_backend_service(
402
+ return MU::Cloud::Google.compute(credentials: @config['credentials']).insert_backend_service(
395
403
  @config['project'],
396
404
  backend_obj
397
405
  )
@@ -399,7 +407,7 @@ module MU
399
407
  end
400
408
 
401
409
  def createHealthCheck(hc, namebase)
402
- MU.log "HEALTH CHECK", MU::NOTICE, details: hc
410
+ # MU.log "HEALTH CHECK", MU::NOTICE, details: hc
403
411
  target = hc['target'].match(/^([^:]+):(\d+)(.*)/)
404
412
  proto = target[1]
405
413
  port = target[2]
@@ -421,12 +429,12 @@ module MU
421
429
  # type: SSL, HTTP2
422
430
  MU.log "Creating #{proto} health check #{name}", details: hc_obj
423
431
  if proto == "HTTP"
424
- return MU::Cloud::Google.compute.insert_http_health_check(
432
+ return MU::Cloud::Google.compute(credentials: @config['credentials']).insert_http_health_check(
425
433
  @config['project'],
426
434
  hc_obj
427
435
  )
428
436
  else
429
- return MU::Cloud::Google.compute.insert_https_health_check(
437
+ return MU::Cloud::Google.compute(credentials: @config['credentials']).insert_https_health_check(
430
438
  @config['project'],
431
439
  hc_obj
432
440
  )
@@ -466,7 +474,7 @@ module MU
466
474
  end
467
475
  hc_obj = MU::Cloud::Google.compute(:HealthCheck).new(desc)
468
476
  MU.log "INSERTING HEALTH CHECK", MU::NOTICE, details: hc_obj
469
- return MU::Cloud::Google.compute.insert_health_check(
477
+ return MU::Cloud::Google.compute(credentials: @config['credentials']).insert_health_check(
470
478
  @config['project'],
471
479
  hc_obj
472
480
  )