Class: Bcome::Orchestration::InteractiveTerraform

Inherits:
Base
  • Object
show all
Defined in:
lib/objects/orchestration/interactive_terraform.rb

Constant Summary collapse

QUIT =
  • Provides access to the metadata framework, so that data may be shared between Orchestrative processes and Terraform

  • Transparent authorization, by passing in cloud authorisation details from the bcome session

  • Passes in SSH credentials directly, which can be used to bootstrap machines.

'\\q'
COMMAND_PROMPT =
"enter command or '#{QUIT}' to quit: " + 'terraform'.informational + "\s"

Instance Method Summary collapse

Methods inherited from Base

#do_execute, #method_missing

Constructor Details

#initialize(*params) ⇒ InteractiveTerraform

Returns a new instance of InteractiveTerraform.



14
15
16
17
# File 'lib/objects/orchestration/interactive_terraform.rb', line 14

def initialize(*params)
  super
  raise ::Bcome::Exception::Generic, "Missing terraform configuration directory #{path_to_env_config}" unless File.exist?(path_to_env_config)
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method in the class Bcome::Orchestration::Base

Instance Method Details

#backend_config_parameter_stringObject



86
87
88
89
90
91
92
93
94
95
# File 'lib/objects/orchestration/interactive_terraform.rb', line 86

def backend_config_parameter_string
  ## Backend configs are loaded before Terraform Core which means that we cannot use variables directly in our backend config.
  ## This is a pain as we'll have authorised with GCP via the console, and so all sesssion have an access token readily available.
  ## This patch passes the access token directly to terraform as a parameter.

  ## GCP only for now. Support for AWS may come later as needed/requested.
  return '' unless @node.network_driver.is_a?(::Bcome::Driver::Gcp)

  "\s-backend-config \"access_token=#{@node.network_driver.network_credentials[:access_token]}\"\s"
end

#command(raw_command) ⇒ Object

Formulate a terraform command



103
104
105
106
107
# File 'lib/objects/orchestration/interactive_terraform.rb', line 103

def command(raw_command)
  cmd = "cd #{path_to_env_config} ; terraform #{raw_command}"
  cmd = "#{cmd} #{var_string}" if raw_command =~ Regexp.new(/^apply$|plan|destroy|refresh/)
  cmd
end

#executeObject



19
20
21
22
# File 'lib/objects/orchestration/interactive_terraform.rb', line 19

def execute
  show_intro_text
  wait_for_command_input
end

#form_var_stringObject

Get the terraform variables for this stack, and merge in with our networking & ssh credentials



59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
# File 'lib/objects/orchestration/interactive_terraform.rb', line 59

def form_var_string
  terraform_vars = 

  terraform_vars.each do |key, value|
    # Join arrays into a string (note we cannot handle nested arrays yet)
    terraform_vars[key] = value.join(',') if value.is_a?(Array)
  end

  cleaned_data = terraform_vars.reject do |_k, v|
    v.is_a?(Hash)
  end # we can't yet handle nested terraform metadata on the command line so no hashes

  all_vars = cleaned_data

  if @node.network_driver.has_network_credentials?
    network_credentials = @node.network_driver.network_credentials
    all_vars = cleaned_data.merge(network_credentials)
  end

  all_vars[:ssh_user] = @node.ssh_driver.user
  all_vars.collect { |key, value| "-var #{key}=\"#{value}\"" }.join("\s")
end

#path_to_env_configObject

Retrieve the path to the terraform configurations for this stack



98
99
100
# File 'lib/objects/orchestration/interactive_terraform.rb', line 98

def path_to_env_config
  @path_to_env_config ||= "terraform/environments/#{@node.namespace.gsub(':', '_')}"
end

#process_command(raw_command) ⇒ Object

PROCESSING INTERACTIVE COMMANDS



36
37
38
39
40
# File 'lib/objects/orchestration/interactive_terraform.rb', line 36

def process_command(raw_command)
  full_command = command(raw_command)
  @node.execute_local(full_command)
  wait_for_command_input
end

#show_intro_textObject



24
25
26
27
28
29
30
31
32
# File 'lib/objects/orchestration/interactive_terraform.rb', line 24

def show_intro_text
  puts "\n\n"
  puts "Interactive Terraform\n".underline
  puts "Namespace:\s" + @node.namespace.to_s.informational
  puts "Configuration Path:\s" + "#{path_to_env_config}/*".informational
  puts "\nConfigured metadata:\s" + .inspect.informational

  puts "\nAny commands you enter here will be passed directly to Terraform in your configuration path scope."
end

#terraform_metadataObject

COMMAND PROCESSING



54
55
56
# File 'lib/objects/orchestration/interactive_terraform.rb', line 54

def 
  @terraform_metadata ||= @node..fetch('terraform', @node..fetch(:terraform, {}))
end

#var_stringObject



82
83
84
# File 'lib/objects/orchestration/interactive_terraform.rb', line 82

def var_string
  @var_string ||= form_var_string
end

#wait_for_command_inputObject

HANDLING USER INPUT



44
45
46
47
# File 'lib/objects/orchestration/interactive_terraform.rb', line 44

def wait_for_command_input
  raw_command = wait_for_input
  process_command(raw_command) unless raw_command == QUIT
end

#wait_for_input(message = COMMAND_PROMPT) ⇒ Object



49
50
51
# File 'lib/objects/orchestration/interactive_terraform.rb', line 49

def wait_for_input(message = COMMAND_PROMPT)
  ::Readline.readline("\n#{message}", true).squeeze('').to_s
end