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.
@@ -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
- # polulate @modules
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
- 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}"
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
- puts "remote_url #{remote_url} did not have the expected format. weird..."
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
- 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]
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
- abort('only the :git and :tarball provider are currently supported')
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
- print_verbose output
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
- private
38
- def print_verbose(text)
39
- puts text if @verbose
40
- end
44
+ def print_verbose(text)
45
+ puts text if @verbose
46
+ end
41
47
 
42
48
  end
43
49
  end
@@ -1,7 +1,7 @@
1
1
  module Librarian
2
2
  module Puppet
3
3
  module Simple
4
- VERSION = "0.0.1"
4
+ VERSION = "0.0.2"
5
5
  end
6
6
  end
7
7
  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 'spec/spec_helper'
1
+ require 'spec_helper'
2
2
 
3
3
  require 'tmpdir'
4
4
 
@@ -1,4 +1,4 @@
1
- require 'spec/spec_helper'
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
- version: 0.0.1
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-05-23 00:00:00 Z
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
- - &id003
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
- - *id003
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: 2.0.3
101
+ rubygems_version: 1.3.6
86
102
  signing_key:
87
- specification_version: 4
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