vanagon 0.8.2 → 0.9.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +1 -0
- data/bin/build +1 -1
- data/lib/vanagon/component/dsl.rb +14 -24
- data/lib/vanagon/component/source/git.rb +1 -6
- data/lib/vanagon/component/source/http.rb +7 -0
- data/lib/vanagon/component/source/local.rb +8 -2
- data/lib/vanagon/driver.rb +31 -11
- data/lib/vanagon/engine/always_be_scheduling.rb +92 -0
- data/lib/vanagon/engine/base.rb +1 -2
- data/lib/vanagon/engine/hardware.rb +1 -1
- data/lib/vanagon/engine/pooler.rb +42 -10
- data/lib/vanagon/optparse.rb +1 -0
- data/lib/vanagon/platform.rb +10 -7
- data/lib/vanagon/platform/dsl.rb +13 -2
- data/lib/vanagon/project.rb +41 -3
- data/lib/vanagon/project/dsl.rb +9 -4
- data/lib/vanagon/utilities.rb +10 -13
- data/resources/Makefile.erb +1 -1
- data/resources/rpm/project.spec.erb +9 -0
- data/spec/fixtures/files/fake_dir/fake_file.txt +0 -0
- data/spec/fixtures/files/fake_nested_dir/fake_dir/fake_file.txt +0 -0
- data/spec/lib/vanagon/component/dsl_spec.rb +51 -2
- data/spec/lib/vanagon/component/source/git_spec.rb +8 -0
- data/spec/lib/vanagon/component/source/http_spec.rb +15 -15
- data/spec/lib/vanagon/component/source/local_spec.rb +17 -1
- data/spec/lib/vanagon/component/source_spec.rb +1 -1
- data/spec/lib/vanagon/driver_spec.rb +33 -1
- data/spec/lib/vanagon/engine/always_be_scheduling_spec.rb +84 -0
- data/spec/lib/vanagon/engine/pooler_spec.rb +80 -16
- data/spec/lib/vanagon/platform/dsl_spec.rb +14 -0
- data/spec/lib/vanagon/platform/windows_spec.rb +2 -2
- data/spec/lib/vanagon/project_spec.rb +79 -5
- data/spec/lib/vanagon/utilities_spec.rb +5 -0
- data/spec/spec_helper.rb +22 -2
- metadata +29 -24
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 66a9286e3d7f89a5d145e4a5745cbb4d08ac9276
|
4
|
+
data.tar.gz: 6e1cf377bd79799c726e583bd8401d81fc8e1475
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 594d72e7506ae70075e34a690981f144b4d332204ceeee433462aaa82ec9611baf12f3e516d9283598532d4bc150b097b1d2fd2491f3d566feddb024cfb1e0bc
|
7
|
+
data.tar.gz: f2387a452a90af391f7cff1a5e498bb2322cc4ce8729b6fa26c6c43166173a0dd44285814bb1a2ab0009ec8d5b3b720e1b7dc7167a9f8707c2725689d3669fc1
|
data/README.md
CHANGED
@@ -68,6 +68,7 @@ the comma). If less targets are specified than platforms, the default engine
|
|
68
68
|
(`pooler`) will be used for platforms without a target. If more targets are specified
|
69
69
|
than platforms, the extra platforms will be ignored.
|
70
70
|
|
71
|
+
Build machines should be cleaned between builds.
|
71
72
|
|
72
73
|
#### Flagged arguments (can be anywhere in the command)
|
73
74
|
|
data/bin/build
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
load File.expand_path(File.join(File.dirname(__FILE__), "..", "lib", "vanagon.rb"))
|
3
3
|
|
4
4
|
optparse = Vanagon::OptParse.new("#{File.basename(__FILE__)} <project-name> <platform-name> [<target>] [options]",
|
5
|
-
[:workdir, :configdir, :engine, :preserve, :verbose, :skipcheck])
|
5
|
+
[:workdir, :configdir, :engine, :preserve, :verbose, :skipcheck, :only_build])
|
6
6
|
options = optparse.parse! ARGV
|
7
7
|
|
8
8
|
project = ARGV[0]
|
@@ -39,8 +39,8 @@ class Vanagon
|
|
39
39
|
# We only magically handle get_ methods, any other methods just get the
|
40
40
|
# standard method_missing treatment.
|
41
41
|
#
|
42
|
-
def method_missing(
|
43
|
-
attribute_match =
|
42
|
+
def method_missing(method_name, *args)
|
43
|
+
attribute_match = method_name.to_s.match(/get_(.*)/)
|
44
44
|
if attribute_match
|
45
45
|
attribute = attribute_match.captures.first
|
46
46
|
else
|
@@ -50,6 +50,10 @@ class Vanagon
|
|
50
50
|
@component.send(attribute)
|
51
51
|
end
|
52
52
|
|
53
|
+
def respond_to_missing?(method_name, include_private = false)
|
54
|
+
method_name.to_s.start_with?('get_') || super
|
55
|
+
end
|
56
|
+
|
53
57
|
# Set or add to the configure call for the component. The commands required to configure the component before building it.
|
54
58
|
#
|
55
59
|
# @param block [Proc] the command(s) required to configure the component
|
@@ -273,29 +277,15 @@ class Vanagon
|
|
273
277
|
@component.url = the_url
|
274
278
|
end
|
275
279
|
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
@component.options[:sum] = md5
|
281
|
-
@component.options[:sum_type] = "md5"
|
282
|
-
end
|
283
|
-
|
284
|
-
# Sets the sha256 sum to verify the sum of the source
|
285
|
-
#
|
286
|
-
# @param sha256 [String] sha256 sum of the source for verification
|
287
|
-
def sha256sum(sha256)
|
288
|
-
@component.options[:sum] = sha256
|
289
|
-
@component.options[:sum_type] = "sha256"
|
290
|
-
end
|
291
|
-
|
292
|
-
# Sets the sha512 sum to verify the sum of the source
|
293
|
-
#
|
294
|
-
# @param sha512 [String] sha512 sum of the source for verification
|
295
|
-
def sha512sum(sha512)
|
296
|
-
@component.options[:sum] = sha512
|
297
|
-
@component.options[:sum_type] = "sha512"
|
280
|
+
def sum(value)
|
281
|
+
type = __callee__.to_s.gsub(/sum$/, '')
|
282
|
+
@component.options[:sum] = value
|
283
|
+
@component.options[:sum_type] = type
|
298
284
|
end
|
285
|
+
alias_method :md5sum, :sum
|
286
|
+
alias_method :sha1sum, :sum
|
287
|
+
alias_method :sha256sum, :sum
|
288
|
+
alias_method :sha512sum, :sum
|
299
289
|
|
300
290
|
# Sets the ref of the source for use in a git source
|
301
291
|
#
|
@@ -30,7 +30,7 @@ class Vanagon
|
|
30
30
|
# Default options used when cloning; this may expand
|
31
31
|
# or change over time.
|
32
32
|
def default_options
|
33
|
-
@default_options ||= { ref: "
|
33
|
+
@default_options ||= { ref: "HEAD" }
|
34
34
|
end
|
35
35
|
private :default_options
|
36
36
|
|
@@ -46,7 +46,6 @@ class Vanagon
|
|
46
46
|
@url = URI.parse(url.to_s)
|
47
47
|
@ref = opts[:ref]
|
48
48
|
@workdir = workdir
|
49
|
-
@ref_name, @ref_type, = @ref.split('/', 3).reverse
|
50
49
|
|
51
50
|
# We can test for Repo existence without cloning
|
52
51
|
raise Vanagon::InvalidRepo, "#{url} not a valid Git repo" unless valid_remote?
|
@@ -62,10 +61,6 @@ class Vanagon
|
|
62
61
|
update_submodules
|
63
62
|
end
|
64
63
|
|
65
|
-
def ref
|
66
|
-
@ref_name || @ref
|
67
|
-
end
|
68
|
-
|
69
64
|
# Return the correct incantation to cleanup the source directory for a given source
|
70
65
|
#
|
71
66
|
# @return [String] command to cleanup the source
|
@@ -12,6 +12,9 @@ class Vanagon
|
|
12
12
|
# Accessors :url, :file, :extension, :workdir, :cleanup are inherited from Local
|
13
13
|
attr_accessor :sum, :sum_type
|
14
14
|
|
15
|
+
# Allowed checksum algorithms to use when validating files
|
16
|
+
CHECKSUM_TYPES = %w(md5 sha1 sha256 sha512).freeze
|
17
|
+
|
15
18
|
class << self
|
16
19
|
def valid_url?(target_url) # rubocop:disable Metrics/AbcSize
|
17
20
|
uri = URI.parse(target_url.to_s)
|
@@ -51,6 +54,10 @@ class Vanagon
|
|
51
54
|
unless sum_type
|
52
55
|
fail "sum_type is required to validate the http source"
|
53
56
|
end
|
57
|
+
unless CHECKSUM_TYPES.include? sum_type
|
58
|
+
fail %(checksum type "#{sum_type}" is invalid; please use #{CHECKSUM_TYPES.join(', ')})
|
59
|
+
end
|
60
|
+
|
54
61
|
@url = url
|
55
62
|
@sum = sum
|
56
63
|
@workdir = workdir
|
@@ -60,7 +60,7 @@ class Vanagon
|
|
60
60
|
def copy
|
61
61
|
puts "Copying file '#{url.basename}' to workdir"
|
62
62
|
|
63
|
-
FileUtils.
|
63
|
+
FileUtils.cp_r(url, file)
|
64
64
|
end
|
65
65
|
alias_method :fetch, :copy
|
66
66
|
|
@@ -148,7 +148,13 @@ class Vanagon
|
|
148
148
|
# @return [String] the directory that should be traversed into to build this source
|
149
149
|
# @raise [RuntimeError] if the @extension for the @file isn't currently handled by the method
|
150
150
|
def dirname
|
151
|
-
|
151
|
+
# We are not treating file as a Pathname since other sources can inherit from this class
|
152
|
+
# which could cause file to be a URI instead of a string.
|
153
|
+
if archive? || File.directory?(file)
|
154
|
+
File.basename(file, extension)
|
155
|
+
else
|
156
|
+
'./'
|
157
|
+
end
|
152
158
|
end
|
153
159
|
|
154
160
|
# Wrapper around the class method '.mangle'
|
data/lib/vanagon/driver.rb
CHANGED
@@ -13,12 +13,13 @@ class Vanagon
|
|
13
13
|
attr_accessor :platform, :project, :target, :workdir, :verbose, :preserve
|
14
14
|
attr_accessor :timeout, :retry_count
|
15
15
|
|
16
|
-
def initialize(platform, project, options = { :configdir => nil, :target => nil, :engine => nil, :components => nil, :skipcheck => false, :verbose => false, :preserve => false }) # rubocop:disable Metrics/AbcSize
|
16
|
+
def initialize(platform, project, options = { :configdir => nil, :target => nil, :engine => nil, :components => nil, :skipcheck => false, :verbose => false, :preserve => false, :only_build => nil }) # rubocop:disable Metrics/AbcSize
|
17
17
|
@verbose = options[:verbose]
|
18
18
|
@preserve = options[:preserve]
|
19
19
|
|
20
20
|
@@configdir = options[:configdir] || File.join(Dir.pwd, "configs")
|
21
21
|
components = options[:components] || []
|
22
|
+
only_build = options[:only_build]
|
22
23
|
target = options[:target]
|
23
24
|
engine = options[:engine] || 'pooler'
|
24
25
|
|
@@ -26,6 +27,7 @@ class Vanagon
|
|
26
27
|
@project = Vanagon::Project.load_project(project, File.join(@@configdir, "projects"), @platform, components)
|
27
28
|
@project.settings[:verbose] = options[:verbose]
|
28
29
|
@project.settings[:skipcheck] = options[:skipcheck]
|
30
|
+
filter_out_components(only_build) if only_build
|
29
31
|
loginit('vanagon_hosts.log')
|
30
32
|
|
31
33
|
load_engine(engine, @platform, target)
|
@@ -33,24 +35,42 @@ class Vanagon
|
|
33
35
|
raise Vanagon::Error.wrap(e, "Could not load the desired engine '#{engine}'")
|
34
36
|
end
|
35
37
|
|
38
|
+
def filter_out_components(only_build)
|
39
|
+
# map each element in the only_build array to it's set of filtered components, then
|
40
|
+
# flatten all the results in to one array and set project.components to that.
|
41
|
+
@project.components = only_build.flat_map { |comp| @project.filter_component(comp) }.uniq
|
42
|
+
if @verbose
|
43
|
+
puts "Only building:"
|
44
|
+
@project.components.each { |comp| puts comp.name }
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
36
48
|
def load_engine(engine_type, platform, target)
|
37
|
-
if
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
49
|
+
if engine_type != 'always_be_scheduling'
|
50
|
+
if platform.build_hosts
|
51
|
+
engine_type = 'hardware'
|
52
|
+
elsif platform.aws_ami
|
53
|
+
engine_type = 'ec2'
|
54
|
+
elsif platform.docker_image
|
55
|
+
engine_type = 'docker'
|
56
|
+
elsif target
|
57
|
+
engine_type = 'base'
|
58
|
+
end
|
45
59
|
end
|
46
60
|
load_engine_object(engine_type, platform, target)
|
47
61
|
end
|
48
62
|
|
49
63
|
def load_engine_object(engine_type, platform, target)
|
50
64
|
require "vanagon/engine/#{engine_type}"
|
51
|
-
@engine = Object::const_get("Vanagon::Engine::#{engine_type
|
65
|
+
@engine = Object::const_get("Vanagon::Engine::#{camelize(engine_type)}").new(platform, target)
|
52
66
|
rescue
|
53
|
-
fail "No such engine '#{engine_type
|
67
|
+
fail "No such engine '#{camelize(engine_type)}'"
|
68
|
+
end
|
69
|
+
|
70
|
+
def camelize(string)
|
71
|
+
string.gsub(/(?:^|_)([a-z])?/) do |match|
|
72
|
+
(Regexp.last_match[1] || '').capitalize
|
73
|
+
end
|
54
74
|
end
|
55
75
|
|
56
76
|
def cleanup_workdir
|
@@ -0,0 +1,92 @@
|
|
1
|
+
require 'vanagon/engine/base'
|
2
|
+
require 'json'
|
3
|
+
|
4
|
+
class Vanagon
|
5
|
+
class Engine
|
6
|
+
# This engine allows build resources to be managed by the "Always be
|
7
|
+
# Scheduling" (ABS) scheduler (https://github.com/puppetlabs/always-be-scheduling)
|
8
|
+
#
|
9
|
+
# ABS expects to ask `build_host_info` for the needed resources for a build,
|
10
|
+
# and to have that return a platform name. ABS will then acquire the
|
11
|
+
# desired build host resources and will later run a vanagon build, passing
|
12
|
+
# those resource hostnames in specifically.
|
13
|
+
#
|
14
|
+
# `build_host_info` will normally use the `hardware` engine when a hardware
|
15
|
+
# platform is queried. The `always_be_scheduling` engine's behavior will
|
16
|
+
# be invoked instead when:
|
17
|
+
#
|
18
|
+
# `build_host_info ... --engine always_be_scheduling` is specified on the
|
19
|
+
# command-line.
|
20
|
+
#
|
21
|
+
# Configuration:
|
22
|
+
#
|
23
|
+
# Project platform configurations can specify the platform name to be returned
|
24
|
+
# via the `abs_resource_name` attribute. If this is not set but `vmpooler_template`
|
25
|
+
# is set, then the `vmpooler_template` value will be used. Otherwise, the
|
26
|
+
# platform name will be returned unchanged.
|
27
|
+
#
|
28
|
+
# Example 1:
|
29
|
+
#
|
30
|
+
# platform 'ubuntu-10.04-amd64' do |plat|
|
31
|
+
# plat.vmpooler_template 'ubuntu-1004-amd64'
|
32
|
+
# end
|
33
|
+
#
|
34
|
+
# $ build_host_info puppet-agent ubuntu-10.04-amd64
|
35
|
+
# {"name":"ubuntu-10.04-amd64","engine":"pooler"}
|
36
|
+
#
|
37
|
+
# $ build_host_info puppet-agent ubuntu-10.04-amd64 --engine always_be_scheduling
|
38
|
+
# {"name":"ubuntu-10.04-amd64","engine":"always_be_scheduling"}
|
39
|
+
#
|
40
|
+
#
|
41
|
+
# Example 2:
|
42
|
+
#
|
43
|
+
# platform 'aix-5.3-ppc' do |plat|
|
44
|
+
# plat.build_host ['aix53-builder-1.example.com']
|
45
|
+
# plat.abs_resource_name 'aix-53-ppc'
|
46
|
+
# end
|
47
|
+
#
|
48
|
+
# $ build_host_info puppet-agent aix-5.3-ppc
|
49
|
+
# {"name":"aix53-builder-1.example.com","engine":"hardware"}
|
50
|
+
#
|
51
|
+
# $ build_host_info puppet-agent aix-5.3-ppc --engine always_be_scheduling
|
52
|
+
# {"name":"aix-53-ppc","engine":"always_be_scheduling"}
|
53
|
+
#
|
54
|
+
#
|
55
|
+
# Example 3:
|
56
|
+
#
|
57
|
+
# platform 'aix-5.3-ppc' do |plat|
|
58
|
+
# plat.build_host ['aix53-builder-1.example.com']
|
59
|
+
# plat.vmpooler_template
|
60
|
+
# plat.abs_resource_name 'aix-53-ppc'
|
61
|
+
# end
|
62
|
+
#
|
63
|
+
# $ build_host_info puppet-agent aix-5.3-ppc
|
64
|
+
# {"name":"aix53-builder-1.example.com","engine":"hardware"}
|
65
|
+
#
|
66
|
+
# $ build_host_info puppet-agent aix-5.3-ppc --engine always_be_scheduling
|
67
|
+
# {"name":"aix-53-ppc","engine":"always_be_scheduling"}
|
68
|
+
class AlwaysBeScheduling < Base
|
69
|
+
def initialize(platform, target)
|
70
|
+
super
|
71
|
+
|
72
|
+
Vanagon::Driver.logger.debug "AlwaysBeScheduling engine invoked."
|
73
|
+
end
|
74
|
+
|
75
|
+
# Get the engine name
|
76
|
+
def name
|
77
|
+
'always_be_scheduling'
|
78
|
+
end
|
79
|
+
|
80
|
+
# return the platform name as the "host" name
|
81
|
+
def build_host_name
|
82
|
+
if @platform.abs_resource_name
|
83
|
+
@platform.abs_resource_name
|
84
|
+
elsif @platform.vmpooler_template
|
85
|
+
@platform.vmpooler_template
|
86
|
+
else
|
87
|
+
@platform.name
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
data/lib/vanagon/engine/base.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'vanagon/engine/base'
|
2
|
+
require 'yaml'
|
2
3
|
|
3
4
|
class Vanagon
|
4
5
|
class Engine
|
@@ -29,19 +30,50 @@ class Vanagon
|
|
29
30
|
@build_host_template_name
|
30
31
|
end
|
31
32
|
|
32
|
-
#
|
33
|
+
# Retrieve the pooler token from an environment variable
|
34
|
+
# ("VMPOOLER_TOKEN") or from a number of potential configuration
|
35
|
+
# files (~/.vanagon-token or ~/.vmfloaty.yml).
|
33
36
|
# @return [String, nil] token for use with the vmpooler
|
34
37
|
def load_token
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
38
|
+
ENV['VMPOOLER_TOKEN'] || token_from_file
|
39
|
+
end
|
40
|
+
|
41
|
+
# a wrapper method around retrieving a vmpooler token,
|
42
|
+
# with an explicitly ordered preference for a Vanagon-specific
|
43
|
+
# token file or a preexisting vmfoaty yaml file.
|
44
|
+
#
|
45
|
+
# @return [String, nil] token for use with the vmpooler
|
46
|
+
def token_from_file
|
47
|
+
read_vanagon_token || read_vmfloaty_token
|
48
|
+
end
|
49
|
+
private :token_from_file
|
50
|
+
|
51
|
+
# Read a vmpooler token from the plaintext vanagon-token file,
|
52
|
+
# as outlined in the project README.
|
53
|
+
#
|
54
|
+
# @return [String, nil] the vanagon vmpooler token value
|
55
|
+
def read_vanagon_token(path = "~/.vanagon-token")
|
56
|
+
absolute_path = File.expand_path(path)
|
57
|
+
return nil unless File.exist?(absolute_path)
|
58
|
+
|
59
|
+
puts "Reading vmpooler token from: #{path}"
|
60
|
+
File.read(absolute_path).chomp
|
61
|
+
end
|
62
|
+
private :read_vanagon_token
|
63
|
+
|
64
|
+
# Read a vmpooler token from the yaml formatted vmfloaty config,
|
65
|
+
# as outlined by the vmfloaty project:
|
66
|
+
# https://github.com/briancain/vmfloaty
|
67
|
+
#
|
68
|
+
# @return [String, nil] the vmfloaty vmpooler token value
|
69
|
+
def read_vmfloaty_token(path = "~/.vmfloaty.yml")
|
70
|
+
absolute_path = File.expand_path(path)
|
71
|
+
return nil unless File.exist?(absolute_path)
|
72
|
+
|
73
|
+
puts "Reading vmpooler token from: #{path}"
|
74
|
+
YAML.load_file(absolute_path)['token']
|
44
75
|
end
|
76
|
+
private :read_vmfloaty_token
|
45
77
|
|
46
78
|
# This method is used to obtain a vm to build upon using the Puppet Labs'
|
47
79
|
# vmpooler (https://github.com/puppetlabs/vmpooler)
|
data/lib/vanagon/optparse.rb
CHANGED
@@ -10,6 +10,7 @@ class Vanagon
|
|
10
10
|
:skipcheck => ['--skipcheck', 'Skip the `check` stage when building components'],
|
11
11
|
:preserve => ['-p', '--preserve', 'Whether to tear down the VM on success or not (defaults to false)'],
|
12
12
|
:verbose => ['-v', '--verbose', 'Verbose output (does nothing)'],
|
13
|
+
:only_build => ["--only-build COMPONENT,COMPONENT,...", Array, 'Only build this array of components']
|
13
14
|
}.freeze
|
14
15
|
|
15
16
|
def initialize(banner, options = [])
|
data/lib/vanagon/platform.rb
CHANGED
@@ -2,13 +2,16 @@ require 'vanagon/platform/dsl'
|
|
2
2
|
|
3
3
|
class Vanagon
|
4
4
|
class Platform
|
5
|
-
attr_accessor :make, :servicedir, :defaultdir, :provisioning, :num_cores
|
6
|
-
attr_accessor :build_dependencies, :name, :vmpooler_template
|
7
|
-
attr_accessor :
|
8
|
-
attr_accessor :
|
9
|
-
attr_accessor :
|
10
|
-
attr_accessor :
|
11
|
-
attr_accessor :
|
5
|
+
attr_accessor :make, :servicedir, :defaultdir, :provisioning, :num_cores
|
6
|
+
attr_accessor :tar, :build_dependencies, :name, :vmpooler_template
|
7
|
+
attr_accessor :abs_resource_name, :cflags, :ldflags, :settings
|
8
|
+
attr_accessor :servicetype, :patch, :architecture, :codename, :os_name
|
9
|
+
attr_accessor :os_version, :docker_image, :ssh_port, :rpmbuild, :install
|
10
|
+
attr_accessor :platform_triple, :target_user, :package_type, :find, :sort
|
11
|
+
attr_accessor :build_hosts, :copy, :cross_compiled, :aws_ami
|
12
|
+
attr_accessor :aws_user_data, :aws_shutdown_behavior, :aws_key_name
|
13
|
+
attr_accessor :aws_region, :aws_key, :aws_instance_type, :aws_vpc_id
|
14
|
+
attr_accessor :aws_subnet_id, :output_dir
|
12
15
|
|
13
16
|
# Platform names currently contain some information about the platform. Fields
|
14
17
|
# within the name are delimited by the '-' character, and this regex can be used to
|