diff --git a/lib/puppet/face/module/install.rb b/lib/puppet/face/module/install.rb index db0a0eb91..2e695cde6 100644 --- a/lib/puppet/face/module/install.rb +++ b/lib/puppet/face/module/install.rb @@ -1,173 +1,174 @@ # encoding: UTF-8 Puppet::Face.define(:module, '1.0.0') do action(:install) do summary "Install a module from a repository or release archive." description <<-EOT Installs a module from the Puppet Forge, from a release archive file on-disk, or from a private Forge-like repository. The specified module will be installed into the directory specified with the `--target-dir` option, which defaults to #{Puppet.settings[:modulepath].split(File::PATH_SEPARATOR).first}. EOT returns "Pathname object representing the path to the installed module." examples <<-EOT Install a module: $ puppet module install puppetlabs-vcsrepo Preparing to install into /etc/puppet/modules ... Downloading from http://forge.puppetlabs.com ... Installing -- do not interrupt ... /etc/puppet/modules └── puppetlabs-vcsrepo (v0.0.4) Install a module to a specific environment: $ puppet module install puppetlabs-vcsrepo --environment development Preparing to install into /etc/puppet/environments/development/modules ... Downloading from http://forge.puppetlabs.com ... Installing -- do not interrupt ... /etc/puppet/environments/development/modules └── puppetlabs-vcsrepo (v0.0.4) Install a specific module version: $ puppet module install puppetlabs-vcsrepo -v 0.0.4 Preparing to install into /etc/puppet/modules ... Downloading from http://forge.puppetlabs.com ... Installing -- do not interrupt ... /etc/puppet/modules └── puppetlabs-vcsrepo (v0.0.4) Install a module into a specific directory: $ puppet module install puppetlabs-vcsrepo --target-dir=/usr/share/puppet/modules Preparing to install into /usr/share/puppet/modules ... Downloading from http://forge.puppetlabs.com ... Installing -- do not interrupt ... /usr/share/puppet/modules └── puppetlabs-vcsrepo (v0.0.4) Install a module into a specific directory and check for dependencies in other directories: $ puppet module install puppetlabs-vcsrepo --target-dir=/usr/share/puppet/modules --modulepath /etc/puppet/modules Preparing to install into /usr/share/puppet/modules ... Downloading from http://forge.puppetlabs.com ... Installing -- do not interrupt ... /usr/share/puppet/modules └── puppetlabs-vcsrepo (v0.0.4) Install a module from a release archive: $ puppet module install puppetlabs-vcsrepo-0.0.4.tar.gz Preparing to install into /etc/puppet/modules ... Downloading from http://forge.puppetlabs.com ... Installing -- do not interrupt ... /etc/puppet/modules └── puppetlabs-vcsrepo (v0.0.4) Install a module from a release archive and ignore dependencies: $ puppet module install puppetlabs-vcsrepo-0.0.4.tar.gz --ignore-dependencies Preparing to install into /etc/puppet/modules ... Installing -- do not interrupt ... /etc/puppet/modules └── puppetlabs-vcsrepo (v0.0.4) EOT arguments "" option "--force", "-f" do summary "Force overwrite of existing module, if any." description <<-EOT Force overwrite of existing module, if any. EOT end option "--target-dir DIR", "-i DIR" do summary "The directory into which modules are installed." description <<-EOT The directory into which modules are installed; defaults to the first directory in the modulepath. Specifying this option will change the installation directory, and will use the existing modulepath when checking for dependencies. If you wish to check a different set of directories for dependencies, you must also use the `--environment` or `--modulepath` options. EOT end option "--ignore-dependencies" do summary "Do not attempt to install dependencies" description <<-EOT Do not attempt to install dependencies. EOT end option "--modulepath MODULEPATH" do default_to { Puppet.settings[:modulepath] } summary "Which directories to look for modules in" description <<-EOT The list of directories to check for modules. When installing a new module, this setting determines where the module tool will look for its dependencies. If the `--target dir` option is not specified, the first directory in the modulepath will also be used as the install directory. When installing a module into an environment whose modulepath is specified in puppet.conf, you can use the `--environment` option instead, and its modulepath will be used automatically. This setting should be a list of directories separated by the path separator character. (The path separator is `:` on Unix-like platforms and `;` on Windows.) EOT end option "--version VER", "-v VER" do summary "Module version to install." description <<-EOT Module version to install; can be an exact version or a requirement string, eg '>= 1.0.3'. Defaults to latest version. EOT end option "--environment NAME" do default_to { "production" } summary "The target environment to install modules into." description <<-EOT The target environment to install modules into. Only applicable if multiple environments (with different modulepaths) have been configured in puppet.conf. EOT end when_invoked do |name, options| sep = File::PATH_SEPARATOR if options[:target_dir] + options[:target_dir] = File.expand_path(options[:target_dir]) options[:modulepath] = "#{options[:target_dir]}#{sep}#{options[:modulepath]}" end Puppet.settings[:modulepath] = options[:modulepath] options[:target_dir] = Puppet.settings[:modulepath].split(sep).first Puppet.notice "Preparing to install into #{options[:target_dir]} ..." Puppet::ModuleTool::Applications::Installer.run(name, options) end when_rendering :console do |return_value, name, options| if return_value[:result] == :failure Puppet.err(return_value[:error][:multiline]) exit 1 else tree = Puppet::ModuleTool.build_tree(return_value[:installed_modules], return_value[:install_dir]) return_value[:install_dir] + "\n" + Puppet::ModuleTool.format_tree(tree) end end end end diff --git a/spec/unit/face/module/install_spec.rb b/spec/unit/face/module/install_spec.rb index 33101d338..6f3780293 100644 --- a/spec/unit/face/module/install_spec.rb +++ b/spec/unit/face/module/install_spec.rb @@ -1,158 +1,169 @@ require 'spec_helper' require 'puppet/face' require 'puppet/module_tool' describe "puppet module install" do subject { Puppet::Face[:module, :current] } let(:options) do {} end describe "option validation" do before do Puppet.settings[:modulepath] = fakemodpath end let(:expected_options) do { :target_dir => fakefirstpath, :modulepath => fakemodpath, :environment => 'production' } end let(:sep) { File::PATH_SEPARATOR } let(:fakefirstpath) { "/my/fake/modpath" } let(:fakesecondpath) { "/other/fake/path" } let(:fakemodpath) { "#{fakefirstpath}#{sep}#{fakesecondpath}" } let(:fakedirpath) { "/my/fake/path" } context "without any options" do it "should require a name" do pattern = /wrong number of arguments/ expect { subject.install }.to raise_error ArgumentError, pattern end it "should not require any options" do Puppet::ModuleTool::Applications::Installer.expects(:run).with("puppetlabs-apache", expected_options).once subject.install("puppetlabs-apache") end end it "should accept the --force option" do options[:force] = true expected_options.merge!(options) Puppet::ModuleTool::Applications::Installer.expects(:run).with("puppetlabs-apache", expected_options).once subject.install("puppetlabs-apache", options) end it "should accept the --target-dir option" do options[:target_dir] = "/foo/puppet/modules" expected_options.merge!(options) expected_options[:modulepath] = "#{options[:target_dir]}#{sep}#{fakemodpath}" Puppet::ModuleTool::Applications::Installer.expects(:run).with("puppetlabs-apache", expected_options).once subject.install("puppetlabs-apache", options) end it "should accept the --version option" do options[:version] = "0.0.1" expected_options.merge!(options) Puppet::ModuleTool::Applications::Installer.expects(:run).with("puppetlabs-apache", expected_options).once subject.install("puppetlabs-apache", options) end it "should accept the --ignore-dependencies option" do options[:ignore_dependencies] = true expected_options.merge!(options) Puppet::ModuleTool::Applications::Installer.expects(:run).with("puppetlabs-apache", expected_options).once subject.install("puppetlabs-apache", options) end describe "when modulepath option is passed" do let(:expected_options) { { :modulepath => fakemodpath, :environment => 'production' } } let(:options) { { :modulepath => fakemodpath } } describe "when target-dir option is not passed" do it "should set target-dir to be first path from modulepath" do expected_options[:target_dir] = fakefirstpath Puppet::ModuleTool::Applications::Installer. expects(:run). with("puppetlabs-apache", expected_options) Puppet::Face[:module, :current].install("puppetlabs-apache", options) Puppet.settings[:modulepath].should == fakemodpath end end describe "when target-dir option is passed" do + it "should expand the target directory" do + options[:target_dir] = "modules" + expanded_path = File.expand_path("modules") + expected_options.merge!(options) + expected_options[:target_dir] = expanded_path + expected_options[:modulepath] = "#{expanded_path}#{sep}#{fakemodpath}" + + Puppet::ModuleTool::Applications::Installer.expects(:run).with("puppetlabs-apache", expected_options).once + subject.install("puppetlabs-apache", options) + end + it "should set target-dir to be first path of modulepath" do options[:target_dir] = fakedirpath expected_options[:target_dir] = fakedirpath expected_options[:modulepath] = "#{fakedirpath}#{sep}#{fakemodpath}" Puppet::ModuleTool::Applications::Installer. expects(:run). with("puppetlabs-apache", expected_options) Puppet::Face[:module, :current].install("puppetlabs-apache", options) Puppet.settings[:modulepath].should == "#{fakedirpath}#{sep}#{fakemodpath}" end end end describe "when modulepath option is not passed" do before do Puppet.settings[:modulepath] = fakemodpath end describe "when target-dir option is not passed" do it "should set target-dir to be first path of default mod path" do expected_options[:target_dir] = fakefirstpath expected_options[:modulepath] = fakemodpath Puppet::ModuleTool::Applications::Installer. expects(:run). with("puppetlabs-apache", expected_options) Puppet::Face[:module, :current].install("puppetlabs-apache", options) end end describe "when target-dir option is passed" do it "should prepend target-dir to modulepath" do options[:target_dir] = fakedirpath expected_options[:target_dir] = fakedirpath expected_options[:modulepath] = "#{options[:target_dir]}#{sep}#{fakemodpath}" Puppet::ModuleTool::Applications::Installer. expects(:run). with("puppetlabs-apache", expected_options) Puppet::Face[:module, :current].install("puppetlabs-apache", options) Puppet.settings[:modulepath].should == expected_options[:modulepath] end end end end describe "inline documentation" do subject { Puppet::Face[:module, :current].get_action :install } its(:summary) { should =~ /install.*module/im } its(:description) { should =~ /install.*module/im } its(:returns) { should =~ /pathname/i } its(:examples) { should_not be_empty } %w{ license copyright summary description returns examples }.each do |doc| context "of the" do its(doc.to_sym) { should_not =~ /(FIXME|REVISIT|TODO)/ } end end end end