runpuppet 1.0.0.rc1 → 1.0.0.rc2
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/Gemfile +1 -0
- data/Gemfile.lock +2 -0
- data/README.rdoc +23 -1
- data/Rakefile +1 -1
- data/VERSION +1 -1
- data/bin/runpuppet +9 -7
- data/lib/ext/core.rb +8 -0
- data/lib/runpuppet.rb +21 -131
- data/lib/runpuppet/agent.rb +77 -0
- data/lib/runpuppet/client.rb +76 -0
- data/lib/runpuppet/config.rb +94 -0
- data/lib/runpuppet/logger.rb +6 -0
- data/runpuppet.gemspec +16 -1
- data/sh/c +1 -0
- data/sh/console.rb +14 -0
- data/sh/test +1 -0
- data/test/agent_test.rb +49 -0
- data/test/binary_test.rb +7 -0
- data/test/client_test.rb +37 -0
- data/test/config_test.rb +89 -0
- data/test/fixtures/runpuppet.yml +7 -0
- data/test/fixtures/shell/arp_eth0.txt +2 -0
- data/test/fixtures/shell/ip_addr_list_eth0.txt +5 -0
- data/test/helper.rb +32 -0
- metadata +18 -3
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
data/README.rdoc
CHANGED
@@ -11,6 +11,28 @@ cat /etc/runpuppet.yml:
|
|
11
11
|
lock_file: /tmp/runpuppet.lock
|
12
12
|
|
13
13
|
|
14
|
+
### Run tests
|
15
|
+
|
16
|
+
sh/test
|
17
|
+
|
18
|
+
|
19
|
+
#### Start console
|
20
|
+
|
21
|
+
sh/c
|
22
|
+
|
23
|
+
#### Playing in console
|
24
|
+
|
25
|
+
@ctx = Runpuppet.setup_context({})
|
26
|
+
|
27
|
+
# client
|
28
|
+
@ctx.client
|
29
|
+
|
30
|
+
# config
|
31
|
+
@ctx.config
|
32
|
+
|
33
|
+
# agent ### HTTP agent
|
34
|
+
@ctx.agent
|
35
|
+
|
14
36
|
|
15
37
|
|
16
38
|
This is the companion for our puppet_controller, a light-weight web-service to coordinate local puppet runs on servers.
|
@@ -27,6 +49,6 @@ This is the companion for our puppet_controller, a light-weight web-service to c
|
|
27
49
|
|
28
50
|
== Copyright
|
29
51
|
|
30
|
-
Copyright (c)
|
52
|
+
Copyright (c) 2012 Roman Heinrich. See LICENSE.txt for
|
31
53
|
further details.
|
32
54
|
|
data/Rakefile
CHANGED
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
1.0.0.rc2
|
data/bin/runpuppet
CHANGED
@@ -20,17 +20,19 @@ BANNER
|
|
20
20
|
|
21
21
|
opts.on("-h", "--help","Show this.") { puts opts; exit }
|
22
22
|
opts.on("--readme", 'Show Readme'){ puts File.read(File.join(File.dirname(__FILE__), '..', 'README.rdoc')); exit }
|
23
|
-
opts.on('
|
24
|
-
opts.on('--try','Runs only if selected on puppet_controller'){ options[:try] = true }
|
25
|
-
opts.on('-f', '--facts','Report facts'){ options[:facts] = true }
|
26
|
-
opts.on('--verbose','Verbose
|
23
|
+
opts.on('--version', 'Show Version'){ puts Runpuppet::VERSION; exit}
|
24
|
+
opts.on('--try', 'Runs only if selected on puppet_controller'){ options[:try] = true }
|
25
|
+
opts.on('-f', '--facts', 'Report facts'){ options[:facts] = true }
|
26
|
+
opts.on('-v', '--verbose', 'Execute Verbose Command'){ options[:verbose] = true }
|
27
|
+
opts.on('-d', '--debug', 'With debug output'){ options[:debug] = true }
|
27
28
|
opts.on('-b x', '--branch x', 'Run this branch') do |branch|
|
28
29
|
options[:branch] = branch
|
29
30
|
end
|
30
31
|
end.parse!
|
31
32
|
|
33
|
+
PuppetContext = Runpuppet.setup_context(options)
|
32
34
|
if options[:facts]
|
33
|
-
|
35
|
+
PuppetContext.client.report_facts
|
34
36
|
else
|
35
|
-
|
36
|
-
end
|
37
|
+
PuppetContext.client.run
|
38
|
+
end
|
data/lib/ext/core.rb
ADDED
data/lib/runpuppet.rb
CHANGED
@@ -2,151 +2,41 @@ require 'open-uri'
|
|
2
2
|
require 'socket'
|
3
3
|
require 'yaml'
|
4
4
|
require 'rest-client'
|
5
|
-
require '
|
6
|
-
|
7
|
-
STDOUT.sync = true
|
8
|
-
|
9
|
-
class Runpuppet
|
10
|
-
def self.with_lock(lock_file)
|
11
|
-
recently_locked = (File.exists?(lock_file) and File.mtime(lock_file) > Time.now - 15*60)
|
12
|
-
|
13
|
-
if recently_locked
|
14
|
-
puts "can not run, lockfile #{lock_file} exists"
|
15
|
-
else
|
16
|
-
begin
|
17
|
-
`touch #{lock_file}`
|
18
|
-
yield
|
19
|
-
ensure
|
20
|
-
`rm #{lock_file}`
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
# simplified copy of rake`s sh
|
26
|
-
def self.sh(cmd)
|
27
|
-
puts cmd
|
28
|
-
IO.popen(cmd) do |pipe|
|
29
|
-
while str = pipe.gets
|
30
|
-
puts str
|
31
|
-
end
|
32
|
-
end
|
33
|
-
$?.success?
|
34
|
-
end
|
35
|
-
|
36
|
-
|
37
|
-
def self.get(path, options={})
|
38
|
-
path += (path.include?('?') ? '&' : '?')
|
39
|
-
path += "hostname=#{Socket.gethostname}&ip=#{Config.local_ip}"
|
40
|
-
begin
|
41
|
-
url = Config.puppet_controller_url + path
|
42
|
-
puts "Getting #{url}" if options[:verbose]
|
43
|
-
RestClient.get(url)
|
44
|
-
rescue Exception => e
|
45
|
-
puts e.inspect
|
46
|
-
puts "WARNING: error connecting in GET (PuppetMaster)"
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
|
-
|
51
|
-
def self.post(path, params)
|
52
|
-
params[:hostname] = Socket.gethostname
|
53
|
-
params[:ip] = Config.local_ip
|
54
|
-
begin
|
55
|
-
RestClient.post "#{Config.puppet_controller_url}/puppet/#{path}", params
|
56
|
-
rescue Exception => e
|
57
|
-
puts e.inspect
|
58
|
-
puts "WARNING: error connecting in POST (PuppetMaster)"
|
59
|
-
end
|
60
|
-
end
|
5
|
+
require 'dim'
|
61
6
|
|
7
|
+
require 'ext/core'
|
8
|
+
require 'runpuppet/config'
|
9
|
+
require 'runpuppet/client'
|
10
|
+
require 'runpuppet/agent'
|
11
|
+
require 'runpuppet/logger'
|
62
12
|
|
63
|
-
|
64
|
-
with_lock(Config.lock_file) do
|
65
|
-
time = Time.now.utc.strftime("%Y-%m-%d %H:%M:%S")
|
66
|
-
|
67
|
-
todo, branch = get("/puppet/run", options).split('-') rescue []
|
68
|
-
puts "got #{todo} with branch #{branch}" if options[:verbose]
|
69
|
-
branch ||= (options[:branch] || Config.default_branch)
|
70
|
-
if todo == 'run' or !options[:try] # try allows not running
|
71
|
-
get '/puppet/status?status=started', options
|
72
|
-
cmd = Config.command.gsub('@@branch@@', branch)
|
73
|
-
puts "#{time}: run #{branch}"
|
74
|
-
|
75
|
-
if sh(cmd)
|
76
|
-
get '/puppet/status?status=finished', options
|
77
|
-
else
|
78
|
-
get '/puppet/status?status=error', options
|
79
|
-
exit 2
|
80
|
-
end
|
81
|
-
else
|
82
|
-
puts "#{time}: nothing to do"
|
83
|
-
end
|
84
|
-
end
|
85
|
-
end
|
86
|
-
|
87
|
-
def self.report_facts(options={})
|
88
|
-
require 'facter/application'
|
89
|
-
facts = Facter::Application.run([])
|
90
|
-
post('facts', :facts => facts.to_hash)
|
91
|
-
end
|
92
|
-
|
93
|
-
|
94
|
-
class Config
|
95
|
-
def self.config
|
96
|
-
home = File.expand_path('~')
|
97
|
-
["#{home}/.runpuppet.yml", '/etc/runpuppet.yml'].each do |file|
|
98
|
-
return YAML.load(File.read(file)) if File.exist?(file)
|
99
|
-
end
|
100
|
-
raise "No runpuppet.yml found in /etc or #{home}"
|
101
|
-
end
|
102
|
-
|
103
|
-
def self.puppet_controller_url
|
104
|
-
config['puppet_controller_url'].sub(%r{/$},'')
|
105
|
-
end
|
13
|
+
STDOUT.sync = true
|
106
14
|
|
107
|
-
def self.puppet_controller_auth
|
108
|
-
extract_auth_from_url!(config['puppet_controller_url'])
|
109
|
-
end
|
110
15
|
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
auth.empty? ? nil : auth
|
115
|
-
end
|
16
|
+
module Runpuppet
|
17
|
+
def self.setup_context(options={})
|
18
|
+
ctx = Dim::Container.new
|
116
19
|
|
117
|
-
|
118
|
-
|
20
|
+
ctx.register(:run_options) do
|
21
|
+
options
|
119
22
|
end
|
120
23
|
|
121
|
-
|
122
|
-
|
24
|
+
ctx.register(:config) do
|
25
|
+
Runpuppet::Config.find_system_config
|
123
26
|
end
|
124
27
|
|
125
|
-
|
126
|
-
|
28
|
+
ctx.register(:client) do |context|
|
29
|
+
Runpuppet::Client.new(context)
|
127
30
|
end
|
128
31
|
|
129
|
-
|
130
|
-
|
131
|
-
require 'facter'
|
132
|
-
require 'facter/ec2'
|
133
|
-
ip = Facter.value("ec2_public_ipv4")
|
134
|
-
elsif config['local_ip_interface']
|
135
|
-
parse_local_ip_from_interface
|
136
|
-
else
|
137
|
-
config['local_ip'] or %x(ifconfig)[/192.168.\d+.\d+/] or %x(ifconfig)[/10.10.\d+.\d+/]
|
138
|
-
end
|
32
|
+
ctx.register(:agent) do |context|
|
33
|
+
Runpuppet::Agent.new(context)
|
139
34
|
end
|
140
35
|
|
141
|
-
|
142
|
-
|
143
|
-
# %x(ifconfig #{config['local_ip_interface']}).lines.grep(/inet addr/).first.match(/addr:(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})?/)
|
144
|
-
%x(ip addr list #{config['local_ip_interface']}).match(/inet (\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})?/)
|
145
|
-
return $1
|
36
|
+
ctx.register(:logger) do
|
37
|
+
Runpuppet::Logger
|
146
38
|
end
|
147
39
|
|
148
|
-
|
149
|
-
%x(arp -n -i eth0) =~ /fe:ff:ff:ff:ff/
|
150
|
-
end
|
40
|
+
return ctx
|
151
41
|
end
|
152
42
|
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
### http client
|
2
|
+
module Runpuppet
|
3
|
+
class Agent
|
4
|
+
attr_accessor :config
|
5
|
+
attr_accessor :run_options
|
6
|
+
def initialize(context)
|
7
|
+
@config = context.config
|
8
|
+
@run_options = context.run_options
|
9
|
+
end
|
10
|
+
|
11
|
+
##### puppet
|
12
|
+
|
13
|
+
def check_status
|
14
|
+
action, branch = get("/puppet/run", @run_options).split('-') rescue []
|
15
|
+
branch ||= (run_options[:branch] || config.default_branch)
|
16
|
+
return action, branch
|
17
|
+
end
|
18
|
+
|
19
|
+
def report_start
|
20
|
+
get '/puppet/status?status=started'
|
21
|
+
end
|
22
|
+
|
23
|
+
def report_success
|
24
|
+
get '/puppet/status?status=finished'
|
25
|
+
end
|
26
|
+
|
27
|
+
def report_failure
|
28
|
+
get '/puppet/status?status=error'
|
29
|
+
end
|
30
|
+
|
31
|
+
def report_facts
|
32
|
+
require 'facter/application'
|
33
|
+
facts = Facter::Application.run([])
|
34
|
+
post('/puppet/facts', :facts => facts.to_hash)
|
35
|
+
end
|
36
|
+
|
37
|
+
#### base
|
38
|
+
|
39
|
+
def get(path)
|
40
|
+
begin
|
41
|
+
url = append_params_to_url(base_url(path))
|
42
|
+
puts "Getting #{url}" if run_options[:verbose]
|
43
|
+
result = RestClient.get(url)
|
44
|
+
puts "got #{result}" if run_options[:verbose]
|
45
|
+
rescue Exception => e
|
46
|
+
puts e.inspect
|
47
|
+
puts "WARNING: error connecting in GET (PuppetMaster)"
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def post(path, params)
|
52
|
+
begin
|
53
|
+
RestClient.post base_url(path), append_params_to_post(params)
|
54
|
+
rescue Exception => e
|
55
|
+
puts e.inspect
|
56
|
+
puts "WARNING: error connecting in POST (PuppetMaster)"
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def append_params_to_post(params)
|
61
|
+
params = params.dup
|
62
|
+
params[:hostname] = config.hostname
|
63
|
+
params[:ip] = config.local_ip
|
64
|
+
return params
|
65
|
+
end
|
66
|
+
|
67
|
+
def append_params_to_url(url)
|
68
|
+
url += (url.include?('?') ? '&' : '?')
|
69
|
+
url += "hostname=#{config.hostname}&ip=#{config.local_ip}"
|
70
|
+
url
|
71
|
+
end
|
72
|
+
|
73
|
+
def base_url(path)
|
74
|
+
"#{config.puppet_controller_url.gsub(/\/$/, '')}/#{path.gsub(/^\//, '')}"
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
module Runpuppet
|
2
|
+
class Client
|
3
|
+
attr_accessor :config
|
4
|
+
attr_accessor :run_options
|
5
|
+
attr_accessor :agent
|
6
|
+
attr_accessor :logger
|
7
|
+
def initialize(context)
|
8
|
+
@config = context.config
|
9
|
+
@run_options = context.run_options
|
10
|
+
@agent = context.agent
|
11
|
+
end
|
12
|
+
|
13
|
+
def run
|
14
|
+
with_lock(config.lock_file) do
|
15
|
+
action, branch = agent.check_status
|
16
|
+
if should_run?(action)
|
17
|
+
agent.report_start
|
18
|
+
log "run #{branch}"
|
19
|
+
|
20
|
+
if sh(run_command(branch))
|
21
|
+
agent.report_success
|
22
|
+
else
|
23
|
+
agent.report_failure
|
24
|
+
exit 2
|
25
|
+
end
|
26
|
+
else
|
27
|
+
log "nothing to do"
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def run_command(branch)
|
33
|
+
cmd = if run_options[:verbose]
|
34
|
+
config.verbose_command
|
35
|
+
else
|
36
|
+
config.command
|
37
|
+
end
|
38
|
+
cmd.gsub('@@branch@@', branch)
|
39
|
+
end
|
40
|
+
|
41
|
+
def should_run?(action)
|
42
|
+
## always run if started without --try
|
43
|
+
(!run_options[:try] or action == 'run')
|
44
|
+
end
|
45
|
+
|
46
|
+
def with_lock(lock_file)
|
47
|
+
recently_locked = (File.exists?(lock_file) and File.mtime(lock_file) > Time.now - 15*60)
|
48
|
+
|
49
|
+
if recently_locked
|
50
|
+
log "can not run, lockfile #{lock_file} exists"
|
51
|
+
else
|
52
|
+
begin
|
53
|
+
`touch #{lock_file}`
|
54
|
+
yield
|
55
|
+
ensure
|
56
|
+
`rm #{lock_file}`
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
# simplified copy of rake`s sh
|
62
|
+
def sh(cmd)
|
63
|
+
puts cmd
|
64
|
+
IO.popen(cmd) do |pipe|
|
65
|
+
while str = pipe.gets
|
66
|
+
puts str
|
67
|
+
end
|
68
|
+
end
|
69
|
+
$?.success?
|
70
|
+
end
|
71
|
+
|
72
|
+
def log(msg)
|
73
|
+
logger.log(msg)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,94 @@
|
|
1
|
+
module Runpuppet
|
2
|
+
class Config
|
3
|
+
attr_accessor :config_path
|
4
|
+
attr_accessor :data
|
5
|
+
def initialize(config_path)
|
6
|
+
@config_path = config_path
|
7
|
+
load_data
|
8
|
+
end
|
9
|
+
|
10
|
+
|
11
|
+
def load_data
|
12
|
+
raise "No runpuppet.yml found in #{config_path}" unless File.exist?(config_path)
|
13
|
+
@data = YAML.load(File.read(config_path))
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.find_system_config
|
17
|
+
home = File.expand_path('~')
|
18
|
+
pathes = ["#{home}/.runpuppet.yml", '/etc/runpuppet.yml']
|
19
|
+
pathes.each do |file|
|
20
|
+
return Runpuppet::Config.new(file) if File.exist?(file)
|
21
|
+
end
|
22
|
+
puts "No runpuppet.yml found in #{pathes.join(' or ')}"
|
23
|
+
exit
|
24
|
+
end
|
25
|
+
|
26
|
+
def puppet_controller_url
|
27
|
+
data['puppet_controller_url'].sub(%r{/$},'')
|
28
|
+
end
|
29
|
+
|
30
|
+
def puppet_controller_auth
|
31
|
+
extract_auth_from_url!(puppet_controller_url)
|
32
|
+
end
|
33
|
+
|
34
|
+
def extract_auth_from_url!(url)
|
35
|
+
url.sub!(%r{//(.*?):(.*?)@}, '//')
|
36
|
+
auth = [$1, $2].compact
|
37
|
+
auth.empty? ? nil : auth
|
38
|
+
end
|
39
|
+
|
40
|
+
def lock_file
|
41
|
+
data['lock_file'] || '/tmp/runpuppet.lock'
|
42
|
+
end
|
43
|
+
|
44
|
+
def command
|
45
|
+
# "cd /etc/puppet/repo && git fetch && git checkout -f origin/@@branch@@ && puppet -v --debug --logdest console --modulepath /etc/puppet/repo/modules /etc/puppet/repo/manifests/site.pp"
|
46
|
+
data['command']
|
47
|
+
end
|
48
|
+
|
49
|
+
def verbose_command
|
50
|
+
unless data['verbose_command']
|
51
|
+
puts "No verbose_command param in #{config_path} found! using normal command."
|
52
|
+
return self.command
|
53
|
+
end
|
54
|
+
data['verbose_command']
|
55
|
+
end
|
56
|
+
|
57
|
+
def default_branch
|
58
|
+
data['branch'] || 'master'
|
59
|
+
end
|
60
|
+
|
61
|
+
def local_ip
|
62
|
+
if is_ec2?
|
63
|
+
require 'facter'
|
64
|
+
require 'facter/ec2'
|
65
|
+
ip = Facter.value("ec2_public_ipv4")
|
66
|
+
elsif data['local_ip_interface']
|
67
|
+
parse_local_ip_from_interface
|
68
|
+
else
|
69
|
+
ifconfig = read_shell('ifconfig')
|
70
|
+
data['local_ip'] or
|
71
|
+
ifconfig[/192.168.\d+.\d+/] or
|
72
|
+
ifconfig[/10.10.\d+.\d+/]
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def hostname
|
77
|
+
Socket.gethostname
|
78
|
+
end
|
79
|
+
|
80
|
+
def parse_local_ip_from_interface
|
81
|
+
cmd = "ip addr list #{data['local_ip_interface']}"
|
82
|
+
read_shell(cmd).match(/inet (\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})?/)
|
83
|
+
return $1
|
84
|
+
end
|
85
|
+
|
86
|
+
def is_ec2?
|
87
|
+
read_shell('arp -n -i eth0') =~ /fe:ff:ff:ff:ff/
|
88
|
+
end
|
89
|
+
|
90
|
+
def read_shell(cmd)
|
91
|
+
%x(#{cmd})
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
data/runpuppet.gemspec
CHANGED
@@ -5,7 +5,7 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = "runpuppet"
|
8
|
-
s.version = "1.0.0.
|
8
|
+
s.version = "1.0.0.rc2"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new("> 1.3.1") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Roman Heinrich"]
|
@@ -26,8 +26,23 @@ Gem::Specification.new do |s|
|
|
26
26
|
"Rakefile",
|
27
27
|
"VERSION",
|
28
28
|
"bin/runpuppet",
|
29
|
+
"lib/ext/core.rb",
|
29
30
|
"lib/runpuppet.rb",
|
31
|
+
"lib/runpuppet/agent.rb",
|
32
|
+
"lib/runpuppet/client.rb",
|
33
|
+
"lib/runpuppet/config.rb",
|
34
|
+
"lib/runpuppet/logger.rb",
|
30
35
|
"runpuppet.gemspec",
|
36
|
+
"sh/c",
|
37
|
+
"sh/console.rb",
|
38
|
+
"sh/test",
|
39
|
+
"test/agent_test.rb",
|
40
|
+
"test/binary_test.rb",
|
41
|
+
"test/client_test.rb",
|
42
|
+
"test/config_test.rb",
|
43
|
+
"test/fixtures/runpuppet.yml",
|
44
|
+
"test/fixtures/shell/arp_eth0.txt",
|
45
|
+
"test/fixtures/shell/ip_addr_list_eth0.txt",
|
31
46
|
"test/helper.rb"
|
32
47
|
]
|
33
48
|
s.homepage = "http://github.com/dawanda/runpuppet"
|
data/sh/console.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
|
2
|
+
require 'rubygems'
|
3
|
+
require 'bundler'
|
4
|
+
begin
|
5
|
+
Bundler.setup(:default, :development)
|
6
|
+
rescue Bundler::BundlerError => e
|
7
|
+
$stderr.puts e.message
|
8
|
+
$stderr.puts "Run `bundle install` to install missing gems"
|
9
|
+
exit e.status_code
|
10
|
+
end
|
11
|
+
|
12
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
13
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
14
|
+
require 'runpuppet'
|
data/sh/test
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
rake test
|
data/test/agent_test.rb
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'test/helper'
|
2
|
+
|
3
|
+
describe "Runpuppet::Agent" do
|
4
|
+
before do
|
5
|
+
@agent = TestContext.agent
|
6
|
+
end
|
7
|
+
|
8
|
+
describe :check_status do
|
9
|
+
it "returns the action for puppet and branch" do
|
10
|
+
@agent.stubs(:get).returns('run-master')
|
11
|
+
@agent.check_status.must_equal ["run", "master"]
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
describe :base_url do
|
16
|
+
it 'works' do
|
17
|
+
@agent.base_url('/action').must_equal "http://user:pass@puppet.example.com/action"
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
describe "URL manipulation" do
|
22
|
+
before do
|
23
|
+
TestContext.config.stubs(:local_ip).returns('10.10.10.10')
|
24
|
+
TestContext.config.stubs(:hostname).returns('example-vm')
|
25
|
+
end
|
26
|
+
|
27
|
+
|
28
|
+
describe :append_params_to_post do
|
29
|
+
it "adds hostname and local ip to params" do
|
30
|
+
params = {}
|
31
|
+
new_params = @agent.append_params_to_post(params)
|
32
|
+
new_params[:hostname].must_equal 'example-vm'
|
33
|
+
new_params[:ip].must_equal '10.10.10.10'
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
describe :append_params_to_url do
|
38
|
+
it "adds ip and hostname to url" do
|
39
|
+
new_url = @agent.append_params_to_url('/action')
|
40
|
+
new_url.must_equal "/action?hostname=example-vm&ip=10.10.10.10"
|
41
|
+
end
|
42
|
+
|
43
|
+
it "appends to existing params, if needed" do
|
44
|
+
new_url = @agent.append_params_to_url('/action?some_funny_param=1')
|
45
|
+
new_url.must_equal "/action?some_funny_param=1&hostname=example-vm&ip=10.10.10.10"
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
data/test/binary_test.rb
ADDED
data/test/client_test.rb
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'test/helper'
|
2
|
+
|
3
|
+
describe "Client" do
|
4
|
+
before do
|
5
|
+
@ctx = Dim::Container.new(TestContext)
|
6
|
+
end
|
7
|
+
|
8
|
+
describe :run_command do
|
9
|
+
it "without --verbose param" do
|
10
|
+
cmd = "cd /etc/puppet/repo && git fetch && git checkout -f origin/feature && puppet apply /etc/puppet/repo/manifests/site.pp"
|
11
|
+
@ctx.client.run_command('feature').must_equal cmd
|
12
|
+
end
|
13
|
+
|
14
|
+
it "with --verbose param" do
|
15
|
+
@ctx.register(:run_options){ {:verbose => true} }
|
16
|
+
cmd = "cd /etc/puppet/repo && git fetch && git checkout -f origin/feature && /etc/puppet/repo/bin/prepare_environment.rb && puppet apply -v /etc/puppet/repo/manifests/site.pp"
|
17
|
+
@ctx.client.run_command('feature').must_equal cmd
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
describe :should_run? do
|
22
|
+
it "always runs without --try option" do
|
23
|
+
@ctx.register(:run_options){ {:try => false} }
|
24
|
+
@ctx.client.should_run?('branch_does_not_matter').must_equal true
|
25
|
+
end
|
26
|
+
|
27
|
+
it "runs with --try option only for 'run' action" do
|
28
|
+
@ctx.register(:run_options){ {:try => true} }
|
29
|
+
@ctx.client.should_run?('run').must_equal true
|
30
|
+
end
|
31
|
+
|
32
|
+
it "does not run with --try option, if not 'run' action" do
|
33
|
+
@ctx.register(:run_options){ {:try => true} }
|
34
|
+
@ctx.client.should_run?('some_random_action').must_equal false
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
data/test/config_test.rb
ADDED
@@ -0,0 +1,89 @@
|
|
1
|
+
require 'test/helper'
|
2
|
+
|
3
|
+
describe 'Config' do
|
4
|
+
def shell_fixture(path)
|
5
|
+
File.read("test/fixtures/shell/#{path}").strip
|
6
|
+
end
|
7
|
+
|
8
|
+
before do
|
9
|
+
@config = TestContext.config
|
10
|
+
end
|
11
|
+
|
12
|
+
it "reports facts" do
|
13
|
+
ec2_facts = [["architecture", "x86_64"], ["arp", "fe:ff:ff:ff:ff:ff"], ["arp_eth0", "fe:ff:ff:ff:ff:ff"], ["domain", "eu-west-1.compute.internal"], ["ec2_ami_id", "ami-7acafc0e"], ["ec2_ami_launch_index", "0"], ["ec2_ami_manifest_path", "(unknown)"], ["ec2_block_device_mapping_ami", "/dev/sda1"], ["ec2_block_device_mapping_ephemeral0", "/dev/sdb"], ["ec2_block_device_mapping_root", "/dev/sda1"], ["ec2_hostname", "ip-10-234-151-254.eu-west-1.compute.internal"], ["ec2_instance_id", "i-cc511dba"], ["ec2_instance_type", "t1.micro"], ["ec2_kernel_id", "aki-4feec43b"], ["ec2_local_hostname", "ip-10-234-151-254.eu-west-1.compute.internal"], ["ec2_local_ipv4", "10.234.151.254"], ["ec2_placement_availability_zone", "eu-west-1a"], ["ec2_profile", "default-paravirtual"], ["ec2_public_hostname", "ec2-46-137-37-20.eu-west-1.compute.amazonaws.com"], ["ec2_public_ipv4", "46.137.37.20"], ["ec2_public_keys_0_openssh_key", "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCn6ld1os3dZkdIjJ0zqOUrZWi9zODc2WEaonlPRjyxqhX5nDYJMFrvKRXAIi41TKxwGXzor55gbLb5GnLDFMHEZwtye9MH4n98DdSFu8Nxb9wZgT1xZ+UE/9+GKVAJq77yIWP5qe6iJe80JQAaO/WbinMoqBZ9YOF2MgPNIUoP/bPHZ6Fb+/3Nv1NV+aAMB2vqOlrujcGkI49vFmH6qbNKgAAyuakGSIlBab4PBPti3B+tOoLeimqL4H8iAQAWZCjinG12oUTkl07ZpU1waFUTDaKv4QvwFU4bGgZYk7hysAjE7A8NxI7ApEenbxySnkjew4zQlmPmV21u16E3kGYx node-autoscaling"], ["ec2_reservation_id", "r-7c31b10a"], ["ec2_security_groups", "default"], ["facterversion", "1.5.9"], ["fqdn", "ip-10-234-151-254.eu-west-1.compute.internal"], ["hardwareisa", "unknown"], ["hardwaremodel", "x86_64"], ["hostname", "ip-10-234-151-254"], ["id", "root"], ["interfaces", "dummy0,eql,eth0,ifb0,ifb1,lo"], ["ipaddress", "10.234.151.254"], ["ipaddress_eth0", "10.234.151.254"], ["ipaddress_lo", "127.0.0.1"], ["is_virtual", "true"], ["kernel", "Linux"], ["kernelmajversion", "2.6"], ["kernelrelease", "2.6.32-314-ec2"], ["kernelversion", "2.6.32"], ["lib", "/var/lib/puppet/facts"], ["lsbdistcodename", "lucid"], ["lsbdistdescription", "Ubuntu 10.04.2 LTS"], ["lsbdistid", "Ubuntu"], ["lsbdistrelease", "10.04"], ["lsbmajdistrelease", "10"], ["macaddress", "26:73:1b:a3:48:2a"], ["macaddress_dummy0", "26:73:1b:a3:48:2a"], ["macaddress_eth0", "12:31:3b:05:94:10"], ["macaddress_ifb0", "5e:5b:e7:92:26:c2"], ["macaddress_ifb1", "72:50:ad:1d:a1:0f"], ["memoryfree", "430.29 MB"], ["memorysize", "635.17 MB"], ["netmask", "255.255.254.0"], ["netmask_eth0", "255.255.254.0"], ["netmask_lo", "255.0.0.0"], ["network_eth0", "10.234.150.0"], ["network_lo", "127.0.0.0"], ["operatingsystem", "Ubuntu"], ["operatingsystemrelease", "10.04"], ["path", "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/rvm/bin"], ["physicalprocessorcount", "1"], ["processor0", "Intel(R) Xeon(R) CPU E5430 @ 2.66GHz"], ["processorcount", "1"], ["ps", "ps -ef"], ["puppetversion", "2.6.7"], ["rubysitedir", "/usr/local/lib/ruby/site_ruby/1.8"], ["rubyversion", "1.8.7"], ["selinux", "false"], ["sshdsakey", "AAAAB3NzaC1kc3MAAACBAM2/DHTO3olTFG6lmWXNJcEYKZtFylFWCLJomNEaMMkf7qEtCLSPVWdhgYKHmk/UBPrpuzWrapVa1/eap77CNgQ6e8LmKdcgkCVcuKSLqtm+e989lb9RrcIUYYd4UXIZbLPKF3z3AOmESxikaiQs9M8x4Jn5kmpPb6fixSvOi577AAAAFQDAQMxsywSbD3W28MCI3kfrbKhEPwAAAIBm5HQwsY8VZnfLgWdkpZfcDv2V/9U+0+Atd6O37wpmF4HjIqbIbTJ1ABCXhLgo5oX2YVsRWfVLLxsmgxPoF5CLBNPQcFhNldto4H8sGkcbNFU8oBEiOgnZ6ZEax/Ooe/bO7wR+dz0F5u9IuMj4QK1GWuiAUr7U8E9Ithhe3DVq1QAAAIB3xFxOwbewB9YaeajoTfJDZzt/ovgSD3V4YYgX7mRG8Zv5UW2LduLgifwBJLWVt/Qp44STI1wON2OFRNDvhIH82+5iW3m5ifIy5c8ZviupZVpYy2adw/Ay3+bP/w0TtosmlzyWW7tj2jXVTc79ul3y9uXfZcQw8EB0ISbafy6+2Q=="], ["sshrsakey", "AAAAB3NzaC1yc2EAAAABIwAAAQEAtdvq2CjLz74rL1peJiZakeZtgeJ6lQ1vzCHseSkB3kjsPBMckz9RIec0PrLcY7BmEMfTIJJOq8OrrKdeCauRWQ47tuajVtXr+FXB0U+4FRLs2onBzUI8k2ToY8qNR7TfD5MmirBrYb26S/r0Lm8d86RkkMl4snbwEU0b42e6NbzcjVShAkbGGols7FpziqQWZY4Coo4Z2b2IBLqBZXg4N9laAsR3NlH8JclkUZ34gh5Bnzmr6b/IxTR06aIP0s0W9KEmzuHGv7S/loC1xAgxJMZf/ViLGAGf83jpnp7mMJ5Pbtbbys8tv+Jp4Jobmn/90FkMstkxpoPZX48ImwDfbQ=="], ["swapfree", "0.00 kB"], ["swapsize", "0.00 kB"], ["timezone", "CEST"], ["uniqueid", "ea0afe97"], ["uptime", "4:51 hours"], ["uptime_days", 0], ["uptime_hours", 4], ["uptime_seconds", 17517], ["virtual", "xenu"]]
|
14
|
+
end
|
15
|
+
|
16
|
+
describe :local_ip do
|
17
|
+
it 'on ec2' do
|
18
|
+
@config.stubs(:is_ec2?).returns(true)
|
19
|
+
## require factor or not?
|
20
|
+
#Facter.stubs(:value).with('ec2_public_ipv4').returns('x.x')
|
21
|
+
#@config.local_ip.must_equal 'xx'
|
22
|
+
end
|
23
|
+
|
24
|
+
it "from ip addr, if local_ip_interface" do
|
25
|
+
@config.stubs(:is_ec2?).returns(false)
|
26
|
+
@config.data['local_ip_interface'] = 'something'
|
27
|
+
@config.stubs(:parse_local_ip_from_interface).returns('x.x.x.x')
|
28
|
+
@config.local_ip.must_equal 'x.x.x.x'
|
29
|
+
end
|
30
|
+
|
31
|
+
describe 'otherwise' do
|
32
|
+
it "from local_ip, if present" do
|
33
|
+
@config.stubs(:is_ec2?).returns(false)
|
34
|
+
@config.data['local_ip_interface'] = nil
|
35
|
+
@config.data['local_ip'] = 'x.x.x.y'
|
36
|
+
@config.local_ip.must_equal 'x.x.x.y'
|
37
|
+
end
|
38
|
+
|
39
|
+
it "from ifconfig with 192.168.x.x regex" do
|
40
|
+
|
41
|
+
end
|
42
|
+
it "from ifconfig with 10.10.x.x regex" do
|
43
|
+
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
describe :hostname do
|
49
|
+
it 'read from socket' do
|
50
|
+
Socket.stubs(:gethostname).returns('some_host')
|
51
|
+
@config.hostname.must_equal 'some_host'
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
describe :is_ec2? do
|
56
|
+
it 'works' do
|
57
|
+
@config.stubs(:read_shell).returns(shell_fixture('arp_eth0.txt'))
|
58
|
+
@config.is_ec2?.must_be :>, 0
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
describe :parse_local_ip_from_interface do
|
63
|
+
it 'works' do
|
64
|
+
cmd = "ip addr list #{@config.data['local_ip_interface']}"
|
65
|
+
@config.stubs(:read_shell).with(cmd).returns(shell_fixture('ip_addr_list_eth0.txt'))
|
66
|
+
@config.parse_local_ip_from_interface.must_equal "10.10.10.10"
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
describe :puppet_controller_url do
|
71
|
+
it 'works' do
|
72
|
+
@config.puppet_controller_url.must_equal "http://user:pass@puppet.example.com"
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
describe "puppet_controller_auth" do
|
77
|
+
it "parses the auth info from url" do
|
78
|
+
@config.stubs(:puppet_controller_url).returns('http://user:pass@puppet.example.com')
|
79
|
+
"http://user:pass@puppet.example.com".must_equal(@config.puppet_controller_url)
|
80
|
+
['user', 'pass'].must_equal(@config.puppet_controller_auth)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
describe :lock_file do
|
85
|
+
it "defaults to /tmp/runpuppet.lock" do
|
86
|
+
@config.lock_file.must_equal "/tmp/runpuppet.lock"
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
puppet_controller_url: http://user:pass@puppet.example.com
|
3
|
+
command: 'cd /etc/puppet/repo && git fetch && git checkout -f origin/@@branch@@ && puppet apply /etc/puppet/repo/manifests/site.pp'
|
4
|
+
verbose_command: 'cd /etc/puppet/repo && git fetch && git checkout -f origin/@@branch@@ && /etc/puppet/repo/bin/prepare_environment.rb && puppet apply -v /etc/puppet/repo/manifests/site.pp'
|
5
|
+
branch: master
|
6
|
+
local_ip: 10.10.10.10
|
7
|
+
local_ip_interface: eth0
|
data/test/helper.rb
CHANGED
@@ -13,3 +13,35 @@ require 'mocha'
|
|
13
13
|
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
14
14
|
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
15
15
|
require 'runpuppet'
|
16
|
+
|
17
|
+
def self.fixture_path(path)
|
18
|
+
"test/fixtures/#{path}"
|
19
|
+
end
|
20
|
+
|
21
|
+
|
22
|
+
def create_test_context(options={})
|
23
|
+
ctx = Dim::Container.new
|
24
|
+
|
25
|
+
ctx.register(:config) do
|
26
|
+
Runpuppet::Config.new(fixture_path('runpuppet.yml'))
|
27
|
+
end
|
28
|
+
|
29
|
+
ctx.register(:client) do |context|
|
30
|
+
Runpuppet::Client.new(context)
|
31
|
+
end
|
32
|
+
|
33
|
+
ctx.register(:agent) do |context|
|
34
|
+
Runpuppet::Agent.new(context)
|
35
|
+
end
|
36
|
+
|
37
|
+
ctx.register(:run_options) do
|
38
|
+
{}
|
39
|
+
end
|
40
|
+
|
41
|
+
ctx.register(:logger) do
|
42
|
+
Runpuppet::Logger
|
43
|
+
end
|
44
|
+
return ctx
|
45
|
+
end
|
46
|
+
|
47
|
+
TestContext = create_test_context({})
|
metadata
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: runpuppet
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 3495532457
|
5
5
|
prerelease: 6
|
6
6
|
segments:
|
7
7
|
- 1
|
8
8
|
- 0
|
9
9
|
- 0
|
10
10
|
- rc
|
11
|
-
-
|
12
|
-
version: 1.0.0.
|
11
|
+
- 2
|
12
|
+
version: 1.0.0.rc2
|
13
13
|
platform: ruby
|
14
14
|
authors:
|
15
15
|
- Roman Heinrich
|
@@ -141,8 +141,23 @@ files:
|
|
141
141
|
- Rakefile
|
142
142
|
- VERSION
|
143
143
|
- bin/runpuppet
|
144
|
+
- lib/ext/core.rb
|
144
145
|
- lib/runpuppet.rb
|
146
|
+
- lib/runpuppet/agent.rb
|
147
|
+
- lib/runpuppet/client.rb
|
148
|
+
- lib/runpuppet/config.rb
|
149
|
+
- lib/runpuppet/logger.rb
|
145
150
|
- runpuppet.gemspec
|
151
|
+
- sh/c
|
152
|
+
- sh/console.rb
|
153
|
+
- sh/test
|
154
|
+
- test/agent_test.rb
|
155
|
+
- test/binary_test.rb
|
156
|
+
- test/client_test.rb
|
157
|
+
- test/config_test.rb
|
158
|
+
- test/fixtures/runpuppet.yml
|
159
|
+
- test/fixtures/shell/arp_eth0.txt
|
160
|
+
- test/fixtures/shell/ip_addr_list_eth0.txt
|
146
161
|
- test/helper.rb
|
147
162
|
homepage: http://github.com/dawanda/runpuppet
|
148
163
|
licenses:
|