packer-config 0.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +36 -0
  3. data/.rubocop.yml +340 -0
  4. data/.travis.yml +6 -0
  5. data/Gemfile +17 -0
  6. data/LICENSE +176 -0
  7. data/README.md +107 -0
  8. data/Rakefile +47 -0
  9. data/TODO.md +8 -0
  10. data/lib/packer-config.rb +181 -0
  11. data/lib/packer/builder.rb +65 -0
  12. data/lib/packer/builders/all.rb +17 -0
  13. data/lib/packer/builders/amazon.rb +214 -0
  14. data/lib/packer/builders/docker.rb +47 -0
  15. data/lib/packer/builders/virtualbox.rb +169 -0
  16. data/lib/packer/dataobject.rb +128 -0
  17. data/lib/packer/envvar.rb +27 -0
  18. data/lib/packer/macro.rb +28 -0
  19. data/lib/packer/postprocessor.rb +77 -0
  20. data/lib/packer/postprocessors/all.rb +16 -0
  21. data/lib/packer/postprocessors/docker.rb +35 -0
  22. data/lib/packer/postprocessors/vagrant.rb +47 -0
  23. data/lib/packer/provisioner.rb +86 -0
  24. data/lib/packer/provisioners/all.rb +16 -0
  25. data/lib/packer/provisioners/file.rb +36 -0
  26. data/lib/packer/provisioners/shell.rb +60 -0
  27. data/packer-config.gemspec +46 -0
  28. data/spec/integration/README.md +14 -0
  29. data/spec/integration/builds/.gitignore +4 -0
  30. data/spec/integration/centos_vagrant_spec.rb +76 -0
  31. data/spec/integration/packer_cache/.gitignore +4 -0
  32. data/spec/integration/scripts/chef.sh +199 -0
  33. data/spec/integration/scripts/cleanup.sh +17 -0
  34. data/spec/integration/scripts/fix-slow-dns.sh +13 -0
  35. data/spec/integration/scripts/hello.sh +3 -0
  36. data/spec/integration/scripts/kickstart/centos-6.5-ks.cfg +71 -0
  37. data/spec/integration/scripts/minimize.sh +9 -0
  38. data/spec/integration/scripts/sshd.sh +6 -0
  39. data/spec/integration/scripts/vagrant.sh +10 -0
  40. data/spec/integration/scripts/vmtools.sh +39 -0
  41. data/spec/packer/builder_spec.rb +39 -0
  42. data/spec/packer/builders/amazon_spec.rb +88 -0
  43. data/spec/packer/builders/docker_spec.rb +25 -0
  44. data/spec/packer/builders/virtualbox_spec.rb +44 -0
  45. data/spec/packer/dataobject_spec.rb +239 -0
  46. data/spec/packer/envvar_spec.rb +38 -0
  47. data/spec/packer/macro_spec.rb +38 -0
  48. data/spec/packer/postprocessor_spec.rb +72 -0
  49. data/spec/packer/postprocessors/docker_import_spec.rb +27 -0
  50. data/spec/packer/postprocessors/docker_push_spec.rb +27 -0
  51. data/spec/packer/postprocessors/vagrant_spec.rb +27 -0
  52. data/spec/packer/provisioner_spec.rb +78 -0
  53. data/spec/packer/provisioners/file_spec.rb +63 -0
  54. data/spec/packer/provisioners/shell_spec.rb +116 -0
  55. data/spec/packer_config_spec.rb +197 -0
  56. data/spec/spec_helper.rb +19 -0
  57. data/spec/unit_helper.rb +15 -0
  58. metadata +220 -0
data/README.md ADDED
@@ -0,0 +1,107 @@
1
+ # packer-config
2
+
3
+ A Ruby model that lets you build [Packer](http://packer.io) configurations in Ruby.
4
+
5
+ Building the Packer JSON configurations in raw JSON can be quite an adventure.
6
+ There's limited facilities for variable expansion and absolutely no support for
7
+ nice things like comments. I decided it would just be easier to have an object
8
+ model to build the Packer configurations in that would easily write to the
9
+ correct JSON format. It also saved me having to remember the esoteric Packer
10
+ syntax for referencing variables and whatnot in the JSON.
11
+
12
+ Bonus: you can really go to town with templates when it's all done it Ruby.
13
+
14
+ ## Installation
15
+
16
+ gem install packer-config
17
+
18
+ ## Examples
19
+
20
+ ### Packing a Vagrant Basebox from a CentOS ISO Using VirtualBox
21
+
22
+ This example is based on the integration test [spec/integration/centos_vagrant_spec.rb](spec/integration/centos_vagrant_spec.rb). It produces a Vagrant Basebox that's provisionable with [Chef](http://www.getchef.com/) and the packer config and provisioning is taken from the [Bento](https://github.com/opscode/bento) project from the OpsCode crew.
23
+
24
+ OS = 'centos-6.5'
25
+
26
+ pconfig = Packer::Config.new "#{OS}-vagrant.json"
27
+ pconfig.description "#{OS} VirtualBox Vagrant"
28
+ pconfig.add_variable 'mirror', 'http://mirrors.kernel.org/centos'
29
+ pconfig.add_variable 'my_version', '0.0.1'
30
+ pconfig.add_variable 'chef_version', 'latest'
31
+
32
+ builder = pconfig.add_builder Packer::Builder::VIRTUALBOX_ISO
33
+ builder.boot_command ["<tab> text ks=http://#{pconfig.macro.HTTPIP}:#{pconfig.macro.HTTPPort}/#{OS}-ks.cfg<enter><wait>"]
34
+ builder.boot_wait '10s'
35
+ builder.disk_size 40960
36
+ builder.guest_additions_path "VBoxGuestAdditions_#{pconfig.macro.Version}.iso"
37
+ builder.guest_os_type "RedHat_64"
38
+ builder.http_directory "scripts/kickstart"
39
+ builder.iso_checksum '32c7695b97f7dcd1f59a77a71f64f2957dddf738'
40
+ builder.iso_checksum_type 'sha1'
41
+ builder.iso_url "#{pconfig.variable 'mirror'}/6.5/isos/x86_64/CentOS-6.5-x86_64-bin-DVD1.iso"
42
+ builder.output_directory "#{OS}-x86_64-virtualbox"
43
+ builder.shutdown_command "echo 'vagrant'|sudo -S /sbin/halt -h -p"
44
+ builder.ssh_password "vagrant"
45
+ builder.ssh_port 22
46
+ builder.ssh_username "vagrant"
47
+ builder.ssh_wait_timeout "10000s"
48
+ builder.vboxmanage [
49
+ [
50
+ "modifyvm",
51
+ pconfig.macro.Name,
52
+ "--memory",
53
+ "480"
54
+ ],
55
+ [
56
+ "modifyvm",
57
+ pconfig.macro.Name,
58
+ "--cpus",
59
+ "1"
60
+ ]
61
+ ]
62
+ builder.virtualbox_version_file ".vbox_version"
63
+ builder.vm_name "packer-#{OS}-x86_64"
64
+
65
+ provisioner = pconfig.add_provisioner Packer::Provisioner::FILE
66
+ provisioner.source 'scripts/hello.sh'
67
+ provisioner.destination '/home/vagrant/hello.sh'
68
+
69
+ provisioner = pconfig.add_provisioner Packer::Provisioner::SHELL
70
+ provisioner.scripts [
71
+ 'scripts/fix-slow-dns.sh',
72
+ 'scripts/sshd.sh',
73
+ 'scripts/vagrant.sh',
74
+ 'scripts/vmtools.sh',
75
+ 'scripts/chef.sh',
76
+ 'scripts/cleanup.sh',
77
+ 'scripts/minimize.sh'
78
+ ]
79
+ provisioner.environment_vars [
80
+ "CHEF_VERSION=#{pconfig.variable 'chef_version'}",
81
+ "MY_VERSION=#{pconfig.variable 'my_version'}"
82
+ ]
83
+ provisioner.execute_command "echo 'vagrant' | #{pconfig.macro.Vars} sudo -S -E bash '#{pconfig.macro.Path}'"
84
+
85
+ postprocessor = pconfig.add_postprocessor Packer::PostProcessor::VAGRANT
86
+ postprocessor.output File.join('builds', pconfig.macro.Provider, "#{OS}-x86_64-#{pconfig.variable 'my_version'}.box")
87
+
88
+ pconfig.validate
89
+ pconfig.build
90
+
91
+ ## Development
92
+
93
+ ### Continuous Integration
94
+
95
+ I'm using Travis CI to build and test on every push to the public github repository. You can find the Travis CI page for this project here: https://travis-ci.org/ianchesal/packer-config/
96
+
97
+ ### Branching in Git
98
+
99
+ I'm using [git-flow](http://nvie.com/posts/a-successful-git-branching-model/) for development in git via github. I've loved the branching model git-flow proposed from day one and the addon to git makes it very intuitive and easy to follow. I generally don't push my `feature/*` branches to the public repository; I do keep `development` and `master` up to date here though.
100
+
101
+ ### TODO Work
102
+
103
+ Please see [TODO.md](TODO.md) for the short list of big things I thought worth writing down.
104
+
105
+ ## Contact Me
106
+
107
+ Questions or comments about `packer-config`? Hit me up at ian.chesal@gmail.com or ianc@squareup.com.
data/Rakefile ADDED
@@ -0,0 +1,47 @@
1
+ # Encoding: utf-8
2
+ # Copyright 2014 Ian Chesal
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+
16
+ require 'rubocop/rake_task'
17
+ require 'rspec/core/rake_task'
18
+ require 'fileutils'
19
+
20
+ RuboCop::RakeTask.new(:lint)
21
+
22
+ task :default => [:lint, 'test:spec']
23
+
24
+ task :build => ['test:spec'] do
25
+ `gem build packer-config.gemspec`
26
+ end
27
+
28
+ namespace :test do
29
+ RSpec::Core::RakeTask.new(:spec) do |t|
30
+ t.pattern = Dir['spec/**/*_spec.rb'].reject{ |f| f['/integration'] }
31
+ end
32
+
33
+ RSpec::Core::RakeTask.new(:integration) do |t|
34
+ t.pattern = "spec/integration/**/*_spec.rb"
35
+ end
36
+ end
37
+
38
+ CLEAN = FileList['deployment_dir/**/*'].exclude('*.txt')
39
+
40
+ task :clean do
41
+ FileList['spec/integration/packer_cache/*'].each do |f|
42
+ FileUtils.rm_f(f)
43
+ end
44
+ Dir.glob('spec/integration/builds/*').select {|f| File.directory? f}.each do |d|
45
+ FileUtils.rm_rf(d)
46
+ end
47
+ end
data/TODO.md ADDED
@@ -0,0 +1,8 @@
1
+ # TODO
2
+
3
+ * Add an option to Packer::Config#validate to run the configuration through packer's `validate` command
4
+ * Add spec tests for every method on every sub-class. Found during integration testing that some methods on the sub-classes had typos in the `__*` method calls. Spec tests would have caught this.
5
+ * Look in to something like VCR to drive the tests of the child classes -- there's a lot of repetitive testing that could be done on them.
6
+ * Add missing builders, provisioners and post-processors. I only implemented the builders, provisioners and post-processors that I'm currently using.
7
+ * Refactor the child classes. I get the feeling that these could be implemented in some better, templated, type of way
8
+ * Building can take a long time. Look in to a way to query the state of a build. Maybe return the stdout from it on query.
@@ -0,0 +1,181 @@
1
+ # Encoding: utf-8
2
+ # Copyright 2014 Ian Chesal
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+ require 'json'
16
+ require 'open3'
17
+ require 'packer/dataobject'
18
+ require 'packer/builder'
19
+ require 'packer/provisioner'
20
+ require 'packer/postprocessor'
21
+ require 'packer/macro'
22
+ require 'packer/envvar'
23
+
24
+ module Packer
25
+ class Config < Packer::DataObject
26
+
27
+ VERSION = '0.0.2'
28
+
29
+ attr_accessor :builders
30
+ attr_accessor :postprocessors
31
+ attr_accessor :provisioners
32
+ attr_accessor :packer
33
+ attr_accessor :packer_options
34
+ attr_reader :macro
35
+ attr_reader :envvar
36
+ attr_reader :output_file
37
+
38
+ def initialize(file)
39
+ super()
40
+ self.data['variables'] = {}
41
+ self.output_file = file
42
+ self.builders = []
43
+ self.provisioners = []
44
+ self.postprocessors = []
45
+ self.packer = 'packer'
46
+ self.packer_options = []
47
+ self.macro = Macro.new
48
+ self.envvar = EnvVar.new
49
+ end
50
+
51
+ def validate
52
+ super
53
+ if self.builders.length == 0
54
+ raise DataValidationError.new("At least one builder is required")
55
+ end
56
+ self.builders.each do |thing|
57
+ thing.validate
58
+ end
59
+ self.provisioners.each do |thing|
60
+ thing.validate
61
+ end
62
+ self.postprocessors.each do |thing|
63
+ thing.validate
64
+ end
65
+ self.write
66
+ Dir.chdir(File.dirname(self.output_file)) do
67
+ cmd = [self.packer, 'validate', File.basename(self.output_file)].join(' ')
68
+ stdout, stderr, status = Open3.capture3(cmd)
69
+ raise PackerBuildError.new(stderr) unless status == 0
70
+ end
71
+ self.delete
72
+ end
73
+
74
+ class DumpError < StandardError
75
+ end
76
+
77
+ def dump(format='json', pretty=false)
78
+ data_copy = self.deep_copy
79
+ data_copy['builders'] = []
80
+ self.builders.each do |thing|
81
+ data_copy['builders'].push(thing.deep_copy)
82
+ end
83
+ if self.provisioners.length > 0
84
+ data_copy['provisioners'] = []
85
+ self.provisioners.each do |thing|
86
+ data_copy['provisioners'].push(thing.deep_copy)
87
+ end
88
+ end
89
+ if self.postprocessors.length > 0
90
+ data_copy['post-processors'] = []
91
+ self.postprocessors.each do |thing|
92
+ data_copy['post-processors'].push(thing.deep_copy)
93
+ end
94
+ end
95
+ case format
96
+ when 'json'
97
+ if pretty
98
+ JSON.pretty_generate(data_copy)
99
+ else
100
+ data_copy.to_json
101
+ end
102
+ else
103
+ raise DumpError.new("Unrecognized format #{format} use one of ['json']")
104
+ end
105
+ end
106
+
107
+ def write(format='json')
108
+ File.write(self.output_file, self.dump(format))
109
+ end
110
+
111
+ def delete
112
+ File.delete(self.output_file)
113
+ end
114
+
115
+ class PackerBuildError < StandardError
116
+ end
117
+
118
+ def build
119
+ self.validate
120
+ self.write
121
+ Dir.chdir(File.dirname(self.output_file)) do
122
+ cmd = [self.packer, 'build', self.packer_options, File.basename(self.output_file)].join(' ')
123
+ stdout, stderr, status = Open3.capture3(cmd)
124
+ raise PackerBuildError.new(stderr) unless status == 0
125
+ end
126
+ self.delete
127
+ end
128
+
129
+ def description(description)
130
+ self.__add_string('description', description)
131
+ end
132
+
133
+ def min_packer_version(version)
134
+ self.__add_string('min_packer_version', version)
135
+ end
136
+
137
+ def variables
138
+ self.data['variables']
139
+ end
140
+
141
+ def add_builder(type)
142
+ builder = Packer::Builder.get_builder(type)
143
+ self.builders.push(builder)
144
+ builder
145
+ end
146
+
147
+ def add_provisioner(type)
148
+ provisioner = Packer::Provisioner.get_provisioner(type)
149
+ self.provisioners.push(provisioner)
150
+ provisioner
151
+ end
152
+
153
+ def add_postprocessor(type)
154
+ postprocessor = Packer::PostProcessor.get_postprocessor(type)
155
+ self.postprocessors.push(postprocessor)
156
+ postprocessor
157
+ end
158
+
159
+ def add_variable(name, value)
160
+ variables_copy = Marshal.load(Marshal.dump(self.variables))
161
+ variables_copy[name.to_s] = value.to_s
162
+ self.__add_hash('variables', variables_copy)
163
+ end
164
+
165
+ class UndefinedVariableError < StandardError
166
+ end
167
+
168
+ def variable(name)
169
+ unless self.variables.has_key? name
170
+ raise UndefinedVariableError.new("No variable named #{name} has been defined -- did you forget to call add_variable?")
171
+ end
172
+ "{{user `#{name}`}}"
173
+ end
174
+
175
+ private
176
+ attr_writer :output_file
177
+ attr_writer :macro
178
+ attr_writer :envvar
179
+
180
+ end
181
+ end
@@ -0,0 +1,65 @@
1
+ # Encoding: utf-8
2
+ # Copyright 2014 Ian Chesal
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+ require 'packer/builders/all'
16
+
17
+ module Packer
18
+ class Builder < DataObject
19
+
20
+ AMAZON_EBS = 'amazon-ebs'
21
+ AMAZON_INSTANCE = 'amazon-instance'
22
+ DOCKER = 'docker'
23
+ VIRTUALBOX_ISO = 'virtualbox-iso'
24
+
25
+ VALID_BUILDER_TYPES = [
26
+ AMAZON_EBS,
27
+ AMAZON_INSTANCE,
28
+ DOCKER,
29
+ VIRTUALBOX_ISO
30
+ ]
31
+
32
+ class UnrecognizedBuilderTypeError < StandardError
33
+ end
34
+
35
+ def self.get_builder(type)
36
+ unless validate_type(type)
37
+ raise UnrecognizedBuilderTypeError.new("Unrecognized builder type #{type}")
38
+ end
39
+ {
40
+ AMAZON_EBS => Packer::Builder::Amazon::EBS,
41
+ AMAZON_INSTANCE => Packer::Builder::Amazon::Instance,
42
+ DOCKER => Packer::Builder::Docker,
43
+ VIRTUALBOX_ISO => Packer::Builder::VirtualBoxISO
44
+ }.fetch(type).new
45
+ end
46
+
47
+ def self.types
48
+ VALID_BUILDER_TYPES
49
+ end
50
+
51
+ def initialize
52
+ super
53
+ self.add_required('type')
54
+ end
55
+
56
+ def name(name)
57
+ self.__add_string('name', name)
58
+ end
59
+
60
+ private
61
+ def self.validate_type(type)
62
+ VALID_BUILDER_TYPES.include? type
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,17 @@
1
+ # Encoding: utf-8
2
+ # Copyright 2014 Ian Chesal
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+ require 'packer/builders/amazon'
16
+ require 'packer/builders/docker'
17
+ require 'packer/builders/virtualbox'
@@ -0,0 +1,214 @@
1
+ # Encoding: utf-8
2
+ # Copyright 2014 Ian Chesal
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+ require 'packer/builder'
16
+ require 'packer/dataobject'
17
+
18
+ module Packer
19
+ class Builder < Packer::DataObject
20
+ class Amazon < Builder
21
+
22
+ def initialize
23
+ super
24
+ self.add_required(
25
+ 'ami_name',
26
+ 'instance_type',
27
+ 'region',
28
+ 'source_ami',
29
+ 'ssh_username'
30
+ )
31
+ end
32
+
33
+ def access_key(key)
34
+ self.__add_string('access_key', key)
35
+ end
36
+
37
+ def ami_name(name)
38
+ self.__add_string('ami_name', name)
39
+ end
40
+
41
+ def instance_type(type)
42
+ self.__add_string('instance_type', type)
43
+ end
44
+
45
+ def region(name)
46
+ self.__add_string('region', name)
47
+ end
48
+
49
+ def source_ami(name)
50
+ self.__add_string('source_ami', name)
51
+ end
52
+
53
+ def ssh_username(username)
54
+ self.__add_string('ssh_username', username)
55
+ end
56
+
57
+ def secret_key(key)
58
+ self.__add_string('secret_key', key)
59
+ end
60
+
61
+ def ami_block_device_mappings(mappings)
62
+ self.__add_array_of_hashes('ami_block_device_mappings', mappings)
63
+ end
64
+
65
+ def ami_description(description)
66
+ self.__add_string('ami_description', description)
67
+ end
68
+
69
+ def ami_groups(groups)
70
+ self.__add_array_of_strings('ami_groups', groups)
71
+ end
72
+
73
+ def ami_product_codes(codes)
74
+ self.__add_array_of_strings('ami_product_codes', codes)
75
+ end
76
+
77
+ def ami_regions(regions)
78
+ self.__add_array_of_strings('ami_regions', regions)
79
+ end
80
+
81
+ def ami_users(users)
82
+ self.__add_array_of_strings('ami_users', users)
83
+ end
84
+
85
+ def ami_virtualization_type(type)
86
+ self.__add_string('ami_virtualization_type', type)
87
+ end
88
+
89
+ def associate_public_ip_address(bool)
90
+ self.__add_boolean('associate_public_ip_address', bool)
91
+ end
92
+
93
+ def availability_zone(zone)
94
+ self.__add_string('availability_zone', zone)
95
+ end
96
+
97
+ def enhanced_networking(bool)
98
+ self.__add_boolean('enhanced_networking', bool)
99
+ end
100
+
101
+ def iam_instance_profile(profile)
102
+ self.__add_string('iam_instance_profile', profile)
103
+ end
104
+
105
+ def launch_block_device_mappings(mappings)
106
+ self.__add_array_of_hashes('launch_block_device_mappings', mappings)
107
+ end
108
+
109
+ def run_tags(tags)
110
+ self.__add_hash('run_tags', tags)
111
+ end
112
+
113
+ def security_group_id(id)
114
+ self.__add_string('security_group_id', id, %w[security_group_ids])
115
+ end
116
+
117
+ def security_group_ids(ids)
118
+ self.__add_array_of_strings('security_group_ids', ids, %w[security_group_id])
119
+ end
120
+
121
+ def ssh_port(port)
122
+ self.__add_integer('ssh_port', port)
123
+ end
124
+
125
+ def ssh_private_key_file(file)
126
+ self.__add_string('ssh_private_key_file', file)
127
+ end
128
+
129
+ def ssh_timeout(time)
130
+ self.__add_string('ssh_timeout', time)
131
+ end
132
+
133
+ def subnet_id(id)
134
+ self.__add_string('subnet_id', id)
135
+ end
136
+
137
+ def tags(tags)
138
+ self.__add_hash('tags', tags)
139
+ end
140
+
141
+ def temporary_key_pair_name(name)
142
+ self.__add_string('temporary_key_pair_name', name)
143
+ end
144
+
145
+ def user_data(data)
146
+ self.__add_string('user_data', data)
147
+ end
148
+
149
+ def user_data_file(file)
150
+ self.__add_string('user_data_file', file)
151
+ end
152
+
153
+ def vpc_id(id)
154
+ self.__add_string('vpc_id', id)
155
+ end
156
+
157
+ class EBS < Amazon
158
+ def initialize
159
+ super
160
+ self.data['type'] = AMAZON_EBS
161
+ end
162
+ end
163
+
164
+ class Instance < Amazon
165
+ def initialize
166
+ super
167
+ self.data['type'] = AMAZON_INSTANCE
168
+ self.add_required(
169
+ 'account_id',
170
+ 's3_bucket',
171
+ 'x509_cert_path',
172
+ 'x509_key_path'
173
+ )
174
+ end
175
+
176
+ def account_id(id)
177
+ self.__add_string('account_id', id)
178
+ end
179
+
180
+ def s3_bucket(bucket)
181
+ self.__add_string('s3_bucket', bucket)
182
+ end
183
+
184
+ def x509_cert_path(path)
185
+ self.__add_string('x509_cert_path', path)
186
+ end
187
+
188
+ def x509_key_path(path)
189
+ self.__add_string('x509_key_path', path)
190
+ end
191
+
192
+ def bundle_destination(directory)
193
+ self.__add_string('bundle_destination', directory)
194
+ end
195
+
196
+ def bundle_prefix(prefix)
197
+ self.__add_string('bundle_prefix', prefix)
198
+ end
199
+
200
+ def bundle_upload_command(command)
201
+ self.__add_string('bundle_upload_command', command)
202
+ end
203
+
204
+ def bundle_vol_command(command)
205
+ self.__add_string('bundle_vol_command', command)
206
+ end
207
+
208
+ def x509_upload_path(path)
209
+ self.__add_string('x509_upload_path', path)
210
+ end
211
+ end
212
+ end
213
+ end
214
+ end