cloudspin-stack 0.1.31 → 0.1.32

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 678301e9078d489fdeb291e89c89b211d00331c49602667ff731ed8b4e890854
4
- data.tar.gz: a08a9749c18e6a6ad20f12c4bbb229c32d2c6b6fab8453fd9f078377ccdab2cc
3
+ metadata.gz: 5068a21e5f23f92d3b1b193e2b7c7f59f95488643a3c3720508501f2fb473172
4
+ data.tar.gz: 549543ec361272038346e41cf139b4f94f5d9dc044c3b039c978dff116654e26
5
5
  SHA512:
6
- metadata.gz: 76f814c40a4775c4018ea824c56ace5a39711c336fcd26cf04c9d992f320ea059c5f44cdd5f868fd13086bfe52168b15f4a2c728f48b5e8785f1be156252bd54
7
- data.tar.gz: 3942f2712d44d275b154c2f234132e56e124e3cd0583b3693132669aefd9873eee9eed5d4b76a94b7b7ba9690e10f86c89318bb0ea556eb1f73f3ada80ff5965
6
+ metadata.gz: ff1b4c4f407821ab6529a63af72e5947160ae91a62978a7558ddc85c63b5a219fa62ec02885188fcac04a95c7fb4586e2456074f18318b3195771370ce13f53d
7
+ data.tar.gz: f482061aed3d5b2daab47ceeabf20f80eb0fca74a8ff2950693313b0fa7ed515a143a94977d2d36af7c3f8cb39a692743cc02c871fee427007120f3b9f464a93
data/lib/cloudspin/cli.rb CHANGED
@@ -27,32 +27,46 @@ module Cloudspin
27
27
  option :plan, :type => :boolean, :default => false
28
28
  option :'show-init', :type => :boolean, :default => true
29
29
  def up
30
- puts instance.init_dry if options[:'show-init']
30
+ puts terraform_runner.init_dry if options[:'show-init']
31
31
  if options[:plan] && options[:dry]
32
- puts instance.plan_dry
32
+ puts terraform_runner.plan_dry
33
33
  elsif options[:plan] && ! options[:dry]
34
- puts instance.plan
34
+ instance.prepare
35
+ puts terraform_runner.plan
35
36
  elsif ! options[:plan] && options[:dry]
36
- puts instance.up_dry
37
+ puts terraform_runner.up_dry
37
38
  else
38
- instance.up
39
+ instance.prepare
40
+ terraform_runner.up
39
41
  end
40
42
  end
41
43
 
44
+ desc 'prepare', 'Prepare the working folder and backend for the stack instance'
45
+ option :'show-init', :type => :boolean, :default => true
46
+ def prepare
47
+ instance.prepare
48
+ puts terraform_runner.init_dry if options[:'show-init']
49
+ puts terraform_runner.init
50
+ puts "Working folder prepared: #{instance.working_folder}"
51
+ puts "Ready:\ncd #{instance.working_folder} && terraform apply"
52
+ end
53
+
42
54
  desc 'down', 'Destroy the stack instance'
43
55
  option :dry, :type => :boolean, :default => false
44
56
  option :plan, :type => :boolean, :default => false
45
57
  option :'show-init', :type => :boolean, :default => true
46
58
  def down
47
- puts instance.init_dry if options[:'show-init']
59
+ puts terraform_runner.init_dry if options[:'show-init']
48
60
  if options[:plan] && options[:dry]
49
- puts instance.plan_dry(plan_destroy: true)
61
+ puts terraform_runner.plan_dry(plan_destroy: true)
50
62
  elsif options[:plan] && ! options[:dry]
51
- puts instance.plan(plan_destroy: true)
63
+ instance.prepare
64
+ puts terraform_runner.plan(plan_destroy: true)
52
65
  elsif ! options[:plan] && options[:dry]
53
- puts instance.down_dry
66
+ puts terraform_runner.down_dry
54
67
  else
55
- instance.down
68
+ instance.prepare
69
+ terraform_runner.down
56
70
  end
57
71
  end
58
72
 
@@ -77,6 +91,14 @@ module Cloudspin
77
91
  )
78
92
  end
79
93
 
94
+ def terraform_runner
95
+ Cloudspin::Stack::Terraform.new(
96
+ working_folder: instance.working_folder,
97
+ terraform_variables: instance.terraform_variables,
98
+ terraform_init_arguments: instance.terraform_init_arguments
99
+ )
100
+ end
101
+
80
102
  def instance_configuration_files
81
103
  file_list = options[:file]
82
104
  if options[:environment]
@@ -4,3 +4,4 @@ require 'cloudspin/stack/definition'
4
4
  require 'cloudspin/stack/backend_configuration'
5
5
  require 'cloudspin/stack/instance_configuration'
6
6
  require 'cloudspin/stack/instance'
7
+ require 'cloudspin/stack/terraform'
@@ -19,24 +19,37 @@ module Cloudspin
19
19
  @stack_name = stack_name
20
20
  @base_folder = base_folder
21
21
 
22
- @has_remote_state = ! @terraform_backend_configuration_values['bucket'].nil?
22
+ configure_for_remote_backend
23
+ configure_to_migrate_backend
24
+ configure_for_local_backend
25
+ end
23
26
 
24
- if @has_remote_state
27
+ def configure_for_remote_backend
28
+ @has_remote_state = if @terraform_backend_configuration_values['bucket'].nil?
29
+ false
30
+ else
25
31
  # puts "DEBUG: Using remote state"
26
32
  @local_state_folder = nil
27
33
  @local_statefile = nil
28
34
  @terraform_backend_configuration_values['key'] = default_state_key
29
- @migrate_state = initialize_migrate_flag
35
+ true
36
+ end
37
+ end
38
+
39
+ def configure_to_migrate_backend
40
+ @migrate_state = if @terraform_backend_configuration_values['migrate'].nil?
41
+ false
30
42
  else
31
- # puts "DEBUG: Not using remote state"
32
- @migrate_state = false
43
+ migrate_value = @terraform_backend_configuration_values.delete('migrate')
44
+ migrate_value.to_s.downcase == 'true'
33
45
  end
46
+ end
34
47
 
48
+ def configure_for_local_backend
35
49
  if !@has_remote_state || @migrate_state
36
- @local_state_folder = intialize_state_folder
50
+ # puts "DEBUG: Not using remote state, or else is migrating state"
51
+ @local_state_folder = "#{@base_folder}/state/#{@instance_identifier}"
37
52
  @local_statefile = "#{@local_state_folder}/#{@instance_identifier}.tfstate"
38
- # puts "DEBUG: Local statefile: #{@local_statefile}"
39
- # puts "DEBUG: Migrating? #{@migrate_state}"
40
53
  end
41
54
  end
42
55
 
@@ -62,21 +75,34 @@ module Cloudspin
62
75
  end
63
76
  end
64
77
 
65
- def intialize_state_folder
66
- # TODO: Prefer to not actually create the folder, but seemed necessary to build the full path string.
67
- FileUtils.mkdir_p "#{@base_folder}/state"
68
- Pathname.new("#{@base_folder}/state/#{@instance_identifier}").realdirpath.to_s
69
- end
70
-
71
- def initialize_migrate_flag
72
- if @terraform_backend_configuration_values['migrate'].nil?
73
- false
78
+ def prepare(working_folder:)
79
+ if remote_state?
80
+ add_backend_terraform_file(working_folder)
81
+ # puts "DEBUG: Prepare for use of remote state"
74
82
  else
75
- migrate_value = @terraform_backend_configuration_values.delete('migrate')
76
- migrate_value.to_s.downcase == 'true'
83
+ # puts "DEBUG: Prepare for use of local state"
84
+ create_local_state_folder
77
85
  end
78
86
  end
79
87
 
88
+ def add_backend_terraform_file(working_folder)
89
+ # puts "DEBUG: Creating file #{working_folder}/_cloudspin_backend.tf"
90
+ File.open("#{working_folder}/_cloudspin_backend.tf", 'w') { |backend_file|
91
+ backend_file.write(<<~TF_BACKEND_SOURCE
92
+ terraform {
93
+ backend "s3" {}
94
+ }
95
+ TF_BACKEND_SOURCE
96
+ )
97
+ }
98
+ end
99
+
100
+ def create_local_state_folder
101
+ # puts "DEBUG: backend_configuration.create_local_state_folder: #{@local_state_folder}"
102
+ FileUtils.mkdir_p @local_state_folder
103
+ # Pathname.new(@local_state_folder).realdirpath.to_s
104
+ end
105
+
80
106
  def default_state_key
81
107
  "#{@instance_identifier}.tfstate"
82
108
  end
@@ -1,4 +1,3 @@
1
- require 'ruby_terraform'
2
1
  require 'fileutils'
3
2
 
4
3
  module Cloudspin
@@ -8,20 +7,25 @@ module Cloudspin
8
7
  include FileUtils
9
8
 
10
9
  attr_reader :id,
11
- :working_folder,
12
- :configuration
10
+ :configuration,
11
+ :working_folder,
12
+ :backend_configuration,
13
+ :terraform_command_arguments
13
14
 
14
15
  def initialize(
15
16
  id:,
16
17
  stack_definition:,
17
- working_folder:,
18
+ base_working_folder:,
18
19
  configuration:
19
20
  )
20
21
  validate_id(id)
21
22
  @id = id
22
23
  @stack_definition = stack_definition
23
- @working_folder = working_folder
24
+ @working_folder = "#{base_working_folder}/#{id}"
24
25
  @configuration = configuration
26
+ @backend_configuration = configuration.backend_configuration
27
+ @terraform_command_arguments = {}
28
+ # puts "DEBUG: instance working_folder: #{@working_folder}"
25
29
  end
26
30
 
27
31
  def self.from_folder(
@@ -54,35 +58,50 @@ module Cloudspin
54
58
  base_folder: base_folder
55
59
  )
56
60
 
57
- if instance_configuration.has_remote_state_configuration? && stack_definition.is_from_remote?
58
- # puts "DEBUG: Stack instance is configured to use remote terraform state AND remote stack definition code"
59
- add_backend_configuration_source(stack_definition.source_path)
60
- # else
61
- # puts "DEBUG: Stack instance is configured to use local terraform state AND/OR local stack definition code"
62
- end
63
-
64
61
  self.new(
65
62
  id: instance_configuration.instance_identifier,
66
63
  stack_definition: stack_definition,
67
- working_folder: ensure_folder("#{base_working_folder}/#{instance_configuration.instance_identifier}"),
64
+ base_working_folder: base_working_folder,
68
65
  configuration: instance_configuration
69
66
  )
70
67
  end
71
68
 
72
- def self.ensure_folder(folder)
69
+ def prepare
70
+ clean_working_folder
71
+ create_working_folder
72
+ copy_instance_source
73
+ prepare_state
74
+ create_variables_file
75
+ @working_folder
76
+ end
77
+
78
+ def clean_working_folder
79
+ FileUtils.rm_rf(working_folder)
80
+ end
81
+
82
+ def create_working_folder
83
+ mkdir_p File.dirname(working_folder)
84
+ end
85
+
86
+ def copy_instance_source
87
+ cp_r @stack_definition.source_path, working_folder
88
+ end
89
+
90
+ def ensure_folder(folder)
73
91
  FileUtils.mkdir_p folder
74
92
  Pathname.new(folder).realdirpath.to_s
75
93
  end
76
94
 
77
- def self.add_backend_configuration_source(terraform_source_folder)
78
- # puts "DEBUG: Creating file #{terraform_source_folder}/_cloudspin_created_backend.tf"
79
- File.open("#{terraform_source_folder}/_cloudspin_created_backend.tf", 'w') { |backend_file|
80
- backend_file.write(<<~TF_BACKEND_SOURCE
81
- terraform {
82
- backend "s3" {}
83
- }
84
- TF_BACKEND_SOURCE
85
- )
95
+ def prepare_state
96
+ @backend_configuration.prepare(working_folder: working_folder)
97
+ end
98
+
99
+ def create_variables_file
100
+ # puts "DEBUG: Creating file #{working_folder}/_cloudspin-#{id}.auto.tfvars"
101
+ File.open("#{working_folder}/_cloudspin-#{id}.auto.tfvars", 'w') { |tfvars_file|
102
+ tfvars_file.write("# Automatically generated by cloudspin\n")
103
+ tfvars_file.write(terraform_variables.map { |name,value| "#{name} = \"#{value}\"" }.join("\n"))
104
+ tfvars_file.write("\n")
86
105
  }
87
106
  end
88
107
 
@@ -100,138 +119,42 @@ module Cloudspin
100
119
  configuration.resource_values
101
120
  end
102
121
 
122
+ def terraform_variables
123
+ parameter_values.merge(resource_values) { |key, oldval, newval|
124
+ raise "Duplicate values for terraform variable '#{key}' ('#{oldval}' and '#{newval}')"
125
+ }.merge({ 'instance_identifier' => id })
126
+ end
127
+
128
+ def terraform_init_arguments
129
+ @backend_configuration.terraform_init_parameters
130
+ end
131
+
132
+ def terraform_command_arguments
133
+ @backend_configuration.terraform_command_parameters
134
+ end
135
+
103
136
  # def migrate
104
137
  # RubyTerraform.clean(directory: working_folder)
105
138
  # mkdir_p File.dirname(working_folder)
106
139
  # cp_r @stack_definition.source_path, working_folder
107
140
  # Dir.chdir(working_folder) do
108
- # # cp configuration.backend_configuration.local_state_folder
141
+ # # cp @backend_configuration.local_state_folder
109
142
  # terraform_init
110
143
  # # terraform_state_push()
111
144
  # RubyTerraform.plan(terraform_command_parameters)
112
145
  # end
113
146
  # end
114
147
 
115
- def plan(plan_destroy: false)
116
- RubyTerraform.clean(directory: working_folder)
117
- mkdir_p File.dirname(working_folder)
118
- cp_r @stack_definition.source_path, working_folder
119
- ensure_state_folder
120
- Dir.chdir(working_folder) do
121
- terraform_init
122
- RubyTerraform.plan(terraform_command_parameters(destroy: plan_destroy))
123
- end
124
- end
125
-
126
- def plan_dry(plan_destroy: false)
127
- plan_command = RubyTerraform::Commands::Plan.new
128
- command_line_builder = plan_command.instantiate_builder
129
- configured_command = plan_command.configure_command(
130
- command_line_builder,
131
- terraform_command_parameters(:destroy => plan_destroy)
132
- )
133
- built_command = configured_command.build
134
- "cd #{working_folder} && #{built_command.to_s}"
135
- end
136
-
137
- def up
138
- RubyTerraform.clean(directory: working_folder)
139
- mkdir_p File.dirname(working_folder)
140
- cp_r @stack_definition.source_path, working_folder
141
- ensure_state_folder
142
- Dir.chdir(working_folder) do
143
- terraform_init
144
- RubyTerraform.apply(terraform_command_parameters(auto_approve: true))
145
- end
146
- end
147
-
148
- def up_dry
149
- up_command = RubyTerraform::Commands::Apply.new
150
- command_line_builder = up_command.instantiate_builder
151
- configured_command = up_command.configure_command(command_line_builder, terraform_command_parameters)
152
- built_command = configured_command.build
153
- "cd #{working_folder} && #{built_command.to_s}"
154
- end
155
-
156
- def down
157
- RubyTerraform.clean(directory: working_folder)
158
- mkdir_p File.dirname(working_folder)
159
- cp_r @stack_definition.source_path, working_folder
160
- ensure_state_folder
161
- Dir.chdir(working_folder) do
162
- terraform_init
163
- RubyTerraform.destroy(terraform_command_parameters(force: true))
164
- end
165
- end
166
-
167
- def down_dry
168
- down_command = RubyTerraform::Commands::Destroy.new
169
- command_line_builder = down_command.instantiate_builder
170
- configured_command = down_command.configure_command(command_line_builder, terraform_command_parameters)
171
- built_command = configured_command.build
172
- "cd #{working_folder} && #{built_command.to_s}"
173
- end
174
-
175
- def refresh
176
- RubyTerraform.clean(directory: working_folder)
177
- mkdir_p File.dirname(working_folder)
178
- cp_r @stack_definition.source_path, working_folder
179
- ensure_state_folder
180
- Dir.chdir(working_folder) do
181
- terraform_init
182
- RubyTerraform.refresh(terraform_command_parameters(force: true))
183
- end
184
- end
185
-
186
- def terraform_init
187
- if configuration.backend_configuration.migrate_state?
188
- prepare_state_for_migration
189
- end
190
- RubyTerraform.init(terraform_init_params)
191
- end
192
-
193
- def prepare_state_for_migration
194
- # puts "DEBUG: Preparing to migrate state from #{configuration.backend_configuration.local_statefile}"
195
- cp configuration.backend_configuration.local_statefile, "#{working_folder}/terraform.tfstate"
196
- end
197
-
198
- def init_dry
199
- if configuration.backend_configuration.migrate_state?
200
- "cp #{configuration.backend_configuration.local_statefile} -> #{working_folder}/terraform.tfstate"
201
- end
202
- init_command = RubyTerraform::Commands::Init.new
203
- command_line_builder = init_command.instantiate_builder
204
- configured_command = init_command.configure_command(
205
- command_line_builder,
206
- terraform_init_params
207
- )
208
- built_command = configured_command.build
209
- "cd #{working_folder} && #{built_command.to_s}"
210
- end
211
-
212
- def terraform_init_params
213
- configuration.backend_configuration.terraform_init_parameters
214
- end
215
-
216
- # TODO: Redundant? The folder is created in the BackendConfiguration class ...
217
- def ensure_state_folder
218
- if configuration.has_local_state_configuration?
219
- Instance.ensure_folder(configuration.backend_configuration.local_state_folder)
220
- end
221
- end
222
-
223
- def terraform_command_parameters(added_parameters = {})
224
- {
225
- vars: terraform_variables
226
- }.merge(configuration.backend_configuration.terraform_command_parameters)
227
- .merge(added_parameters)
228
- end
148
+ # def init
149
+ # if @backend_configuration.migrate_state?
150
+ # prepare_state_for_migration
151
+ # end
152
+ # end
229
153
 
230
- def terraform_variables
231
- parameter_values.merge(resource_values) { |key, oldval, newval|
232
- raise "Duplicate values for terraform variable '#{key}' ('#{oldval}' and '#{newval}')"
233
- }.merge({ 'instance_identifier' => id })
234
- end
154
+ # def prepare_state_for_migration
155
+ # # puts "DEBUG: Preparing to migrate state from #{@backend_configuration.local_statefile}"
156
+ # cp @backend_configuration.local_statefile, "#{working_folder}/terraform.tfstate"
157
+ # end
235
158
 
236
159
  end
237
160
  end
@@ -17,9 +17,6 @@ module Cloudspin
17
17
  attr_reader :instance_identifier
18
18
  attr_reader :backend_configuration
19
19
 
20
-
21
- attr_reader :Xterraform_backend
22
-
23
20
  def initialize(
24
21
  configuration_values: {},
25
22
  stack_definition:,
@@ -0,0 +1,128 @@
1
+ require 'ruby_terraform'
2
+ require 'fileutils'
3
+
4
+ module Cloudspin
5
+ module Stack
6
+ class Terraform
7
+
8
+ # KSM: Maybe this should be a static class - pass in the working directory and
9
+ # the arguments, and call them. All the logic of assembling the command line
10
+ # arguments should be in the caller?? Since I want the caller to be able to
11
+ # spit out the things in a variables file, for instance.
12
+ def initialize(
13
+ working_folder: '.',
14
+ terraform_variables: {},
15
+ terraform_init_arguments: {}
16
+ )
17
+ @working_folder = working_folder
18
+ # @terraform_variables = terraform_variables
19
+ @terraform_variables = {}
20
+ @terraform_init_arguments = terraform_init_arguments
21
+ end
22
+
23
+ def plan(plan_destroy: false)
24
+ Dir.chdir(@working_folder) do
25
+ terraform_init
26
+ RubyTerraform.plan(terraform_command_parameters(destroy: plan_destroy))
27
+ end
28
+ end
29
+
30
+ def plan_dry(plan_destroy: false)
31
+ plan_command = RubyTerraform::Commands::Plan.new
32
+ command_line_builder = plan_command.instantiate_builder
33
+ configured_command = plan_command.configure_command(
34
+ command_line_builder,
35
+ terraform_command_parameters(:destroy => plan_destroy)
36
+ )
37
+ built_command = configured_command.build
38
+ "cd #{@working_folder} && #{built_command.to_s}"
39
+ end
40
+
41
+ def up
42
+ # RubyTerraform.clean(directory: @working_folder)
43
+ # mkdir_p File.dirname(@working_folder)
44
+ # cp_r @stack_definition.source_path, @working_folder
45
+ # ensure_state_folder
46
+ Dir.chdir(@working_folder) do
47
+ terraform_init
48
+ RubyTerraform.apply(terraform_command_parameters(auto_approve: true))
49
+ end
50
+ end
51
+
52
+ def up_dry
53
+ up_command = RubyTerraform::Commands::Apply.new
54
+ command_line_builder = up_command.instantiate_builder
55
+ configured_command = up_command.configure_command(command_line_builder, terraform_command_parameters)
56
+ built_command = configured_command.build
57
+ "cd #{@working_folder} && #{built_command.to_s}"
58
+ end
59
+
60
+ def down
61
+ # RubyTerraform.clean(directory: @working_folder)
62
+ # mkdir_p File.dirname(@working_folder)
63
+ # cp_r @stack_definition.source_path, @working_folder
64
+ # ensure_state_folder
65
+ Dir.chdir(@working_folder) do
66
+ terraform_init
67
+ RubyTerraform.destroy(terraform_command_parameters(force: true))
68
+ end
69
+ end
70
+
71
+ def down_dry
72
+ down_command = RubyTerraform::Commands::Destroy.new
73
+ command_line_builder = down_command.instantiate_builder
74
+ configured_command = down_command.configure_command(command_line_builder, terraform_command_parameters)
75
+ built_command = configured_command.build
76
+ "cd #{@working_folder} && #{built_command.to_s}"
77
+ end
78
+
79
+ def refresh
80
+ # RubyTerraform.clean(directory: @working_folder)
81
+ # mkdir_p File.dirname(@working_folder)
82
+ # cp_r @stack_definition.source_path, @working_folder
83
+ # ensure_state_folder
84
+ Dir.chdir(@working_folder) do
85
+ terraform_init
86
+ RubyTerraform.refresh(terraform_command_parameters(force: true))
87
+ end
88
+ end
89
+
90
+ def terraform_init
91
+ RubyTerraform.init(@terraform_init_arguments)
92
+ end
93
+
94
+ def init
95
+ Dir.chdir(@working_folder) do
96
+ terraform_init
97
+ end
98
+ end
99
+
100
+ def init_dry
101
+ # if configuration.backend_configuration.migrate_state?
102
+ # "cp #{configuration.backend_configuration.local_statefile} -> #{@working_folder}/terraform.tfstate"
103
+ # end
104
+ init_command = RubyTerraform::Commands::Init.new
105
+ command_line_builder = init_command.instantiate_builder
106
+ configured_command = init_command.configure_command(
107
+ command_line_builder,
108
+ @terraform_init_arguments
109
+ )
110
+ built_command = configured_command.build
111
+ "cd #{@working_folder} && #{built_command.to_s}"
112
+ end
113
+
114
+ # KSM: Do we have this here, or do we munge all this up in the calling method and
115
+ # just pass in the processed list of arguments?
116
+ # For that matter, should we just call each of the actions on this class as static
117
+ # methods? Does this class really need to hold any kind of state?
118
+
119
+ def terraform_command_parameters(added_parameters = {})
120
+ {
121
+ vars: @terraform_variables
122
+ }.merge(added_parameters)
123
+ end
124
+
125
+ end
126
+ end
127
+ end
128
+
@@ -1,5 +1,5 @@
1
1
  module Cloudspin
2
2
  module Stack
3
- VERSION = '0.1.31'
3
+ VERSION = '0.1.32'
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cloudspin-stack
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.31
4
+ version: 0.1.32
5
5
  platform: ruby
6
6
  authors:
7
7
  - 'kief '
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2018-11-19 00:00:00.000000000 Z
11
+ date: 2018-12-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: ruby-terraform
@@ -136,6 +136,7 @@ files:
136
136
  - lib/cloudspin/stack/instance.rb
137
137
  - lib/cloudspin/stack/instance_configuration.rb
138
138
  - lib/cloudspin/stack/remote_definition.rb
139
+ - lib/cloudspin/stack/terraform.rb
139
140
  - lib/cloudspin/stack/version.rb
140
141
  homepage: https://github.com/cloudspinners
141
142
  licenses: