bin/mu-configure in cloud-mu-2.0.0.pre.alpha vs bin/mu-configure in cloud-mu-2.0.0.pre.alpha2

- old
+ new

@@ -26,10 +26,15 @@ require 'readline' require 'fileutils' require 'erb' require 'tmpdir' +$IN_GEM = false +if Gem.paths and Gem.paths.home and File.dirname(__FILE__).match(/^#{Gem.paths.home}/) + $IN_GEM = true +end + GIT_PATTERN = /(((git|ssh|http(s)?)|(git@[\w\.]+))(:(\/\/)?))?([\w\.@\:\/\-~]+)(\.git)?(\/)?/ # Top-level keys in $MU_CFG for which we'll provide interactive, menu-driven # configuration. $CONFIGURABLES = { @@ -195,10 +200,15 @@ "title" => "Log and Secret Bucket Name", "desc" => "Cloud Storage bucket into which we'll synchronize deploy secrets, and if we're hosted in GCP, collected system logs", "required" => true, "changes" => ["chefrun"] }, + "masequerade_as" => { + "title" => "GSuite Masquerade User", + "required" => false, + "desc" => "For Google Cloud projects which are attached to a GSuite domain. GCP service accounts cannot view or manage GSuite resources (groups, users, etc) directly, but must instead masquerade as a GSuite user which has delegated authority to the service account. See also: https://developers.google.com/identity/protocols/OAuth2ServiceAccount#delegatingauthority" + }, "default" => { "title" => "Is Default Account", "default" => false, "desc" => "If set to true, Mu will use this set of GCP credentials when targeting the Google Cloud without a specific account having been requested", "boolean" => true @@ -279,14 +289,15 @@ MU_BASE = "/opt/mu" end $INITIALIZE = (!File.size?("#{MU_BASE}/etc/mu.yaml") or $opts[:force]) $HAVE_GLOBAL_CONFIG = File.size?("#{MU_BASE}/etc/mu.yaml") -if !AMROOT and ($INITIALIZE or !$HAVE_GLOBAL_CONFIG) +if !AMROOT and ($INITIALIZE or !$HAVE_GLOBAL_CONFIG) and !$IN_GEM puts "Global configuration has not been initialized or is missing. Must run as root to correct." exit 1 end + if !$HAVE_GLOBAL_CONFIG and $opts[:noninteractive] and (!$opts[:public_address] or !$opts[:mu_admin_email]) puts "Specify --public-address and --mu-admin-email on new non-interactive configs" exit 1 end @@ -313,11 +324,11 @@ begin Timeout.timeout(2) do instance_id = open("http://169.254.169.254/metadata/instance/compute").read $IN_AWS = true if !instance_id.nil? and instance_id.size > 0 end -rescue OpenURI::HTTPError, Timeout::Error, SocketError, Errno::ENETUNREACH +rescue OpenURI::HTTPError, Timeout::Error, SocketError, Errno::ENETUNREACH, Errno::EHOSTUNREACH end KNIFE_TEMPLATE = "log_level :info log_location STDOUT @@ -383,10 +394,11 @@ "title" => "Name", "desc" => "A name/alias for this account.", "required" => true } map[count.to_s]["#addnew"] = true + map[count.to_s]["#title"] = data['title'] map[count.to_s]["#key"] = key # Now the menu entries for the existing ones if data['subtree']['#entries'] data['subtree']['#entries'].each_pair { |nameentry, subdata| @@ -478,11 +490,11 @@ def cloneGitRepo(repo) puts "Testing ability to check out Git repository #{repo.bold}" fullrepo = repo if !repo.match(/@|:\/\//) # we try ssh first - fullrepo = "git@github.com:"+repo + fullrepo = "git@github.com:"+repo puts "Doesn't look like a full URL, trying SSH to #{fullrepo}" end cwd = Dir.pwd Dir.mktmpdir("mu-git-test-") { |dir| Dir.chdir(dir) @@ -509,22 +521,22 @@ return fullrepo end end end if !repo.match(/@|:\/\//) - fullrepo = "git://github.com/"+repo + fullrepo = "git://github.com/"+repo puts "" puts "No luck there, trying #{fullrepo}".bold puts "/usr/bin/git clone #{fullrepo}" output = %x{/usr/bin/git clone #{fullrepo} 2>&1} if $?.exitstatus == 0 puts "Successfully cloned #{fullrepo}".green.on_black Dir.chdir(cwd) return fullrepo else puts output.red.on_black - fullrepo = "https://github.com/"+repo + fullrepo = "https://github.com/"+repo puts "Final attempt, trying #{fullrepo}" puts "/usr/bin/git clone #{fullrepo}" output = %x{/usr/bin/git clone #{fullrepo} 2>&1} if $?.exitstatus == 0 puts "Successfully cloned #{fullrepo}".green.on_black @@ -743,12 +755,12 @@ def displayCurrentOpts(tree = $CONFIGURABLES) count = 1 optlist = [] tree.each_pair { |key, data| - next if !AMROOT and data['rootonly'] next if !data.is_a?(Hash) + next if !AMROOT and data['rootonly'] if data["title"].nil? or data["#menu"].nil? next end print data["#menu"].bold+") "+data["title"] if data.has_key?("subtree") @@ -778,11 +790,11 @@ end ############################################################################### trap("INT"){ puts "" ; exit } -importCurrentValues if !$INITIALIZE or $HAVE_GLOBAL_CONFIG +importCurrentValues if !$INITIALIZE or $HAVE_GLOBAL_CONFIG or $IN_GEM importCLIValues setDefaults assignMenuEntries # populates $MENU_MAP def ask(desc) @@ -819,20 +831,20 @@ ok = true if reqs['boolean'] and newval != true and newval != false and newval != nil puts "\nInvalid value '#{newval.bold}' for #{reqs['title'].bold} (must be true or false)".light_red.on_black puts "\n\n" if addnewline ok = false - elsif in_use.size > 0 and in_use.include?(newval) + elsif in_use and in_use.size > 0 and in_use.include?(newval) puts "\n##{reqs['title'].bold} #{newval} not available".light_red.on_black puts "\n\n" if addnewline ok = false elsif reqs['pattern'] if newval.nil? puts "\nSupplied value for #{reqs['title'].bold} did not pass validation".light_red.on_black puts "\n\n" if addnewline ok = false - elsif reqs['negate_pattern'] + elsif reqs['negate_pattern'] if newval.to_s.match(reqs['pattern']) puts "\nInvalid value '#{newval.bold}' for #{reqs['title'].bold} (must NOT match #{reqs['pattern']})".light_red.on_black puts "\n\n" if addnewline ok = false end @@ -913,11 +925,13 @@ assignMenuEntries(map[answer], minimap) newtree, newmap = menu( map[answer], minimap, map[answer]['#title']+" (NEW)", - map[answer]['#entries'].keys.reject { |k| k.match(/^#/) } + if map[answer]['#entries'] + map[answer]['#entries'].keys.reject { |k| k.match(/^#/) } + end ) if newtree newname = newtree["name"]["value"] newtree.delete("#addnew") parentname = map[answer]['#key'] @@ -943,11 +957,11 @@ puts PP.pp(tree[parentname]['subtree']['#entries'][entryname], '').red assignMenuEntries(tree[parentname]['subtree']['#entries'][entryname], minimap) newtree, newmap = menu( map[answer], minimap, - map[answer]["#title"], + map[answer]["#title"], (map[answer]['#entries'].keys - [map[answer]['#title']]) ) map[answer] = newtree if newtree elsif map.has_key?(answer) and !map[answer].has_key?("subtree") newval = ask(map[answer]) @@ -1068,11 +1082,13 @@ system("/opt/chef/bin/chef-apply #{MU_BASE}/lib/cookbooks/mu-master/recipes/init.rb"); end end if $INITIALIZE - %x{/sbin/service iptables stop} # Chef run will set up correct rules later + if AMROOT + %x{/sbin/service iptables stop} # Chef run will set up correct rules later + end $MU_SET_DEFAULTS = setConfigTree require File.realpath(File.expand_path(File.dirname(__FILE__)+"/mu-load-config.rb")) else if AMROOT $NEW_CFG = $MU_CFG.merge(setConfigTree) @@ -1091,10 +1107,16 @@ rescue LoadError system("cd #{MU_BASE}/lib/modules && umask 0022 && /usr/local/ruby-current/bin/bundle install") require 'mu' end +if $IN_GEM + puts $MU_CFG.to_yaml + saveMuConfig($MU_CFG) + exit +end + if AMROOT and ($INITIALIZE or $CHANGES.include?("hostname")) system("/bin/hostname #{$MU_CFG['hostname']}") end # Do some more basic-but-Chef-dependent configuration *before* we meddle with @@ -1128,10 +1150,11 @@ def updateChefRbs user = AMROOT ? "mu" : Etc.getpwuid(Process.uid).name chefuser = user.gsub(/\./, "") templates = { HOMEDIR+"/.chef/knife.rb" => KNIFE_TEMPLATE } + Dir.mkdir(HOMEDIR+"/.chef") if !Dir.exists?(HOMEDIR+"/.chef") if AMROOT templates["/etc/chef/client.rb"] = CLIENT_TEMPLATE templates["/etc/opscode/pivotal.rb"] = PIVOTAL_TEMPLATE end templates.each_pair { |file, template| @@ -1250,10 +1273,10 @@ if $INITIALIZE or $CHANGES.include?("vault") MU.log "Setting up Hashicorp Vault", MU::NOTICE system("chef-client -o 'recipe[mu-master::vault]'") end -if $MU_CFG['ldap']['type'] == "389 Directory Services" +if $MU_CFG['ldap']['type'] == "389 Directory Services" begin MU::Master::LDAP.listUsers rescue Exception => e # XXX lazy exception handling is lazy $CHANGES << "389ds" end