lib/terragov/cli.rb in terragov-0.2.1 vs lib/terragov/cli.rb in terragov-0.2.2

- old
+ new

@@ -1,26 +1,28 @@ require 'commander' require 'yaml' +require 'highline' require_relative 'buildpaths' require_relative 'terraform' require_relative 'cleaner' require_relative 'version' +require_relative 'git' module Terragov class Cli include Commander::Methods def initialize program :name, 'terragov' program :version, Terragov::VERSION program :description, 'Wrapper for GOV.UK Terraform deployments.' - global_option('-c', "--config-file FILE", 'Specify a config file. Has less precedence than environment variables, which in turn have left precedence than CLI options') do |config_file| + global_option('-c', "--config-file FILE", 'Specify a config file. Has less precedence than environment variables, which in turn have less precedence than CLI options') do |config_file| $config_file = config_file end - global_option('-d', "--data-dir DIRECTORY", 'Location of the data directory') do |data_dir| + global_option('-d', "--data-dir DIRECTORY", String, 'Location of the data directory') do |data_dir| $data_dir = data_dir end global_option( '-e', '--environment STRING', String, 'Select environment') do |environment| $environment = environment @@ -40,18 +42,21 @@ global_option('--extra STRING', String, 'Any additional arguments to pass in the following format: --extra \\\\-target resource.foo.') do |extra| $extra = extra end - global_option('--verbose', String, 'Verbose mode') do |verbose| + global_option('--verbose', 'Verbose mode') do |verbose| $verbose = verbose end - global_option('--dry-run', String, 'Verbose mode', 'Output the commands to run, but do not run them') do |dryrun| + global_option('--dry-run', 'Dry run mode', 'Output the commands to run, but do not run them') do |dryrun| $dryrun = dryrun end + global_option('--skip-git-check', 'Skip git check', 'Do not check the status of git repositories') do |skip_git_check| + $skip_git_check = skip_git_check + end end def data_dir return $data_dir ? $data_dir : false end @@ -74,22 +79,33 @@ def extra return $extra if $extra end + def verbose + return true ? $verbose : false + end + + def dryrun + return true ? $dryrun : false + end + + def skip_git_check + return true ? $skip_git_check : false + end + def load_config_file if $config_file || ENV['TERRAGOV_CONFIG_FILE'] file = $config_file || ENV['TERRAGOV_CONFIG_FILE'] $values = YAML.load_file(File.expand_path(file)) return $values end end - def config(option, file=false) + def config(option, file=false, required=true) env_var = "TERRAGOV_#{option.upcase}" error_message = "Must set #{option}. Use --help for details." - #require 'pry'; binding.pry if public_send(option) if file return File.expand_path(public_send(option)) else return public_send(option) @@ -106,14 +122,22 @@ return File.expand_path(load_config_file[option]) else return load_config_file[option] end else - abort(error_message) + if required + abort(error_message) + else + return false + end end else - abort(error_message) + if required + abort(error_message) + else + return false + end end end def cmd_options cmd_options_hash = { @@ -125,73 +149,86 @@ "extra" => extra, } return cmd_options_hash end + def git_compare_repo_and_data(skip=false) + git_helper = Terragov::Git.new + # FIXME this is confusing as we want to check the repository git status from + # the root, but the "data" directory is one level down in the repository + repo_dir_root = cmd_options['repo_dir'] + data_dir_root = File.expand_path(File.join(cmd_options['data_dir'], '../')) + + repo_dir_branch = git_helper.branch_name(repo_dir_root) + data_dir_branch = git_helper.branch_name(data_dir_root) + + branches = { + "repo_dir" => repo_dir_branch, + "data_dir" => data_dir_branch, + } + + unless skip + branches.each do |name, branch| + unless branch =~ /^master$/ + exit unless HighLine.agree("#{name} not on 'master' branch, continue on branch '#{branch}'?") + end + end + + unless git_helper.compare_branch(repo_dir_root, data_dir_root) + puts "Warning: repo_dir(#{repo_dir_branch}) and data_dir(#{data_dir_branch}) on different branches" + exit unless HighLine.agree("Do you wish to continue?") + end + end + end + def run_terraform_cmd(cmd, opt = nil) paths = Terragov::BuildPaths.new.base(cmd_options) varfiles = Terragov::BuildPaths.new.build_command(cmd_options) backend = paths[:backend_file] project_dir = paths[:project_dir] + + be_verbose = config('verbose', false, false) + + do_dryrun = config('dryrun', false, false) + + skip_check = config('skip_git_check', false, false) + git_compare_repo_and_data(skip_check) + + if be_verbose + puts cmd_options.to_yaml + end + if opt cmd = "#{cmd} #{opt}" end - Terragov::Terraform.new.execute(cmd, varfiles, backend, project_dir) + Terragov::Terraform.new.execute(cmd, varfiles, backend, project_dir, do_dryrun, be_verbose) end def run command :plan do |c| c.syntax = 'terragov plan' c.description = 'Runs a plan of your code' c.action do |args, options| - if options.verbose - ENV['TERRAGOV_VERBOSE'] = "true" - puts "Planning..." - puts cmd_options.to_yaml - end - if options.dry_run - ENV['TERRAGOV_DRYRUN'] = "true" - end - run_terraform_cmd(c.name) end end command :apply do |c| c.syntax = 'terragov apply' c.description = 'Apply your code' c.action do |args, options| - if options.verbose - ENV['TERRAGOV_VERBOSE'] = "true" - puts "Applying..." - puts cmd_options.to_yaml - end - if options.dry_run - ENV['TERRAGOV_DRYRUN'] = "true" - end - run_terraform_cmd(c.name) end end command :destroy do |c| c.syntax = 'terragov destroy' c.description = 'Destroy your selected project' c.option '--force', 'Force destroy' c.action do |args, options| - if options.verbose - ENV['TERRAGOV_VERBOSE'] = "true" - puts "Destroying..." - puts cmd_options.to_yaml - end - - if options.dry_run - ENV['TERRAGOV_DRYRUN'] = "true" - end - if options.force run_terraform_cmd("#{c.name} -force") else run_terraform_cmd(c.name) end @@ -201,10 +238,10 @@ command :clean do |c| c.syntax = 'terragov clean' c.description = 'Clean your directory of any files terraform may have left lying around' c.option '--force', 'Force removal of files' c.action do |args, options| - if options.verbose + if config('verbose', false, false) puts "Selecting directory #{repo_dir}" end Terragov::Cleaner.new.delete(repo_dir, /terraform\.tfstate\.backup/, options.force) end