cloud-mu 2.0.0.pre.alpha3 → 2.0.0.pre.alpha4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 674e427624161a3b7026346a10320e7dcf5331222d8cc683d186c3d648fc0c77
4
- data.tar.gz: 71c6ddb375bf199f767fa2b8143b98f7de422d6095921c5db0d0cf191bac39bb
3
+ metadata.gz: fc4fa3ace543abb312bf853be83b0b229a61cf4cd1dbb00f7a4ac1c383fe2538
4
+ data.tar.gz: 35ed1769840efedaa2b2408e0f0c24c07417c77aeaf8cb43dd11f758970a9d47
5
5
  SHA512:
6
- metadata.gz: 8cac89b0d850377f39635f40aafc4fe148fc6b38c971da05592a55dba83a7f8847c3734eddbdb830724e2cda51c7c3968c38facd22eab15814b892913641b2ab
7
- data.tar.gz: bce36278c7e00872d5f1f553d41f24abf0593d0a8f1bf076e071d472932e1aa727f196a8e34b37dc4ba3465068420305c3079cd472d9c8a26a9ed65edc06ddc0
6
+ metadata.gz: 38feb71676cf984e102f90e41b96849521762f3cf0bcfc2e06af0b69a45e9255b02ff503f84ca27346dedb501e362b07b26be172cec0e4e118302cd9af5853b9
7
+ data.tar.gz: 2cdacd00b476374c45a94dddf0ee5e60b018200dbf58e34510bef8cb0169ea03a7edc1f7726c7f742304687cdeade991b05a71f40cb0326590e1091e757aada1
data/cloud-mu.gemspec CHANGED
@@ -17,7 +17,7 @@ end
17
17
 
18
18
  Gem::Specification.new do |s|
19
19
  s.name = 'cloud-mu'
20
- s.version = '2.0.0-alpha3'
20
+ s.version = '2.0.0-alpha4'
21
21
  s.date = '2018-12-11'
22
22
  s.require_paths = ['modules']
23
23
  s.required_ruby_version = '>= 2.4'
@@ -6,4 +6,4 @@ metadata
6
6
  # Mu Cookbooks
7
7
 
8
8
  # Supermarket Cookbooks
9
- cookbook 'firewall', '~> 2.6.5'
9
+ cookbook 'firewall', '~> 2.7.0'
data/install/installer CHANGED
@@ -4,7 +4,7 @@ BOLD=`tput bold`
4
4
  NORM=`tput sgr0`
5
5
  CHEF_CLIENT_VERSION="14.4.56"
6
6
  if [ "$MU_BRANCH" == "" ];then
7
- MU_BRANCH="i_yam_what_i_yam" # GIT HOOK EDITABLE DO NOT TOUCH
7
+ MU_BRANCH="Azure_you_want_azure" # GIT HOOK EDITABLE DO NOT TOUCH
8
8
  mydir="`dirname $0`"
9
9
  cd $mydir
10
10
  if git rev-parse --abbrev-ref HEAD > /dev/null 2>&1;then
data/modules/mu/cloud.rb CHANGED
@@ -1424,7 +1424,6 @@ MU.log "in dependencies() and findLitterMate gave me "+sib_by_name.to_s+" on beh
1424
1424
  # Wrapper for the cleanup class method of underlying cloud object implementations.
1425
1425
  def self.cleanup(*flags)
1426
1426
  params = flags.first
1427
-
1428
1427
  clouds = MU::Cloud.supportedClouds
1429
1428
  if params[:cloud]
1430
1429
  clouds = [params[:cloud]]
@@ -327,6 +327,11 @@ module MU
327
327
  # cloud.
328
328
  # @return [Boolean]
329
329
  def self.hosted?
330
+ if $MU_CFG.has_key?("aws_is_hosted")
331
+ @@is_in_aws = $MU_CFG["aws_is_hosted"]
332
+ return $MU_CFG["aws_is_hosted"]
333
+ end
334
+
330
335
  require 'open-uri'
331
336
 
332
337
  if !@@is_in_aws.nil?
@@ -514,7 +514,7 @@ module MU
514
514
  sleep 10
515
515
  retry
516
516
  rescue Aws::Route53::Errors::InvalidChangeBatch, Aws::Route53::Errors::InvalidInput, Exception => e
517
- return if e.message.match(/ but it already exists$/) and !delete
517
+ return if e.message.match(/ but it already exists/) and !delete
518
518
  MU.log "Failed to change DNS records, #{e.inspect}", MU::ERR, details: params
519
519
  raise e if !delete
520
520
  MU.log "Record #{name} (#{type}) in #{id} can't be deleted. Already removed? #{e.inspect}", MU::WARN, details: params if delete
@@ -104,14 +104,11 @@ module MU
104
104
 
105
105
  if resp and resp.accounts
106
106
  resp.accounts.each { |acct|
107
- if acct.name.match(/^#{Regexp.quote(MU.deploy_id)}/)
108
- MU.log "Would delete account #{acct.name} if that was a thing"
107
+ if acct.name.match(/^#{Regexp.quote(MU.deploy_id)}/) or acct.name.match(/BUNS/)
109
108
  if !noop
110
109
  pp acct
111
110
  end
112
- else
113
- pp acct if acct.name.match(/BUNS/)
114
- #https://687950501457.signin.aws.amazon.com/console/organizations/complete-signup
111
+ MU.log "AWS accounts cannot be deleted via the API. To delete #{acct.name}, you must sign in with its root user #{acct.email}, ensure that its signup process has been completed, then visit ", MU::NOTICE, details: ["https://console.aws.amazon.com/", acct.email, acct.id]
115
112
  end
116
113
  }
117
114
  end
@@ -31,6 +31,11 @@ module MU
31
31
  # Determine whether we (the Mu master, presumably) are hosted in Azure.
32
32
  # @return [Boolean]
33
33
  def self.hosted?
34
+ if $MU_CFG.has_key?("azure_is_hosted")
35
+ @@is_in_aws = $MU_CFG["azure_is_hosted"]
36
+ return $MU_CFG["azure_is_hosted"]
37
+ end
38
+
34
39
  if !@@is_in_azure.nil?
35
40
  return @@is_in_azure
36
41
  end
@@ -242,6 +242,10 @@ module MU
242
242
  # cloud.
243
243
  # @return [Boolean]
244
244
  def self.hosted?
245
+ if $MU_CFG.has_key?("google_is_hosted")
246
+ @@is_in_aws = $MU_CFG["google_is_hosted"]
247
+ return $MU_CFG["google_is_hosted"]
248
+ end
245
249
  if !@@is_in_gcp.nil?
246
250
  return @@is_in_gcp
247
251
  end
@@ -411,6 +415,8 @@ module MU
411
415
  # Our credentials map to a project, an organizational structure in Google
412
416
  # Cloud. This fetches the identifier of the project associated with our
413
417
  # default credentials.
418
+ # @param credentials [String]
419
+ # @return [String]
414
420
  def self.defaultProject(credentials = nil)
415
421
  cfg = credConfig(credentials)
416
422
  return myProject if !cfg or !cfg['project']
@@ -418,6 +424,21 @@ module MU
418
424
  cfg['project']
419
425
  end
420
426
 
427
+ # We want a default place to put new projects for the Habitat resource,
428
+ # so if we have a root folder, we can go ahead and use that.
429
+ # @param credentials [String]
430
+ # @return [String]
431
+ def self.defaultFolder(credentials = nil)
432
+ project = defaultProject(credentials)
433
+ resp = MU::Cloud::Google.resource_manager(credentials: credentials).get_project_ancestry(project)
434
+ resp.ancestor.each { |a|
435
+ if a.resource_id.type == "folder"
436
+ return a.resource_id.id
437
+ end
438
+ }
439
+ nil
440
+ end
441
+
421
442
  # List all Google Cloud Platform projects available to our credentials
422
443
  def self.listProjects(credentials = nil)
423
444
  cfg = credConfig(credentials)
@@ -575,6 +596,19 @@ module MU
575
596
  end
576
597
  end
577
598
 
599
+ # Google's Cloud Resource Manager API V2, which apparently has all the folder bits
600
+ # @param subclass [<Google::Apis::CloudresourcemanagerV2beta1>]: If specified, will return the class ::Google::Apis::CloudresourcemanagerV2beta1::subclass instead of an API client instance
601
+ def self.folder(subclass = nil, credentials: nil)
602
+ require 'google/apis/cloudresourcemanager_v2beta1'
603
+
604
+ if subclass.nil?
605
+ @@resource2_api[credentials] ||= MU::Cloud::Google::Endpoint.new(api: "CloudresourcemanagerV2beta1::CloudResourceManagerService", scopes: ['https://www.googleapis.com/auth/cloud-platform'], credentials: credentials)
606
+ return @@resource2_api[credentials]
607
+ elsif subclass.is_a?(Symbol)
608
+ return Object.const_get("::Google").const_get("Apis").const_get("CloudresourcemanagerV2beta1").const_get(subclass)
609
+ end
610
+ end
611
+
578
612
  # Google's Container API
579
613
  # @param subclass [<Google::Apis::ContainerV1>]: If specified, will return the class ::Google::Apis::ContainerV1::subclass instead of an API client instance
580
614
  def self.container(subclass = nil, credentials: nil)
@@ -909,6 +943,7 @@ module MU
909
943
  @@iam_api = {}
910
944
  @@logging_api = {}
911
945
  @@resource_api = {}
946
+ @@resource2_api = {}
912
947
  @@service_api = {}
913
948
  @@admin_directory_api = {}
914
949
  end
@@ -0,0 +1,120 @@
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::folders}
19
+ class Folder < MU::Cloud::Folder
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::folders}
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
+
39
+ name_string = @deploy.getResourceName(@config["name"], max_length: 30).downcase
40
+
41
+ folder_obj = MU::Cloud::Google.folder(:Folder).new(
42
+ name: name_string,
43
+ display_name: name_string
44
+ )
45
+ pp folder_obj
46
+ MU.log "Creating folder #{@mu_name}", details: folder_obj
47
+ resp = MU::Cloud::Google.folder(credentials: @config['credentials']).create_folder(folder_obj)
48
+
49
+ @cloud_id = name_string.downcase
50
+ end
51
+
52
+ # Return the cloud descriptor for the Folder
53
+ def cloud_desc
54
+ MU::Cloud::Google::Folder.find(cloud_id: @cloud_id).values.first
55
+ end
56
+
57
+ # Return the metadata for this project's configuration
58
+ # @return [Hash]
59
+ def notify
60
+ desc = MU.structToHash(MU::Cloud::Google.folder(credentials: credentials).get_folder(@cloud_id))
61
+ desc["mu_name"] = @mu_name
62
+ desc["cloud_id"] = @cloud_id
63
+ desc
64
+ end
65
+
66
+ # Does this resource type exist as a global (cloud-wide) artifact, or
67
+ # is it localized to a region/zone?
68
+ # @return [Boolean]
69
+ def self.isGlobal?
70
+ true
71
+ end
72
+
73
+ # Remove all Google projects associated with the currently loaded deployment. Try to, anyway.
74
+ # @param noop [Boolean]: If true, will only print what would be done
75
+ # @param ignoremaster [Boolean]: If true, will remove resources not flagged as originating from this Mu server
76
+ # @param region [String]: The cloud provider region
77
+ # @return [void]
78
+ def self.cleanup(noop: false, ignoremaster: false, region: MU.curRegion, credentials: nil, flags: {})
79
+ end
80
+
81
+ # Locate an existing project
82
+ # @param cloud_id [String]: The cloud provider's identifier for this resource.
83
+ # @param region [String]: The cloud provider region.
84
+ # @param flags [Hash]: Optional flags
85
+ # @return [OpenStruct]: The cloud provider's complete descriptions of matching project
86
+ def self.find(cloud_id: nil, region: MU.curRegion, credentials: nil, flags: {})
87
+ found = {}
88
+ if cloud_id
89
+ found[cloud_id] = MU::Cloud::Google.folder(credentials: credentials).get_folder(cloud_id)
90
+ else
91
+ end
92
+
93
+ found
94
+ end
95
+
96
+ # Cloud-specific configuration properties.
97
+ # @param config [MU::Config]: The calling MU::Config object
98
+ # @return [Array<Array,Hash>]: List of required fields, and json-schema Hash of cloud-specific configuration parameters for this resource
99
+ def self.schema(config)
100
+ toplevel_required = []
101
+ schema = {
102
+ }
103
+ [toplevel_required, schema]
104
+ end
105
+
106
+ # Cloud-specific pre-processing of {MU::Config::BasketofKittens::folders}, bare and unvalidated.
107
+ # @param folder [Hash]: The resource to process and validate
108
+ # @param configurator [MU::Config]: The overall deployment configurator of which this resource is a member
109
+ # @return [Boolean]: True if validation succeeded, False otherwise
110
+ def self.validateConfig(folder, configurator)
111
+ ok = true
112
+
113
+
114
+ ok
115
+ end
116
+
117
+ end
118
+ end
119
+ end
120
+ end
@@ -35,6 +35,31 @@ module MU
35
35
 
36
36
  # Called automatically by {MU::Deploy#createResources}
37
37
  def create
38
+ labels = {}
39
+
40
+ name_string = @deploy.getResourceName(@config["name"], max_length: 30).downcase
41
+
42
+ MU::MommaCat.listStandardTags.each_pair { |name, value|
43
+ if !value.nil?
44
+ labels[name.downcase] = value.downcase.gsub(/[^a-z0-9\-\_]/i, "_")
45
+ end
46
+ }
47
+
48
+ desc = {
49
+ name: name_string,
50
+ project_id: name_string,
51
+ labels: labels
52
+ }
53
+ if @config['folder'] and @config['folder']['id']
54
+ desc["parent"] = @config['folder']['id']
55
+ end
56
+
57
+ project_obj = MU::Cloud::Google.resource_manager(:Project).new(desc)
58
+ pp project_obj
59
+ MU.log "Creating project #{@mu_name}", details: project_obj
60
+ resp = MU::Cloud::Google.resource_manager(credentials: @config['credentials']).create_project(project_obj)
61
+
62
+ @cloud_id = name_string.downcase
38
63
  end
39
64
 
40
65
  # Return the cloud descriptor for the Habitat
@@ -42,17 +67,15 @@ module MU
42
67
  MU::Cloud::Google::Habitat.find(cloud_id: @cloud_id).values.first
43
68
  end
44
69
 
45
- # Canonical Amazon Resource Number for this resource
46
- # @return [String]
47
- def arn
48
- nil
49
- end
50
-
51
70
  # Return the metadata for this project's configuration
52
71
  # @return [Hash]
53
72
  def notify
54
- {
55
- }
73
+ desc = MU.structToHash(MU::Cloud::Google.resource_manager(credentials: credentials).list_projects(
74
+ filter: "name:#{cloud_id}"
75
+ ).projects.first)
76
+ desc["mu_name"] = @mu_name
77
+ desc["cloud_id"] = @cloud_id
78
+ desc
56
79
  end
57
80
 
58
81
  # Does this resource type exist as a global (cloud-wide) artifact, or
@@ -76,7 +99,20 @@ module MU
76
99
  # @param flags [Hash]: Optional flags
77
100
  # @return [OpenStruct]: The cloud provider's complete descriptions of matching project
78
101
  def self.find(cloud_id: nil, region: MU.curRegion, credentials: nil, flags: {})
79
- {}
102
+ found = {}
103
+ if cloud_id
104
+ resp = MU::Cloud::Google.resource_manager(credentials: credentials).list_projects(
105
+ filter: "name:#{cloud_id}"
106
+ ).projects.first
107
+ found[resp.name] = resp
108
+ else
109
+ resp = MU::Cloud::Google.resource_manager(credentials: credentials).list_projects().projects
110
+ resp.each { |p|
111
+ found[p.name] = p
112
+ }
113
+ end
114
+
115
+ found
80
116
  end
81
117
 
82
118
  # Cloud-specific configuration properties.
@@ -96,6 +132,14 @@ module MU
96
132
  def self.validateConfig(habitat, configurator)
97
133
  ok = true
98
134
 
135
+ if habitat['folder'] and habitat['folder']['name'] and !habitat['folder']['deploy_id']
136
+ habitat["dependencies"] ||= []
137
+ habitat["dependencies"] << {
138
+ "type" => "folder",
139
+ "name" => habitat['folder']['name']
140
+ }
141
+ end
142
+
99
143
  ok
100
144
  end
101
145
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cloud-mu
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.0.pre.alpha3
4
+ version: 2.0.0.pre.alpha4
5
5
  platform: ruby
6
6
  authors:
7
7
  - John Stange
@@ -863,6 +863,7 @@ files:
863
863
  - modules/mu/clouds/google/container_cluster.rb
864
864
  - modules/mu/clouds/google/database.rb
865
865
  - modules/mu/clouds/google/firewall_rule.rb
866
+ - modules/mu/clouds/google/folder.rb
866
867
  - modules/mu/clouds/google/group.rb
867
868
  - modules/mu/clouds/google/habitat.rb
868
869
  - modules/mu/clouds/google/loadbalancer.rb