packer-config 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
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
@@ -0,0 +1,16 @@
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_relative 'docker'
16
+ require_relative 'vagrant'
@@ -0,0 +1,35 @@
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/postprocessor'
16
+ require 'packer/dataobject'
17
+
18
+ module Packer
19
+ class PostProcessor < Packer::DataObject
20
+ class DockerImport < PostProcessor
21
+ def initialize
22
+ super
23
+ self.data['type'] = DOCKER_IMPORT
24
+ self.add_required('repository')
25
+ end
26
+ end
27
+
28
+ class DockerPush < PostProcessor
29
+ def initialize
30
+ super
31
+ self.data['type'] = DOCKER_PUSH
32
+ end
33
+ end
34
+ end
35
+ end
@@ -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
+ require 'packer/postprocessor'
16
+ require 'packer/dataobject'
17
+
18
+ module Packer
19
+ class PostProcessor < Packer::DataObject
20
+ class Vagrant < PostProcessor
21
+ def initialize
22
+ super()
23
+ self.data['type'] = VAGRANT
24
+ end
25
+
26
+ def compression_level(level)
27
+ self.__add_integer('compression_level', level)
28
+ end
29
+
30
+ def include(files)
31
+ self.__add_array_of_strings('include', files)
32
+ end
33
+
34
+ def keep_input_artifact(bool)
35
+ self.__add_boolean('keep_input_artifact', bool)
36
+ end
37
+
38
+ def output(file)
39
+ self.__add_string('output', file)
40
+ end
41
+
42
+ def vagrantfile_template(file)
43
+ self.__add_string('vagrantfile_template', file)
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,86 @@
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/provisioners/all'
16
+ require 'packer/dataobject'
17
+
18
+ module Packer
19
+ class Provisioner < Packer::DataObject
20
+
21
+ SHELL = 'shell'
22
+ FILE = 'file'
23
+
24
+ VALID_PROVISIONER_TYPES = [
25
+ SHELL,
26
+ FILE
27
+ ]
28
+
29
+ class UnrecognizedProvisionerTypeError < StandardError
30
+ end
31
+
32
+ def self.get_provisioner(type)
33
+ unless validate_type(type)
34
+ raise UnrecognizedProvisionerTypeError.new("Unrecognized provisioner type #{type}")
35
+ end
36
+ {
37
+ SHELL => Packer::Provisioner::Shell,
38
+ FILE => Packer::Provisioner::File,
39
+ }.fetch(type).new
40
+ end
41
+
42
+ def self.types
43
+ VALID_PROVISIONER_TYPES
44
+ end
45
+
46
+ def initialize
47
+ super
48
+ self.add_required('type')
49
+ end
50
+
51
+ def only(buildname)
52
+ unless self.data.has_key? 'only'
53
+ self.data['only'] = []
54
+ end
55
+ self.data['only'] << buildname.to_s
56
+ end
57
+
58
+ def except(buildname)
59
+ unless self.data.has_key? 'except'
60
+ self.data['except'] = []
61
+ end
62
+ self.data['except'] << buildname.to_s
63
+ end
64
+
65
+ def pause_before(duration)
66
+ self.data["pause_before"] = duration.to_s
67
+ end
68
+
69
+ def override(builddefinition, values)
70
+ raise TypeError.new() unless values.is_a?(Hash)
71
+ unless self.data.has_key? 'override'
72
+ self.data['override'] = {}
73
+ end
74
+ if self.data.has_key? @data['override'][builddefinition]
75
+ self.data['override'][builddefinition].merge! values
76
+ else
77
+ self.data['override'][builddefinition] = values
78
+ end
79
+ end
80
+
81
+ private
82
+ def self.validate_type(type)
83
+ VALID_PROVISIONER_TYPES.include? type
84
+ end
85
+ end
86
+ end
@@ -0,0 +1,16 @@
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_relative 'file'
16
+ require_relative 'shell'
@@ -0,0 +1,36 @@
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/provisioner'
16
+ require 'packer/dataobject'
17
+
18
+ module Packer
19
+ class Provisioner < Packer::DataObject
20
+ class File < Provisioner
21
+ def initialize
22
+ super
23
+ self.data['type'] = FILE
24
+ self.add_required('source', 'destination')
25
+ end
26
+
27
+ def source(filename)
28
+ self.__add_string('source', filename)
29
+ end
30
+
31
+ def destination(filename)
32
+ self.__add_string('destination', filename)
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,60 @@
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/provisioner'
16
+ require 'packer/dataobject'
17
+
18
+ module Packer
19
+ class Provisioner < Packer::DataObject
20
+ class Shell < Provisioner
21
+ def initialize
22
+ super
23
+ self.data['type'] = SHELL
24
+ self.add_required(['inline', 'script', 'scripts'])
25
+ end
26
+
27
+ def inline(commands)
28
+ self.__add_array_of_strings('inline', commands, %w[script scripts])
29
+ end
30
+
31
+ def script(filename)
32
+ self.__add_string('script', filename, %w[inline scripts])
33
+ end
34
+
35
+ def scripts(filenames)
36
+ self.__add_array_of_strings('scripts', filenames, %w[inline script])
37
+ end
38
+
39
+ def binary(bool)
40
+ self.__add_boolean('binary', bool, [])
41
+ end
42
+
43
+ def environment_vars(envpairs)
44
+ self.__add_array_of_strings('environment_vars', envpairs)
45
+ end
46
+
47
+ def execute_command(command)
48
+ self.__add_string('execute_command', command)
49
+ end
50
+
51
+ def inline_shebang(command)
52
+ self.__add_string('inline_shebang', command)
53
+ end
54
+
55
+ def remote_path(command)
56
+ self.__add_string('remote_path', command)
57
+ end
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,46 @@
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
+ Gem::Specification.new do |spec|
17
+ spec.name = "packer-config"
18
+ spec.version = "0.0.3"
19
+ # For deploying alpha versions via Travis CI
20
+ spec.version = "#{spec.version}-alpha-#{ENV['TRAVIS_BUILD_NUMBER']}" if ENV['TRAVIS']
21
+ spec.authors = ["Ian Chesal"]
22
+ spec.email = ["ian.chesal@gmail.colm"]
23
+ spec.summary = 'An object model to build packer.io configurations in Ruby.'
24
+ spec.description = <<-END
25
+ Building the Packer JSON configurations in raw JSON can be quite an adventure.
26
+ There's limited facilities for variable expansion and absolutely no support for
27
+ nice things like comments. I decided it would just be easier to have an object
28
+ model to build the Packer configurations in that would easily write to the
29
+ correct JSON format. It also saved me having to remember the esoteric Packer
30
+ syntax for referencing variables and whatnot in the JSON.
31
+ END
32
+ spec.homepage = "https://github.com/ianchesal/packer-config"
33
+ spec.license = "Apache 2.0"
34
+
35
+ spec.files = `git ls-files -z`.split("\x0")
36
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
37
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
38
+ spec.require_paths = ["lib"]
39
+
40
+ spec.add_development_dependency "bundler", "~> 1.6"
41
+ spec.add_development_dependency "rake", "~> 10.3"
42
+ spec.add_development_dependency "rspec", "~> 3.0"
43
+ spec.add_development_dependency "rspec-mocks", "~> 3.0"
44
+ spec.add_development_dependency "fakefs", "~> 0.5"
45
+ spec.add_development_dependency "rubocop", "~> 0.24"
46
+ end
@@ -0,0 +1,14 @@
1
+ # Integration Testing packer-config
2
+
3
+ You can run the integration tests via the Rakefile with:
4
+
5
+ bundle exec rake test:integration
6
+
7
+ The integration tests actually run Packer builds and can take some time to run. As of now I've only run them on an OS X system but, in theory, they should run on any system where the `packer` command and VirtualBox are available.
8
+
9
+ The provisioning and kickstart scripts are largely taken from the [OpsCode Bento](https://github.com/opscode/bento) project which is most awesome and you should check it out.
10
+
11
+ ## Requirements
12
+
13
+ * [Packer.io](http://www.packer.io/downloads.html)
14
+ * [VirtualBox](https://www.virtualbox.org/wiki/Downloads)
@@ -0,0 +1,4 @@
1
+ # Ignore everything in this directory
2
+ *
3
+ # Except this file
4
+ !.gitignore
@@ -0,0 +1,76 @@
1
+ # Encoding: utf-8
2
+ require 'spec_helper'
3
+
4
+ RSpec.describe Packer::Config do
5
+ it 'can build a centos-6.5 Vagrant base box' do
6
+ OS = 'centos-6.5'
7
+
8
+ pconfig = Packer::Config.new "#{OS}-vagrant.json"
9
+ pconfig.description "#{OS} VirtualBox Vagrant"
10
+ pconfig.add_variable 'mirror', 'http://mirrors.kernel.org/centos'
11
+ pconfig.add_variable 'my_version', '0.0.1'
12
+ pconfig.add_variable 'chef_version', 'latest'
13
+
14
+ builder = pconfig.add_builder Packer::Builder::VIRTUALBOX_ISO
15
+ builder.boot_command ["<tab> text ks=http://#{pconfig.macro.HTTPIP}:#{pconfig.macro.HTTPPort}/#{OS}-ks.cfg<enter><wait>"]
16
+ builder.boot_wait '10s'
17
+ builder.disk_size 40960
18
+ builder.guest_additions_path "VBoxGuestAdditions_#{pconfig.macro.Version}.iso"
19
+ builder.guest_os_type "RedHat_64"
20
+ builder.http_directory "scripts/kickstart"
21
+ builder.iso_checksum '32c7695b97f7dcd1f59a77a71f64f2957dddf738'
22
+ builder.iso_checksum_type 'sha1'
23
+ builder.iso_url "#{pconfig.variable 'mirror'}/6.5/isos/x86_64/CentOS-6.5-x86_64-bin-DVD1.iso"
24
+ builder.output_directory "#{OS}-x86_64-virtualbox"
25
+ builder.shutdown_command "echo 'vagrant'|sudo -S /sbin/halt -h -p"
26
+ builder.ssh_password "vagrant"
27
+ builder.ssh_port 22
28
+ builder.ssh_username "vagrant"
29
+ builder.ssh_wait_timeout "10000s"
30
+ builder.vboxmanage [
31
+ [
32
+ "modifyvm",
33
+ pconfig.macro.Name,
34
+ "--memory",
35
+ "480"
36
+ ],
37
+ [
38
+ "modifyvm",
39
+ pconfig.macro.Name,
40
+ "--cpus",
41
+ "1"
42
+ ]
43
+ ]
44
+ builder.virtualbox_version_file ".vbox_version"
45
+ builder.vm_name "packer-#{OS}-x86_64"
46
+
47
+ provisioner = pconfig.add_provisioner Packer::Provisioner::FILE
48
+ provisioner.source 'scripts/hello.sh'
49
+ provisioner.destination '/home/vagrant/hello.sh'
50
+
51
+ provisioner = pconfig.add_provisioner Packer::Provisioner::SHELL
52
+ provisioner.scripts [
53
+ 'scripts/fix-slow-dns.sh',
54
+ 'scripts/sshd.sh',
55
+ 'scripts/vagrant.sh',
56
+ 'scripts/vmtools.sh',
57
+ 'scripts/chef.sh',
58
+ 'scripts/cleanup.sh',
59
+ 'scripts/minimize.sh'
60
+ ]
61
+ provisioner.environment_vars [
62
+ "CHEF_VERSION=#{pconfig.variable 'chef_version'}",
63
+ "MY_VERSION=#{pconfig.variable 'my_version'}"
64
+ ]
65
+ provisioner.execute_command "echo 'vagrant' | #{pconfig.macro.Vars} sudo -S -E bash '#{pconfig.macro.Path}'"
66
+
67
+ postprocessor = pconfig.add_postprocessor Packer::PostProcessor::VAGRANT
68
+ postprocessor.output File.join('builds', pconfig.macro.Provider, "#{OS}-x86_64-#{pconfig.variable 'my_version'}.box")
69
+
70
+ Dir.chdir('spec/integration')
71
+ expect(pconfig.validate).to be_truthy
72
+ expect(pconfig.build).to be_truthy
73
+ Dir.chdir('../..')
74
+ end
75
+ end
76
+