librarian-puppet-simple-force 0.0.5

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
+ metadata.gz: 4dcc659f7b1e17ed2c2cd38c3b2494b706608569
4
+ data.tar.gz: 5cfa4319360802b23895e27788ab2f0a0c630497
5
+ SHA512:
6
+ metadata.gz: cdeb6ca3cf01a89c5b03fb7da22a2dca8b875b7b8f65d51e6deacbe9b1e22580c3083e59348f21aa18995e5f5ff5843c7fb60366b0af70869c4e36290b652d20
7
+ data.tar.gz: e5abec691441b7bfb0f00e30ad3291a4ca4d1c57cd344509d7ce5953e22ee7ac9f5c30d9718ed2febbaab2d30a65fea4b4d6dbe2a138ba2ee69a97a953971526
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,13 @@
1
+ Copyright 2013-2014 Dan Bode
2
+
3
+ Licensed under the Apache License, Version 2.0 (the "License");
4
+ you may not use this file except in compliance with the License.
5
+ You may obtain a copy of the License at
6
+
7
+ http://www.apache.org/licenses/LICENSE-2.0
8
+
9
+ Unless required by applicable law or agreed to in writing, software
10
+ distributed under the License is distributed on an "AS IS" BASIS,
11
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ See the License for the specific language governing permissions and
13
+ limitations under the License.
data/README.md ADDED
@@ -0,0 +1,69 @@
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
+ ### Update
28
+ Iterates through your Puppetfile and updates git sources. If a SHA-1 hash is specified in the `:ref`, the module will not be updated.
29
+
30
+ Supported options are:<br/>
31
+ <li>`--verbose` display progress messages</li>
32
+ <li>`--path` override the default `./modules` where modules will be installed</li>
33
+ <li> `--puppetfile` override the default `./Puppetfile` used to find the modules</li>
34
+
35
+ ```
36
+ librarian-puppet update [--verbose] [--path] [--puppetfile]
37
+ ```
38
+
39
+ ## Puppetfile
40
+ The processed Puppetfile may contain two different types of modules, `git` and `tarball`. The `git` option accepts an optional `ref` parameter.
41
+
42
+ 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`.
43
+
44
+ Here's an example of a valid Puppetfile showcasing all valid options:
45
+
46
+ ```
47
+ mod "puppetlabs/ntp",
48
+ :git => "git://github.com/puppetlabs/puppetlabs-ntp.git",
49
+ :ref => "99bae40f225db0dd052efbf1d4078a21f0333331"
50
+
51
+ mod "apache",
52
+ :tarball => "https://forge.puppetlabs.com/puppetlabs/apache/0.6.0.tar.gz"
53
+ ```
54
+
55
+ ## Setting up for development and running the specs
56
+ Just clone the repo and run the following commands:
57
+ ```
58
+ bundle exec install --path=vendor
59
+ bundle exec rspec
60
+ ```
61
+
62
+ Beware that the functional tests will download files from GitHub and PuppetForge and will break if either is unavailable.
63
+
64
+ ## License
65
+
66
+ See [LICENSE](/LICENSE)
67
+
68
+ ## Credits
69
+ 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,285 @@
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::Util
11
+ include Librarian::Puppet::Simple::Installer
12
+ include Librarian::Puppet::Simple::Iterator
13
+
14
+ class_option :verbose, :type => :boolean,
15
+ :desc => 'verbose output for executed commands'
16
+
17
+ class_option :path, :type => :string,
18
+ :desc => "overrides target directory, default is ./modules"
19
+ class_option :puppetfile, :type => :string,
20
+ :desc => "overrides used Puppetfile",
21
+ :default => './Puppetfile'
22
+
23
+
24
+ def self.bin!
25
+ start
26
+ end
27
+
28
+ desc 'install', 'installs all git sources from your Puppetfile'
29
+ method_option :clean, :type => :boolean, :desc => "calls clean before executing install"
30
+ def install
31
+ @verbose = options[:verbose]
32
+ clean if options[:clean]
33
+ @custom_module_path = options[:path]
34
+ # evaluate the file to populate @modules
35
+ eval(File.read(File.expand_path(options[:puppetfile])))
36
+ install!
37
+ end
38
+
39
+ desc 'update', 'updates all git sources from your Puppetfile'
40
+ method_option :update, :type => :boolean, :desc => "Updates git sources"
41
+ def update
42
+ @verbose = options[:verbose]
43
+ @custom_module_path = options[:path]
44
+ eval(File.read(File.expand_path(options[:puppetfile])))
45
+ each_module_of_type(:git) do |repo|
46
+ if Dir.exists?(File.join(module_path, repo[:name]))
47
+ Dir.chdir(File.join(module_path, repo[:name])) do
48
+ remote = repo[:git]
49
+ # if no ref is given, assume master
50
+ branch = repo[:ref] || 'master'
51
+ if branch =~ /^origin\/(.*)$/
52
+ branch = $1
53
+ end
54
+ co_cmd = 'git checkout FETCH_HEAD'
55
+ update_cmd = "git fetch #{repo[:git]} #{branch} && #{co_cmd}"
56
+ print_verbose "\n\n#{repo[:name]} -- #{update_cmd}"
57
+ git_pull_cmd = system_cmd(update_cmd)
58
+ end
59
+ else
60
+ install_git module_path, repo[:name], repo[:git], repo[:ref]
61
+ end
62
+ end
63
+ end
64
+
65
+ desc 'clean', 'clean modules directory'
66
+ def clean
67
+ target_directory = options[:path] || File.expand_path("./modules")
68
+ puts "Target Directory: #{target_directory}" if options[:verbose]
69
+ FileUtils.rm_rf target_directory
70
+ end
71
+
72
+ desc 'git_status', 'determine the current status of checked out git repos'
73
+ def git_status
74
+ @custom_module_path = options[:path]
75
+ # populate @modules
76
+ eval(File.read(File.expand_path(options[:puppetfile])))
77
+ each_module_of_type(:git) do |repo|
78
+ Dir.chdir(File.join(module_path, repo[:name])) do
79
+ status = system_cmd('git status')
80
+ if status.include?('nothing to commit (working directory clean)')
81
+ puts "Module #{repo[:name]} has not changed" if options[:verbose]
82
+ else
83
+ puts "Uncommitted changes for: #{repo[:name]}"
84
+ puts " #{status.join("\n ")}"
85
+ end
86
+ end
87
+ end
88
+ end
89
+
90
+ desc 'dev_setup', 'adds development r/w remotes to each repo (assumes remote has the same name as current repo)'
91
+ def dev_setup(remote_name)
92
+ @custom_module_path = options[:path]
93
+ # populate @modules
94
+ eval(File.read(File.expand_path(options[:puppetfile])))
95
+ each_module_of_type(:git) do |repo|
96
+ Dir.chdir(File.join((options[:path] || 'modules'), repo[:name])) do
97
+ print_verbose "Adding development remote for git repo #{repo[:name]}"
98
+ remotes = system_cmd('git remote')
99
+ if remotes.include?(remote_name)
100
+ puts "Did not have to add remote #{remote_name} to #{repo[:name]}"
101
+ elsif ! remotes.include?('origin')
102
+ raise(TestException, "Repo #{repo[:name]} has no remote called origin, failing")
103
+ else
104
+ remote_url = system_cmd('git remote show origin').detect {|x| x =~ /\s+Push\s+URL: / }
105
+ if remote_url =~ /(git|https?):\/\/(.+)\/(.+)?\/(.+)/
106
+ url = "git@#{$2}:#{remote_name}/#{$4}"
107
+ puts "Adding remote #{remote_name} as #{url}"
108
+ system_cmd("git remote add #{remote_name} #{url}")
109
+ elsif remote_url =~ /^git@/
110
+ puts "Origin is already a read/write remote, skipping b/c this is unexpected"
111
+ else
112
+ puts "remote_url #{remote_url} did not have the expected format. weird..."
113
+ end
114
+ end
115
+ end
116
+ end
117
+ end
118
+
119
+ #
120
+ # I am not sure if anyone besides me (Dan Bode) should use this command.
121
+ # It is specifically for the use case where you are managing downstream versions
122
+ # of Puppet modules, where you want to track the relationship between your downstream
123
+ # forks and upstream.
124
+ # It required a specially formatted Puppetfile that expects an environment variable called
125
+ # repo_to_use that accepts the values 'upstream' and 'downstream'. It should use that environment
126
+ # variable to be able to generate either the upstream or downstream set of repos.
127
+ #
128
+ # Given those requirements, it can be used to compare the revision history differences betwee
129
+ # those commits.
130
+ #
131
+ desc 'compare_repos', 'compares the specified upstream and downstream repos'
132
+ method_option :output_file, :type => :string,
133
+ :desc => "Name of Puppetfile to save the results as"
134
+ method_option :ignore_merges, :type => :boolean,
135
+ :desc => 'Indicates that merge commits should be ignored'
136
+ method_option :show_diffs, :type => :boolean,
137
+ :desc => 'Show code differences of divergent commits (add -u)'
138
+ # I was really just using this for testing
139
+ # not sure if end users need it
140
+ method_option :existing_tmp_dir, :type => :string,
141
+ :desc => 'Uses an existing directory. Assumes the downstream repos have already been populated.'
142
+ method_option :upstream_only, :type => :boolean,
143
+ :desc => 'Only show commits that are only in the upstream'
144
+ method_option :downstream_only, :type => :boolean,
145
+ :desc => 'Only show commits that are only in downstream'
146
+ method_option :oneline, :type => :boolean,
147
+ :desc => 'Condense log output to one line'
148
+
149
+
150
+ def compare_repos
151
+
152
+ repo_hash = {}
153
+ @verbose = options[:verbose]
154
+ abort('path not supported by compare_repos command') if options[:path]
155
+ if options[:downstream_only] and options[:upstream_only]
156
+ abort('Cannot specify both downstream_only and upstream_only')
157
+ end
158
+
159
+ # create path where code will be stored
160
+ if options[:existing_tmp_dir]
161
+ path = options[:existing_tmp_dir]
162
+ else
163
+ path = File.join('.tmp', Time.now.strftime("%Y_%m_%d_%H_%S"))
164
+ end
165
+
166
+ FileUtils.mkdir_p(path)
167
+ @custom_module_path = path
168
+
169
+ # install the downstream modules in our tmp directory and build out a hash
170
+ downstream = build_puppetfile_hash('downstream', !options[:existing_tmp_dir])
171
+ # just build a hash of the downstream modules
172
+ upstream = build_puppetfile_hash('upstream', false)
173
+
174
+ unless ( (downstream.keys - upstream.keys) == [] and
175
+ (upstream.keys - downstream.keys)
176
+ )
177
+ abort('Your Puppetfile did not produce the same upstream and downstream repos, this is not yet supported')
178
+ else
179
+
180
+ upstream.each do |us_name, us_repo|
181
+ # compare to see if the source of revisions are the same
182
+ ds_repo = downstream[us_name]
183
+ if ds_repo[:git] == us_repo[:git] and ds_repo[:ref] == us_repo[:ref]
184
+ print_verbose("\nSources of #{us_name} are the same, nothing to compare.")
185
+ else
186
+ Dir.chdir(File.join(path, us_name)) do
187
+ if us_repo[:git] =~ /(git|https?):\/\/(.+)\/(.+)?\/(.+)/
188
+ remote_name = $3
189
+ remotes = system_cmd('git remote')
190
+ if remotes.include?(remote_name)
191
+ puts "Did not have to add remote #{remote_name} to #{us_repo[:name]}, it was already there"
192
+ else
193
+ puts "Adding remote #{remote_name} #{us_repo[:git]}"
194
+ system_cmd("git remote add #{remote_name} #{us_repo[:git]}")
195
+ end
196
+ system_cmd("git fetch #{remote_name}")
197
+ if us_repo[:ref] =~ /^origin\/(\S+)$/
198
+ compare_ref = "#{remote_name}/#{$1}"
199
+ else
200
+ compare_ref = "#{remote_name}/#{us_repo[:ref]}"
201
+ end
202
+
203
+ # set up parameters for git log call
204
+ ignore_merges = options[:ignore_merges] ? '--no-merges' : ''
205
+ show_diffs = options[:show_diffs] ? '-u' : ''
206
+ oneline = options[:oneline] ? '--oneline' : ''
207
+ # show the results, this assumes that HEAD is up-to-date (which it should be)
208
+
209
+ if options[:downstream_only] and options[:upstream_only]
210
+ abort('Cannot specify both downstream_only and upstream_only')
211
+ end
212
+ puts "########## Results for #{us_name} ##########"
213
+ unless options[:upstream_only]
214
+ puts " ######## Commits only in downstream ########"
215
+ results = system_cmd("git log --left-only HEAD...#{compare_ref} #{ignore_merges} #{show_diffs} #{oneline}", true)
216
+ puts " ######## End Downstream results ########"
217
+ end
218
+ unless options[:downstream_only]
219
+ puts " ######## Commits only in upstream ########"
220
+ results = system_cmd("git log --right-only HEAD...#{compare_ref} #{ignore_merges} #{show_diffs} #{oneline}", true)
221
+ puts " ######## End upstream ########"
222
+ end
223
+ puts "########## End of Results for #{us_name} ##########"
224
+ else
225
+ abort("Unrecognizable upstream url #{us_repo[:git]}")
226
+ end
227
+ end
228
+ end
229
+ end
230
+ end
231
+ end
232
+
233
+ desc 'generate_puppetfile', 'generates a static version of the Puppetfile'
234
+ method_option :out_file,
235
+ :desc => 'output file where static puppetfile should be written to'
236
+ def generate_puppetfile
237
+ eval(File.read(File.expand_path(options[:puppetfile])))
238
+ if options[:out_file]
239
+ File.open(options[:out_file], 'w') do |fh|
240
+ print_puppet_file(fh)
241
+ end
242
+ else
243
+ print_puppet_file(STDOUT)
244
+ end
245
+ end
246
+
247
+ private
248
+
249
+ def print_puppet_file(stream)
250
+ each_module do |repo|
251
+ repo.delete(:name)
252
+ out_str = repo.delete(:full_name)
253
+ repo.each do |k,v|
254
+ out_str << ", :#{k} => #{v}"
255
+ end
256
+ stream.puts(out_str)
257
+ end
258
+ end
259
+
260
+ # builds out a certain type of repo
261
+ def build_puppetfile_hash(name, perform_installation=false)
262
+ repo_hash = {}
263
+ # set environment variable to determine what version of modules to install
264
+ # this assumes that the environment variable repos_to_use has been coded in
265
+ # your Puppetfile to allow installation of different versions of modules
266
+ ENV['repos_to_use'] = name
267
+ # parse Puppetfile and install modules in our tmp directory.
268
+ eval(File.read(File.expand_path(options[:puppetfile])))
269
+ # install modules if desired
270
+ install! if perform_installation
271
+
272
+ # iterate through all git modules
273
+ each_module_of_type(:git) do |git_repo|
274
+ abort("Module git_repo[:name] was defined multiple times in same Puppetfile") if repo_hash[git_repo[:name]]
275
+ repo_hash[git_repo[:name]] = git_repo
276
+ end
277
+ # clear out the modules once finished
278
+ clear_modules
279
+ repo_hash
280
+ end
281
+
282
+ end
283
+ end
284
+ end
285
+ end
@@ -0,0 +1,113 @@
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
+ module_dir = File.join(module_path, repo[:name])
29
+
30
+ unless File.exists?(module_dir)
31
+ case
32
+ when repo[:git]
33
+ install_git module_path, repo[:name], repo[:git], repo[:ref]
34
+ when repo[:tarball]
35
+ install_tarball module_path, repo[:name], repo[:tarball]
36
+ else
37
+ abort('only the :git and :tarball provider are currently supported')
38
+ end
39
+ else
40
+ print_verbose "\nModule #{repo[:name]} already installed in #{module_path}"
41
+ end
42
+ end
43
+ end
44
+
45
+ private
46
+
47
+ # installs sources that are git repos
48
+ def install_git(module_path, module_name, repo, ref = nil)
49
+ module_dir = File.join(module_path, module_name)
50
+
51
+ Dir.chdir(module_path) do
52
+ print_verbose "cloning #{repo}"
53
+ system_cmd("git clone #{repo} #{module_name}")
54
+ Dir.chdir(module_dir) do
55
+ system_cmd('git branch -r')
56
+ system_cmd("git checkout -f #{ref}") if ref
57
+ end
58
+ end
59
+ end
60
+
61
+ def install_tarball(module_path, module_name, remote_tarball)
62
+ Dir.mktmpdir do |tmp|
63
+ temp_file = File.join(tmp,"downloaded_module.tar.gz")
64
+ File.open(temp_file, "w+b") do |saved_file|
65
+ print_verbose "Downloading #{remote_tarball}..."
66
+ open(remote_tarball, 'rb') do |read_file|
67
+ saved_file.write(read_file.read)
68
+ end
69
+ saved_file.rewind
70
+
71
+ target_directory = File.join(module_path, module_name)
72
+ print_verbose "Extracting #{remote_tarball} to #{target_directory}..."
73
+ unzipped_target = ungzip(saved_file)
74
+ tarfile_full_name = untar(unzipped_target, module_path)
75
+ FileUtils.mv File.join(module_path, tarfile_full_name), target_directory
76
+ end
77
+ end
78
+ end
79
+
80
+ # un-gzips the given IO, returning the
81
+ # decompressed version as a StringIO
82
+ def ungzip(tarfile)
83
+ z = Zlib::GzipReader.new(tarfile)
84
+ unzipped = StringIO.new(z.read)
85
+ z.close
86
+ unzipped
87
+ end
88
+
89
+ # untars the given IO into the specified
90
+ # directory
91
+ def untar(io, destination)
92
+ tarfile_full_name = nil
93
+ Gem::Package::TarReader.new io do |tar|
94
+ tar.each do |tarfile|
95
+ tarfile_full_name ||= tarfile.full_name
96
+ destination_file = File.join destination, tarfile.full_name
97
+ if tarfile.directory?
98
+ FileUtils.mkdir_p destination_file
99
+ else
100
+ destination_directory = File.dirname(destination_file)
101
+ FileUtils.mkdir_p destination_directory unless File.directory?(destination_directory)
102
+ File.open destination_file, "wb" do |f|
103
+ f.write tarfile.read
104
+ end
105
+ end
106
+ end
107
+ end
108
+ tarfile_full_name
109
+ end
110
+ end
111
+ end
112
+ end
113
+ end
@@ -0,0 +1,56 @@
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
+ full_name = name
12
+ module_name = name.split('/', 2).last
13
+
14
+ case
15
+ when options[:git]
16
+ @modules[:git] ||= {}
17
+ @modules[:git][module_name] = options.merge(:name => module_name, :full_name => full_name)
18
+ when options[:tarball]
19
+ @modules[:tarball] ||= {}
20
+ @modules[:tarball][module_name] = options.merge(:name => module_name, :full_name => full_name)
21
+ else
22
+ @modules[:forge] ||= {}
23
+ @modules[:forge][module_name] = options.merge(:name => module_name, :full_name => full_name)
24
+ #abort('only the :git and :tarball providers are currently supported')
25
+ end
26
+ end
27
+
28
+ def modules
29
+ @modules
30
+ end
31
+
32
+ def clear_modules
33
+ @modules = nil
34
+ end
35
+
36
+ # iterate through all modules
37
+ def each_module(&block)
38
+ (@modules || {}).each do |type, repos|
39
+ (repos || {}).values.each do |repo|
40
+ yield repo
41
+ end
42
+ end
43
+ end
44
+
45
+ # loop over each module of a certain type
46
+ def each_module_of_type(type, &block)
47
+ abort("undefined type #{type}") unless [:git, :tarball].include?(type)
48
+ ((@modules || {})[type] || {}).values.each do |repo|
49
+ yield repo
50
+ end
51
+ end
52
+
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,51 @@
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
+ def forge(repo)
11
+ # this does nothing atm
12
+ end
13
+ # figure out what directory we are working out og
14
+ def base_dir
15
+ @base_dir ||= Dir.pwd
16
+ end
17
+
18
+ # figure out what the modulepath is
19
+ def module_path(dir=base_dir)
20
+ unless @module_path
21
+ if @custom_module_path
22
+ @module_path = File.expand_path @custom_module_path
23
+ else
24
+ @module_path = File.join(dir, 'modules')
25
+ end
26
+ Dir.mkdir(@module_path) unless File.exists?(@module_path)
27
+ end
28
+ @module_path
29
+ end
30
+
31
+ # run a command on the system
32
+ def system_cmd (cmd, print_output=false)
33
+ print_verbose "Running cmd: #{cmd}"
34
+ output = `#{cmd}`.split("\n")
35
+ if print_output
36
+ puts output
37
+ else
38
+ print_verbose output
39
+ end
40
+ raise(StandardError, "Cmd #{cmd} failed") unless $?.success?
41
+ output
42
+ end
43
+
44
+ def print_verbose(text)
45
+ puts text if @verbose
46
+ end
47
+
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,7 @@
1
+ module Librarian
2
+ module Puppet
3
+ module Simple
4
+ VERSION = "0.0.5"
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,25 @@
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-force'
7
+ s.version = Librarian::Puppet::Simple::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ['Jon McCreery']
10
+ s.email = ['jonathan.mccreery@nytimes.com']
11
+ s.homepage = 'https://github.com/jonmccreery/librarian-puppet-simple-force'
12
+ s.summary = 'Bundler for your Puppet modules, with force'
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
+
17
+ s.files = `git ls-files`.split($/)
18
+ s.executables = s.files.grep(%r{^bin/}) { |f| File.basename(f) }
19
+ s.test_files = s.files.grep(%r{^(test|spec|features)/})
20
+ s.require_paths = ["lib"]
21
+
22
+ s.add_dependency "thor", "~> 0.15"
23
+
24
+ s.add_development_dependency "rspec", "~> 2.13"
25
+ end
@@ -0,0 +1,13 @@
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'
7
+
8
+ mod 'ghoneycutt/testlps',
9
+ :git => 'git://github.com/ghoneycutt/testlps.git'
10
+
11
+ mod 'ghoneycutt/dnsclient',
12
+ :git => 'git://github.com/ghoneycutt/puppet-module-dnsclient.git',
13
+ :ref => 'v3.0.4'
@@ -0,0 +1,42 @@
1
+ require '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,74 @@
1
+ require '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 =~ %w|. .. apache ntp trashfile dnsclient testlps|
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 =~ %w|. .. apache ntp dnsclient testlps|
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
+
55
+ describe 'when modules are already installed' do
56
+ temp_directory = nil
57
+
58
+ before :each do
59
+ temp_directory = Dir.mktmpdir
60
+ Dir.entries(temp_directory).should =~ ['.', '..']
61
+ FileUtils.touch File.join(temp_directory, 'apache')
62
+ Dir.entries(temp_directory).should =~ ['.', '..', 'apache']
63
+ end
64
+
65
+ it 'without clean it should only install ntp' do
66
+ output, status = execute_captured("bin/librarian-puppet install --verbose --path=#{temp_directory} --puppetfile=spec/fixtures/Puppetfile")
67
+ status.should == 0
68
+ output.should include('Module apache already installed')
69
+ Dir.entries(temp_directory).should =~ %w|. .. apache ntp dnsclient testlps|
70
+ end
71
+ end
72
+ end
73
+
74
+ 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,95 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: librarian-puppet-simple-force
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.5
5
+ platform: ruby
6
+ authors:
7
+ - Jon McCreery
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2017-05-31 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: thor
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: '0.15'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '0.15'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rspec
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ~>
32
+ - !ruby/object:Gem::Version
33
+ version: '2.13'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ~>
39
+ - !ruby/object:Gem::Version
40
+ version: '2.13'
41
+ description: |-
42
+ Simplify deployment of your Puppet infrastructure by
43
+ automatically pulling in modules from the forge and git repositories with
44
+ a single command.
45
+ email:
46
+ - jonathan.mccreery@nytimes.com
47
+ executables:
48
+ - librarian-puppet
49
+ extensions: []
50
+ extra_rdoc_files: []
51
+ files:
52
+ - .gitignore
53
+ - Gemfile
54
+ - LICENSE
55
+ - README.md
56
+ - bin/librarian-puppet
57
+ - lib/librarian/puppet/simple.rb
58
+ - lib/librarian/puppet/simple/cli.rb
59
+ - lib/librarian/puppet/simple/installer.rb
60
+ - lib/librarian/puppet/simple/iterator.rb
61
+ - lib/librarian/puppet/simple/util.rb
62
+ - lib/librarian/puppet/simple/version.rb
63
+ - librarian-puppet-simple-force.gemspec
64
+ - spec/fixtures/Puppetfile
65
+ - spec/functional/clean_spec.rb
66
+ - spec/functional/install_spec.rb
67
+ - spec/spec_helper.rb
68
+ homepage: https://github.com/jonmccreery/librarian-puppet-simple-force
69
+ licenses: []
70
+ metadata: {}
71
+ post_install_message:
72
+ rdoc_options: []
73
+ require_paths:
74
+ - lib
75
+ required_ruby_version: !ruby/object:Gem::Requirement
76
+ requirements:
77
+ - - '>='
78
+ - !ruby/object:Gem::Version
79
+ version: '0'
80
+ required_rubygems_version: !ruby/object:Gem::Requirement
81
+ requirements:
82
+ - - '>='
83
+ - !ruby/object:Gem::Version
84
+ version: '0'
85
+ requirements: []
86
+ rubyforge_project:
87
+ rubygems_version: 2.0.14.1
88
+ signing_key:
89
+ specification_version: 4
90
+ summary: Bundler for your Puppet modules, with force
91
+ test_files:
92
+ - spec/fixtures/Puppetfile
93
+ - spec/functional/clean_spec.rb
94
+ - spec/functional/install_spec.rb
95
+ - spec/spec_helper.rb