Class: Cloudspin::Stack::Instance

Inherits:
Object
  • Object
show all
Includes:
FileUtils
Defined in:
lib/cloudspin/stack/instance.rb

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(id:, stack_definition:, working_folder:, configuration:) ⇒ Instance

Returns a new instance of Instance.



14
15
16
17
18
19
20
21
22
23
24
25
# File 'lib/cloudspin/stack/instance.rb', line 14

def initialize(
      id:,
      stack_definition:,
      working_folder:,
      configuration:
)
  validate_id(id)
  @id = id
  @stack_definition = stack_definition
  @working_folder   = working_folder
  @configuration    = configuration
end

Instance Attribute Details

#configurationObject (readonly)

Returns the value of attribute configuration.



10
11
12
# File 'lib/cloudspin/stack/instance.rb', line 10

def configuration
  @configuration
end

#idObject (readonly)

Returns the value of attribute id.



10
11
12
# File 'lib/cloudspin/stack/instance.rb', line 10

def id
  @id
end

#working_folderObject (readonly)

Returns the value of attribute working_folder.



10
11
12
# File 'lib/cloudspin/stack/instance.rb', line 10

def working_folder
  @working_folder
end

Class Method Details

.add_terraform_backend_source(terraform_source_folder) ⇒ Object



74
75
76
77
78
79
80
81
82
83
84
# File 'lib/cloudspin/stack/instance.rb', line 74

def self.add_terraform_backend_source(terraform_source_folder)
  puts "DEBUG: Creating file #{terraform_source_folder}/_cloudspin_created_backend.tf"
  File.open("#{terraform_source_folder}/_cloudspin_created_backend.tf", 'w') { |backend_file|
    backend_file.write(<<~TF_BACKEND_SOURCE
      terraform {
        backend "s3" {}
      }
    TF_BACKEND_SOURCE
    )
  }
end

.ensure_folder(folder) ⇒ Object



69
70
71
72
# File 'lib/cloudspin/stack/instance.rb', line 69

def self.ensure_folder(folder)
  FileUtils.mkdir_p folder
  Pathname.new(folder).realdirpath.to_s
end

.from_files(*instance_configuration_files, stack_name: nil, stack_definition:, base_folder: '.', base_working_folder:) ⇒ Object



43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
# File 'lib/cloudspin/stack/instance.rb', line 43

def self.from_files(
      *instance_configuration_files,
      stack_name: nil,
      stack_definition:,
      base_folder: '.',
      base_working_folder:
)
  instance_configuration = InstanceConfiguration.from_files(
    instance_configuration_files,
    stack_name: stack_name,
    stack_definition: stack_definition,
    base_folder: base_folder
  )

  if instance_configuration.has_remote_state_configuration? && stack_definition.is_from_remote?
    add_terraform_backend_source(stack_definition.source_path)
  end

  self.new(
      id: instance_configuration.instance_identifier,
      stack_definition: stack_definition,
      working_folder: ensure_folder("#{base_working_folder}/#{instance_configuration.instance_identifier}"),
      configuration: instance_configuration
    )
end

.from_folder(*instance_configuration_files, stack_name: nil, definition_location:, base_folder: '.', base_working_folder:) ⇒ Object



27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
# File 'lib/cloudspin/stack/instance.rb', line 27

def self.from_folder(
      *instance_configuration_files,
      stack_name: nil,
      definition_location:,
      base_folder: '.',
      base_working_folder:
)
  self.from_files(
      instance_configuration_files,
      stack_name: stack_name,
      stack_definition: Definition.from_location(definition_location),
      base_folder: base_folder,
      base_working_folder: base_working_folder
    )
end

Instance Method Details

#backend_parametersObject



224
225
226
227
228
229
230
# File 'lib/cloudspin/stack/instance.rb', line 224

def backend_parameters
  if configuration.has_remote_state_configuration?
    configuration.terraform_backend
  else
    {}
  end
end

#downObject



141
142
143
144
145
146
147
148
149
150
# File 'lib/cloudspin/stack/instance.rb', line 141

def down
  RubyTerraform.clean(directory: working_folder)
  mkdir_p File.dirname(working_folder)
  cp_r @stack_definition.source_path, working_folder
  ensure_state_folder
  Dir.chdir(working_folder) do
    terraform_init
    RubyTerraform.destroy(terraform_command_parameters(force: true))
  end
end

#down_dryObject



152
153
154
155
156
157
158
# File 'lib/cloudspin/stack/instance.rb', line 152

def down_dry
  down_command = RubyTerraform::Commands::Destroy.new
  command_line_builder = down_command.instantiate_builder
  configured_command = down_command.configure_command(command_line_builder, terraform_command_parameters)
  built_command = configured_command.build
  "cd #{working_folder} && #{built_command.to_s}"
end

#ensure_state_folderObject



198
199
200
201
202
# File 'lib/cloudspin/stack/instance.rb', line 198

def ensure_state_folder
  if configuration.has_local_state_configuration?
    Instance.ensure_folder(configuration.terraform_backend['statefile_folder'])
  end
end

#init_dryObject



176
177
178
179
180
181
182
183
184
185
# File 'lib/cloudspin/stack/instance.rb', line 176

def init_dry
  init_command = RubyTerraform::Commands::Init.new
  command_line_builder = init_command.instantiate_builder
  configured_command = init_command.configure_command(
    command_line_builder,
    terraform_init_params
  )
  built_command = configured_command.build
  "cd #{working_folder} && #{built_command.to_s}"
end

#local_state_parametersObject



216
217
218
219
220
221
222
# File 'lib/cloudspin/stack/instance.rb', line 216

def local_state_parameters
  if configuration.has_local_state_configuration?
    { state: configuration.local_statefile }
  else
    {}
  end
end

#parameter_valuesObject



92
93
94
# File 'lib/cloudspin/stack/instance.rb', line 92

def parameter_values
  configuration.parameter_values
end

#plan(plan_destroy: false) ⇒ Object



100
101
102
103
104
105
106
107
108
109
# File 'lib/cloudspin/stack/instance.rb', line 100

def plan(plan_destroy: false)
  RubyTerraform.clean(directory: working_folder)
  mkdir_p File.dirname(working_folder)
  cp_r @stack_definition.source_path, working_folder
  ensure_state_folder
  Dir.chdir(working_folder) do
    terraform_init
    RubyTerraform.plan(terraform_command_parameters(destroy: plan_destroy))
  end
end

#plan_dry(plan_destroy: false) ⇒ Object



111
112
113
114
115
116
117
118
119
120
# File 'lib/cloudspin/stack/instance.rb', line 111

def plan_dry(plan_destroy: false)
  plan_command = RubyTerraform::Commands::Plan.new
  command_line_builder = plan_command.instantiate_builder
  configured_command = plan_command.configure_command(
    command_line_builder,
    terraform_command_parameters(:destroy => plan_destroy)
  )
  built_command = configured_command.build
  "cd #{working_folder} && #{built_command.to_s}"
end

#refreshObject



160
161
162
163
164
165
166
167
168
169
# File 'lib/cloudspin/stack/instance.rb', line 160

def refresh
  RubyTerraform.clean(directory: working_folder)
  mkdir_p File.dirname(working_folder)
  cp_r @stack_definition.source_path, working_folder
  ensure_state_folder
  Dir.chdir(working_folder) do
    terraform_init
    RubyTerraform.refresh(terraform_command_parameters(force: true))
  end
end

#resource_valuesObject



96
97
98
# File 'lib/cloudspin/stack/instance.rb', line 96

def resource_values
  configuration.resource_values
end

#terraform_command_parameters(added_parameters = {}) ⇒ Object



204
205
206
207
208
# File 'lib/cloudspin/stack/instance.rb', line 204

def terraform_command_parameters(added_parameters = {})
  {
    vars: terraform_variables
  }.merge(local_state_parameters).merge(added_parameters)
end

#terraform_initObject



172
173
174
# File 'lib/cloudspin/stack/instance.rb', line 172

def terraform_init
  RubyTerraform.init(terraform_init_params)
end

#terraform_init_paramsObject



187
188
189
190
191
192
193
194
195
196
# File 'lib/cloudspin/stack/instance.rb', line 187

def terraform_init_params
  if configuration.has_remote_state_configuration?
    {
      backend: 'true',
      backend_config: backend_parameters
    }
  else
    {}
  end
end

#terraform_variablesObject



210
211
212
213
214
# File 'lib/cloudspin/stack/instance.rb', line 210

def terraform_variables
  parameter_values.merge(resource_values) { |key, oldval, newval|
    raise "Duplicate values for terraform variable '#{key}' ('#{oldval}' and '#{newval}')"
  }.merge({ 'instance_identifier' => id })
end

#upObject



122
123
124
125
126
127
128
129
130
131
# File 'lib/cloudspin/stack/instance.rb', line 122

def up
  RubyTerraform.clean(directory: working_folder)
  mkdir_p File.dirname(working_folder)
  cp_r @stack_definition.source_path, working_folder
  ensure_state_folder
  Dir.chdir(working_folder) do
    terraform_init
    RubyTerraform.apply(terraform_command_parameters(auto_approve: true))
  end
end

#up_dryObject



133
134
135
136
137
138
139
# File 'lib/cloudspin/stack/instance.rb', line 133

def up_dry
  up_command = RubyTerraform::Commands::Apply.new
  command_line_builder = up_command.instantiate_builder
  configured_command = up_command.configure_command(command_line_builder, terraform_command_parameters)
  built_command = configured_command.build
  "cd #{working_folder} && #{built_command.to_s}"
end

#validate_id(raw_id) ⇒ Object



86
87
88
89
90
# File 'lib/cloudspin/stack/instance.rb', line 86

def validate_id(raw_id)
  raise "Stack instance ID '#{raw_id}' won't work. It needs to work as a filename." if /[^0-9A-Za-z.\-\_]/ =~ raw_id
  raise "Stack instance ID '#{raw_id}' won't work. No double dots allowed." if /\.\./ =~ raw_id
  raise "Stack instance ID '#{raw_id}' won't work. First character should be a letter." if /^[^A-Za-z]/ =~ raw_id
end