librarian-puppet-simple 0.0.1 → 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/lib/librarian/puppet/simple/cli.rb +186 -14
- data/lib/librarian/puppet/simple/installer.rb +13 -6
- data/lib/librarian/puppet/simple/iterator.rb +12 -3
- data/lib/librarian/puppet/simple/util.rb +12 -6
- data/lib/librarian/puppet/simple/version.rb +1 -1
- data/librarian-puppet-simple.gemspec +1 -2
- data/spec/functional/clean_spec.rb +1 -1
- data/spec/functional/install_spec.rb +21 -1
- metadata +26 -11
- checksums.yaml +0 -7
@@ -7,8 +7,10 @@ module Librarian
|
|
7
7
|
module Simple
|
8
8
|
class CLI < Thor
|
9
9
|
|
10
|
+
include Librarian::Puppet::Simple::Util
|
10
11
|
include Librarian::Puppet::Simple::Installer
|
11
12
|
include Librarian::Puppet::Simple::Iterator
|
13
|
+
|
12
14
|
class_option :verbose, :type => :boolean,
|
13
15
|
:desc => 'verbose output for executed commands'
|
14
16
|
|
@@ -44,7 +46,7 @@ module Librarian
|
|
44
46
|
desc 'git_status', 'determine the current status of checked out git repos'
|
45
47
|
def git_status
|
46
48
|
@custom_module_path = options[:path]
|
47
|
-
#
|
49
|
+
# populate @modules
|
48
50
|
eval(File.read(File.expand_path(options[:puppetfile])))
|
49
51
|
each_module_of_type(:git) do |repo|
|
50
52
|
Dir.chdir(File.join(module_path, repo[:name])) do
|
@@ -60,27 +62,197 @@ module Librarian
|
|
60
62
|
end
|
61
63
|
|
62
64
|
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
65
|
def dev_setup(remote_name)
|
66
|
+
@custom_module_path = options[:path]
|
67
|
+
# populate @modules
|
68
|
+
eval(File.read(File.expand_path(options[:puppetfile])))
|
65
69
|
each_module_of_type(:git) do |repo|
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
if remote_url =~ /(git|https?):\/\/(.+)\/(.+)?\/(.+)/
|
74
|
-
url = "git@#{$2}:#{remote_name}/#{$4}"
|
70
|
+
Dir.chdir(File.join((options[:path] || 'modules'), repo[:name])) do
|
71
|
+
print_verbose "Adding development remote for git repo #{repo[:name]}"
|
72
|
+
remotes = system_cmd('git remote')
|
73
|
+
if remotes.include?(remote_name)
|
74
|
+
puts "Did not have to add remote #{remote_name} to #{repo[:name]}"
|
75
|
+
elsif ! remotes.include?('origin')
|
76
|
+
raise(TestException, "Repo #{repo[:name]} has no remote called origin, failing")
|
75
77
|
else
|
76
|
-
|
78
|
+
remote_url = system_cmd('git remote show origin').detect {|x| x =~ /\s+Push\s+URL: / }
|
79
|
+
if remote_url =~ /(git|https?):\/\/(.+)\/(.+)?\/(.+)/
|
80
|
+
url = "git@#{$2}:#{remote_name}/#{$4}"
|
81
|
+
puts "Adding remote #{remote_name} as #{url}"
|
82
|
+
system_cmd("git remote add #{remote_name} #{url}")
|
83
|
+
elsif remote_url =~ /^git@/
|
84
|
+
puts "Origin is already a read/write remote, skipping b/c this is unexpected"
|
85
|
+
else
|
86
|
+
puts "remote_url #{remote_url} did not have the expected format. weird..."
|
87
|
+
end
|
77
88
|
end
|
78
|
-
puts "Adding remote #{remote_name} as #{url}"
|
79
|
-
git_cmd("remote add #{remote_name} #{url}")
|
80
89
|
end
|
81
90
|
end
|
82
91
|
end
|
83
92
|
|
93
|
+
#
|
94
|
+
# I am not sure if anyone besides me (Dan Bode) should use this command.
|
95
|
+
# It is specifically for the use case where you are managing downstream versions
|
96
|
+
# of Puppet modules, where you want to track the relationship between your downstream
|
97
|
+
# forks and upstream.
|
98
|
+
# It required a specially formatted Puppetfile that expects an environment variable called
|
99
|
+
# repo_to_use that accepts the values 'upstream' and 'downstream'. It should use that environment
|
100
|
+
# variable to be able to generate either the upstream or downstream set of repos.
|
101
|
+
#
|
102
|
+
# Given those requirements, it can be used to compare the revision history differences betwee
|
103
|
+
# those commits.
|
104
|
+
#
|
105
|
+
desc 'compare_repos', 'compares the specified upstream and downstream repos'
|
106
|
+
method_option :output_file, :type => :string,
|
107
|
+
:desc => "Name of Puppetfile to save the results as"
|
108
|
+
method_option :ignore_merges, :type => :boolean,
|
109
|
+
:desc => 'Indicates that merge commits should be ignored'
|
110
|
+
method_option :show_diffs, :type => :boolean,
|
111
|
+
:desc => 'Show code differences of divergent commits (add -u)'
|
112
|
+
# I was really just using this for testing
|
113
|
+
# not sure if end users need it
|
114
|
+
method_option :existing_tmp_dir, :type => :string,
|
115
|
+
:desc => 'Uses an existing directory. Assumes the downstream repos have already been populated.'
|
116
|
+
method_option :upstream_only, :type => :boolean,
|
117
|
+
:desc => 'Only show commits that are only in the upstream'
|
118
|
+
method_option :downstream_only, :type => :boolean,
|
119
|
+
:desc => 'Only show commits that are only in downstream'
|
120
|
+
method_option :oneline, :type => :boolean,
|
121
|
+
:desc => 'Condense log output to one line'
|
122
|
+
|
123
|
+
|
124
|
+
def compare_repos
|
125
|
+
|
126
|
+
repo_hash = {}
|
127
|
+
@verbose = options[:verbose]
|
128
|
+
abort('path not supported by compare_repos command') if options[:path]
|
129
|
+
if options[:downstream_only] and options[:upstream_only]
|
130
|
+
abort('Cannot specify both downstream_only and upstream_only')
|
131
|
+
end
|
132
|
+
|
133
|
+
# create path where code will be stored
|
134
|
+
if options[:existing_tmp_dir]
|
135
|
+
path = options[:existing_tmp_dir]
|
136
|
+
else
|
137
|
+
path = File.join('.tmp', Time.now.strftime("%Y_%m_%d_%H_%S"))
|
138
|
+
end
|
139
|
+
|
140
|
+
FileUtils.mkdir_p(path)
|
141
|
+
@custom_module_path = path
|
142
|
+
|
143
|
+
# install the downstream modules in our tmp directory and build out a hash
|
144
|
+
downstream = build_puppetfile_hash('downstream', !options[:existing_tmp_dir])
|
145
|
+
# just build a hash of the downstream modules
|
146
|
+
upstream = build_puppetfile_hash('upstream', false)
|
147
|
+
|
148
|
+
unless ( (downstream.keys - upstream.keys) == [] and
|
149
|
+
(upstream.keys - downstream.keys)
|
150
|
+
)
|
151
|
+
abort('Your Puppetfile did not produce the same upstream and downstream repos, this is not yet supported')
|
152
|
+
else
|
153
|
+
|
154
|
+
upstream.each do |us_name, us_repo|
|
155
|
+
# compare to see if the source of revisions are the same
|
156
|
+
ds_repo = downstream[us_name]
|
157
|
+
if ds_repo[:git] == us_repo[:git] and ds_repo[:ref] == us_repo[:ref]
|
158
|
+
print_verbose("\nSources of #{us_name} are the same, nothing to compare.")
|
159
|
+
else
|
160
|
+
Dir.chdir(File.join(path, us_name)) do
|
161
|
+
if us_repo[:git] =~ /(git|https?):\/\/(.+)\/(.+)?\/(.+)/
|
162
|
+
remote_name = $3
|
163
|
+
remotes = system_cmd('git remote')
|
164
|
+
if remotes.include?(remote_name)
|
165
|
+
puts "Did not have to add remote #{remote_name} to #{us_repo[:name]}, it was already there"
|
166
|
+
else
|
167
|
+
puts "Adding remote #{remote_name} #{us_repo[:git]}"
|
168
|
+
system_cmd("git remote add #{remote_name} #{us_repo[:git]}")
|
169
|
+
end
|
170
|
+
system_cmd("git fetch #{remote_name}")
|
171
|
+
if us_repo[:ref] =~ /^origin\/(\S+)$/
|
172
|
+
compare_ref = "#{remote_name}/#{$1}"
|
173
|
+
else
|
174
|
+
compare_ref = "#{remote_name}/#{us_repo[:ref]}"
|
175
|
+
end
|
176
|
+
|
177
|
+
# set up parameters for git log call
|
178
|
+
ignore_merges = options[:ignore_merges] ? '--no-merges' : ''
|
179
|
+
show_diffs = options[:show_diffs] ? '-u' : ''
|
180
|
+
oneline = options[:oneline] ? '--oneline' : ''
|
181
|
+
# show the results, this assumes that HEAD is up-to-date (which it should be)
|
182
|
+
|
183
|
+
if options[:downstream_only] and options[:upstream_only]
|
184
|
+
abort('Cannot specify both downstream_only and upstream_only')
|
185
|
+
end
|
186
|
+
puts "########## Results for #{us_name} ##########"
|
187
|
+
unless options[:upstream_only]
|
188
|
+
puts " ######## Commits only in downstream ########"
|
189
|
+
results = system_cmd("git log --left-only HEAD...#{compare_ref} #{ignore_merges} #{show_diffs} #{oneline}", true)
|
190
|
+
puts " ######## End Downstream results ########"
|
191
|
+
end
|
192
|
+
unless options[:downstream_only]
|
193
|
+
puts " ######## Commits only in upstream ########"
|
194
|
+
results = system_cmd("git log --right-only HEAD...#{compare_ref} #{ignore_merges} #{show_diffs} #{oneline}", true)
|
195
|
+
puts " ######## End upstream ########"
|
196
|
+
end
|
197
|
+
puts "########## End of Results for #{us_name} ##########"
|
198
|
+
else
|
199
|
+
abort("Unrecognizable upstream url #{us_repo[:git]}")
|
200
|
+
end
|
201
|
+
end
|
202
|
+
end
|
203
|
+
end
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
desc 'generate_puppetfile', 'generates a static version of the Puppetfile'
|
208
|
+
method_option :out_file,
|
209
|
+
:desc => 'output file where static puppetfile should be written to'
|
210
|
+
def generate_puppetfile
|
211
|
+
eval(File.read(File.expand_path(options[:puppetfile])))
|
212
|
+
if options[:out_file]
|
213
|
+
File.open(options[:out_file], 'w') do |fh|
|
214
|
+
print_puppet_file(fh)
|
215
|
+
end
|
216
|
+
else
|
217
|
+
print_puppet_file(STDOUT)
|
218
|
+
end
|
219
|
+
end
|
220
|
+
|
221
|
+
private
|
222
|
+
|
223
|
+
def print_puppet_file(stream)
|
224
|
+
each_module do |repo|
|
225
|
+
repo.delete(:name)
|
226
|
+
out_str = repo.delete(:full_name)
|
227
|
+
repo.each do |k,v|
|
228
|
+
out_str << ", :#{k} => #{v}"
|
229
|
+
end
|
230
|
+
stream.puts(out_str)
|
231
|
+
end
|
232
|
+
end
|
233
|
+
|
234
|
+
# builds out a certain type of repo
|
235
|
+
def build_puppetfile_hash(name, perform_installation=false)
|
236
|
+
repo_hash = {}
|
237
|
+
# set environment variable to determine what version of modules to install
|
238
|
+
# this assumes that the environment variable repos_to_use has been coded in
|
239
|
+
# your Puppetfile to allow installation of different versions of modules
|
240
|
+
ENV['repos_to_use'] = name
|
241
|
+
# parse Puppetfile and install modules in our tmp directory.
|
242
|
+
eval(File.read(File.expand_path(options[:puppetfile])))
|
243
|
+
# install modules if desired
|
244
|
+
install! if perform_installation
|
245
|
+
|
246
|
+
# iterate through all git modules
|
247
|
+
each_module_of_type(:git) do |git_repo|
|
248
|
+
abort("Module git_repo[:name] was defined multiple times in same Puppetfile") if repo_hash[git_repo[:name]]
|
249
|
+
repo_hash[git_repo[:name]] = git_repo
|
250
|
+
end
|
251
|
+
# clear out the modules once finished
|
252
|
+
clear_modules
|
253
|
+
repo_hash
|
254
|
+
end
|
255
|
+
|
84
256
|
end
|
85
257
|
end
|
86
258
|
end
|
@@ -25,19 +25,26 @@ module Librarian
|
|
25
25
|
|
26
26
|
print_verbose "\n##### processing module #{repo[:name]}..."
|
27
27
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
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
|
33
39
|
else
|
34
|
-
|
40
|
+
print_verbose "\nModule #{repo[:name]} already installed in #{module_path}"
|
35
41
|
end
|
36
42
|
end
|
37
43
|
end
|
38
44
|
|
39
45
|
private
|
40
46
|
|
47
|
+
# installs sources that are git repos
|
41
48
|
def install_git(module_path, module_name, repo, ref = nil)
|
42
49
|
module_dir = File.join(module_path, module_name)
|
43
50
|
|
@@ -8,22 +8,31 @@ module Librarian
|
|
8
8
|
# evaluate a module and add it our @modules instance variable
|
9
9
|
def mod(name, options = {})
|
10
10
|
@modules ||= {}
|
11
|
+
full_name = name
|
11
12
|
module_name = name.split('/', 2).last
|
12
13
|
|
13
14
|
case
|
14
15
|
when options[:git]
|
15
16
|
@modules[:git] ||= []
|
16
|
-
@modules[:git].push(options.merge(:name => module_name))
|
17
|
+
@modules[:git].push(options.merge(:name => module_name, :full_name => full_name))
|
17
18
|
when options[:tarball]
|
18
19
|
@modules[:tarball] ||= []
|
19
|
-
@modules[:tarball].push(options.merge(:name => module_name))
|
20
|
+
@modules[:tarball].push(options.merge(:name => module_name, :full_name => full_name))
|
20
21
|
else
|
21
22
|
@modules[:forge] ||= []
|
22
|
-
@modules[:forge].push(options.merge(:name => module_name))
|
23
|
+
@modules[:forge].push(options.merge(:name => module_name, :full_name => full_name))
|
23
24
|
#abort('only the :git and :tarball providers are currently supported')
|
24
25
|
end
|
25
26
|
end
|
26
27
|
|
28
|
+
def modules
|
29
|
+
@modules
|
30
|
+
end
|
31
|
+
|
32
|
+
def clear_modules
|
33
|
+
@modules = nil
|
34
|
+
end
|
35
|
+
|
27
36
|
# iterate through all modules
|
28
37
|
def each_module(&block)
|
29
38
|
(@modules || {}).each do |type, repos|
|
@@ -7,6 +7,9 @@ module Librarian
|
|
7
7
|
module Simple
|
8
8
|
module Util
|
9
9
|
|
10
|
+
def forge(repo)
|
11
|
+
# this does nothing atm
|
12
|
+
end
|
10
13
|
# figure out what directory we are working out og
|
11
14
|
def base_dir
|
12
15
|
@base_dir ||= Dir.pwd
|
@@ -26,18 +29,21 @@ module Librarian
|
|
26
29
|
end
|
27
30
|
|
28
31
|
# run a command on the system
|
29
|
-
def system_cmd (cmd)
|
32
|
+
def system_cmd (cmd, print_output=false)
|
30
33
|
print_verbose "Running cmd: #{cmd}"
|
31
34
|
output = `#{cmd}`.split("\n")
|
32
|
-
|
35
|
+
if print_output
|
36
|
+
puts output
|
37
|
+
else
|
38
|
+
print_verbose output
|
39
|
+
end
|
33
40
|
raise(StandardError, "Cmd #{cmd} failed") unless $?.success?
|
34
41
|
output
|
35
42
|
end
|
36
43
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
end
|
44
|
+
def print_verbose(text)
|
45
|
+
puts text if @verbose
|
46
|
+
end
|
41
47
|
|
42
48
|
end
|
43
49
|
end
|
@@ -13,7 +13,6 @@ Gem::Specification.new do |s|
|
|
13
13
|
s.description = 'Simplify deployment of your Puppet infrastructure by
|
14
14
|
automatically pulling in modules from the forge and git repositories with
|
15
15
|
a single command.'
|
16
|
-
s.license = 'Apache v2.0'
|
17
16
|
|
18
17
|
s.files = `git ls-files`.split($/)
|
19
18
|
s.executables = s.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
@@ -23,4 +22,4 @@ Gem::Specification.new do |s|
|
|
23
22
|
s.add_dependency "thor", "~> 0.15"
|
24
23
|
|
25
24
|
s.add_development_dependency "rspec", "~> 2.13"
|
26
|
-
end
|
25
|
+
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
require '
|
1
|
+
require 'spec_helper'
|
2
2
|
|
3
3
|
require 'tmpdir'
|
4
4
|
|
@@ -51,5 +51,25 @@ describe "Functional - Install" do
|
|
51
51
|
status.should == 0
|
52
52
|
output.should include('##### processing module apache')
|
53
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 =~ ['.', '..', 'apache', 'ntp']
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
54
73
|
end
|
74
|
+
|
55
75
|
end
|
metadata
CHANGED
@@ -1,7 +1,12 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: librarian-puppet-simple
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 0
|
8
|
+
- 2
|
9
|
+
version: 0.0.2
|
5
10
|
platform: ruby
|
6
11
|
authors:
|
7
12
|
- Dan Bode
|
@@ -9,7 +14,8 @@ autorequire:
|
|
9
14
|
bindir: bin
|
10
15
|
cert_chain: []
|
11
16
|
|
12
|
-
date: 2013-
|
17
|
+
date: 2013-06-12 00:00:00 -07:00
|
18
|
+
default_executable:
|
13
19
|
dependencies:
|
14
20
|
- !ruby/object:Gem::Dependency
|
15
21
|
name: thor
|
@@ -18,6 +24,9 @@ dependencies:
|
|
18
24
|
requirements:
|
19
25
|
- - ~>
|
20
26
|
- !ruby/object:Gem::Version
|
27
|
+
segments:
|
28
|
+
- 0
|
29
|
+
- 15
|
21
30
|
version: "0.15"
|
22
31
|
type: :runtime
|
23
32
|
version_requirements: *id001
|
@@ -28,6 +37,9 @@ dependencies:
|
|
28
37
|
requirements:
|
29
38
|
- - ~>
|
30
39
|
- !ruby/object:Gem::Version
|
40
|
+
segments:
|
41
|
+
- 2
|
42
|
+
- 13
|
31
43
|
version: "2.13"
|
32
44
|
type: :development
|
33
45
|
version_requirements: *id002
|
@@ -60,10 +72,9 @@ files:
|
|
60
72
|
- spec/functional/clean_spec.rb
|
61
73
|
- spec/functional/install_spec.rb
|
62
74
|
- spec/spec_helper.rb
|
75
|
+
has_rdoc: true
|
63
76
|
homepage: https://github.com/bodepd/librarian-puppet-simple
|
64
|
-
licenses:
|
65
|
-
- Apache v2.0
|
66
|
-
metadata: {}
|
77
|
+
licenses: []
|
67
78
|
|
68
79
|
post_install_message:
|
69
80
|
rdoc_options: []
|
@@ -72,23 +83,27 @@ require_paths:
|
|
72
83
|
- lib
|
73
84
|
required_ruby_version: !ruby/object:Gem::Requirement
|
74
85
|
requirements:
|
75
|
-
-
|
76
|
-
- ">="
|
86
|
+
- - ">="
|
77
87
|
- !ruby/object:Gem::Version
|
88
|
+
segments:
|
89
|
+
- 0
|
78
90
|
version: "0"
|
79
91
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
80
92
|
requirements:
|
81
|
-
-
|
93
|
+
- - ">="
|
94
|
+
- !ruby/object:Gem::Version
|
95
|
+
segments:
|
96
|
+
- 0
|
97
|
+
version: "0"
|
82
98
|
requirements: []
|
83
99
|
|
84
100
|
rubyforge_project:
|
85
|
-
rubygems_version:
|
101
|
+
rubygems_version: 1.3.6
|
86
102
|
signing_key:
|
87
|
-
specification_version:
|
103
|
+
specification_version: 3
|
88
104
|
summary: Bundler for your Puppet modules
|
89
105
|
test_files:
|
90
106
|
- spec/fixtures/Puppetfile
|
91
107
|
- spec/functional/clean_spec.rb
|
92
108
|
- spec/functional/install_spec.rb
|
93
109
|
- spec/spec_helper.rb
|
94
|
-
has_rdoc:
|
checksums.yaml
DELETED
@@ -1,7 +0,0 @@
|
|
1
|
-
---
|
2
|
-
SHA1:
|
3
|
-
data.tar.gz: e70ab85f22c10e06549a8e4084512224a7a85de8
|
4
|
-
metadata.gz: cfad763618e6817a981167e95edaf026908b8ea8
|
5
|
-
SHA512:
|
6
|
-
data.tar.gz: 8450ff50735e8083b294e379a9652175688ac9ef27454e00c519d5842d0331131891aad460dc112f02508de7082c57451b2d0e7e61deee4eaed1ee100992c706
|
7
|
-
metadata.gz: 1f1fe4db05d288c0eb566f2e9e39eef07cea6264e312b1b0bff07d084d4855ada399f70429b8d1bdfc3dece7c283ba74c258ff64f6ee907f820027f66847fbfd
|