librarian-puppet-simple 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -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