diff --git a/.travis.yml b/.travis.yml index 384fc3f..59873a1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,8 +1,8 @@ language: ruby rvm: - - 1.9.3 - 2.0.0 + - 2.1.1 matrix: allow_failures: - - rvm: 2.0.0 + - rvm: 2.1.1 script: "bundle exec rake ci" diff --git a/BOXES.md b/BOXES.md index 10ebde3..5f51ef6 100644 --- a/BOXES.md +++ b/BOXES.md @@ -52,5 +52,5 @@ on knowing what makes a base box for vagrant-lxc, here's what's needed: | --- | --- | --- | | `provider` | Yes | Required by Vagrant | | `version` | Yes | Tracks backward incompatibilities | -| `built-on` | No | Date / time when the box was packaged | +| `built-on` | No | Date / time when the box was packaged for the first time | | `template-opts` | No | Extra options to be passed to the `lxc-template` script provided with the .box package | diff --git a/CHANGELOG.md b/CHANGELOG.md index 6c887dc..00c0272 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -## [0.8.1](https://github.com/fgrehm/vagrant-lxc/compare/v0.8.0...master) (unreleased) +## [1.0.0.beta1](https://github.com/fgrehm/vagrant-lxc/compare/v0.8.0...master) (unreleased) DEPRECATIONS: diff --git a/Gemfile b/Gemfile index 36ab7dc..7fc3a7e 100644 --- a/Gemfile +++ b/Gemfile @@ -3,22 +3,23 @@ source 'https://rubygems.org' gemspec group :development do - gem 'vagrant', github: 'mitchellh/vagrant' - gem 'vagrant-cachier', github: 'fgrehm/vagrant-cachier' - gem 'vagrant-pristine', github: 'fgrehm/vagrant-pristine' - gem 'vagrant-omnibus' + gem 'vagrant', git: 'https://github.com/mitchellh/vagrant.git' gem 'guard' gem 'guard-rspec' gem 'rb-inotify' end - group :development, :test do gem 'rake' - # Update https://github.com/fgrehm/vagrant-lxc/issues/111 once we are able to - # upgrade to a newer release - gem 'rspec', '~> 2.13.0' - gem 'rspec-fire', require: 'rspec/fire' - gem 'rspec-spies', require: false - gem 'coveralls', require: false + gem 'rspec', '2.99.0.beta2' + gem 'coveralls', require: (ENV['COVERAGE'] == 'true') + gem 'vagrant-spec', git: 'https://github.com/mitchellh/vagrant-spec.git' +end + +group :plugins do + gem 'vagrant-lxc', path: '.' + acceptance = (ENV['ACCEPTANCE'] == 'true') + gem 'vagrant-cachier', git: 'https://github.com/fgrehm/vagrant-cachier.git', require: !acceptance + gem 'vagrant-pristine', git: 'https://github.com/fgrehm/vagrant-pristine.git', require: !acceptance + gem 'vagrant-omnibus', require: !acceptance end diff --git a/Gemfile.lock b/Gemfile.lock index 43da11d..e6ae194 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,40 +1,54 @@ GIT - remote: git://github.com/fgrehm/vagrant-cachier.git - revision: 2faa6615466f8d518893f5ba51b493b877d2efde + remote: https://github.com/fgrehm/vagrant-cachier.git + revision: 2df1e319408a7e6f1c6e75d48e36591199e98527 specs: vagrant-cachier (0.6.1.dev) GIT - remote: git://github.com/fgrehm/vagrant-pristine.git - revision: 4638491786943bfbf6f115b1fc379f069963fe46 + remote: https://github.com/fgrehm/vagrant-pristine.git + revision: 503dbc47848c81d0fbfa6840491856f518d244a1 specs: vagrant-pristine (0.3.0) GIT - remote: git://github.com/mitchellh/vagrant.git - revision: a92e03cf4ce936243d3959b7b5603262a234a58d + remote: https://github.com/mitchellh/vagrant-spec.git + revision: aae28ee57071cdd121ca782c6e0709a5c650a4be specs: - vagrant (1.3.6.dev) - childprocess (~> 0.3.7) + vagrant-spec (0.0.1) + childprocess (~> 0.5.0) + log4r (~> 1.1.9) + rspec (~> 2.14) + thor (~> 0.18.1) + +GIT + remote: https://github.com/mitchellh/vagrant.git + revision: 56dd0e8531e1810fc3ceb17411eeded711794f59 + specs: + vagrant (1.5.1.dev) + bundler (~> 1.5.2) + childprocess (~> 0.5.0) erubis (~> 2.7.0) i18n (~> 0.6.0) - log4r (~> 1.1.9) + listen (~> 2.4.0) + log4r (~> 1.1.9, < 1.1.11) net-scp (~> 1.1.0) - net-ssh (~> 2.6.6) + net-ssh (>= 2.6.6, < 2.8.0) + rb-kqueue (~> 0.2.0) + wdm (~> 0.1.0) PATH remote: . specs: - vagrant-lxc (0.8.1.dev) + vagrant-lxc (1.0.0.beta1.dev) GEM remote: https://rubygems.org/ specs: celluloid (0.15.2) timers (~> 1.1.0) - childprocess (0.3.9) + childprocess (0.5.1) ffi (~> 1.0, >= 1.0.11) - coderay (1.0.9) + coderay (1.1.0) coveralls (0.7.0) multi_json (~> 1.3) rest-client @@ -42,64 +56,65 @@ GEM term-ansicolor thor diff-lcs (1.2.5) + docile (1.1.3) erubis (2.7.0) ffi (1.9.3) formatador (0.2.4) - guard (2.2.3) + guard (2.4.0) formatador (>= 0.2.4) listen (~> 2.1) lumberjack (~> 1.0) pry (>= 0.9.12) thor (>= 0.18.1) - guard-rspec (3.1.0) - guard (>= 1.8) - rspec (~> 2.13) - i18n (0.6.5) - listen (2.2.0) + guard-rspec (4.2.8) + guard (~> 2.1) + rspec (>= 2.14, < 4.0) + i18n (0.6.9) + listen (2.4.1) celluloid (>= 0.15.2) rb-fsevent (>= 0.9.3) rb-inotify (>= 0.9) log4r (1.1.10) lumberjack (1.0.4) method_source (0.8.2) - mime-types (2.0) - multi_json (1.8.2) + mime-types (2.1) + multi_json (1.9.0) net-scp (1.1.2) net-ssh (>= 2.6.5) - net-ssh (2.6.8) - pry (0.9.12.2) - coderay (~> 1.0.5) + net-ssh (2.7.0) + pry (0.9.12.6) + coderay (~> 1.0) method_source (~> 0.8) slop (~> 3.4) - rake (10.1.0) - rb-fsevent (0.9.3) - rb-inotify (0.9.2) + rake (10.1.1) + rb-fsevent (0.9.4) + rb-inotify (0.9.3) + ffi (>= 0.5.0) + rb-kqueue (0.2.2) ffi (>= 0.5.0) rest-client (1.6.7) mime-types (>= 1.16) - rspec (2.13.0) - rspec-core (~> 2.13.0) - rspec-expectations (~> 2.13.0) - rspec-mocks (~> 2.13.0) - rspec-core (2.13.1) - rspec-expectations (2.13.0) + rspec (2.99.0.beta2) + rspec-core (= 2.99.0.beta2) + rspec-expectations (= 2.99.0.beta2) + rspec-mocks (= 2.99.0.beta2) + rspec-core (2.99.0.beta2) + rspec-expectations (2.99.0.beta2) diff-lcs (>= 1.1.3, < 2.0) - rspec-fire (1.3.0) - rspec (>= 2.11, < 4) - rspec-mocks (2.13.1) - rspec-spies (2.1.4) - rspec (~> 2.0) - simplecov (0.7.1) - multi_json (~> 1.0) - simplecov-html (~> 0.7.1) - simplecov-html (0.7.1) - slop (3.4.6) - term-ansicolor (1.2.2) - tins (~> 0.8) + rspec-mocks (2.99.0.beta2) + simplecov (0.8.2) + docile (~> 1.1.0) + multi_json + simplecov-html (~> 0.8.0) + simplecov-html (0.8.0) + slop (3.5.0) + term-ansicolor (1.3.0) + tins (~> 1.0) thor (0.18.1) timers (1.1.0) - tins (0.13.0) - vagrant-omnibus (1.1.2) + tins (1.0.0) + vagrant-omnibus (1.3.1) + wdm (0.1.0) PLATFORMS ruby @@ -110,11 +125,10 @@ DEPENDENCIES guard-rspec rake rb-inotify - rspec (~> 2.13.0) - rspec-fire - rspec-spies + rspec (= 2.99.0.beta2) vagrant! vagrant-cachier! vagrant-lxc! vagrant-omnibus vagrant-pristine! + vagrant-spec! diff --git a/README.md b/README.md index 125df53..241dc34 100644 --- a/README.md +++ b/README.md @@ -9,14 +9,18 @@ as an alternative to the built in VirtualBox provider for Linux hosts. Check out [this blog post](http://fabiorehm.com/blog/2013/04/28/lxc-provider-for-vagrant/) to see it in action. +**NOTICE:** The master branch is targetting an initial beta for 1.0.0, for the +latest stable version of the plugin, please check the [0.8-stable](https://github.com/fgrehm/vagrant-lxc/tree/0.8-stable) +branch. -## Features / Limitations + +## Features * Provides the same workflow as the Vagrant VirtualBox provider * Port forwarding via [`redir`](http://linux.die.net/man/1/redir) -* Does not support public / private networks -* Assumes you have a `lxcbr0` bridge configured on your host similar to [Ubuntu's built-in](https://help.ubuntu.com/lts/serverguide/lxc.html#lxcbr0) +As of now, it does not support public / private networks, but [private networks](https://github.com/fgrehm/vagrant-lxc/issues/120) +will be coming along _soon_. ## Requirements diff --git a/lib/vagrant-backports/README.md b/lib/vagrant-backports/README.md new file mode 100644 index 0000000..0d6f2d2 --- /dev/null +++ b/lib/vagrant-backports/README.md @@ -0,0 +1,12 @@ +# vagrant-backports + + + +A _"hypothetical"_ gem that helps Vagrant plugin developers to stay sane when +keeping up with Vagrant improvements by backporting parts of its recent versions +functionality. + +More information will be provided if there is enough interest on having this +extracted as a separate gem. diff --git a/lib/vagrant-backports/action/handle_box.rb b/lib/vagrant-backports/action/handle_box.rb new file mode 100644 index 0000000..56c6c91 --- /dev/null +++ b/lib/vagrant-backports/action/handle_box.rb @@ -0,0 +1 @@ +Vagrant::Action::Builtin.const_set :HandleBox, Vagrant::Action::Builtin::HandleBoxUrl diff --git a/lib/vagrant-backports/action/is_state.rb b/lib/vagrant-backports/action/is_state.rb new file mode 100644 index 0000000..8d956f5 --- /dev/null +++ b/lib/vagrant-backports/action/is_state.rb @@ -0,0 +1,34 @@ +module Vagrant + module Backports + module Action + # This middleware is meant to be used with Call and can check if + # a machine is in the given state ID. + class IsState + # Note: Any of the arguments can be arrays as well. + # + # @param [Symbol] target_state The target state ID that means that + # the machine was properly shut down. + # @param [Symbol] source_state The source state ID that the machine + # must be in to be shut down. + def initialize(app, env, check, **opts) + @app = app + @logger = Log4r::Logger.new("vagrant::action::builtin::is_state") + @check = check + @invert = !!opts[:invert] + end + + def call(env) + @logger.debug("Checking if machine state is '#{@check}'") + state = env[:machine].state.id + @logger.debug("-- Machine state: #{state}") + + env[:result] = @check == state + env[:result] = !env[:result] if @invert + @app.call(env) + end + end + end + end +end + +Vagrant::Action::Builtin.const_set :IsState, Vagrant::Backports::Action::IsState diff --git a/lib/vagrant-backports/action/message.rb b/lib/vagrant-backports/action/message.rb new file mode 100644 index 0000000..1bf7a15 --- /dev/null +++ b/lib/vagrant-backports/action/message.rb @@ -0,0 +1,20 @@ +module Vagrant + module Backports + module Action + # This middleware simply outputs a message to the UI. + class Message + def initialize(app, env, message, **opts) + @app = app + @message = message + end + + def call(env) + env[:ui].info(@message) + @app.call(env) + end + end + end + end +end + +Vagrant::Action::Builtin.const_set :Message, Vagrant::Backports::Action::Message diff --git a/lib/vagrant-lxc/action/wait_for_communicator.rb b/lib/vagrant-backports/action/wait_for_communicator.rb similarity index 81% rename from lib/vagrant-lxc/action/wait_for_communicator.rb rename to lib/vagrant-backports/action/wait_for_communicator.rb index 9f8b72f..39b349b 100644 --- a/lib/vagrant-lxc/action/wait_for_communicator.rb +++ b/lib/vagrant-backports/action/wait_for_communicator.rb @@ -1,12 +1,11 @@ -# This acts like a backport of Vagrant's built in action from 1.3+ for older versions -# and will probably be deprecated on 0.8+ +# This acts like a backport of Vagrant's built in action from 1.3+ for previous version # https://github.com/mitchellh/vagrant/blob/master/lib/vagrant/action/builtin/wait_for_communicator.rb module Vagrant - module LXC + module Backports module Action class WaitForCommunicator def initialize(app, env) - @app = app + @app = app end def call(env) @@ -21,7 +20,7 @@ module Vagrant max_tries = @env[:machine].config.ssh.max_tries.to_i max_tries.times do |i| if @env[:machine].communicate.ready? - @env[:ui].info I18n.t("vagrant_lxc.messages.container_ready") + @env[:ui].info 'Machine booted and ready!' return true end @@ -39,3 +38,5 @@ module Vagrant end end end + +Vagrant::Action::Builtin.const_set :WaitForCommunicator, Vagrant::Backports::Action::WaitForCommunicator diff --git a/lib/vagrant-backports/ui.rb b/lib/vagrant-backports/ui.rb new file mode 100644 index 0000000..f29c5c0 --- /dev/null +++ b/lib/vagrant-backports/ui.rb @@ -0,0 +1,12 @@ +module Vagrant + module UI + class Interface + def output(*args) + info(*args) + end + def detail(*args) + info(*args) + end + end + end +end diff --git a/lib/vagrant-backports/utils.rb b/lib/vagrant-backports/utils.rb new file mode 100644 index 0000000..ca09514 --- /dev/null +++ b/lib/vagrant-backports/utils.rb @@ -0,0 +1,27 @@ +module Vagrant + module Backports + class << self + def vagrant_1_2_or_later? + greater_than?('1.2.0') + end + + def vagrant_1_3_or_later? + greater_than?('1.3.0') + end + + def vagrant_1_4_or_later? + greater_than?('1.4.0') + end + + def vagrant_1_5_or_later? + greater_than?('1.5.0') + end + + private + + def greater_than?(version) + Gem::Version.new(Vagrant::VERSION) >= Gem::Version.new(version) + end + end + end +end diff --git a/lib/vagrant-lxc/action.rb b/lib/vagrant-lxc/action.rb index 625646c..ce53061 100644 --- a/lib/vagrant-lxc/action.rb +++ b/lib/vagrant-lxc/action.rb @@ -1,28 +1,28 @@ require 'vagrant-lxc/action/boot' -require 'vagrant-lxc/action/check_created' -require 'vagrant-lxc/action/check_running' require 'vagrant-lxc/action/clear_forwarded_ports' require 'vagrant-lxc/action/create' -require 'vagrant-lxc/action/created' require 'vagrant-lxc/action/destroy' require 'vagrant-lxc/action/destroy_confirm' -require 'vagrant-lxc/action/disconnect' require 'vagrant-lxc/action/compress_rootfs' require 'vagrant-lxc/action/fetch_ip_with_lxc_attach' require 'vagrant-lxc/action/fetch_ip_from_dnsmasq_leases' require 'vagrant-lxc/action/forced_halt' require 'vagrant-lxc/action/forward_ports' require 'vagrant-lxc/action/handle_box_metadata' -require 'vagrant-lxc/action/is_running' -require 'vagrant-lxc/action/message' +require 'vagrant-lxc/action/prepare_nfs_settings' +require 'vagrant-lxc/action/prepare_nfs_valid_ids' require 'vagrant-lxc/action/remove_temporary_files' require 'vagrant-lxc/action/setup_package_files' -require 'vagrant-lxc/action/share_folders' require 'vagrant-lxc/action/warn_networks' -unless Vagrant::LXC.vagrant_1_3_or_later - require 'vagrant-lxc/action/wait_for_communicator' - Vagrant::Action::Builtin.const_set :WaitForCommunicator, Vagrant::LXC::Action::WaitForCommunicator +unless Vagrant::Backports.vagrant_1_3_or_later? + require 'vagrant-backports/action/wait_for_communicator' +end +unless Vagrant::Backports.vagrant_1_5_or_later? + require 'vagrant-backports/ui' + require 'vagrant-backports/action/handle_box' + require 'vagrant-backports/action/message' + require 'vagrant-backports/action/is_state' end module Vagrant @@ -37,9 +37,9 @@ module Vagrant # machine back up with the new configuration. def self.action_reload Builder.new.tap do |b| - b.use Builtin::Call, Created do |env1, b2| - if !env1[:result] - b2.use Message, :not_created + b.use Builtin::Call, Builtin::IsState, :not_created do |env1, b2| + if env1[:result] + b2.use Builtin::Message, I18n.t("vagrant_lxc.messages.not_created") next end @@ -57,7 +57,15 @@ module Vagrant b.use Builtin::Provision b.use Builtin::EnvSet, :port_collision_repair => true b.use Builtin::HandleForwardedPortCollisions - b.use ShareFolders + if Vagrant::Backports.vagrant_1_4_or_later? + b.use PrepareNFSValidIds + b.use Builtin::SyncedFolderCleanup + b.use Builtin::SyncedFolders + b.use PrepareNFSSettings + else + require 'vagrant-lxc/backports/action/share_folders' + b.use ShareFolders + end b.use Builtin::SetHostname b.use WarnNetworks b.use ForwardPorts @@ -70,15 +78,15 @@ module Vagrant def self.action_provision Builder.new.tap do |b| b.use Builtin::ConfigValidate - b.use Builtin::Call, Created do |env1, b2| - if !env1[:result] - b2.use Message, :not_created + b.use Builtin::Call, Builtin::IsState, :not_created do |env1, b2| + if env1[:result] + b2.use Builtin::Message, I18n.t("vagrant_lxc.messages.not_created") next end - b2.use Builtin::Call, IsRunning do |env2, b3| + b2.use Builtin::Call, Builtin::IsState, :running do |env2, b3| if !env2[:result] - b3.use Message, :not_running + b3.use Builtin::Message, I18n.t("vagrant_lxc.messages.not_running") next end @@ -93,7 +101,7 @@ module Vagrant def self.action_start Builder.new.tap do |b| b.use Builtin::ConfigValidate - b.use Builtin::Call, IsRunning do |env, b2| + b.use Builtin::Call, Builtin::IsState, :running do |env, b2| # If the VM is running, then our work here is done, exit next if env[:result] b2.use action_boot @@ -106,10 +114,10 @@ module Vagrant def self.action_up Builder.new.tap do |b| b.use Builtin::ConfigValidate - b.use Builtin::Call, Created do |env, b2| + b.use Builtin::Call, Builtin::IsState, :not_created do |env, b2| # If the VM is NOT created yet, then do the setup steps - if !env[:result] - b2.use Builtin::HandleBoxUrl + if env[:result] + b2.use Builtin::HandleBox b2.use HandleBoxMetadata b2.use Create end @@ -122,19 +130,18 @@ module Vagrant # the virtual machine, gracefully or by force. def self.action_halt Builder.new.tap do |b| - b.use Builtin::Call, Created do |env, b2| + b.use Builtin::Call, Builtin::IsState, :not_created do |env, b2| if env[:result] - # TODO: Remove once we drop support for vagrant 1.1 - b2.use Disconnect - b2.use ClearForwardedPorts - b2.use RemoveTemporaryFiles - b2.use Builtin::Call, Builtin::GracefulHalt, :stopped, :running do |env2, b3| - if !env2[:result] - b3.use ForcedHalt - end + b2.use Builtin::Message, I18n.t("vagrant_lxc.messages.not_created") + next + end + + b2.use ClearForwardedPorts + b2.use RemoveTemporaryFiles + b2.use Builtin::Call, Builtin::GracefulHalt, :stopped, :running do |env2, b3| + if !env2[:result] + b3.use ForcedHalt end - else - b2.use Message, :not_created end end end @@ -144,9 +151,9 @@ module Vagrant # freeing the resources of the underlying virtual machine. def self.action_destroy Builder.new.tap do |b| - b.use Builtin::Call, Created do |env1, b2| - if !env1[:result] - b2.use Message, :not_created + b.use Builtin::Call, Builtin::IsState, :not_created do |env1, b2| + if env1[:result] + b2.use Builtin::Message, I18n.t("vagrant_lxc.messages.not_created") next end @@ -157,11 +164,11 @@ module Vagrant b3.use Builtin::EnvSet, :force_halt => true b3.use action_halt b3.use Destroy - if Vagrant::LXC.vagrant_1_3_or_later + if Vagrant::Backports.vagrant_1_3_or_later? b3.use Builtin::ProvisionerCleanup end else - b3.use Message, :will_not_destroy + b3.use Builtin::Message, I18n.t("vagrant_lxc.messages.will_not_destroy") end end end @@ -171,9 +178,9 @@ module Vagrant # This action packages the virtual machine into a single box file. def self.action_package Builder.new.tap do |b| - b.use Builtin::Call, Created do |env1, b2| - if !env1[:result] - b2.use Message, :not_created + b.use Builtin::Call, Builtin::IsState, :not_created do |env1, b2| + if env1[:result] + b2.use Builtin::Message, I18n.t("vagrant_lxc.messages.not_created") next end @@ -198,18 +205,44 @@ module Vagrant # This is the action that will exec into an SSH shell. def self.action_ssh Builder.new.tap do |b| - b.use CheckCreated - b.use CheckRunning - b.use Builtin::SSHExec + b.use Builtin::ConfigValidate + b.use Builtin::Call, Builtin::IsState, :not_created do |env, b2| + if env[:result] + b2.use Builtin::Message, I18n.t("vagrant_lxc.messages.not_created") + next + end + + b2.use Builtin::Call, Builtin::IsState, :running do |env1, b3| + if !env1[:result] + b3.use Builtin::Message, I18n.t("vagrant_lxc.messages.not_running") + next + end + + b3.use BuiltIn::SSHExec + end + end end end # This is the action that will run a single SSH command. def self.action_ssh_run Builder.new.tap do |b| - b.use CheckCreated - b.use CheckRunning - b.use Builtin::SSHRun + b.use Builtin::ConfigValidate + b.use Builtin::Call, Builtin::IsState, :not_created do |env, b2| + if env[:result] + b2.use Builtin::Message, I18n.t("vagrant_lxc.messages.not_created") + next + end + + b2.use Builtin::Call, Builtin::IsState, :running do |env1, b3| + if !env1[:result] + b3.use Builtin::Message, I18n.t("vagrant_lxc.messages.not_running") + next + end + + b3.use Builtin::SSHRun + end + end end end end diff --git a/lib/vagrant-lxc/action/check_created.rb b/lib/vagrant-lxc/action/check_created.rb deleted file mode 100644 index 94f7cb8..0000000 --- a/lib/vagrant-lxc/action/check_created.rb +++ /dev/null @@ -1,21 +0,0 @@ -module Vagrant - module LXC - module Action - class CheckCreated - def initialize(app, env) - @app = app - end - - def call(env) - if env[:machine].state.id == :not_created - raise Vagrant::Errors::VMNotCreatedError - end - - # Call the next if we have one (but we shouldn't, since this - # middleware is built to run with the Call-type middlewares) - @app.call(env) - end - end - end - end -end diff --git a/lib/vagrant-lxc/action/check_running.rb b/lib/vagrant-lxc/action/check_running.rb deleted file mode 100644 index c4481a3..0000000 --- a/lib/vagrant-lxc/action/check_running.rb +++ /dev/null @@ -1,21 +0,0 @@ -module Vagrant - module LXC - module Action - class CheckRunning - def initialize(app, env) - @app = app - end - - def call(env) - if env[:machine].state.id != :running - raise Vagrant::Errors::VMNotRunningError - end - - # Call the next if we have one (but we shouldn't, since this - # middleware is built to run with the Call-type middlewares) - @app.call(env) - end - end - end - end -end diff --git a/lib/vagrant-lxc/action/created.rb b/lib/vagrant-lxc/action/created.rb deleted file mode 100644 index 71897e9..0000000 --- a/lib/vagrant-lxc/action/created.rb +++ /dev/null @@ -1,20 +0,0 @@ -module Vagrant - module LXC - module Action - class Created - def initialize(app, env) - @app = app - end - - def call(env) - # Set the result to be true if the machine is created. - env[:result] = env[:machine].state.id != :not_created - - # Call the next if we have one (but we shouldn't, since this - # middleware is built to run with the Call-type middlewares) - @app.call(env) - end - end - end - end -end diff --git a/lib/vagrant-lxc/action/disconnect.rb b/lib/vagrant-lxc/action/disconnect.rb deleted file mode 100644 index 69aee10..0000000 --- a/lib/vagrant-lxc/action/disconnect.rb +++ /dev/null @@ -1,18 +0,0 @@ -module Vagrant - module LXC - module Action - class Disconnect - def initialize(app, env) - @app = app - end - - def call(env) - @app.call env - # FIXME: Vagrant >= 1.1.3 should not need this - # https://github.com/mitchellh/vagrant/compare/715539eac30bc9ae62ddbb6337d13f036f7b774d...ec1bae0#L2R128 - env[:machine].instance_variable_set(:@communicator, nil) - end - end - end - end -end diff --git a/lib/vagrant-lxc/action/is_running.rb b/lib/vagrant-lxc/action/is_running.rb deleted file mode 100644 index 0c14e2d..0000000 --- a/lib/vagrant-lxc/action/is_running.rb +++ /dev/null @@ -1,19 +0,0 @@ -module Vagrant - module LXC - module Action - class IsRunning - def initialize(app, env) - @app = app - end - - def call(env) - env[:result] = env[:machine].state.id == :running - - # Call the next if we have one (but we shouldn't, since this - # middleware is built to run with the Call-type middlewares) - @app.call(env) - end - end - end - end -end diff --git a/lib/vagrant-lxc/action/message.rb b/lib/vagrant-lxc/action/message.rb index ca3d2ee..e69de29 100644 --- a/lib/vagrant-lxc/action/message.rb +++ b/lib/vagrant-lxc/action/message.rb @@ -1,23 +0,0 @@ -module Vagrant - module LXC - module Action - # XXX: Is this really needed? Should we contribute this back to Vagrant's core? - class Message - def initialize(app, env, msg_key, type = :info) - @app = app - @msg_key = msg_key - @type = type - end - - def call(env) - machine = env[:machine] - message = I18n.t("vagrant_lxc.messages.#{@msg_key}", name: machine.name) - - env[:ui].send @type, message - - @app.call env - end - end - end - end -end diff --git a/lib/vagrant-lxc/action/prepare_nfs_settings.rb b/lib/vagrant-lxc/action/prepare_nfs_settings.rb new file mode 100644 index 0000000..82c1a4d --- /dev/null +++ b/lib/vagrant-lxc/action/prepare_nfs_settings.rb @@ -0,0 +1,64 @@ +module Vagrant + module LXC + module Action + class PrepareNFSSettings + include Vagrant::Util::Retryable + + def initialize(app, env) + @app = app + @logger = Log4r::Logger.new("vagrant::action::vm::nfs") + end + + def call(env) + @machine = env[:machine] + + @app.call(env) + + # if using_nfs? # TODO: && !privileged_container? + # raise Errors::NfsWithoutPrivilegedError + # end + + if using_nfs? + @logger.info("Using NFS, preparing NFS settings by reading host IP and machine IP") + add_ips_to_env!(env) + end + end + + # We're using NFS if we have any synced folder with NFS configured. If + # we are not using NFS we don't need to do the extra work to + # populate these fields in the environment. + def using_nfs? + @machine.config.vm.synced_folders.any? { |_, opts| opts[:type] == :nfs } + end + + # TODO: + # def privileged_container? + # @machine.provider.driver.privileged?(@machine.id) + # end + + # Extracts the proper host and guest IPs for NFS mounts and stores them + # in the environment for the SyncedFolder action to use them in + # mounting. + # + # The ! indicates that this method modifies its argument. + def add_ips_to_env!(env) + provider = @machine.provider + + host_ip = read_host_ip + machine_ip = provider.ssh_info[:host] + + raise Vagrant::Errors::NFSNoHostonlyNetwork if !host_ip || !machine_ip + + env[:nfs_host_ip] = host_ip + env[:nfs_machine_ip] = machine_ip + end + + def read_host_ip + @machine.communicate.execute 'echo $SSH_CLIENT' do |buffer, output| + return output.chomp.split(' ')[0] if buffer == :stdout + end + end + end + end + end +end diff --git a/lib/vagrant-lxc/action/prepare_nfs_valid_ids.rb b/lib/vagrant-lxc/action/prepare_nfs_valid_ids.rb new file mode 100644 index 0000000..fcae3b4 --- /dev/null +++ b/lib/vagrant-lxc/action/prepare_nfs_valid_ids.rb @@ -0,0 +1,19 @@ +module Vagrant + module LXC + module Action + class PrepareNFSValidIds + def initialize(app, env) + @app = app + @logger = Log4r::Logger.new("vagrant::action::vm::nfs") + end + + def call(env) + machine = env[:machine] + env[:nfs_valid_ids] = machine.provider.driver.all_containers + + @app.call(env) + end + end + end + end +end diff --git a/lib/vagrant-lxc/action/setup_package_files.rb b/lib/vagrant-lxc/action/setup_package_files.rb index a770604..0132035 100644 --- a/lib/vagrant-lxc/action/setup_package_files.rb +++ b/lib/vagrant-lxc/action/setup_package_files.rb @@ -45,10 +45,12 @@ module Vagrant box_dir = @env[:machine].box.directory FileUtils.cp box_dir.join('lxc-template').to_s, @env['package.directory'].to_s FileUtils.cp box_dir.join('metadata.json').to_s, @env['package.directory'].to_s - # TODO: Update built-on metadata.json if (conf = box_dir.join('lxc.conf')).exist? FileUtils.cp conf.to_s, @env['package.directory'].to_s end + if (conf = box_dir.join('lxc-config')).exist? + FileUtils.cp conf.to_s, @env['package.directory'].to_s + end end end end diff --git a/lib/vagrant-lxc/action/share_folders.rb b/lib/vagrant-lxc/backports/action/share_folders.rb similarity index 100% rename from lib/vagrant-lxc/action/share_folders.rb rename to lib/vagrant-lxc/backports/action/share_folders.rb diff --git a/lib/vagrant-lxc/driver.rb b/lib/vagrant-lxc/driver.rb index 3c14554..7c09ec1 100644 --- a/lib/vagrant-lxc/driver.rb +++ b/lib/vagrant-lxc/driver.rb @@ -31,6 +31,10 @@ module Vagrant raise ContainerNotFound if @container_name && ! @cli.list.include?(@container_name) end + def all_containers + @cli.list + end + def base_path Pathname.new("#{CONTAINERS_PATH}/#{@container_name}") end @@ -58,20 +62,24 @@ module Vagrant def share_folders(folders) folders.each do |folder| - guestpath = rootfs_path.join(folder[:guestpath].gsub(/^\//, '')) - unless guestpath.directory? - begin - @logger.debug("Guest path doesn't exist, creating: #{guestpath}") - @sudo_wrapper.run('mkdir', '-p', guestpath.to_s) - rescue Errno::EACCES - raise Vagrant::Errors::SharedFolderCreateFailed, :path => guestpath.to_s - end - end - - @customizations << ['mount.entry', "#{folder[:hostpath]} #{guestpath} none bind 0 0"] + share_folder(folder[:hostpath], folder[:guestpath]) end end + def share_folder(host_path, guest_path) + guest_path = rootfs_path.join(guest_path.gsub(/^\//, '')) + unless guest_path.directory? + begin + @logger.debug("Guest path doesn't exist, creating: #{guest_path}") + @sudo_wrapper.run('mkdir', '-p', guest_path.to_s) + rescue Errno::EACCES + raise Vagrant::Errors::SharedFolderCreateFailed, :path => guest_path.to_s + end + end + + @customizations << ['mount.entry', "#{host_path} #{guest_path} none bind 0 0"] + end + def start(customizations) @logger.info('Starting container...') @@ -87,6 +95,7 @@ module Vagrant def forced_halt @logger.info('Shutting down container...') + # TODO: Remove `lxc-shutdown` usage, graceful halt is enough @cli.transition_to(:stopped) { |c| c.shutdown } # REFACTOR: Do not use exception to control the flow rescue CLI::TargetStateNotReached, CLI::ShutdownNotSupported diff --git a/lib/vagrant-lxc/plugin.rb b/lib/vagrant-lxc/plugin.rb index 801c927..0bd0e19 100644 --- a/lib/vagrant-lxc/plugin.rb +++ b/lib/vagrant-lxc/plugin.rb @@ -1,4 +1,5 @@ -require "vagrant" +require 'vagrant' +require 'vagrant-backports/utils' module Vagrant module LXC @@ -9,7 +10,9 @@ module Vagrant LXC-based virtual machines. EOF - provider(:lxc, parallel: true) do + extra = [] + extra << {parallel: true} if Vagrant::Backports.vagrant_1_2_or_later? + provider(:lxc, *extra) do require File.expand_path("../provider", __FILE__) I18n.load_path << File.expand_path(File.dirname(__FILE__) + '/../../locales/en.yml') @@ -22,10 +25,20 @@ module Vagrant require File.expand_path("../config", __FILE__) Config end - end - def self.vagrant_1_3_or_later - Gem::Version.new(Vagrant::VERSION) >= Gem::Version.new('1.3.0') + if Vagrant::Backports.vagrant_1_4_or_later? + synced_folder(:lxc) do + require File.expand_path("../synced_folder", __FILE__) + SyncedFolder + end + end + + if Vagrant::Backports.vagrant_1_5_or_later? + provider_capability("lxc", "public_address") do + require_relative "provider/cap/public_address" + Provider::Cap::PublicAddress + end + end end end end diff --git a/lib/vagrant-lxc/provider/cap/public_address.rb b/lib/vagrant-lxc/provider/cap/public_address.rb new file mode 100644 index 0000000..1c8fc8a --- /dev/null +++ b/lib/vagrant-lxc/provider/cap/public_address.rb @@ -0,0 +1,17 @@ +module Vagrant + module LXC + class Provider + module Cap + module PublicAddress + def self.public_address(machine) + return nil if machine.state.id != :running + + ssh_info = machine.ssh_info + return nil if !ssh_info + ssh_info[:host] + end + end + end + end + end +end diff --git a/lib/vagrant-lxc/synced_folder.rb b/lib/vagrant-lxc/synced_folder.rb new file mode 100644 index 0000000..0199d6a --- /dev/null +++ b/lib/vagrant-lxc/synced_folder.rb @@ -0,0 +1,38 @@ +module Vagrant + module LXC + class SyncedFolder < Vagrant.plugin("2", :synced_folder) + def usable?(machine) + # These synced folders only work if the provider is LXC + machine.provider_name == :lxc + end + + def prepare(machine, folders, _opts) + machine.ui.output(I18n.t("vagrant.actions.lxc.share_folders.preparing")) + + folders.each do |id, data| + host_path = Pathname.new(File.expand_path(data[:hostpath], machine.env.root_path)) + guest_path = data[:guestpath] + + if !host_path.directory? && data[:create] + # Host path doesn't exist, so let's create it. + @logger.info("Host path doesn't exist, creating: #{host_path}") + + begin + host_path.mkpath + rescue Errno::EACCES + raise Vagrant::Errors::SharedFolderCreateFailed, + :path => hostpath.to_s + end + end + + machine.provider.driver.share_folder(host_path, guest_path) + # Guest path specified, so mount the folder to specified point + machine.ui.detail(I18n.t("vagrant.actions.vm.share_folders.mounting_entry", + guestpath: data[:guestpath], + hostpath: data[:hostpath], + guest_path: data[:guestpath])) + end + end + end + end +end diff --git a/lib/vagrant-lxc/version.rb b/lib/vagrant-lxc/version.rb index 714ec29..4bc60a1 100644 --- a/lib/vagrant-lxc/version.rb +++ b/lib/vagrant-lxc/version.rb @@ -1,5 +1,5 @@ module Vagrant module LXC - VERSION = "0.8.1.dev" + VERSION = "1.0.0.beta1.dev" end end diff --git a/locales/en.yml b/locales/en.yml index 2958b99..7aec249 100644 --- a/locales/en.yml +++ b/locales/en.yml @@ -12,11 +12,6 @@ en: Starting container... force_shutdown: |- Forcing shutdown of container... - # TODO: Remove the following keys after we drop support for vagrant < 1.3 - waiting_for_start: |- - Waiting for container to start. This should not take long. - container_ready: |- - Container started and ready for use! warn_networks: |- Warning! The LXC provider doesn't support any of the Vagrant public / private network configurations (ex: `config.vm.network :private_network, ip: "some-ip"`). diff --git a/spec/acceptance/sanity_check_spec.rb b/spec/acceptance/sanity_check_spec.rb deleted file mode 100644 index c3c4d97..0000000 --- a/spec/acceptance/sanity_check_spec.rb +++ /dev/null @@ -1,111 +0,0 @@ -require 'acceptance_helper' - -describe 'Sanity check' do - after(:all) { destroy_container } - - context 'running `vagrant up` from scratch' do - before(:all) do - destroy_container - vagrant_up - end - - it 'creates a container' do - containers = `sudo lxc-ls`.chomp.split(/\s+/).uniq - expect(containers).to include vagrant_container_name - end - - it 'starts the newly created container' do - status = `sudo lxc-info -n #{vagrant_container_name}` - expect(status).to include 'RUNNING' - end - - it "is able to be SSH'ed" do - expect(vagrant_ssh('hostname')).to eq 'lxc-test-box' - end - - it 'mounts shared folders with the right permissions' do - vagrant_ssh 'mkdir -p /vagrant/tmp && echo -n "Shared" > /vagrant/tmp/shared' - shared_file_contents = File.read('/vagrant/spec/tmp/shared') - expect(shared_file_contents).to eq 'Shared' - end - - it 'provisions the container based on Vagrantfile configs' do - provisioned_file_contents = File.read('/vagrant/spec/tmp/provisioning') - expect(provisioned_file_contents).to eq 'Provisioned' - end - - it 'forwards configured ports' do - output = `curl -s localhost:8080`.strip.chomp - expect(output).to include 'It works!' - end - end - - context '`vagrant halt` on a running container' do - before(:all) do - destroy_container - vagrant_up - vagrant_ssh 'touch /tmp/{some,files}' - vagrant_halt - end - - it 'shuts down the container' do - status = `sudo lxc-info -n #{vagrant_container_name}` - expect(status).to include 'STOPPED' - end - - it 'clears forwarded ports' do - `curl -s localhost:8080 --connect-timeout 2` - expect($?.exitstatus).to_not eq 0 - end - - it 'kills redir processes' do - processes = `pgrep redir` - expect($?.exitstatus).to_not eq 0 - end - - xit 'removes files under `/tmp`' do - container_tmp_files = `sudo ls -l "/var/lib/lxc/#{vagrant_container_name}/rootfs/tmp"`.split("\n") - puts container_tmp_files.join("\n") - expect(container_tmp_files).to be_empty - end - end - - context '`vagrant destroy`' do - before(:all) do - destroy_container - vagrant_up - @container_name = vagrant_container_name - vagrant_destroy - end - - it 'destroys the underlying container' do - containers = `sudo lxc-ls`.chomp.split(/\s+/).uniq - expect(containers).to_not include @container_name - end - end - - pending 'box packaging' do - before(:all) do - destroy_container - vagrant_box_remove('new-box') - vagrant_up - vagrant_package - @box_name = ENV['BOX_NAME'] - # This will make - ENV["BOX_NAME"] = 'new-box' - ENV['BOX_URL'] = '/vagrant/spec/tmp/package.box' - end - - after(:all) do - vagrant_box_remove('new-box') - ENV["BOX_NAME"] = @box_name - ENV['BOX_URL'] = nil - end - - it 'creates a package that can be successfully brought up on a later `vagrant up`' do - vagrant_up - # Just to make sure we packaged it properly - expect(vagrant_ssh('cat /home/vagrant/original-box')).to eq @box_name - end - end -end diff --git a/spec/acceptance/support/acceptance_example_group.rb b/spec/acceptance/support/acceptance_example_group.rb deleted file mode 100644 index 7042117..0000000 --- a/spec/acceptance/support/acceptance_example_group.rb +++ /dev/null @@ -1,76 +0,0 @@ -module AcceptanceExampleGroup - def self.included(base) - base.metadata[:type] = :acceptance - end - - ID_FILE = "/vagrant/spec/.vagrant/machines/default/lxc/id" - def vagrant_container_name - File.read(ID_FILE).strip.chomp if File.exists?(ID_FILE) - end - - def destroy_container - if name = vagrant_container_name - `sudo lxc-shutdown -n #{name} 2>/dev/null` - `sudo lxc-wait -n #{name} --state STOPPED 2>/dev/null` - `sudo lxc-destroy -n #{name} 2>/dev/null` - `rm -rf /vagrant/spec/.vagrant/` - end - `sudo killall -9 redir 2>/dev/null` - end - - def with_vagrant_environment - opts = { cwd: '/vagrant/spec', ui_class: TestUI } - env = Vagrant::Environment.new(opts) - yield env - env.unload - end - - def vagrant_up - with_vagrant_environment do |env| - env.cli('up', '--provider', 'lxc') - end - end - - def vagrant_halt - with_vagrant_environment do |env| - env.cli('halt') - end - end - - def vagrant_destroy - with_vagrant_environment do |env| - env.cli('destroy', '-f') - end - end - - def vagrant_ssh(cmd) - output = nil - with_vagrant_environment do |env| - result = env.cli('ssh', '-c', cmd) - if result.to_i != 0 - raise "SSH command failed: '#{cmd}'\n#{env.ui.messages.inspect}" - end - output = env.ui.messages[:info].join("\n").chomp - end - output - end - - def vagrant_package - with_vagrant_environment do |env| - pkg = '/vagrant/spec/tmp/package.box' - `rm -f #{pkg}` - env.cli('package', '--output', pkg) - end - end - - def vagrant_box_remove(name) - with_vagrant_environment do |env| - env.cli('box', 'list') - output = env.ui.messages[:info].join("\n").chomp - - if output.include?(name) - env.cli('box', 'remove', name) - end - end - end -end diff --git a/spec/acceptance/support/machine_ext.rb b/spec/acceptance/support/machine_ext.rb deleted file mode 100644 index 9b28a61..0000000 --- a/spec/acceptance/support/machine_ext.rb +++ /dev/null @@ -1,12 +0,0 @@ -# Monkey patch vagrant in order to reuse the UI test object that is set on -# our Vagrant::Environments -# -require 'vagrant/machine' -Vagrant::Machine.class_eval do - alias :old_action :action - - define_method :action do |action_name, extra_env = nil| - extra_env = { ui: @env.ui }.merge(extra_env || {}) - old_action action_name, extra_env - end -end diff --git a/spec/acceptance/support/test_ui.rb b/spec/acceptance/support/test_ui.rb deleted file mode 100644 index 9fc1ff6..0000000 --- a/spec/acceptance/support/test_ui.rb +++ /dev/null @@ -1,22 +0,0 @@ -class TestUI < Vagrant::UI::Interface - attr_reader :messages - - METHODS = [:clear_line, :report_progress, :warn, :error, :info, :success] - - def initialize - super - @messages = METHODS.each_with_object({}) { |m, h| h[m] = [] } - end - - def ask(*args) - super - # Automated tests should not depend on user input, obviously. - raise Errors::UIExpectsTTY - end - - METHODS.each do |method| - define_method(method) do |*args|#message, *opts| - @messages[method].push args[0] - end - end -end diff --git a/spec/acceptance_helper.rb b/spec/acceptance_helper.rb deleted file mode 100644 index ff45967..0000000 --- a/spec/acceptance_helper.rb +++ /dev/null @@ -1,21 +0,0 @@ -require 'spec_helper' - -unless ENV['USER'] == 'vagrant' - puts 'Acceptance specs are supposed to run from one of the vagrant-lxc dev machines' - exit 1 -end - -if defined? SimpleCov - SimpleCov.command_name 'acceptance' -end - -require 'vagrant' -require 'vagrant-lxc' - -Dir[File.dirname(__FILE__) + "/acceptance/support/**/*.rb"].each { |f| require f } - -RSpec.configure do |config| - config.include AcceptanceExampleGroup, :type => :acceptance, :example_group => { - :file_path => /\bspec\/acceptance\// - } -end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index bdbc54b..9129f95 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -10,22 +10,10 @@ require 'bundler/setup' require 'i18n' -require 'rspec-spies' +require 'vagrant-lxc/plugin' Dir[File.dirname(__FILE__) + "/support/**/*.rb"].each { |f| require f } -# If we should verify constant names, eager loads -if ENV['VERIFY_CONSTANT_NAMES'] - require 'vagrant-lxc/plugin' - require 'vagrant-lxc/provider' - require 'vagrant-lxc/config' -end - -require 'rspec/fire' -RSpec::Fire.configure do |config| - config.verify_constant_names = ENV['VERIFY_CONSTANT_NAMES'] == '1' -end - RSpec.configure do |config| config.treat_symbols_as_metadata_keys_with_true_values = true config.run_all_when_everything_filtered = true diff --git a/spec/unit/action/compress_rootfs_spec.rb b/spec/unit/action/compress_rootfs_spec.rb index 2a70ba4..0a81c72 100644 --- a/spec/unit/action/compress_rootfs_spec.rb +++ b/spec/unit/action/compress_rootfs_spec.rb @@ -1,13 +1,15 @@ require 'unit_helper' +require 'vagrant-lxc/plugin' +require 'vagrant-lxc/provider' require 'vagrant-lxc/action/compress_rootfs' describe Vagrant::LXC::Action::CompressRootFS do let(:app) { double(:app, call: true) } let(:env) { {machine: machine, ui: double(info: true)} } - let(:machine) { instance_double('Vagrant::Machine', provider: provider) } - let(:provider) { instance_double('Vagrant::LXC::Provider', driver: driver) } - let(:driver) { instance_double('Vagrant::LXC::Driver', compress_rootfs: compressed_rootfs_path) } + let(:machine) { double(Vagrant::Machine, provider: provider) } + let(:provider) { double(Vagrant::LXC::Provider, driver: driver) } + let(:driver) { double(Vagrant::LXC::Driver, compress_rootfs: compressed_rootfs_path) } let(:compressed_rootfs_path) { '/path/to/rootfs.tar.gz' } subject { described_class.new(app, env) } diff --git a/spec/unit/action/forward_ports_spec.rb b/spec/unit/action/forward_ports_spec.rb index 126907e..077ee7d 100644 --- a/spec/unit/action/forward_ports_spec.rb +++ b/spec/unit/action/forward_ports_spec.rb @@ -1,7 +1,7 @@ require 'unit_helper' require 'tmpdir' -require 'vagrant-lxc/errors' +require 'vagrant-lxc/provider' require 'vagrant-lxc/action/forward_ports' describe Vagrant::LXC::Action::ForwardPorts do @@ -9,7 +9,7 @@ describe Vagrant::LXC::Action::ForwardPorts do let(:env) { {machine: machine, ui: double(info: true)} } let(:machine) { double(:machine) } let!(:data_dir) { Pathname.new(Dir.mktmpdir) } - let(:provider) { instance_double('Vagrant::LXC::Provider', ssh_info: {host: container_ip}) } + let(:provider) { double(Vagrant::LXC::Provider, ssh_info: {host: container_ip}) } let(:host_ip) { '127.0.0.1' } let(:host_port) { 8080 } let(:guest_port) { 80 } diff --git a/spec/unit/action/handle_box_metadata_spec.rb b/spec/unit/action/handle_box_metadata_spec.rb index 3208355..78c2ce4 100644 --- a/spec/unit/action/handle_box_metadata_spec.rb +++ b/spec/unit/action/handle_box_metadata_spec.rb @@ -102,15 +102,11 @@ describe Vagrant::LXC::Action::HandleBoxMetadata do it 'validates box versions' do %w( 2 3 1.0.0 ).each do |v| metadata['version'] = v - expect { - subject.call(env) - }.to_not raise_error(Vagrant::LXC::Errors::IncompatibleBox) + expect { subject.call(env) }.to_not raise_error end metadata['version'] = '1' - expect { - subject.call(env) - }.to raise_error(Vagrant::LXC::Errors::IncompatibleBox) + expect { subject.call(env) }.to raise_error end it 'raises an error if the rootfs tarball cant be found' do diff --git a/spec/unit/action/setup_package_files_spec.rb b/spec/unit/action/setup_package_files_spec.rb index 6c1c042..00f421a 100644 --- a/spec/unit/action/setup_package_files_spec.rb +++ b/spec/unit/action/setup_package_files_spec.rb @@ -5,16 +5,16 @@ require 'vagrant-lxc/action/setup_package_files' describe Vagrant::LXC::Action::SetupPackageFiles do let(:app) { double(:app, call: true) } let(:env) { {machine: machine, tmp_path: tmp_path, ui: double(info: true), 'package.rootfs' => rootfs_path} } - let(:machine) { instance_double('Vagrant::Machine', box: box) } + let(:machine) { double(Vagrant::Machine, box: box) } let!(:tmp_path) { Pathname.new(Dir.mktmpdir) } - let(:box) { instance_double('Vagrant::Box', directory: tmp_path.join('box')) } + let(:box) { double(Vagrant::Box, directory: tmp_path.join('box')) } let(:rootfs_path) { tmp_path.join('rootfs-amd64.tar.gz') } subject { described_class.new(app, env) } before do box.directory.mkdir - files = %w( lxc-template metadata.json lxc.conf ).map { |f| box.directory.join(f) } + files = %w( lxc-template metadata.json lxc.conf lxc-config ).map { |f| box.directory.join(f) } (files + [rootfs_path]).each do |file| file.open('w') { |f| f.puts file.to_s } end @@ -41,6 +41,10 @@ describe Vagrant::LXC::Action::SetupPackageFiles do env['package.directory'].join('lxc-template').should be_file end + it 'copies box lxc-config to package directory' do + env['package.directory'].join('lxc-config').should be_file + end + it 'moves the compressed rootfs to package directory' do env['package.directory'].join(rootfs_path.basename).should be_file env['package.rootfs'].should_not be_file @@ -56,4 +60,14 @@ describe Vagrant::LXC::Action::SetupPackageFiles do expect { subject.call(env) }.to_not raise_error end end + + context 'when lxc-config file is not present' do + before do + box.directory.join('lxc-config').delete + end + + it 'does not blow up' do + expect { subject.call(env) }.to_not raise_error + end + end end diff --git a/spec/unit/driver/cli_spec.rb b/spec/unit/driver/cli_spec.rb index 9e78353..e2f6c4a 100644 --- a/spec/unit/driver/cli_spec.rb +++ b/spec/unit/driver/cli_spec.rb @@ -1,9 +1,10 @@ require 'unit_helper' +require 'vagrant-lxc/sudo_wrapper' require 'vagrant-lxc/driver/cli' describe Vagrant::LXC::Driver::CLI do - let(:sudo_wrapper) { instance_double('Vagrant::LXC::SudoWrapper', run: true) } + let(:sudo_wrapper) { double(Vagrant::LXC::SudoWrapper, run: true) } subject { described_class.new(sudo_wrapper) } @@ -197,6 +198,6 @@ describe Vagrant::LXC::Driver::CLI do }.to raise_error(described_class::TransitionBlockNotProvided) end - pending 'waits for the expected container state' + skip 'waits for the expected container state' end end diff --git a/spec/unit/driver_spec.rb b/spec/unit/driver_spec.rb index 1b31e22..ad52b29 100644 --- a/spec/unit/driver_spec.rb +++ b/spec/unit/driver_spec.rb @@ -1,15 +1,15 @@ require 'unit_helper' -require 'vagrant' require 'vagrant-lxc/driver' require 'vagrant-lxc/driver/cli' +require 'vagrant-lxc/sudo_wrapper' describe Vagrant::LXC::Driver do describe 'container name validation' do let(:unknown_container) { described_class.new('unknown', nil, cli) } let(:valid_container) { described_class.new('valid', nil, cli) } let(:new_container) { described_class.new(nil, nil) } - let(:cli) { instance_double('Vagrant::LXC::Driver::CLI', list: ['valid']) } + let(:cli) { double(Vagrant::LXC::Driver::CLI, list: ['valid']) } it 'raises a ContainerNotFound error if an unknown container name gets provided' do expect { @@ -37,7 +37,7 @@ describe Vagrant::LXC::Driver do let(:template_opts) { {'--some' => 'random-option'} } let(:config_file) { '/path/to/lxc-config-from-box' } let(:rootfs_tarball) { '/path/to/cache/rootfs.tar.gz' } - let(:cli) { instance_double('Vagrant::LXC::Driver::CLI', :create => true, :name= => true) } + let(:cli) { double(Vagrant::LXC::Driver::CLI, :create => true, :name= => true) } subject { described_class.new(nil, nil, cli) } @@ -60,7 +60,7 @@ describe Vagrant::LXC::Driver do end describe 'destruction' do - let(:cli) { instance_double('Vagrant::LXC::Driver::CLI', destroy: true) } + let(:cli) { double(Vagrant::LXC::Driver::CLI, destroy: true) } subject { described_class.new('name', nil, cli) } @@ -74,8 +74,8 @@ describe Vagrant::LXC::Driver do describe 'start' do let(:customizations) { [['a', '1'], ['b', '2']] } let(:internal_customization) { ['internal', 'customization'] } - let(:cli) { instance_double('Vagrant::LXC::Driver::CLI', start: true) } - let(:sudo) { instance_double('Vagrant::LXC::SudoWrapper', su_c: true) } + let(:cli) { double(Vagrant::LXC::Driver::CLI, start: true) } + let(:sudo) { double(Vagrant::LXC::SudoWrapper, su_c: true) } subject { described_class.new('name', sudo, cli) } @@ -94,7 +94,7 @@ describe Vagrant::LXC::Driver do end describe 'halt' do - let(:cli) { instance_double('Vagrant::LXC::Driver::CLI', shutdown: true) } + let(:cli) { double(Vagrant::LXC::Driver::CLI, shutdown: true) } subject { described_class.new('name', nil, cli) } @@ -129,7 +129,7 @@ describe Vagrant::LXC::Driver do describe 'state' do let(:cli_state) { :something } - let(:cli) { instance_double('Vagrant::LXC::Driver::CLI', state: cli_state) } + let(:cli) { double(Vagrant::LXC::Driver::CLI, state: cli_state) } subject { described_class.new('name', nil, cli) } @@ -143,7 +143,7 @@ describe Vagrant::LXC::Driver do let(:folders) { [shared_folder] } let(:rootfs_path) { Pathname('/path/to/rootfs') } let(:expected_guest_path) { "#{rootfs_path}/vagrant" } - let(:sudo_wrapper) { instance_double('Vagrant::LXC::SudoWrapper', run: true) } + let(:sudo_wrapper) { double(Vagrant::LXC::SudoWrapper, run: true) } subject { described_class.new('name', sudo_wrapper) } diff --git a/spec/unit_helper.rb b/spec/unit_helper.rb index 4122faf..844be91 100644 --- a/spec/unit_helper.rb +++ b/spec/unit_helper.rb @@ -7,8 +7,6 @@ if defined? SimpleCov end RSpec.configure do |config| - config.include RSpec::Fire - config.include UnitExampleGroup, :type => :unit, :example_group => { :file_path => /\bspec\/unit\// } diff --git a/tasks/spec.rake b/tasks/spec.rake index ddd4867..a44bf01 100644 --- a/tasks/spec.rake +++ b/tasks/spec.rake @@ -3,7 +3,7 @@ begin require 'coveralls/rake/task' desc 'Run all specs' - task :spec => ['spec:unit', 'spec:acceptance'] + task :spec => ['spec:set_coverage', 'spec:unit', 'spec:acceptance'] desc 'Default task which runs all specs with code coverage enabled' task :default => ['spec:set_coverage', 'spec:unit'] @@ -17,17 +17,24 @@ namespace :spec do ENV['COVERAGE'] = 'true' end - def types - dirs = Dir['./spec/**/*_spec.rb'].map { |f| f.sub(/^\.\/(spec\/\w+)\/.*/, '\\1') }.uniq - Hash[dirs.map { |d| [d.split('/').last, d] }] + desc 'Run acceptance specs using vagrant-spec' + task :acceptance do + components = %w( + basic + network/forwarded_port + synced_folder + synced_folder/nfs + synced_folder/rsync + provisioner/shell + provisioner/puppet + provisioner/chef-solo + package + ).map{|s| "provider/lxc/#{s}" } + sh "export ACCEPTANCE=true && bundle exec vagrant-spec test --components=#{components.join(' ')}" end - types.each do |type, dir| - desc "Run the code examples in #{dir}" - RSpec::Core::RakeTask.new(type) do |t| - # Tells rspec-fire to verify if constants used really exist - ENV['VERIFY_CONSTANT_NAMES'] = '1' - t.pattern = "./#{dir}/**/*_spec.rb" - end + desc "Run unit specs with rspec" + RSpec::Core::RakeTask.new(:unit) do |t| + t.pattern = "./unit/**/*_spec.rb" end end diff --git a/vagrant-spec.config.rb b/vagrant-spec.config.rb new file mode 100644 index 0000000..dbb4f05 --- /dev/null +++ b/vagrant-spec.config.rb @@ -0,0 +1,33 @@ +unless ENV['USER'] == 'vagrant' + puts 'Acceptance specs are supposed to run from one of the vagrant-lxc dev machines' + exit 1 +end + +# FIXME: Figure out why this doesn't work +if ENV['COVERAGE'] == 'true' + require 'simplecov' + require 'coveralls' + + SimpleCov.start { add_filter '/spec/' } + SimpleCov.command_name 'acceptance' +end + +# if defined? SimpleCov +# SimpleCov.command_name 'acceptance' +# end + +if ENV['BOX_PATH'] == nil + latest = ENV.fetch('LATEST_BOXES','2014-03-11') + release = ENV.fetch('RELEASE', 'precise') + local_path ="#{File.expand_path("../", __FILE__)}/boxes/output/#{latest}/vagrant-lxc-#{release}-amd64.box" + if File.exists?(local_path) + ENV['BOX_PATH'] = local_path + else + raise 'Set $BOX_PATH to the latest released boxes' + end +end + +Vagrant::Spec::Acceptance.configure do |c| + c.component_paths << "spec/acceptance" + c.provider 'lxc', box: ENV['BOX_PATH'], features: ['!suspend'] +end