Class: GeoCLI

Inherits:
Object
  • Object
show all
Includes:
Commander::Methods, StatusCommand, TerraformCommands, HasLifecycle, Singleton
Defined in:
lib/geoengineer/cli/geo_cli.rb,
lib/geoengineer/cli/geo_cli.rb

Overview

GeoCLI context

Defined Under Namespace

Modules: StatusCommand, TerraformCommands

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from HasLifecycle

#execute_lifecycle, included

Methods included from TerraformCommands

#apply_cmd, #create_terraform_files, #destroy_cmd, #plan_cmd, #terraform_apply, #terraform_destroy, #terraform_parallelism, #terraform_plan, #terraform_plan_destroy

Methods included from StatusCommand

#calculate_status, #calculate_type_status, #default_status_types, #only_codified, #report_json, #resource_id_array, #status_action, #status_cmd, #status_types, #type_stats

Instance Attribute Details

#env_nameObject

Returns the value of attribute env_name


36
37
38
# File 'lib/geoengineer/cli/geo_cli.rb', line 36

def env_name
  @env_name
end

#environmentObject

Returns the value of attribute environment


36
37
38
# File 'lib/geoengineer/cli/geo_cli.rb', line 36

def environment
  @environment
end

#no_colorObject

CLI FLAGS AND OPTIONS


39
40
41
# File 'lib/geoengineer/cli/geo_cli.rb', line 39

def no_color
  @no_color
end

#verboseObject

CLI FLAGS AND OPTIONS


39
40
41
# File 'lib/geoengineer/cli/geo_cli.rb', line 39

def verbose
  @verbose
end

Instance Method Details

#add_commandsObject


189
190
191
192
193
194
195
# File 'lib/geoengineer/cli/geo_cli.rb', line 189

def add_commands
  plan_cmd
  apply_cmd
  destroy_cmd
  graph_cmd
  status_cmd
end

#create_environment(name, &block) ⇒ Object


63
64
65
66
67
68
69
70
71
72
73
74
# File 'lib/geoengineer/cli/geo_cli.rb', line 63

def create_environment(name, &block)
  return @environment if @environment
  if name != @env_name
    puts "Not loading environment #{name} as env_name is #{@env_name}" if @verbose
    return NullObject.new
  end

  @environment = GeoEngineer::Environment.new(name, &block)
  init_tmp_dir(name)
  init_terraform_files()
  @environment
end

#global_optionsObject


169
170
171
172
173
174
175
176
177
178
179
180
181
182
# File 'lib/geoengineer/cli/geo_cli.rb', line 169

def global_options
  global_option('-e', '--environment <name>', "Environment to use")

  @verbose = true
  global_option('--quiet', 'reduce the noisy outputs (default they are on)') {
    @verbose = false
  }

  @no_color = ''
  global_option('--no-color', 'removes color from the terraform output') {
    String.disable_colorization = true
    @no_color = ' -no-color'
  }
end

#graph_cmdObject


158
159
160
161
162
163
164
165
166
167
# File 'lib/geoengineer/cli/geo_cli.rb', line 158

def graph_cmd
  command :graph do |c|
    c.syntax = 'geo graph [<geo_files>]'
    c.description = 'Generate and graph of the environment resources to GraphViz'
    action = lambda do |args, options|
      puts env.to_dot
    end
    c.action init_action(:graph, &action)
  end
end

#init_action(action_name) ⇒ Object

This defines the typical action in geo engineer

  • require the environment

  • require the geo files

  • ensure everything is valid

  • execute the action

  • execute the after hook


135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
# File 'lib/geoengineer/cli/geo_cli.rb', line 135

def init_action(action_name)
  lambda do |args, options|
    require_environment(options)
    require_geo_files(args)
    throw "Environment not set" unless @environment

    @environment.execute_lifecycle(:before, action_name.to_sym)
    errs = @environment.errors.flatten.sort
    unless errs.empty?
      print_validation_errors(errs)
      exit 1
    end

    yield args, options
    @environment.execute_lifecycle(:after, action_name.to_sym)
  end
end

#init_terraform_filesObject


46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
# File 'lib/geoengineer/cli/geo_cli.rb', line 46

def init_terraform_files
  @terraform_file       = "terraform.tf.json"
  @terraform_state_file = "terraform.tfstate"
  @plan_file            = "plan.terraform"

  files = [
    "#{@tmpdir}/#{@terraform_state_file}.backup",
    "#{@tmpdir}/#{@terraform_file}",
    "#{@tmpdir}/#{@terraform_state_file}",
    "#{@tmpdir}/#{@plan_file}"
  ]

  files.each do |file|
    File.delete(file) if File.exist?(file)
  end
end

#init_tmp_dir(name) ⇒ Object


41
42
43
44
# File 'lib/geoengineer/cli/geo_cli.rb', line 41

def init_tmp_dir(name)
  @tmpdir = "#{Dir.pwd}/tmp/#{name}"
  FileUtils.mkdir_p @tmpdir
end

109
110
111
112
# File 'lib/geoengineer/cli/geo_cli.rb', line 109

def print_validation_errors(errs)
  puts errs.map { |s| "ERROR: #{s}".colorize(:red) }
  puts "Total Errors #{errs.length}"
end

#require_all_projectsObject


90
91
92
93
94
95
# File 'lib/geoengineer/cli/geo_cli.rb', line 90

def require_all_projects
  Dir["#{Dir.pwd}/projects/**/*.rb"].each do |project_file|
    puts "LOADING #{project_file}" if @verbose
    require project_file
  end
end

#require_environment(options) ⇒ Object


80
81
82
83
84
85
86
87
88
# File 'lib/geoengineer/cli/geo_cli.rb', line 80

def require_environment(options)
  @env_name = options.environment || ENV['GEO_ENV'] || 'staging'
  puts "Using environment '#{@env_name}'\n" if @verbose
  begin
    require_from_pwd "environments/#{@env_name}"
  rescue LoadError
    puts "unable to load 'environments/#{@env_name}'" if @verbose
  end
end

#require_from_pwd(file) ⇒ Object


76
77
78
# File 'lib/geoengineer/cli/geo_cli.rb', line 76

def require_from_pwd(file)
  require "#{Dir.pwd}/#{file}"
end

#require_geo_files(args) ⇒ Object


104
105
106
107
# File 'lib/geoengineer/cli/geo_cli.rb', line 104

def require_geo_files(args)
  return require_all_projects if args.empty?
  args.each { |project_file| require_project_file(project_file) }
end

#require_project_file(project_file) ⇒ Object


97
98
99
100
101
102
# File 'lib/geoengineer/cli/geo_cli.rb', line 97

def require_project_file(project_file)
  if !File.exist?(project_file) && !File.exist?("#{project_file}.rb")
    throw "The file \"#{project_file}\" does not exist"
  end
  require_from_pwd project_file
end

#runObject


197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
# File 'lib/geoengineer/cli/geo_cli.rb', line 197

def run
  program :name, 'GeoEngineer'
  program :version, GeoEngineer::VERSION
  program :description, 'GeoEngineer will help you Terraform your resources'
  always_trace!

  # check terraform installed
  return puts "Please install terraform" unless terraform_installed?

  # global_options
  global_options

  # Require any patches to the way geo works
  require_from_pwd '.geo' if File.file?("#{Dir.pwd}/.geo.rb")

  # Add commands
  add_commands
  execute_lifecycle(:after, :add_commands)

  # Execute the CLI
  run!
end

#shell_exec(cmd, verbose = @verbose) ⇒ Object


114
115
116
117
118
119
120
121
122
123
124
125
126
127
# File 'lib/geoengineer/cli/geo_cli.rb', line 114

def shell_exec(cmd, verbose = @verbose)
  stdin, stdout_and_stderr, wait_thr = Open3.popen2e({}, *cmd)

  puts(">> #{cmd}\n") if verbose
  stdout_and_stderr.each do |line|
    puts(line) if verbose
  end
  puts("<< Exited with status: #{wait_thr.value.exitstatus}\n\n") if verbose

  stdin.close
  stdout_and_stderr.close

  wait_thr.value
end

#terraform_installed?Boolean

Returns:

  • (Boolean)

184
185
186
187
# File 'lib/geoengineer/cli/geo_cli.rb', line 184

def terraform_installed?
  terraform_version = shell_exec('which terraform')
  terraform_version.exitstatus.zero?
end

#yes?(question) ⇒ Boolean

Returns:

  • (Boolean)

153
154
155
156
# File 'lib/geoengineer/cli/geo_cli.rb', line 153

def yes?(question)
  answer = ask question
  answer.strip.upcase.start_with? "YES"
end