librarian-puppet-simple 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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ data.tar.gz: e70ab85f22c10e06549a8e4084512224a7a85de8
4
+ metadata.gz: cfad763618e6817a981167e95edaf026908b8ea8
5
+ SHA512:
6
+ data.tar.gz: 8450ff50735e8083b294e379a9652175688ac9ef27454e00c519d5842d0331131891aad460dc112f02508de7082c57451b2d0e7e61deee4eaed1ee100992c706
7
+ metadata.gz: 1f1fe4db05d288c0eb566f2e9e39eef07cea6264e312b1b0bff07d084d4855ada399f70429b8d1bdfc3dece7c283ba74c258ff64f6ee907f820027f66847fbfd
data/.gitignore ADDED
@@ -0,0 +1,19 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ .rspec
7
+ Gemfile.lock
8
+ InstalledFiles
9
+ _yardoc
10
+ coverage
11
+ doc/
12
+ lib/bundler/man
13
+ pkg
14
+ rdoc
15
+ spec/reports
16
+ test/tmp
17
+ test/version_tmp
18
+ tmp
19
+ vendor/
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source "https://rubygems.org"
2
+
3
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1 @@
1
+ Apache License 2.0
data/README.md ADDED
@@ -0,0 +1,57 @@
1
+ # librarian-puppet-simple
2
+
3
+ This project was created out of my frustration with dependency management in librarian-puppet, some people need external dependencies, I just need to be able to pin revisions for a collection of modules, and I found the dependency managment features of librarian-puppet too heavy for my simple use case.
4
+
5
+ This project just has fewer commands, but they should be compatible with the original librarian-puppet:
6
+
7
+ ### Clean
8
+ Remove the directory where the modules will be installed. At the moment the supported options are:
9
+ * `--verbose` display progress messages
10
+ * `--path` override the default `./modules` where modules will be installed
11
+
12
+ ```
13
+ librarian-puppet clean [--verbose] [--path]
14
+ ```
15
+
16
+ ### Install
17
+ Iterates through your Puppetfile and installs git sources. At the moment the supported options are:
18
+ * `--verbose` display progress messages
19
+ * `--clean` remove the directory before installing modules
20
+ * `--path` override the default `./modules` where modules will be installed
21
+ * `--puppetfile` override the default `./Puppetfile` used to find the modules
22
+
23
+ ```
24
+ librarian-puppet install [--verbose] [--clean] [--path] [--puppetfile]
25
+ ```
26
+
27
+ ## Puppetfile
28
+ The processed Puppetfile may contain two different types of modules, `git` and `tarball`. The `git` option accepts an optional `ref` parameter.
29
+
30
+ The module names can be namespaced, but the created directory will only contain the last part of the name. For example, a module named `puppetlabs/ntp` will generate a directory `ntp`, and so will a module simply named `ntp`.
31
+
32
+ Here's an example of a valid Puppetfile showcasing all valid options:
33
+
34
+ ```
35
+ mod "puppetlabs/ntp",
36
+ :git => "git://github.com/puppetlabs/puppetlabs-ntp.git",
37
+ :ref => "99bae40f225db0dd052efbf1d4078a21f0333331"
38
+
39
+ mod "apache",
40
+ :tarball => "https://forge.puppetlabs.com/puppetlabs/apache/0.6.0.tar.gz"
41
+ ```
42
+
43
+ ## Setting up for development and running the specs
44
+ Just clone the repo and run the following commands:
45
+ ```
46
+ bundle exec install --path=vendor
47
+ bundle exec rspec
48
+ ```
49
+
50
+ Beware that the functional tests will download files from GitHub and PuppetForge and will break if either is unavailable.
51
+
52
+ ## License
53
+
54
+ See [LICENSE](/LICENSE)
55
+
56
+ ## Credits
57
+ The untar and ungzip methods came from https://gist.github.com/sinisterchipmunk/1335041
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env ruby
2
+ require 'rubygems'
3
+ require 'thor'
4
+ lib = File.expand_path('../../lib', __FILE__)
5
+ $:.unshift(lib) unless $:.include?(lib)
6
+ require 'librarian/puppet/simple/cli'
7
+
8
+ Librarian::Puppet::Simple::CLI.bin!
@@ -0,0 +1,87 @@
1
+ require 'librarian/puppet/simple/installer'
2
+ require 'librarian/puppet/simple/iterator'
3
+ require 'fileutils'
4
+
5
+ module Librarian
6
+ module Puppet
7
+ module Simple
8
+ class CLI < Thor
9
+
10
+ include Librarian::Puppet::Simple::Installer
11
+ include Librarian::Puppet::Simple::Iterator
12
+ class_option :verbose, :type => :boolean,
13
+ :desc => 'verbose output for executed commands'
14
+
15
+ class_option :path, :type => :string,
16
+ :desc => "overrides target directory, default is ./modules"
17
+ class_option :puppetfile, :type => :string,
18
+ :desc => "overrides used Puppetfile",
19
+ :default => './Puppetfile'
20
+
21
+
22
+ def self.bin!
23
+ start
24
+ end
25
+
26
+ desc 'install', 'installs all git sources from your Puppetfile'
27
+ method_option :clean, :type => :boolean, :desc => "calls clean before executing install"
28
+ def install
29
+ @verbose = options[:verbose]
30
+ clean if options[:clean]
31
+ @custom_module_path = options[:path]
32
+ # evaluate the file to populate @modules
33
+ eval(File.read(File.expand_path(options[:puppetfile])))
34
+ install!
35
+ end
36
+
37
+ desc 'clean', 'clean modules directory'
38
+ def clean
39
+ target_directory = options[:path] || File.expand_path("./modules")
40
+ puts "Target Directory: #{target_directory}" if options[:verbose]
41
+ FileUtils.rm_rf target_directory
42
+ end
43
+
44
+ desc 'git_status', 'determine the current status of checked out git repos'
45
+ def git_status
46
+ @custom_module_path = options[:path]
47
+ # polulate @modules
48
+ eval(File.read(File.expand_path(options[:puppetfile])))
49
+ each_module_of_type(:git) do |repo|
50
+ Dir.chdir(File.join(module_path, repo[:name])) do
51
+ status = system_cmd('git status')
52
+ if status.include?('nothing to commit (working directory clean)')
53
+ puts "Module #{repo[:name]} has not changed" if options[:verbose]
54
+ else
55
+ puts "Uncommitted changes for: #{repo[:name]}"
56
+ puts " #{status.join("\n ")}"
57
+ end
58
+ end
59
+ end
60
+ end
61
+
62
+ desc 'dev_setup', 'adds development r/w remotes to each repo (assumes remote has the same name as current repo)'
63
+ method_option :remote, :type => :string, :desc => "Account name of remote to add"
64
+ def dev_setup(remote_name)
65
+ each_module_of_type(:git) do |repo|
66
+ remotes = system_cmd('git remote')
67
+ if remotes.include?(remote_name)
68
+ puts "Did not have to add remote #{remote_name} to #{repo[:name]}"
69
+ elsif ! remotes.include?('origin')
70
+ raise(TestException, "Repo #{repo[:name]} has no remote called origin, failing")
71
+ else
72
+ remote_url = git_cmd('remote show origin').detect {|x| x =~ /\s+Push\s+URL: / }
73
+ if remote_url =~ /(git|https?):\/\/(.+)\/(.+)?\/(.+)/
74
+ url = "git@#{$2}:#{remote_name}/#{$4}"
75
+ else
76
+ puts "remote_url #{remote_url} did not have the expected format. weird..."
77
+ end
78
+ puts "Adding remote #{remote_name} as #{url}"
79
+ git_cmd("remote add #{remote_name} #{url}")
80
+ end
81
+ end
82
+ end
83
+
84
+ end
85
+ end
86
+ end
87
+ end
@@ -0,0 +1,106 @@
1
+ require 'fileutils'
2
+ require 'rubygems/package'
3
+ require 'zlib'
4
+ require 'open-uri'
5
+ require 'librarian/puppet/simple/util'
6
+ require 'librarian/puppet/simple/iterator'
7
+
8
+ # This is an extremely simple file that can consume
9
+ # a Puppet file with git references
10
+ #
11
+ # It does absolutely no dependency resolution by design.
12
+ #
13
+ module Librarian
14
+ module Puppet
15
+ module Simple
16
+ module Installer
17
+
18
+ include Librarian::Puppet::Simple::Util
19
+ include Librarian::Puppet::Simple::Iterator
20
+
21
+ # installs modules using the each_module method from our
22
+ # iterator mixin
23
+ def install!
24
+ each_module do |repo|
25
+
26
+ print_verbose "\n##### processing module #{repo[:name]}..."
27
+
28
+ case
29
+ when repo[:git]
30
+ install_git module_path, repo[:name], repo[:git], repo[:ref]
31
+ when repo[:tarball]
32
+ install_tarball module_path, repo[:name], repo[:tarball]
33
+ else
34
+ abort('only the :git and :tarball provider are currently supported')
35
+ end
36
+ end
37
+ end
38
+
39
+ private
40
+
41
+ def install_git(module_path, module_name, repo, ref = nil)
42
+ module_dir = File.join(module_path, module_name)
43
+
44
+ Dir.chdir(module_path) do
45
+ print_verbose "cloning #{repo}"
46
+ system_cmd("git clone #{repo} #{module_name}")
47
+ Dir.chdir(module_dir) do
48
+ system_cmd('git branch -r')
49
+ system_cmd("git checkout #{ref}") if ref
50
+ end
51
+ end
52
+ end
53
+
54
+ def install_tarball(module_path, module_name, remote_tarball)
55
+ Dir.mktmpdir do |tmp|
56
+ temp_file = File.join(tmp,"downloaded_module.tar.gz")
57
+ File.open(temp_file, "w+b") do |saved_file|
58
+ print_verbose "Downloading #{remote_tarball}..."
59
+ open(remote_tarball, 'rb') do |read_file|
60
+ saved_file.write(read_file.read)
61
+ end
62
+ saved_file.rewind
63
+
64
+ target_directory = File.join(module_path, module_name)
65
+ print_verbose "Extracting #{remote_tarball} to #{target_directory}..."
66
+ unzipped_target = ungzip(saved_file)
67
+ tarfile_full_name = untar(unzipped_target, module_path)
68
+ FileUtils.mv File.join(module_path, tarfile_full_name), target_directory
69
+ end
70
+ end
71
+ end
72
+
73
+ # un-gzips the given IO, returning the
74
+ # decompressed version as a StringIO
75
+ def ungzip(tarfile)
76
+ z = Zlib::GzipReader.new(tarfile)
77
+ unzipped = StringIO.new(z.read)
78
+ z.close
79
+ unzipped
80
+ end
81
+
82
+ # untars the given IO into the specified
83
+ # directory
84
+ def untar(io, destination)
85
+ tarfile_full_name = nil
86
+ Gem::Package::TarReader.new io do |tar|
87
+ tar.each do |tarfile|
88
+ tarfile_full_name ||= tarfile.full_name
89
+ destination_file = File.join destination, tarfile.full_name
90
+ if tarfile.directory?
91
+ FileUtils.mkdir_p destination_file
92
+ else
93
+ destination_directory = File.dirname(destination_file)
94
+ FileUtils.mkdir_p destination_directory unless File.directory?(destination_directory)
95
+ File.open destination_file, "wb" do |f|
96
+ f.write tarfile.read
97
+ end
98
+ end
99
+ end
100
+ end
101
+ tarfile_full_name
102
+ end
103
+ end
104
+ end
105
+ end
106
+ end
@@ -0,0 +1,47 @@
1
+ require 'librarian/puppet/simple/util'
2
+
3
+ module Librarian
4
+ module Puppet
5
+ module Simple
6
+ module Iterator
7
+
8
+ # evaluate a module and add it our @modules instance variable
9
+ def mod(name, options = {})
10
+ @modules ||= {}
11
+ module_name = name.split('/', 2).last
12
+
13
+ case
14
+ when options[:git]
15
+ @modules[:git] ||= []
16
+ @modules[:git].push(options.merge(:name => module_name))
17
+ when options[:tarball]
18
+ @modules[:tarball] ||= []
19
+ @modules[:tarball].push(options.merge(:name => module_name))
20
+ else
21
+ @modules[:forge] ||= []
22
+ @modules[:forge].push(options.merge(:name => module_name))
23
+ #abort('only the :git and :tarball providers are currently supported')
24
+ end
25
+ end
26
+
27
+ # iterate through all modules
28
+ def each_module(&block)
29
+ (@modules || {}).each do |type, repos|
30
+ (repos || []).each do |repo|
31
+ yield repo
32
+ end
33
+ end
34
+ end
35
+
36
+ # loop over each module of a certain type
37
+ def each_module_of_type(type, &block)
38
+ abort("undefined type #{type}") unless [:git, :tarball].include?(type)
39
+ ((@modules || {})[type] || []).each do |repo|
40
+ yield repo
41
+ end
42
+ end
43
+
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,45 @@
1
+ #
2
+ # this module contains all of the base helper methods
3
+ # used by the other actions
4
+ #
5
+ module Librarian
6
+ module Puppet
7
+ module Simple
8
+ module Util
9
+
10
+ # figure out what directory we are working out og
11
+ def base_dir
12
+ @base_dir ||= Dir.pwd
13
+ end
14
+
15
+ # figure out what the modulepath is
16
+ def module_path(dir=base_dir)
17
+ unless @module_path
18
+ if @custom_module_path
19
+ @module_path = File.expand_path @custom_module_path
20
+ else
21
+ @module_path = File.join(dir, 'modules')
22
+ end
23
+ Dir.mkdir(@module_path) unless File.exists?(@module_path)
24
+ end
25
+ @module_path
26
+ end
27
+
28
+ # run a command on the system
29
+ def system_cmd (cmd)
30
+ print_verbose "Running cmd: #{cmd}"
31
+ output = `#{cmd}`.split("\n")
32
+ print_verbose output
33
+ raise(StandardError, "Cmd #{cmd} failed") unless $?.success?
34
+ output
35
+ end
36
+
37
+ private
38
+ def print_verbose(text)
39
+ puts text if @verbose
40
+ end
41
+
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,7 @@
1
+ module Librarian
2
+ module Puppet
3
+ module Simple
4
+ VERSION = "0.0.1"
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,9 @@
1
+ require "librarian/puppet/simple/version"
2
+
3
+ module Librarian
4
+ module Puppet
5
+ module Simple
6
+ # Your code goes here...
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,26 @@
1
+ $:.push File.expand_path("../lib", __FILE__)
2
+
3
+ require 'librarian/puppet/simple/version'
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = 'librarian-puppet-simple'
7
+ s.version = Librarian::Puppet::Simple::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ['Dan Bode']
10
+ s.email = ['bodepd@gmail.com']
11
+ s.homepage = 'https://github.com/bodepd/librarian-puppet-simple'
12
+ s.summary = 'Bundler for your Puppet modules'
13
+ s.description = 'Simplify deployment of your Puppet infrastructure by
14
+ automatically pulling in modules from the forge and git repositories with
15
+ a single command.'
16
+ s.license = 'Apache v2.0'
17
+
18
+ s.files = `git ls-files`.split($/)
19
+ s.executables = s.files.grep(%r{^bin/}) { |f| File.basename(f) }
20
+ s.test_files = s.files.grep(%r{^(test|spec|features)/})
21
+ s.require_paths = ["lib"]
22
+
23
+ s.add_dependency "thor", "~> 0.15"
24
+
25
+ s.add_development_dependency "rspec", "~> 2.13"
26
+ end
@@ -0,0 +1,6 @@
1
+ mod "puppetlabs/ntp",
2
+ :git => "git://github.com/puppetlabs/puppetlabs-ntp.git",
3
+ :ref => "99bae40f225db0dd052efbf1d4078a21f0333331"
4
+
5
+ mod "apache",
6
+ :tarball => "https://forge.puppetlabs.com/puppetlabs/apache/0.6.0.tar.gz"
@@ -0,0 +1,42 @@
1
+ require 'spec/spec_helper'
2
+
3
+ require 'tmpdir'
4
+
5
+ describe "Functional - Clean" do
6
+ it "displays install help message" do
7
+ output, status = execute_captured("bin/librarian-puppet help clean")
8
+ output.should_not include("ERROR")
9
+ output.should_not include("Could not find command")
10
+ status.should == 0
11
+ end
12
+
13
+ describe "when running 'librarian-puppet clean'" do
14
+ temp_directory = nil
15
+
16
+ before :each do
17
+ temp_directory = Dir.mktmpdir
18
+ Dir.entries(temp_directory).should =~ ['.', '..']
19
+ FileUtils.touch File.join(temp_directory, 'trashfile')
20
+ Dir.entries(temp_directory).should =~ ['.', '..', 'trashfile']
21
+ end
22
+
23
+ after :each do
24
+ FileUtils.rm_rf temp_directory if File.exist?(temp_directory)
25
+ end
26
+
27
+ it "with --path it cleans the directory" do
28
+ output, status = execute_captured("bin/librarian-puppet clean --path=#{temp_directory}")
29
+
30
+ status.should == 0
31
+ # Using File.exist? to be compatible with Ruby 1.8.7
32
+ File.exist?(temp_directory).should be_false
33
+ end
34
+
35
+ it "with --verbose it shows progress messages" do
36
+ output, status = execute_captured("bin/librarian-puppet clean --verbose --path=#{temp_directory}")
37
+
38
+ status.should == 0
39
+ output.should include("Target Directory: #{temp_directory}")
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,55 @@
1
+ require 'spec/spec_helper'
2
+
3
+ require 'tmpdir'
4
+
5
+ describe "Functional - Install" do
6
+ before :all do
7
+ warning_message = "ATTENTION: these tests download information from github.com and forge.puppetlabs.com"
8
+ puts '*' * warning_message.length
9
+ puts warning_message
10
+ puts '*' * warning_message.length
11
+ end
12
+
13
+ it "displays install help message" do
14
+ output, status = execute_captured("bin/librarian-puppet help install")
15
+ output.should_not include("ERROR")
16
+ output.should_not include("Could not find command")
17
+ status.should == 0
18
+ end
19
+
20
+ describe "when running 'librarian-puppet install'" do
21
+ temp_directory = nil
22
+
23
+ before :each do
24
+ temp_directory = Dir.mktmpdir
25
+ Dir.entries(temp_directory).should =~ ['.', '..']
26
+ FileUtils.touch File.join(temp_directory, 'trashfile')
27
+ Dir.entries(temp_directory).should =~ ['.', '..', 'trashfile']
28
+ end
29
+
30
+ after :each do
31
+ FileUtils.rm_rf temp_directory
32
+ end
33
+
34
+ it "install the modules in a temp directory" do
35
+ output, status = execute_captured("bin/librarian-puppet install --path=#{temp_directory} --puppetfile=spec/fixtures/Puppetfile")
36
+
37
+ status.should == 0
38
+ Dir.entries(temp_directory).should =~ ['.', '..', 'apache', 'ntp', 'trashfile']
39
+ end
40
+
41
+ it "with --clean it cleans the directory before installing the modules in a temp directory" do
42
+ output, status = execute_captured("bin/librarian-puppet install --clean --path=#{temp_directory} --puppetfile=spec/fixtures/Puppetfile")
43
+
44
+ status.should == 0
45
+ Dir.entries(temp_directory).should =~ ['.', '..', 'apache', 'ntp']
46
+ end
47
+
48
+ it "with --verbose it outputs progress messages" do
49
+ output, status = execute_captured("bin/librarian-puppet install --verbose --path=#{temp_directory} --puppetfile=spec/fixtures/Puppetfile")
50
+
51
+ status.should == 0
52
+ output.should include('##### processing module apache')
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,25 @@
1
+ # This file was generated by the `rspec --init` command. Conventionally, all
2
+ # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
3
+ # Require this file using `require "spec_helper"` to ensure that it is only
4
+ # loaded once.
5
+ #
6
+ # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
7
+ require 'open3'
8
+
9
+ RSpec.configure do |config|
10
+ config.treat_symbols_as_metadata_keys_with_true_values = true
11
+ config.run_all_when_everything_filtered = true
12
+ config.filter_run :focus
13
+
14
+ # Run specs in random order to surface order dependencies. If you find an
15
+ # order dependency and want to debug it, you can fix the order by providing
16
+ # the seed, which is printed after each run.
17
+ # --seed 1234
18
+ config.order = 'random'
19
+
20
+ def execute_captured(command)
21
+ stdin, stdout, stderr = Open3.popen3(command)
22
+ condensed = stdout.readlines.join + stderr.readlines.join
23
+ [condensed, $?.exitstatus]
24
+ end
25
+ end
metadata ADDED
@@ -0,0 +1,94 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: librarian-puppet-simple
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Dan Bode
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2013-05-23 00:00:00 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: thor
16
+ prerelease: false
17
+ requirement: &id001 !ruby/object:Gem::Requirement
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: "0.15"
22
+ type: :runtime
23
+ version_requirements: *id001
24
+ - !ruby/object:Gem::Dependency
25
+ name: rspec
26
+ prerelease: false
27
+ requirement: &id002 !ruby/object:Gem::Requirement
28
+ requirements:
29
+ - - ~>
30
+ - !ruby/object:Gem::Version
31
+ version: "2.13"
32
+ type: :development
33
+ version_requirements: *id002
34
+ description: |-
35
+ Simplify deployment of your Puppet infrastructure by
36
+ automatically pulling in modules from the forge and git repositories with
37
+ a single command.
38
+ email:
39
+ - bodepd@gmail.com
40
+ executables:
41
+ - librarian-puppet
42
+ extensions: []
43
+
44
+ extra_rdoc_files: []
45
+
46
+ files:
47
+ - .gitignore
48
+ - Gemfile
49
+ - LICENSE
50
+ - README.md
51
+ - bin/librarian-puppet
52
+ - lib/librarian/puppet/simple.rb
53
+ - lib/librarian/puppet/simple/cli.rb
54
+ - lib/librarian/puppet/simple/installer.rb
55
+ - lib/librarian/puppet/simple/iterator.rb
56
+ - lib/librarian/puppet/simple/util.rb
57
+ - lib/librarian/puppet/simple/version.rb
58
+ - librarian-puppet-simple.gemspec
59
+ - spec/fixtures/Puppetfile
60
+ - spec/functional/clean_spec.rb
61
+ - spec/functional/install_spec.rb
62
+ - spec/spec_helper.rb
63
+ homepage: https://github.com/bodepd/librarian-puppet-simple
64
+ licenses:
65
+ - Apache v2.0
66
+ metadata: {}
67
+
68
+ post_install_message:
69
+ rdoc_options: []
70
+
71
+ require_paths:
72
+ - lib
73
+ required_ruby_version: !ruby/object:Gem::Requirement
74
+ requirements:
75
+ - &id003
76
+ - ">="
77
+ - !ruby/object:Gem::Version
78
+ version: "0"
79
+ required_rubygems_version: !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - *id003
82
+ requirements: []
83
+
84
+ rubyforge_project:
85
+ rubygems_version: 2.0.3
86
+ signing_key:
87
+ specification_version: 4
88
+ summary: Bundler for your Puppet modules
89
+ test_files:
90
+ - spec/fixtures/Puppetfile
91
+ - spec/functional/clean_spec.rb
92
+ - spec/functional/install_spec.rb
93
+ - spec/spec_helper.rb
94
+ has_rdoc: