vagrant-ami 0.0.1

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.
data/.gitignore ADDED
@@ -0,0 +1,19 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ Vagrantfile
19
+ .vagrant
data/Gemfile ADDED
@@ -0,0 +1,11 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in vagrant-ami.gemspec
4
+ gemspec
5
+
6
+ group :development do
7
+ # We depend on Vagrant for development, but we don't add it as a
8
+ # gem dependency because we expect to be installed within the
9
+ # Vagrant environment itself using `vagrant plugin`.
10
+ gem "vagrant", :git => "git://github.com/mitchellh/vagrant.git"
11
+ end
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Mike Ryan
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,40 @@
1
+ # Create AMIs from Vagrant EC2 boxes
2
+
3
+ This is a [Vagrant](http://www.vagrantup.com) 1.2+ plugin that adds a command
4
+ to create [AWS](http://aws.amazon.com) AMIs.
5
+
6
+ This plugin has a very short lifespan in terms of usefulness.
7
+
8
+ Technically this plugin is already superseded by [Packer](http://packer.io) which
9
+ is a more general solution for creating various types of machine images.
10
+
11
+ However, Packer does not yet have the same level of provisioner support enjoyed
12
+ by Vagrant. Until then, I need a simple way to make AMIs based on Vagrant EC2 boxes
13
+ provisioned with Puppet and Chef, which can be called easily from Jenkins.
14
+
15
+ **NOTE:** This plugin requires Vagrant 1.2+,
16
+
17
+
18
+ ## Features
19
+
20
+ * Create AMIs from Vagrant-managed EC2 instances
21
+ * Assign tags to newly-created AMIs
22
+
23
+
24
+ ## Usage
25
+
26
+ Install using standard Vagrant 1.1+ plugin installation methods. After
27
+ bringing up an AwS instance issue the command to create the AMI as shown
28
+ below.
29
+
30
+ ```
31
+ $ vagrant plugin install vagrant-ami
32
+ ...
33
+ $ vagrant up --provider=aws
34
+ ...
35
+ $ vagrant create_ami --name my-ami --desc "My AMI" --tags role=test,environment=dev
36
+ ...
37
+ $ vagrant destroy
38
+ ```
39
+
40
+ vagrant-ami relies heavily on vagrant-aws, and reuses all of its configuration settings.
data/Rakefile ADDED
@@ -0,0 +1,21 @@
1
+ require 'rubygems'
2
+ require 'bundler/setup'
3
+ require 'rspec/core/rake_task'
4
+
5
+ # Immediately sync all stdout so that tools like buildbot can
6
+ # immediately load in the output.
7
+ $stdout.sync = true
8
+ $stderr.sync = true
9
+
10
+ # Change to the directory of this file.
11
+ Dir.chdir(File.expand_path("../", __FILE__))
12
+
13
+ # This installs the tasks that help with gem creation and
14
+ # publishing.
15
+ Bundler::GemHelper.install_tasks
16
+
17
+ # Install the `spec` task so that we can run tests.
18
+ RSpec::Core::RakeTask.new
19
+
20
+ # Default task is to run the unit tests
21
+ task :default => "spec"
@@ -0,0 +1,18 @@
1
+ require "pathname"
2
+
3
+ require "vagrant-ami/plugin"
4
+
5
+ module VagrantPlugins
6
+ module AMI
7
+ lib_path = Pathname.new(File.expand_path("../vagrant-ami", __FILE__))
8
+ autoload :Action, lib_path.join("action")
9
+ autoload :Errors, lib_path.join("errors")
10
+
11
+ # This returns the path to the source of this plugin.
12
+ #
13
+ # @return [Pathname]
14
+ def self.source_root
15
+ @source_root ||= Pathname.new(File.expand_path("../../", __FILE__))
16
+ end
17
+ end
18
+ end
Binary file
@@ -0,0 +1,27 @@
1
+ require "pathname"
2
+
3
+ require "vagrant/action/builder"
4
+ require "vagrant-aws/action"
5
+
6
+ module VagrantPlugins
7
+ module AMI
8
+ module Action
9
+ # Include the built-in modules so we can use them as top-level things.
10
+ include Vagrant::Action::Builtin
11
+
12
+ # This action is called to create EC2 AMIs.
13
+ def self.action_create_ami
14
+ Vagrant::Action::Builder.new.tap do |b|
15
+ b.use ConfigValidate
16
+ b.use VagrantPlugins::AWS::Action::ConnectAWS
17
+ b.use CreateAMI
18
+ end
19
+ end
20
+
21
+
22
+ # The autoload farm
23
+ action_root = Pathname.new(File.expand_path("../action", __FILE__))
24
+ autoload :CreateAMI, action_root.join("create_ami")
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,74 @@
1
+ require 'date'
2
+ require 'vagrant-aws/util/timer'
3
+ require 'vagrant-aws/errors'
4
+ require 'vagrant/util/retryable'
5
+
6
+ module VagrantPlugins
7
+ module AMI
8
+ module Action
9
+ # This runs the configured instance.
10
+ class CreateAMI
11
+ include Vagrant::Util::Retryable
12
+
13
+ def initialize(app, env)
14
+ @app = app
15
+ @logger = Log4r::Logger.new("vagrant_ami::action::create_ami")
16
+ end
17
+
18
+ def call(env)
19
+ if env[:machine].state.id != :running
20
+ puts "Skipping #{env[:machine].name}: not running"
21
+ else
22
+ _create_ami(env)
23
+ end
24
+
25
+ end
26
+
27
+ protected
28
+
29
+ def _create_ami(env)
30
+ env[:ui].info("Creating AMI named '#{env[:name]}'for #{env[:machine].name} (#{env[:machine].id})")
31
+
32
+ # TODO this isn't getting logged
33
+ @logger.info("Description: #{env[:desc]} Tags: #{env[:tags]}")
34
+
35
+ # TODO error handling on create_image/tags
36
+ # this raises an error if AMI name already exists
37
+ # see this for error handling examples
38
+ # https://github.com/mitchellh/vagrant-aws/blob/master/lib/vagrant-aws/action/run_instance.rb#L79
39
+ server = env[:aws_compute].servers.get(env[:machine].id)
40
+ begin
41
+ data = env[:aws_compute].create_image(server.identity, env[:name], env[:desc])
42
+ rescue Excon::Errors::BadRequest => e
43
+ if e.response.body =~ /InvalidAMIName.Duplicate/
44
+ raise VagrantPlugins::AWS::Errors::FogError,
45
+ :message => "An AMI named #{env[:name]} already exists"
46
+ end
47
+ raise
48
+ end
49
+
50
+ image_id = data.body["imageId"]
51
+
52
+ image = env[:aws_compute].images.get(image_id)
53
+ env[:ui].info("Creating #{image_id}")
54
+
55
+ # Wait for the image to be ready
56
+ # TODO should have a configurable timeout for this
57
+ while true
58
+ # If we're interrupted then just back out
59
+ break if env[:interrupted]
60
+ image = env[:aws_compute].images.get(image_id)
61
+ break if image.ready?
62
+ sleep 2
63
+ end
64
+
65
+ unless env[:tags].empty?
66
+ env[:ui].info("Adding tags to AMI")
67
+ env[:aws_compute].create_tags(image_id, env[:tags])
68
+ end
69
+ env[:ui].info("Created #{image_id}")
70
+ end
71
+ end
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,54 @@
1
+ require 'optparse'
2
+
3
+ module VagrantPlugins
4
+ module AMI
5
+ class Command < Vagrant.plugin("2", :command)
6
+ def execute
7
+
8
+ options = {
9
+ :tags => {}
10
+ }
11
+
12
+ opts = OptionParser.new do |o|
13
+ o.banner = "Usage: vagrant create_ami [vm-name]"
14
+ o.separator ""
15
+
16
+ o.on("-n", "--name NAME", "AMI Name") do |n|
17
+ options[:name] = n
18
+ end
19
+
20
+ o.on("-d", "--desc DESCRIPTION", "AMI Description.") do |d|
21
+ options[:desc] = d
22
+ end
23
+
24
+ o.on("-t", "--tags key1=val1,keyN=valN", Array, "Optional tags to assign to the AMI.") do |t|
25
+ options[:tags] = Hash[t.map {|kv| kv.split("=")}]
26
+ end
27
+
28
+ # TODO add option to wait until AMI creation is complete?
29
+ # TODO does this work if the instance is terminated immediately after hte create_ami call
30
+ # is issues?
31
+
32
+ end
33
+
34
+ # Parse the options
35
+ argv = parse_options(opts)
36
+ return if !argv
37
+
38
+ if options[:name].nil? or options[:desc].nil?
39
+ raise Vagrant::Errors::CLIInvalidOptions, :help => opts.help.chomp
40
+ end
41
+
42
+ with_target_vms(argv, :reverse => true) do |machine|
43
+ @env.action_runner.run(VagrantPlugins::AMI::Action.action_create_ami, {
44
+ :machine => machine,
45
+ :name => options[:name],
46
+ :desc => options[:desc],
47
+ :tags => options[:tags]
48
+ })
49
+ end
50
+ 0
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,50 @@
1
+ require "vagrant"
2
+
3
+ module VagrantPlugins
4
+ module AMI
5
+ class Config < Vagrant.plugin("2", :config)
6
+ # The tags for created AMIs.
7
+ #
8
+ # @return [Hash<String, String>]
9
+ attr_accessor :tags
10
+
11
+ def initialize(region_specific=false)
12
+ @tags = {}
13
+ end
14
+
15
+ def validate(machine)
16
+ errors = _detected_errors
17
+
18
+ errors << I18n.t("vagrant_aws.config.region_required") if @region.nil?
19
+
20
+ if @region
21
+ # Get the configuration for the region we're using and validate only
22
+ # that region.
23
+ config = get_region_config(@region)
24
+
25
+ if !config.use_iam_profile
26
+ errors << I18n.t("vagrant_aws.config.access_key_id_required") if \
27
+ config.access_key_id.nil?
28
+ errors << I18n.t("vagrant_aws.config.secret_access_key_required") if \
29
+ config.secret_access_key.nil?
30
+ end
31
+
32
+ errors << I18n.t("vagrant_aws.config.ami_required") if config.ami.nil?
33
+ end
34
+
35
+ { "AWS Provider" => errors }
36
+ end
37
+
38
+ # This gets the configuration for a specific region. It shouldn't
39
+ # be called by the general public and is only used internally.
40
+ def get_region_config(name)
41
+ if !@__finalized
42
+ raise "Configuration must be finalized before calling this method."
43
+ end
44
+
45
+ # Return the compiled region config
46
+ @__compiled_region_configs[name] || self
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,61 @@
1
+ begin
2
+ require "vagrant"
3
+ rescue LoadError
4
+ raise "The Vagrant AMI plugin must be run within Vagrant."
5
+ end
6
+
7
+ # This is a sanity check to make sure no one is attempting to install
8
+ # this into an early Vagrant version.
9
+ if Vagrant::VERSION < "1.2.0"
10
+ raise "The Vagrant AMI plugin is only compatible with Vagrant 1.2+"
11
+ end
12
+
13
+ module VagrantPlugins
14
+ module AMI
15
+ class Plugin < Vagrant.plugin("2")
16
+ name "AMI"
17
+ description <<-DESC
18
+ This plugin allows Vagrant to create EC2 AMIs.
19
+ DESC
20
+
21
+ #config(:ami, :provider) do
22
+ # require_relative "config"
23
+ # Config
24
+ #end
25
+
26
+ command("create-ami") do
27
+ require File.expand_path("../commands/create_ami.rb", __FILE__)
28
+ Command
29
+ end
30
+
31
+ # This sets up our log level to be whatever VAGRANT_LOG is.
32
+ def self.setup_logging
33
+ require "log4r"
34
+
35
+ level = nil
36
+ begin
37
+ level = Log4r.const_get(ENV["VAGRANT_LOG"].upcase)
38
+ rescue NameError
39
+ # This means that the logging constant wasn't found,
40
+ # which is fine. We just keep `level` as `nil`. But
41
+ # we tell the user.
42
+ level = nil
43
+ end
44
+
45
+ # Some constants, such as "true" resolve to booleans, so the
46
+ # above error checking doesn't catch it. This will check to make
47
+ # sure that the log level is an integer, as Log4r requires.
48
+ level = nil if !level.is_a?(Integer)
49
+
50
+ # Set the logging level on all "vagrant" namespaced
51
+ # logs as long as we have a valid level.
52
+ if level
53
+ logger = Log4r::Logger.new("vagrant_ami")
54
+ logger.outputters = Log4r::Outputter.stderr
55
+ logger.level = level
56
+ logger = nil
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,5 @@
1
+ module Vagrant
2
+ module Ami
3
+ VERSION = "0.0.1"
4
+ end
5
+ end
@@ -0,0 +1,24 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'vagrant-ami/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "vagrant-ami"
8
+ spec.version = Vagrant::Ami::VERSION
9
+ spec.authors = "Mike Ryan"
10
+ spec.email = "mike@epitech.nl"
11
+ spec.description = "Enables Vagrant to create EC2 AMIs."
12
+ spec.summary = "Enables Vagrant to create EC2 AMIs."
13
+ spec.homepage = "http://www.epitech.nl"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.3"
22
+ spec.add_development_dependency "rake"
23
+ spec.add_runtime_dependency "vagrant-aws"
24
+ end
metadata ADDED
@@ -0,0 +1,100 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: vagrant-ami
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Mike Ryan
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-07-27 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: bundler
16
+ requirement: &12417060 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: '1.3'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: *12417060
25
+ - !ruby/object:Gem::Dependency
26
+ name: rake
27
+ requirement: &12416600 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ! '>='
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
33
+ type: :development
34
+ prerelease: false
35
+ version_requirements: *12416600
36
+ - !ruby/object:Gem::Dependency
37
+ name: vagrant-aws
38
+ requirement: &12416120 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ! '>='
42
+ - !ruby/object:Gem::Version
43
+ version: '0'
44
+ type: :runtime
45
+ prerelease: false
46
+ version_requirements: *12416120
47
+ description: Enables Vagrant to create EC2 AMIs.
48
+ email: mike@epitech.nl
49
+ executables: []
50
+ extensions: []
51
+ extra_rdoc_files: []
52
+ files:
53
+ - .gitignore
54
+ - Gemfile
55
+ - LICENSE.txt
56
+ - README.md
57
+ - Rakefile
58
+ - lib/vagrant-ami.rb
59
+ - lib/vagrant-ami/.plugin.rb.swp
60
+ - lib/vagrant-ami/action.rb
61
+ - lib/vagrant-ami/action/.create_ami.rb.swp
62
+ - lib/vagrant-ami/action/create_ami.rb
63
+ - lib/vagrant-ami/commands/.create_ami.rb.swp
64
+ - lib/vagrant-ami/commands/create_ami.rb
65
+ - lib/vagrant-ami/config.rb
66
+ - lib/vagrant-ami/plugin.rb
67
+ - lib/vagrant-ami/version.rb
68
+ - vagrant-ami.gemspec
69
+ homepage: http://www.epitech.nl
70
+ licenses:
71
+ - MIT
72
+ post_install_message:
73
+ rdoc_options: []
74
+ require_paths:
75
+ - lib
76
+ required_ruby_version: !ruby/object:Gem::Requirement
77
+ none: false
78
+ requirements:
79
+ - - ! '>='
80
+ - !ruby/object:Gem::Version
81
+ version: '0'
82
+ segments:
83
+ - 0
84
+ hash: 1894379412045326636
85
+ required_rubygems_version: !ruby/object:Gem::Requirement
86
+ none: false
87
+ requirements:
88
+ - - ! '>='
89
+ - !ruby/object:Gem::Version
90
+ version: '0'
91
+ segments:
92
+ - 0
93
+ hash: 1894379412045326636
94
+ requirements: []
95
+ rubyforge_project:
96
+ rubygems_version: 1.8.11
97
+ signing_key:
98
+ specification_version: 3
99
+ summary: Enables Vagrant to create EC2 AMIs.
100
+ test_files: []