cloud-mu 3.0.1 → 3.0.2
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.
- checksums.yaml +4 -4
- data/bin/mu-configure +7 -1
- data/cloud-mu.gemspec +4 -2
- data/modules/mu/cloud.rb +19 -2
- data/modules/mu/clouds/google/container_cluster.rb +3 -0
- data/modules/mu/clouds/google/firewall_rule.rb +20 -5
- data/modules/mu/clouds/google/server.rb +7 -4
- data/modules/mu/clouds/google/server_pool.rb +3 -0
- data/modules/mu/clouds/google.rb +16 -7
- data/modules/mu/config.rb +11 -1
- data/modules/mu/mommacat.rb +10 -5
- metadata +30 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1d41e45463915304c58cf78023563876314b9877087d44263e0ad3360ab6aea1
|
4
|
+
data.tar.gz: e3926bc8af2bb1cd7d6e2f32fe84e5de21b6073a7e7eda1be908a626f08becd4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 745bd6c7016676750b1306c324eca784821d026a6a255f4e0e33e09d5ca2843501ce3a774fa5cc9dc1b0e6a53270bce0ac79963fe25c1031d7ead2ddb1263c98
|
7
|
+
data.tar.gz: d0bf047ad4aa61a160368daa0a4897fa2904d183f1e478207e93c6e3cacecc1833dab04e9b3d634414298bee5a38ad0987a09e2226df79008b52fc67bac9cc95
|
data/bin/mu-configure
CHANGED
@@ -107,6 +107,12 @@ $CONFIGURABLES = {
|
|
107
107
|
"desc" => "The local system's value for HOSTNAME",
|
108
108
|
"changes" => ["chefrun", "hostname"]
|
109
109
|
},
|
110
|
+
"disable_mommacat" => {
|
111
|
+
"title" => "Disable Momma Cat",
|
112
|
+
"default" => false,
|
113
|
+
"desc" => "Disable the Momma Cat grooming daemon. Nodes which require asynchronous Ansible/Chef bootstraps will not function. This option is only honored in gem-based installations.",
|
114
|
+
"boolean" => true
|
115
|
+
},
|
110
116
|
"mommacat_port" => {
|
111
117
|
"title" => "Momma Cat Listen Port",
|
112
118
|
"pattern" => /^[0-9]+$/i,
|
@@ -804,7 +810,7 @@ if !$NOOP
|
|
804
810
|
# Converts the current $CONFIGURABLES object to a Hash suitable for merging
|
805
811
|
# with $MU_CFG.
|
806
812
|
def setConfigTree(tree = $CONFIGURABLES)
|
807
|
-
cfg = {}
|
813
|
+
cfg = $MU_CFG.nil? ? {} : $MU_CFG.dup
|
808
814
|
tree.each_pair { |key, data|
|
809
815
|
next if !AMROOT and data['rootonly']
|
810
816
|
if data.has_key?("subtree")
|
data/cloud-mu.gemspec
CHANGED
@@ -17,8 +17,8 @@ end
|
|
17
17
|
|
18
18
|
Gem::Specification.new do |s|
|
19
19
|
s.name = 'cloud-mu'
|
20
|
-
s.version = '3.0.
|
21
|
-
s.date = '2019-
|
20
|
+
s.version = '3.0.2'
|
21
|
+
s.date = '2019-12-03'
|
22
22
|
s.require_paths = ['modules']
|
23
23
|
s.required_ruby_version = '>= 2.4'
|
24
24
|
s.summary = "The eGTLabs Mu toolkit for unified cloud deployments"
|
@@ -59,4 +59,6 @@ EOF
|
|
59
59
|
s.add_runtime_dependency 'addressable', '~> 2.5'
|
60
60
|
s.add_runtime_dependency 'slack-notifier', "~> 2.3"
|
61
61
|
s.add_runtime_dependency 'azure_sdk', "~> 0.37"
|
62
|
+
s.add_runtime_dependency 'rack', "~> 2.0"
|
63
|
+
s.add_runtime_dependency 'thin', "~> 1.7"
|
62
64
|
end
|
data/modules/mu/cloud.rb
CHANGED
@@ -1381,8 +1381,16 @@ module MU
|
|
1381
1381
|
if !@config['vpc']["id"].nil? and @config['vpc']["id"].is_a?(Hash)
|
1382
1382
|
@config['vpc']["id"] = MU::Config::Ref.new(@config['vpc']["id"])
|
1383
1383
|
end
|
1384
|
-
if !@config['vpc']["id"].nil?
|
1385
|
-
@vpc
|
1384
|
+
if !@config['vpc']["id"].nil?
|
1385
|
+
if @config['vpc']["id"].is_a?(MU::Config::Ref) and !@config['vpc']["id"].kitten.nil?
|
1386
|
+
@vpc = @config['vpc']["id"].kitten
|
1387
|
+
else
|
1388
|
+
if @config['vpc']['habitat']
|
1389
|
+
@config['vpc']['habitat'] = MU::Config::Ref.get(@config['vpc']['habitat'])
|
1390
|
+
end
|
1391
|
+
vpc_ref = MU::Config::Ref.get(@config['vpc'])
|
1392
|
+
@vpc = vpc_ref.kitten
|
1393
|
+
end
|
1386
1394
|
elsif !@config['vpc']["name"].nil? and @deploy
|
1387
1395
|
MU.log "Attempting findLitterMate on VPC for #{self}", loglevel, details: @config['vpc']
|
1388
1396
|
|
@@ -2054,6 +2062,15 @@ puts "CHOOSING #{@vpc.to_s} 'cause it has #{@config['vpc']['subnet_name']}"
|
|
2054
2062
|
cloudclass.cleanup(params)
|
2055
2063
|
rescue MuCloudResourceNotImplemented
|
2056
2064
|
MU.log "No #{cloud} implementation of #{shortname}.cleanup, skipping", MU::DEBUG, details: flags
|
2065
|
+
rescue Exception => e
|
2066
|
+
in_msg = cloud
|
2067
|
+
if params and params[:region]
|
2068
|
+
in_msg += " "+params[:region]
|
2069
|
+
end
|
2070
|
+
if params and params[:flags] and params[:flags]["project"]
|
2071
|
+
in_msg += " project "+params[:flags]["project"]
|
2072
|
+
end
|
2073
|
+
MU.log "Skipping #{shortname} cleanup method in #{in_msg} due to exception: #{e.message}", MU::WARN
|
2057
2074
|
end
|
2058
2075
|
}
|
2059
2076
|
MU::MommaCat.unlockAll
|
@@ -1044,6 +1044,9 @@ module MU
|
|
1044
1044
|
"credentials" => cluster["credentials"],
|
1045
1045
|
"type" => "service"
|
1046
1046
|
}
|
1047
|
+
if user["name"].length < 6
|
1048
|
+
user["name"] += Password.pronounceable(6)
|
1049
|
+
end
|
1047
1050
|
configurator.insertKitten(user, "users", true)
|
1048
1051
|
cluster['dependencies'] ||= []
|
1049
1052
|
cluster['service_account'] = MU::Config::Ref.get(
|
@@ -45,8 +45,17 @@ module MU
|
|
45
45
|
def create
|
46
46
|
@cloud_id = @mu_name.downcase.gsub(/[^-a-z0-9]/, "-")
|
47
47
|
|
48
|
-
vpc_id =
|
49
|
-
|
48
|
+
vpc_id = if @vpc
|
49
|
+
@vpc.url if !@vpc.nil?
|
50
|
+
else
|
51
|
+
vpc_ref = MU::Config::Ref.get(@config['vpc'])
|
52
|
+
if !vpc_ref.kitten
|
53
|
+
MU.log "Failed to resolve VPC for FirewallRule #{@mu_name}", MU::ERR, details: @config['vpc']
|
54
|
+
raise MuError, "Failed to resolve VPC for FirewallRule #{@mu_name}"
|
55
|
+
else
|
56
|
+
vpc_ref.kitten.url
|
57
|
+
end
|
58
|
+
end
|
50
59
|
|
51
60
|
if vpc_id.nil?
|
52
61
|
raise MuError, "Failed to resolve VPC for #{self}"
|
@@ -419,16 +428,22 @@ end
|
|
419
428
|
# @return [Boolean]: True if validation succeeded, False otherwise
|
420
429
|
def self.validateConfig(acl, config)
|
421
430
|
ok = true
|
422
|
-
acl['project'] ||= MU::Cloud::Google.defaultProject(acl['credentials'])
|
423
431
|
|
424
432
|
if acl['vpc']
|
425
|
-
acl['vpc']['
|
426
|
-
|
433
|
+
if !acl['vpc']['habitat']
|
434
|
+
acl['vpc']['project'] ||= acl['project']
|
435
|
+
elsif acl['vpc']['habitat'] and acl['vpc']['habitat']['id']
|
436
|
+
acl['vpc']['project'] = acl['vpc']['habitat']['id']
|
437
|
+
elsif acl['vpc']['habitat'] and acl['vpc']['habitat']['name']
|
438
|
+
acl['vpc']['project'] = acl['vpc']['habitat']['name']
|
439
|
+
end
|
440
|
+
correct_vpc = MU::Cloud::Google::VPC.pickVPC(
|
427
441
|
acl['vpc'],
|
428
442
|
acl,
|
429
443
|
"firewall_rule",
|
430
444
|
config
|
431
445
|
)
|
446
|
+
acl['vpc'] = correct_vpc if correct_vpc
|
432
447
|
end
|
433
448
|
|
434
449
|
acl['rules'] ||= []
|
@@ -1424,6 +1424,9 @@ next if !create
|
|
1424
1424
|
"credentials" => server["credentials"],
|
1425
1425
|
"type" => "service"
|
1426
1426
|
}
|
1427
|
+
if user["name"].length < 6
|
1428
|
+
user["name"] += Password.pronounceable(6)
|
1429
|
+
end
|
1427
1430
|
if server['roles']
|
1428
1431
|
user['roles'] = server['roles'].dup
|
1429
1432
|
end
|
@@ -1432,13 +1435,13 @@ next if !create
|
|
1432
1435
|
server['service_account'] = MU::Config::Ref.get(
|
1433
1436
|
type: "users",
|
1434
1437
|
cloud: "Google",
|
1435
|
-
name:
|
1436
|
-
project:
|
1437
|
-
credentials:
|
1438
|
+
name: user["name"],
|
1439
|
+
project: user["project"],
|
1440
|
+
credentials: user["credentials"]
|
1438
1441
|
)
|
1439
1442
|
server['dependencies'] << {
|
1440
1443
|
"type" => "user",
|
1441
|
-
"name" =>
|
1444
|
+
"name" => user["name"]
|
1442
1445
|
}
|
1443
1446
|
end
|
1444
1447
|
|
@@ -380,6 +380,9 @@ start = Time.now
|
|
380
380
|
"credentials" => pool["credentials"],
|
381
381
|
"type" => "service"
|
382
382
|
}
|
383
|
+
if user["name"].length < 6
|
384
|
+
user["name"] += Password.pronounceable(6)
|
385
|
+
end
|
383
386
|
configurator.insertKitten(user, "users", true)
|
384
387
|
pool['dependencies'] ||= []
|
385
388
|
pool['service_account'] = MU::Config::Ref.get(
|
data/modules/mu/clouds/google.rb
CHANGED
@@ -165,8 +165,8 @@ module MU
|
|
165
165
|
|
166
166
|
# blow up if this resource *has* to live in a project
|
167
167
|
if cloudobj.cloudclass.canLiveIn == [:Habitat]
|
168
|
-
MU.log "Failed to find project for cloudobj
|
169
|
-
raise MuError, "Failed to find project for cloudobj
|
168
|
+
MU.log "Failed to find project for cloudobj #{cloudobj.to_s}", MU::ERR, details: cloudobj
|
169
|
+
raise MuError, "Failed to find project for cloudobj #{cloudobj.to_s}"
|
170
170
|
end
|
171
171
|
|
172
172
|
nil
|
@@ -816,6 +816,10 @@ MU.log e.message, MU::WARN, details: e.inspect
|
|
816
816
|
def self.admin_directory(subclass = nil, credentials: nil)
|
817
817
|
require 'google/apis/admin_directory_v1'
|
818
818
|
|
819
|
+
# fill in the default credential set name so we don't generate
|
820
|
+
# dopey extra warnings about falling back on scopes
|
821
|
+
credentials ||= MU::Cloud::Google.credConfig(credentials, name_only: true)
|
822
|
+
|
819
823
|
writescopes = ['admin.directory.group.member', 'admin.directory.group', 'admin.directory.user', 'admin.directory.domain', 'admin.directory.orgunit', 'admin.directory.rolemanagement', 'admin.directory.customer', 'admin.directory.user.alias', 'admin.directory.userschema']
|
820
824
|
readscopes = ['admin.directory.group.member.readonly', 'admin.directory.group.readonly', 'admin.directory.user.readonly', 'admin.directory.domain.readonly', 'admin.directory.orgunit.readonly', 'admin.directory.rolemanagement.readonly', 'admin.directory.customer.readonly', 'admin.directory.user.alias.readonly', 'admin.directory.userschema.readonly']
|
821
825
|
@@readonly_semaphore.synchronize {
|
@@ -826,7 +830,7 @@ MU.log e.message, MU::WARN, details: e.inspect
|
|
826
830
|
|
827
831
|
if subclass.nil?
|
828
832
|
begin
|
829
|
-
@@admin_directory_api[credentials] ||= MU::Cloud::Google::GoogleEndpoint.new(api: "AdminDirectoryV1::DirectoryService", scopes: use_scopes, masquerade: MU::Cloud::Google.credConfig(credentials)['masquerade_as'], credentials: credentials)
|
833
|
+
@@admin_directory_api[credentials] ||= MU::Cloud::Google::GoogleEndpoint.new(api: "AdminDirectoryV1::DirectoryService", scopes: use_scopes, masquerade: MU::Cloud::Google.credConfig(credentials)['masquerade_as'], credentials: credentials, auth_error_quiet: true)
|
830
834
|
rescue Signet::AuthorizationError => e
|
831
835
|
MU.log "Falling back to read-only access to DirectoryService API for credential set '#{credentials}'", MU::WARN
|
832
836
|
@@admin_directory_api[credentials] ||= MU::Cloud::Google::GoogleEndpoint.new(api: "AdminDirectoryV1::DirectoryService", scopes: readscopes, masquerade: MU::Cloud::Google.credConfig(credentials)['masquerade_as'], credentials: credentials)
|
@@ -1035,7 +1039,7 @@ MU.log e.message, MU::WARN, details: e.inspect
|
|
1035
1039
|
# Create a Google Cloud Platform API client
|
1036
1040
|
# @param api [String]: Which API are we wrapping?
|
1037
1041
|
# @param scopes [Array<String>]: Google auth scopes applicable to this API
|
1038
|
-
def initialize(api: "ComputeV1::ComputeService", scopes: ['https://www.googleapis.com/auth/cloud-platform', 'https://www.googleapis.com/auth/compute.readonly'], masquerade: nil, credentials: nil)
|
1042
|
+
def initialize(api: "ComputeV1::ComputeService", scopes: ['https://www.googleapis.com/auth/cloud-platform', 'https://www.googleapis.com/auth/compute.readonly'], masquerade: nil, credentials: nil, auth_error_quiet: false)
|
1039
1043
|
@credentials = credentials
|
1040
1044
|
@scopes = scopes.map { |s|
|
1041
1045
|
if !s.match(/\//) # allow callers to use shorthand
|
@@ -1052,11 +1056,16 @@ MU.log e.message, MU::WARN, details: e.inspect
|
|
1052
1056
|
@api.authorization.sub = @masquerade
|
1053
1057
|
@api.authorization.fetch_access_token!
|
1054
1058
|
rescue Signet::AuthorizationError => e
|
1055
|
-
|
1056
|
-
|
1059
|
+
if auth_error_quiet
|
1060
|
+
MU.log "Cannot masquerade as #{@masquerade} to API #{api}: #{e.message}", MU::DEBUG, details: @scopes
|
1061
|
+
else
|
1062
|
+
MU.log "Cannot masquerade as #{@masquerade} to API #{api}: #{e.message}", MU::ERROR, details: @scopes
|
1063
|
+
if e.message.match(/client not authorized for any of the scopes requested/)
|
1057
1064
|
# XXX it'd be helpful to list *all* scopes we like, as well as the API client's numeric id
|
1058
|
-
|
1065
|
+
MU.log "To grant access to API scopes for this service account, see:", MU::ERR, details: "https://admin.google.com/AdminHome?chromeless=1#OGX:ManageOauthClients"
|
1066
|
+
end
|
1059
1067
|
end
|
1068
|
+
|
1060
1069
|
raise e
|
1061
1070
|
end
|
1062
1071
|
end
|
data/modules/mu/config.rb
CHANGED
@@ -525,7 +525,7 @@ end
|
|
525
525
|
region: @region,
|
526
526
|
habitats: hab_arg,
|
527
527
|
credentials: @credentials,
|
528
|
-
dummy_ok: (["habitats", "folders", "users", "groups"].include?(@type))
|
528
|
+
dummy_ok: (["habitats", "folders", "users", "groups", "vpcs"].include?(@type))
|
529
529
|
)
|
530
530
|
@obj ||= found.first if found
|
531
531
|
rescue ThreadError => e
|
@@ -1786,6 +1786,9 @@ $CONFIGURABLES
|
|
1786
1786
|
|
1787
1787
|
|
1788
1788
|
acl = {"name" => name, "rules" => rules, "vpc" => realvpc, "cloud" => cloud, "admin" => true, "credentials" => credentials }
|
1789
|
+
if cloud == "Google" and acl["vpc"] and acl["vpc"]["habitat"]
|
1790
|
+
acl['project'] = acl["vpc"]["habitat"]["id"] || acl["vpc"]["habitat"]["name"]
|
1791
|
+
end
|
1789
1792
|
acl.delete("vpc") if !acl["vpc"]
|
1790
1793
|
if !resclass.isGlobal? and !region.nil? and !region.empty?
|
1791
1794
|
acl["region"] = region
|
@@ -1972,6 +1975,13 @@ $CONFIGURABLES
|
|
1972
1975
|
|
1973
1976
|
# Namespace magic to pass to ERB's result method.
|
1974
1977
|
def get_binding(keyset)
|
1978
|
+
environment = $environment
|
1979
|
+
myPublicIp = $myPublicIp
|
1980
|
+
myRoot = $myRoot
|
1981
|
+
myAZ = $myAZ
|
1982
|
+
myRegion = $myRegion
|
1983
|
+
myAppName = $myAppName
|
1984
|
+
|
1975
1985
|
# return MU::Config.global_bindings[keyset] if MU::Config.global_bindings[keyset]
|
1976
1986
|
MU::Config.global_bindings[keyset] = binding
|
1977
1987
|
MU::Config.global_bindings[keyset]
|
data/modules/mu/mommacat.rb
CHANGED
@@ -2762,6 +2762,9 @@ MESSAGE_END
|
|
2762
2762
|
# Start the Momma Cat daemon and return the exit status of the command used
|
2763
2763
|
# @return [Integer]
|
2764
2764
|
def self.start
|
2765
|
+
if MU.inGem? and MU.muCfg['disable_mommacat']
|
2766
|
+
return
|
2767
|
+
end
|
2765
2768
|
base = (Process.uid == 0 and !MU.localOnly) ? "/var" : MU.dataDir
|
2766
2769
|
[base, "#{base}/log", "#{base}/run"].each { |dir|
|
2767
2770
|
if !Dir.exist?(dir)
|
@@ -2784,20 +2787,19 @@ MESSAGE_END
|
|
2784
2787
|
|
2785
2788
|
MU.log cmd, MU::NOTICE
|
2786
2789
|
|
2787
|
-
output = %x{#{cmd}}
|
2788
|
-
|
2789
|
-
Dir.chdir(origdir)
|
2790
|
-
|
2791
2790
|
retries = 0
|
2792
2791
|
begin
|
2792
|
+
output = %x{#{cmd}}
|
2793
2793
|
sleep 1
|
2794
2794
|
retries += 1
|
2795
2795
|
if retries >= 10
|
2796
|
-
MU.log "MommaCat failed to start (command was #{cmd})", MU::WARN, details: output
|
2796
|
+
MU.log "MommaCat failed to start (command was #{cmd}, working directory #{MU.myRoot}/modules)", MU::WARN, details: output
|
2797
2797
|
pp caller
|
2798
2798
|
return $?.exitstatus
|
2799
2799
|
end
|
2800
2800
|
end while !status
|
2801
|
+
|
2802
|
+
Dir.chdir(origdir)
|
2801
2803
|
|
2802
2804
|
if $?.exitstatus != 0
|
2803
2805
|
exit 1
|
@@ -2809,6 +2811,9 @@ MESSAGE_END
|
|
2809
2811
|
# Return true if the Momma Cat daemon appears to be running
|
2810
2812
|
# @return [Boolean]
|
2811
2813
|
def self.status
|
2814
|
+
if MU.inGem? and MU.muCfg['disable_mommacat']
|
2815
|
+
return true
|
2816
|
+
end
|
2812
2817
|
if File.exist?(daemonPidFile)
|
2813
2818
|
pid = File.read(daemonPidFile).chomp.to_i
|
2814
2819
|
begin
|
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: 3.0.
|
4
|
+
version: 3.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- John Stange
|
@@ -11,7 +11,7 @@ authors:
|
|
11
11
|
autorequire:
|
12
12
|
bindir: bin
|
13
13
|
cert_chain: []
|
14
|
-
date: 2019-
|
14
|
+
date: 2019-12-03 00:00:00.000000000 Z
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
17
17
|
name: erubis
|
@@ -355,6 +355,34 @@ dependencies:
|
|
355
355
|
- - "~>"
|
356
356
|
- !ruby/object:Gem::Version
|
357
357
|
version: '0.37'
|
358
|
+
- !ruby/object:Gem::Dependency
|
359
|
+
name: rack
|
360
|
+
requirement: !ruby/object:Gem::Requirement
|
361
|
+
requirements:
|
362
|
+
- - "~>"
|
363
|
+
- !ruby/object:Gem::Version
|
364
|
+
version: '2.0'
|
365
|
+
type: :runtime
|
366
|
+
prerelease: false
|
367
|
+
version_requirements: !ruby/object:Gem::Requirement
|
368
|
+
requirements:
|
369
|
+
- - "~>"
|
370
|
+
- !ruby/object:Gem::Version
|
371
|
+
version: '2.0'
|
372
|
+
- !ruby/object:Gem::Dependency
|
373
|
+
name: thin
|
374
|
+
requirement: !ruby/object:Gem::Requirement
|
375
|
+
requirements:
|
376
|
+
- - "~>"
|
377
|
+
- !ruby/object:Gem::Version
|
378
|
+
version: '1.7'
|
379
|
+
type: :runtime
|
380
|
+
prerelease: false
|
381
|
+
version_requirements: !ruby/object:Gem::Requirement
|
382
|
+
requirements:
|
383
|
+
- - "~>"
|
384
|
+
- !ruby/object:Gem::Version
|
385
|
+
version: '1.7'
|
358
386
|
description: |+
|
359
387
|
The eGTLabs Mu toolkit for unified cloud deployments. This gem contains the Mu deployment interface to cloud provider APIs. It will generate a sample configuration the first time it is invoked.
|
360
388
|
|