require 'cri' require 'fileutils' require 'pathname' require 'git' require "canzea/config" require "canzea/version" require "canzea/environment" require "helper-run-class" require "trace-component" require "prepare-environment" require "plan-step-class" require "ssh-base-cmd-class" require "template-runner" require "commands/config-git-commit" require "commands/get-catalog" require "commands/remote-run" require "commands/remote-bootstrap" require "commands/gen-user" require "commands/update-config" require "commands/apply-config" require "commands/add-env" require "commands/prepare-plan" require "commands/register-metadata" require "commands/push-config" module Canzea command = Cri::Command.define do name 'canzea' usage 'canzea [options]' aliases :ds, :stuff summary 'canzea cli' description 'Canzea command line interface.' flag :h, :help, 'show help for this command' do |value, cmd| puts cmd.help exit 0 end flag :v, :version, 'Version' do |value, cmd| puts "Canzea CLI: v#{Canzea::VERSION}" end flag nil, :pwd, 'PWD' flag nil, :verbose, 'Verbose' # flag nil, :run, 'Run a step' # flag nil, :helper, 'Execute a helper' flag nil, :remote, 'Remote execution' flag nil, :remote_configure, 'Remote configuration' flag nil, :remote_wire, 'Remote execution of a helper' flag nil, :get, 'Get a file from the remote server' flag nil, :put, 'Put a file onto the remote server' flag nil, :encrypt, 'Encrypt' flag nil, :decrypt, 'Encrypt' flag nil, :raw, 'Result will be sent back in stdout' flag nil, :init, 'Remote init execution' # flag nil, :enable, 'Enable the service' flag nil, :test, 'Run as a test' flag nil, :reset, 'Refresh catalog to latest' flag nil, :checkout, 'Checkout catalog to latest' flag nil, :fv, 'Show version and the catalog version' flag nil, :config_git_commit, 'Manage configuration files in git' option nil, :config, 'Config', argument: :required option nil, :lifecycle, 'Lifecycle action [install, configure, upgrade, uninstall]', argument: :required option nil, :util, "Utility action [gen-user, gen-cert, add-env, add-env-secret, prepare-plan, apply-config]", argument: :required option nil, :catalogTag, 'Specific tag of the catalog', argument: :required option nil, :gitRoot, 'Git root', argument: :required option nil, :gitUri, 'Git URI', argument: :required option nil, :env, 'Dynamic environment json', argument: :required option nil, :commit, 'Commit', argument: :required option nil, :role, 'Role', argument: :required option nil, :solution, 'Solution', argument: :required option nil, :task, 'Task', argument: :required option nil, :step, 'Step', argument: :required option nil, :blueprint, 'Blueprint', argument: :required option nil, :segment, 'Segment', argument: :required option nil, :status, 'Result will be put into the status message', argument: :required option nil, :serverBase, 'Server Base', argument: :required option nil, :serverNumber, 'Server Number', argument: :required option nil, :privateKey, 'Task', argument: :required option nil, :publicKey, 'Task', argument: :required option nil, :template, 'Template', argument: :required option nil, :action, 'Helper Action', argument: :required option nil, :args, 'Arguments (JSON format)', argument: :required run do |opts, args, cmd| test = opts.fetch(:test, false) if opts[:config] file = File.read(opts[:config]) Canzea::configure JSON.parse(file) end extraConfig = Canzea::config[:config_location] + "/config.json" if File.exists?(extraConfig) if (opts[:verbose]) puts "-- Reading #{extraConfig}" end file = File.read(extraConfig) Canzea::configure JSON.parse(file) end if opts[:pwd] puts Dir.pwd end if File.exists?(Canzea::config[:catalog_location]) == false GetCatalog.new.do(opts.fetch(:catalogTag, nil)); end if (opts[:reset]) GetCatalog.new.do(opts.fetch(:catalogTag, nil)); end if (opts[:checkout]) GetCatalog.new.checkout(opts.fetch(:catalogTag, nil)); end GetCatalog.new.state if (opts[:fv]) puts "Canzea CLI: v#{Canzea::VERSION}" puts "Catalog: #{ENV['CATALOG_BRANCH']} ( #{ENV['CATALOG_COMMIT']} )" end if (opts[:env]) env = JSON.parse(opts.fetch(:env, '{}') PrepareEnvironment.new.addToEnvFromJSON(env) end if (opts[:util]) AddEnv.new(opts.fetch(:raw, false)).injectEnvironmentVariables util = opts[:util] if (util == "add-env") AddEnv.new.add(args[0], args[1]) end if (util == "add-env-secret") AddEnv.new.addSecret(args[0], args[1]) end if (util == "register-metadata") RegisterMetadata.new.do(opts[:role], opts[:solution], test) end if (util == "run-command") args = JSON.parse(opts.fetch(:args, "{}")) # If there are args, then parse them and put them in environment variables args.keys.each { | k | if args[k].instance_of? String puts "-- SETTING #{k.upcase} = #{args[k].to_str}" ENV[k.upcase] = args[k].to_str end } ps = HelperRun.new opts.fetch(:raw, false) ps.runCommand args['cmd'] end if (util == "analyze-command") step = Integer(opts.fetch(:step, '0')) list = [] args = JSON.parse(opts.fetch(:args, "{'phases'=>['install']}")) phases = args['phases'] publicIp = File.read("#{Canzea::config[:pwd]}/vps-#{opts[:serverBase]}-#{opts[:serverNumber]}.json") publicIp.strip! basePath = "#{Pathname.new(Canzea::config[:catalog_location]).realpath}" root = "#{basePath}/blocks/#{opts[:solution]}" if File.exists? root phases.each { | phase | basePath = "#{Pathname.new(Canzea::config[:catalog_location]).realpath}" cmd = "#{basePath}/blocks/#{opts[:solution]}/#{phase}.sh" if File.exists? cmd list += Worker.new.find (cmd) end } else phases.each { | phase | basePath = "#{Pathname.new(Canzea::config[:catalog_location]).realpath}" cmd = "#{basePath}/roles/#{opts[:role]}/#{opts[:solution]}/#{phase}.sh" if File.exists? cmd list += Worker.new.find (cmd) end } end list.each_with_index { | cmd, index | if index >= step puts "[#{index}] #{cmd}" # args['cmd'] = cmd # jsonArgs = args.to_json # fullCommand = "canzea --util=run-command --args='#{jsonArgs}'" RemoteRun.new.doCommand publicIp, opts[:privateKey], cmd else puts "[#{index}] SKIP #{cmd}" end } end if (util == "gen-template") t = Template.new # canzea --util=gen-template --template="Result = {{#cname}}A:{{#tf_name}}name{{/tf_name}}{{/cname}} {{gravatar}}" --args='{"a":[{"name":"grafana.mon"}], "cname":[{"name":"www","address":"@"},{"name":"vault","address":"@"},{"name":"consul","address":"@"},{"name":"sc","address":"@"}]}' puts t.processString opts[:template], JSON.parse(opts.fetch(:args, '{}')) end if (util == "gen-user") GenUser.new.do(args[0]) end if (util == "get-key-value") r = Registry.new puts r.getKeyValue (args[0]) end if (util == "set-key-value") r = Registry.new puts r.setKeyValue args[0], args[1], args[2] end if (util == "prepare-plan") ac = PreparePlan.new ac.do opts[:blueprint], opts[:segment], opts[:step], opts[:task], test, opts[:privateKey], opts[:serverBase], opts[:serverNumber] end if (util == "prepare-patch") ac = PreparePlan.new ac.doPatch opts.fetch(:args, '{}'), test, opts[:privateKey], opts[:serverBase], opts[:serverNumber] end if (util == "apply-config") gitRoot = opts.fetch(:gitRoot, Canzea::config[:git_repo]) ac = ApplyConfig.new ac.do gitRoot, test, opts[:step], opts[:task] end if (util == "push-config") PushConfig.new.do(args[0], args[1], JSON.parse(opts.fetch(:args, '{}'))) end end if (opts[:get] || opts[:put]) publicIp = File.read("#{Canzea::config[:pwd]}/vps-#{opts[:serverBase]}-#{opts[:serverNumber]}.json") publicIp.strip! if (opts[:get]) remote = RemoteCall.new remote.get publicIp, opts[:privateKey], args[0], args[1] end if (opts[:put]) remote = RemoteCall.new remote.put publicIp, opts[:privateKey], args[0], args[1] end end if (opts[:encrypt]) remote = RemoteCall.new remote.encrypt args[0], opts[:publicKey] end if (opts[:decrypt]) remote = RemoteCall.new remote.decrypt args[0], opts[:privateKey] end if (opts[:lifecycle]) lifecycle = opts[:lifecycle] AddEnv.new(opts.fetch(:raw, false)).injectEnvironmentVariables if lifecycle == 'install' puts "-- Running install step #{opts[:role]} #{opts[:solution]}" # If there are args, then parse them and put them in environment variables args = JSON.parse(opts.fetch(:args, '{}')) args.keys.each { | k | if args[k].instance_of? String puts "-- SETTING #{k.upcase} = #{args[k].to_str}" ENV[k.upcase] = args[k].to_str end } ps = PlanStep.new ps.runPhaseInstall opts[:role], opts[:solution], test, Integer(opts.fetch(:task, 1)) if (test == false) gitRoot = opts.fetch(:gitRoot, Canzea::config[:git_repo]) conf = { :gitRoot => gitRoot, :role => opts[:role], :solution => opts[:solution] } ps = UpdateConfig.new ps.do opts[:role], opts[:solution], gitRoot end end if lifecycle == 'configure' puts "-- Running configure step #{opts[:role]} #{opts[:solution]}" # If there are args, then parse them and put them in environment variables args = JSON.parse(opts.fetch(:args, '{}')) args.keys.each { | k | if args[k].instance_of? String puts "-- SETTING #{k.upcase} = #{args[k].to_str}" ENV[k.upcase] = args[k].to_str end } ps = PlanStep.new ps.runPhaseConfigure opts[:role], opts[:solution], test, Integer(opts.fetch(:task, 1)) end if lifecycle == 'patch' puts "-- Running patch step #{opts[:commit]} #{opts[:solution]}" ps = PlanStep.new ps.runPhasePatch opts[:commit], opts[:solution], test, Integer(opts.fetch(:task, 1)) end if lifecycle == 'wire' # puts "-- Running helper #{opts[:solution]} #{opts[:action]}" ps = HelperRun.new opts.fetch(:raw, false) ps.run opts[:solution], opts[:action], opts.fetch(:args, '{}'), opts.fetch(:status,nil) end end if opts[:init] publicIp = File.read("#{Canzea::config[:pwd]}/vps-#{opts[:serverBase]}-#{opts[:serverNumber]}.json") publicIp.strip! RemoteInit.new.do publicIp, opts[:privateKey] end if opts[:remote] publicIp = File.read("#{Canzea::config[:pwd]}/vps-#{opts[:serverBase]}-#{opts[:serverNumber]}.json") publicIp.strip! RemoteRun.new.doInstall publicIp, opts[:privateKey], opts[:role], opts[:solution], opts.fetch(:args, '{}') end if opts[:remote_configure] publicIp = File.read("#{Canzea::config[:pwd]}/vps-#{opts[:serverBase]}-#{opts[:serverNumber]}.json") publicIp.strip! RemoteRun.new.doConfigure publicIp, opts[:privateKey], opts[:role], opts[:solution] end if opts[:remote_wire] publicIp = File.read("#{Canzea::config[:pwd]}/vps-#{opts[:serverBase]}-#{opts[:serverNumber]}.json") publicIp.strip! RemoteRun.new.doWire publicIp, opts[:privateKey], opts[:solution], opts[:action], opts.fetch(:args, '{}') end if opts[:config_git_commit] if (Canzea::config[:track_changes_in_git] && ENV.has_key?('ECOSYSTEM') == false) raise "ECOSYSTEM environment variable must be set for this command" end gitRoot = opts.fetch(:gitRoot, Canzea::config[:git_repo]) gitUri = opts.fetch(:gitUri, ""); basePath = "ecosystems/#{ENV['ECOSYSTEM']}/config/#{opts[:serverBase]}-#{opts[:serverNumber]}" cg = ConfigGitCommit.new cg.do gitRoot, gitUri, args[0], opts[:template], basePath, (args.length == 1 ? {}:JSON.parse(args[1])) end end end command.run(ARGV) end