finger-puppet 0.3.0
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/.gitignore +1 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +34 -0
- data/LICENSE +165 -0
- data/README.md +138 -0
- data/Rakefile +1 -0
- data/bin/finger-puppet +30 -0
- data/features/finger-puppet.feature +184 -0
- data/features/step_definitions/finger-puppet_steps.rb +149 -0
- data/features/support/env.rb +11 -0
- data/features/support/repos/simple/Gemfile +5 -0
- data/features/support/repos/simple/manifests/nodes/.stub +0 -0
- data/features/support/repos/simple/manifests/site.pp +1 -0
- data/features/support/repos/simple/modules/test/manifests/init.pp +5 -0
- data/features/support/repos/simple/var/.stub +0 -0
- data/features/support/repos/simple/var/reports/.stub +0 -0
- data/features/support/repos/simple_26/manifests/nodes/.stub +0 -0
- data/features/support/repos/simple_26/manifests/site.pp +1 -0
- data/features/support/repos/simple_26/modules/test/files/checkout +0 -0
- data/features/support/repos/simple_26/modules/test/manifests/init.pp +5 -0
- data/features/support/repos/simple_26/var/.stub +0 -0
- data/features/support/repos/simple_26/var/reports/.stub +0 -0
- data/finger-puppet.gemspec +25 -0
- data/lib/finger-puppet.rb +204 -0
- data/lib/generators/git/description +1 -0
- data/lib/generators/git/hooks/pre-commit +29 -0
- data/lib/generators/git/hooks/pre-receive +0 -0
- data/lib/generators/git/info/exclude +6 -0
- data/lib/generators/puppet/.gitignore +2 -0
- data/lib/generators/puppet/Gemfile +6 -0
- data/lib/generators/puppet/README.md +27 -0
- data/lib/generators/puppet/etc/puppet.conf +2 -0
- data/lib/generators/puppet/manifests/nodes.pp +1 -0
- data/lib/generators/puppet/manifests/site.pp +8 -0
- data/lib/generators/puppet/modules/.gitkeep +0 -0
- data/lib/generators/puppet/var/.gitkeep +0 -0
- data/lib/generators/puppet/vendor/.gitkeep +0 -0
- data/man/finger-puppet.1 +328 -0
- data/man/finger-puppet.1.html +308 -0
- data/man/finger-puppet.1.ronn +214 -0
- metadata +178 -0
@@ -0,0 +1,149 @@
|
|
1
|
+
Given /^I am working in "([^\"]*)"$/ do |directory|
|
2
|
+
@basedir = Pathname.new(directory)
|
3
|
+
end
|
4
|
+
|
5
|
+
Given /^I have an empty git repository named "([^\"]*)"$/ do |repo_name|
|
6
|
+
repo_path = @basedir.join(repo_name)
|
7
|
+
FileUtils.rm_rf(repo_path)
|
8
|
+
FileUtils.mkdir_p(repo_path)
|
9
|
+
|
10
|
+
Dir.chdir(repo_path) do
|
11
|
+
commands = [ "git init -q",
|
12
|
+
"touch foo",
|
13
|
+
"git add foo",
|
14
|
+
"git commit -qm 'init' ." ]
|
15
|
+
commands.each do |command|
|
16
|
+
system(command).should be_true
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
File.exists?(repo_path.join('.git')).should be_true
|
21
|
+
end
|
22
|
+
|
23
|
+
When /^I run "([^\"]*)"$/ do |cmd|
|
24
|
+
if cmd.split(' ').first == "finger-puppet"
|
25
|
+
command = %w(ruby -rubygems)
|
26
|
+
command << ROOT.join('bin', 'finger-puppet')
|
27
|
+
command << cmd.split[1..-1].join(' ')
|
28
|
+
command = command.join(' ')
|
29
|
+
else
|
30
|
+
command = cmd
|
31
|
+
end
|
32
|
+
|
33
|
+
Dir.chdir(@basedir) do
|
34
|
+
system(command).should be_true
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
Then /^running "([^\"]*)" should fail$/ do |command|
|
39
|
+
Dir.chdir(@basedir) do
|
40
|
+
system(command).should be_false
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
Then /^running "([^\"]*)" should succeed$/ do |command|
|
45
|
+
Dir.chdir(@basedir) do
|
46
|
+
system(command).should be_true
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
Then /^running "([^\"]*)" should output "([^\"]*)"$/ do |cmd, string|
|
51
|
+
if cmd.split(' ').first == "finger-puppet"
|
52
|
+
command = %w(ruby -rubygems)
|
53
|
+
command << ROOT.join('bin', 'finger-puppet')
|
54
|
+
command << cmd.split[1..-1].join(' ')
|
55
|
+
command = command.join(' ')
|
56
|
+
else
|
57
|
+
command = cmd
|
58
|
+
end
|
59
|
+
|
60
|
+
Dir.chdir(@basedir) do
|
61
|
+
(`#{command}` =~ /#{string}/).should be_true
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
Then /^I should have a git repository at "([^\"]*)"$/ do |repo_name|
|
66
|
+
repo_path = @basedir.join(repo_name)
|
67
|
+
File.exists?(repo_path.join('.git')).should be_true
|
68
|
+
end
|
69
|
+
|
70
|
+
Given /^there is no "([^\"]*)" repository$/ do |repo_name|
|
71
|
+
repo_path = @basedir.join(repo_name)
|
72
|
+
FileUtils.rm_rf(repo_path)
|
73
|
+
end
|
74
|
+
|
75
|
+
Given /^I have a simple Puppet repository named "([^\"]*)"$/ do |repo_name|
|
76
|
+
repo_path = @basedir.join(repo_name)
|
77
|
+
simple_path = ROOT.join('features', 'support', 'repos', 'simple')
|
78
|
+
hostname = Socket.gethostname.split('.').first
|
79
|
+
|
80
|
+
FileUtils.rm_rf(repo_path)
|
81
|
+
FileUtils.cp_r(simple_path, repo_path)
|
82
|
+
|
83
|
+
File.open(repo_path.join('manifests', 'nodes', "#{hostname}.pp"), 'w') do |f|
|
84
|
+
f << "node #{hostname} { include 'test' }"
|
85
|
+
end
|
86
|
+
|
87
|
+
Dir.chdir(repo_path) do
|
88
|
+
commands = ["git init -q", "git add .", "git commit -qm 'init' ."]
|
89
|
+
commands.each do |command|
|
90
|
+
system(command).should be_true
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
File.exists?(repo_path.join('.git')).should be_true
|
95
|
+
end
|
96
|
+
|
97
|
+
Given /^I have a simple Puppet 2.6 repository named "([^"]*)"$/ do |repo_name|
|
98
|
+
repo_path = @basedir.join(repo_name)
|
99
|
+
simple_path = ROOT.join('features', 'support', 'repos', 'simple_26')
|
100
|
+
hostname = Socket.gethostname.split('.').first
|
101
|
+
|
102
|
+
FileUtils.rm_rf(repo_path)
|
103
|
+
FileUtils.cp_r(simple_path, repo_path)
|
104
|
+
|
105
|
+
File.open(repo_path.join('manifests', 'nodes', "#{hostname}.pp"), 'w') do |f|
|
106
|
+
f << "node #{hostname} { include 'test' }"
|
107
|
+
end
|
108
|
+
|
109
|
+
Dir.chdir(repo_path) do
|
110
|
+
commands = ["git init -q", "git add .", "git commit -qm 'init' ."]
|
111
|
+
commands.each do |command|
|
112
|
+
system(command).should be_true
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
File.exists?(repo_path.join('.git')).should be_true
|
117
|
+
end
|
118
|
+
|
119
|
+
Then /^I should see a file at "([^\"]*)"$/ do |path|
|
120
|
+
File.exists?(path).should be_true
|
121
|
+
end
|
122
|
+
|
123
|
+
Then /^I should see a directory at "([^\"]*)"$/ do |path|
|
124
|
+
File.directory?(path).should be_true
|
125
|
+
end
|
126
|
+
|
127
|
+
Given /^there is no "([^\"]*)" file$/ do |file|
|
128
|
+
FileUtils.rm_rf(file).should be_true
|
129
|
+
end
|
130
|
+
|
131
|
+
Given /^"([^\"]*)" is on my path$/ do |command|
|
132
|
+
system("which #{command} > /dev/null").should be_true
|
133
|
+
end
|
134
|
+
|
135
|
+
Then /^I should see the following directories:$/ do |table|
|
136
|
+
table.hashes.each do |attrs|
|
137
|
+
File.directory?(attrs["directory"]).should be_true
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
When /^I touch "([^\"]*)"$/ do |filename|
|
142
|
+
system("touch #{filename} > /dev/null").should be_true
|
143
|
+
end
|
144
|
+
|
145
|
+
When /^the Gemfile looks like this:$/ do |string|
|
146
|
+
File.open(@basedir + 'Gemfile', 'w') do |f|
|
147
|
+
f << string + "\n"
|
148
|
+
end
|
149
|
+
end
|
File without changes
|
@@ -0,0 +1 @@
|
|
1
|
+
import "nodes/*"
|
File without changes
|
File without changes
|
File without changes
|
@@ -0,0 +1 @@
|
|
1
|
+
import "nodes/*"
|
File without changes
|
File without changes
|
File without changes
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |s|
|
5
|
+
s.name = "finger-puppet"
|
6
|
+
s.version = "0.3.0"
|
7
|
+
s.authors = ["Anthony Somerset"]
|
8
|
+
s.email = ["anthony@somersettechsolutions.co.uk"]
|
9
|
+
s.homepage = "http://github.com/anthonysomerset/finger-puppet"
|
10
|
+
s.summary = %q{finger-puppet helps you run Puppet locally against a Git checkout.}
|
11
|
+
s.description = %q{finger-puppet helps you run Puppet locally against a Git checkout. This is great for locally iterating your Puppet manifests very quickly, then pushng them up to a repository somewhere else to share the changes.}
|
12
|
+
|
13
|
+
s.rubyforge_project = "finger-puppet"
|
14
|
+
|
15
|
+
s.files = `git ls-files`.split("\n")
|
16
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
17
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
18
|
+
s.require_paths = ["lib"]
|
19
|
+
|
20
|
+
s.add_dependency 'thor', '0.13.4'
|
21
|
+
s.add_dependency 'bundler'
|
22
|
+
|
23
|
+
s.add_development_dependency 'puppet'
|
24
|
+
s.add_development_dependency 'cucumber'
|
25
|
+
end
|
@@ -0,0 +1,204 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'thor'
|
4
|
+
require 'pathname'
|
5
|
+
|
6
|
+
module Logging
|
7
|
+
ESCAPES = { :green => "\033[0;32m",
|
8
|
+
:yellow => "\033[0;33m",
|
9
|
+
:red => "\033[47;31m",
|
10
|
+
:reset => "\033[0m" }
|
11
|
+
|
12
|
+
def info(message)
|
13
|
+
emit(:message => message, :color => :green)
|
14
|
+
end
|
15
|
+
|
16
|
+
def warn(message)
|
17
|
+
emit(:message => message, :color => :yellow)
|
18
|
+
end
|
19
|
+
|
20
|
+
def error(message)
|
21
|
+
emit(:message => message, :color => :red)
|
22
|
+
end
|
23
|
+
|
24
|
+
def emit(opts={})
|
25
|
+
color = opts[:color]
|
26
|
+
message = opts[:message]
|
27
|
+
print ESCAPES[color]
|
28
|
+
print message
|
29
|
+
print ESCAPES[:reset]
|
30
|
+
print "\n"
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
# Thor's default stack trace on errors is ugly - make it pretty.
|
35
|
+
class Thor
|
36
|
+
class << self
|
37
|
+
def handle_argument_error(task, error)
|
38
|
+
puts "#{task.name.inspect} was called incorrectly. Call as #{task.formatted_usage(self, banner_base == "thor").inspect}."
|
39
|
+
exit 1
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
|
45
|
+
class finger-puppet < Thor
|
46
|
+
include Logging
|
47
|
+
|
48
|
+
def initialize
|
49
|
+
super
|
50
|
+
@root = Pathname.new(Dir.getwd)
|
51
|
+
@install_root = Pathname.new(File.expand_path(File.join(File.dirname(__FILE__))))
|
52
|
+
end
|
53
|
+
|
54
|
+
desc "clone <repository> [directory]", "clone a Git repository of Puppet manifests"
|
55
|
+
def clone(repository, directory=nil)
|
56
|
+
abort_unless_git_installed
|
57
|
+
directory ||= File.basename(repository.split('/').last, '.git')
|
58
|
+
command = "git clone -q #{repository} #{directory}"
|
59
|
+
system(command)
|
60
|
+
|
61
|
+
# A cloned repo may have submodules - automatically initialise them.
|
62
|
+
if File.exists?(File.join(directory, '.gitmodules'))
|
63
|
+
Dir.chdir(directory) do
|
64
|
+
system("git submodule init")
|
65
|
+
system("git submodule update")
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
desc "go [puppet arguments]", "do a local Puppet run"
|
71
|
+
def go(*puppet_args)
|
72
|
+
if ENV['USER'] != "root"
|
73
|
+
warn "You should probably be root when running this! Proceeding anyway..."
|
74
|
+
end
|
75
|
+
|
76
|
+
args = []
|
77
|
+
if has_frozen_components?
|
78
|
+
args << "bundle exec puppet"
|
79
|
+
info "Using frozen Puppet from #{@root.join('vendor', 'puppet')}."
|
80
|
+
else
|
81
|
+
abort_unless_puppet_installed(:message => "Please either install it on your system or freeze it with 'finger-puppet freeze'")
|
82
|
+
args << "puppet"
|
83
|
+
end
|
84
|
+
|
85
|
+
if puppet_version[0] > 0
|
86
|
+
args << 'apply'
|
87
|
+
end
|
88
|
+
|
89
|
+
args << "--modulepath #{@root.join('modules')}"
|
90
|
+
args << "--confdir #{@root.join('etc')}" unless puppet_args.include?("--confdir")
|
91
|
+
args << "--vardir #{@root.join('var')}" unless puppet_args.include?("--vardir")
|
92
|
+
args << "#{@root.join('manifests', 'site.pp')}"
|
93
|
+
|
94
|
+
args += puppet_args
|
95
|
+
|
96
|
+
command = args.join(' ')
|
97
|
+
puts command if args.include?("--debug")
|
98
|
+
system(command) ? exit(0) : exit(2)
|
99
|
+
end
|
100
|
+
|
101
|
+
desc "freeze [repository, project]", "freeze Puppet into your manifests repository"
|
102
|
+
def freeze(*args)
|
103
|
+
abort_unless_git_installed
|
104
|
+
abort_unless_bundle_installed
|
105
|
+
|
106
|
+
commands = []
|
107
|
+
commands << { :command => "bundle install --path=#{@root + 'vendor'} --binstubs" }
|
108
|
+
commands << { :command => "git add Gemfile.lock bin/ vendor/ .bundle/" }
|
109
|
+
commands << { :command => "git commit --quiet -m 'Bundled Puppet + Facter.' Gemfile* bin/ vendor/ .bundle/" }
|
110
|
+
|
111
|
+
commands.each do |attrs|
|
112
|
+
dir = attrs[:directory] || @root
|
113
|
+
Dir.chdir(dir) do
|
114
|
+
exit(2) unless system(attrs[:command])
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
info "Freezing complete."
|
119
|
+
end
|
120
|
+
|
121
|
+
desc "scaffold <project>", "generate scaffolding for a repository of Puppet manifests"
|
122
|
+
def scaffold(puppet_path)
|
123
|
+
template_path = @install_root.join('generators', 'puppet')
|
124
|
+
FileUtils.cp_r(template_path, puppet_path)
|
125
|
+
end
|
126
|
+
|
127
|
+
desc "init <project>", "initialise a repo of scaffolded Puppet manifests"
|
128
|
+
def init(project)
|
129
|
+
repo_path = @root.join(project)
|
130
|
+
template_path = @install_root.join('generators', 'git')
|
131
|
+
|
132
|
+
scaffold(repo_path)
|
133
|
+
|
134
|
+
Dir.chdir(repo_path) do
|
135
|
+
commands = [ "git init --quiet --template=#{template_path}",
|
136
|
+
"git add .",
|
137
|
+
"git commit --quiet -am 'Initial commit.'" ]
|
138
|
+
commands.each do |command|
|
139
|
+
system(command)
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
info "Your new finger-puppet project has been initialised in #{repo_path}"
|
144
|
+
end
|
145
|
+
|
146
|
+
desc "whoami [rfc2822-address]", "set the current commit author"
|
147
|
+
def whoami(address=nil)
|
148
|
+
# getter
|
149
|
+
if address
|
150
|
+
name = address[/^(.+)\s+</, 1]
|
151
|
+
email = address[/<(.+)>$/, 1]
|
152
|
+
|
153
|
+
unless name && email
|
154
|
+
abort("Supplied address isn't a valid rfc2822 email address")
|
155
|
+
end
|
156
|
+
|
157
|
+
system("git config user.name '#{name}'")
|
158
|
+
system("git config user.email '#{email}'")
|
159
|
+
# setter
|
160
|
+
else
|
161
|
+
name = `git config user.name`.strip
|
162
|
+
email = `git config user.email`.strip
|
163
|
+
|
164
|
+
if name.empty? || email.empty?
|
165
|
+
warn "You don't have a name or email set."
|
166
|
+
else
|
167
|
+
puts "#{name} <#{email}>"
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
private
|
173
|
+
def has_frozen_components?
|
174
|
+
puppet = system("bundle show puppet")
|
175
|
+
facter = system("bundle show facter")
|
176
|
+
|
177
|
+
puppet && facter
|
178
|
+
end
|
179
|
+
|
180
|
+
def puppet_version
|
181
|
+
@puppet_version ||= `puppet --version`.split('.').map(&:to_i)
|
182
|
+
end
|
183
|
+
|
184
|
+
# helper + abortive methods
|
185
|
+
%w(puppet git bundle).each do |bin|
|
186
|
+
class_eval <<-METHOD, __FILE__, __LINE__
|
187
|
+
no_tasks do
|
188
|
+
def #{bin}_installed?
|
189
|
+
`which #{bin}` =~ /#{bin}$/ ? true : false
|
190
|
+
end
|
191
|
+
|
192
|
+
def abort_unless_#{bin}_installed(opts={})
|
193
|
+
unless #{bin}_installed?
|
194
|
+
error "You don't have #{bin.capitalize} installed!"
|
195
|
+
error opts[:message] || "Please install it on your system."
|
196
|
+
exit 3
|
197
|
+
end
|
198
|
+
end
|
199
|
+
end
|
200
|
+
METHOD
|
201
|
+
end
|
202
|
+
|
203
|
+
end
|
204
|
+
|
@@ -0,0 +1 @@
|
|
1
|
+
a finger-puppet-ified repository of Puppet manifests
|
@@ -0,0 +1,29 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "socket"
|
4
|
+
|
5
|
+
name = ENV['GIT_AUTHOR_NAME'] || `git config user.name`
|
6
|
+
email = ENV['GIT_AUTHOR_EMAIL'] || `git config user.email`
|
7
|
+
hostname = Socket.gethostname
|
8
|
+
|
9
|
+
@errors = []
|
10
|
+
case
|
11
|
+
when !name, name.strip.empty?
|
12
|
+
@errors << "You don't have an author name set."
|
13
|
+
@errors << "Please set this to your real name before committing."
|
14
|
+
when !email, email.strip.empty?
|
15
|
+
@errors << "You don't have an author email address set."
|
16
|
+
@errors << "Please set this to your real email address before committing."
|
17
|
+
when name == "root", name =~ /^\s*$/
|
18
|
+
@errors << "Your author name is '#{name}'."
|
19
|
+
@errors << "Please set this to your real name before committing."
|
20
|
+
when email =~ /^\s*$/, email =~ /#{hostname}/
|
21
|
+
@errors << "You author email is '#{email}'."
|
22
|
+
@errors << "This matches part of the system hostname (#{hostname})."
|
23
|
+
@errors << "If this is correct, please run again with --no-verify."
|
24
|
+
end
|
25
|
+
|
26
|
+
if @errors.size > 0
|
27
|
+
puts @errors
|
28
|
+
exit 1
|
29
|
+
end
|
File without changes
|
@@ -0,0 +1,27 @@
|
|
1
|
+
Manifests
|
2
|
+
=========
|
3
|
+
|
4
|
+
modules/ <= Puppet modules
|
5
|
+
manifests/ <= Puppet nodes
|
6
|
+
vendor/ <= frozen Puppet + Facter
|
7
|
+
|
8
|
+
|
9
|
+
Running Puppet with finger-puppet
|
10
|
+
------------------------
|
11
|
+
|
12
|
+
From within this directory, run:
|
13
|
+
|
14
|
+
finger-puppet go
|
15
|
+
|
16
|
+
You can pass options to Puppet after the 'go':
|
17
|
+
|
18
|
+
finger-puppet go --debug --test
|
19
|
+
|
20
|
+
Freezing Puppet
|
21
|
+
---------------
|
22
|
+
|
23
|
+
You can freeze Puppet:
|
24
|
+
|
25
|
+
finger-puppet freeze
|
26
|
+
|
27
|
+
Now finger-puppet will use the frozen Puppet when you run 'finger-puppet go'.
|
@@ -0,0 +1 @@
|
|
1
|
+
# Put yur nodes here!
|
File without changes
|
File without changes
|
File without changes
|