cloud-mu 3.0.1 → 3.0.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
|