pawnee 0.1.1 → 0.1.3
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +3 -0
- data/docs/TODO.md +8 -1
- data/lib/pawnee/pawnee/actions/compile.rb +6 -5
- data/lib/pawnee/pawnee/actions/inject_into_file.rb +23 -0
- data/lib/pawnee/pawnee/actions/package.rb +36 -6
- data/lib/pawnee/pawnee/actions/user.rb +57 -10
- data/lib/pawnee/pawnee/base.rb +18 -3
- data/lib/pawnee/pawnee/cli.rb +10 -8
- data/lib/pawnee/pawnee/invocation.rb +1 -0
- data/lib/pawnee/pawnee/setup.rb +3 -3
- data/lib/pawnee/pawnee/ssh_connection.rb +26 -0
- data/lib/pawnee/pawnee/templates/newgem/lib/{pawnee/newgem.rb.tt → newgem.rb.tt} +0 -0
- data/lib/pawnee/pawnee/templates/newgem/lib/pawnee/newgem/base.rb.tt +1 -1
- data/lib/pawnee/pawnee/templates/newgem/newgem.gemspec.tt +1 -1
- data/lib/pawnee/pawnee/templates/newgem/spec/base_spec.rb.tt +12 -0
- data/lib/pawnee/pawnee/version.rb +1 -1
- data/spec/actions/compile_spec.rb +3 -8
- data/spec/actions/inject_into_file_spec.rb +16 -0
- data/spec/actions/user_spec.rb +6 -3
- data/spec/base_spec.rb +3 -3
- data/spec/spec_helper.rb +1 -1
- data/spec/vagrant/.vagrant +1 -1
- metadata +10 -6
- data/lib/pawnee/pawnee/templates/newgem/bin/newgem.tt +0 -3
data/README.md
CHANGED
@@ -34,6 +34,9 @@ This system will:
|
|
34
34
|
- but deploying should be a separate thing (not like rubber)
|
35
35
|
6. **It should use thor for template stuff**
|
36
36
|
- and just overwrite it so files get copied to remote destinations if needed
|
37
|
+
7. **It should be able to go up to root**
|
38
|
+
- you should be able to login as one user and as long as they are a sudoer all
|
39
|
+
commands should be able to jump up to root when needed
|
37
40
|
|
38
41
|
|
39
42
|
A note on idempotence. Being idempotent is a big selling point for chef. Pawnee strives for idempotence but provides it in different ways. For example, where chef would provide a more dsl like way to declare what to do when changes are made, pawnee tries to avoid too much DSL, so the recipe developer will need to be aware that the task may be run multiple times. We find that either way the recipe developer needs to understand this situation, and with the Pawnee way, its made clearer in the code.
|
data/docs/TODO.md
CHANGED
@@ -9,7 +9,14 @@ TODO: Need to make a clear way for pawnee gems (and recipes) to provide actions
|
|
9
9
|
TODO: Run actions in threads (across multiple servers)
|
10
10
|
TODO: Test to make sure arguments work directly as well (they probably don't right now)
|
11
11
|
TODO: System to check for and register updates/modifications
|
12
|
-
TODO: Add apt-get update to package stuff
|
12
|
+
TODO: Add apt-get update to package stuff - make it only run update once per all jobs
|
13
|
+
TODO: Make it so copied files can be overridden in a rails project
|
14
|
+
TODO: Track modified on compile?
|
15
|
+
TODO: Should setup self.source_root to point to the templates dir in the gem
|
16
|
+
TODO: Add --verbose option that shows the output of any outputs (bundler for example)
|
17
|
+
- maybe show stderr by default?
|
18
|
+
- maybe option to show on run/exec
|
19
|
+
- show stderr when there's a non-0 exit status
|
13
20
|
|
14
21
|
|
15
22
|
def setup
|
@@ -21,7 +21,8 @@ module Pawnee
|
|
21
21
|
# installed
|
22
22
|
#
|
23
23
|
# :bin_file - the name of an executable that the method can check for in the path
|
24
|
-
# :
|
24
|
+
# :config_options - a string of options to pass to the ./configure command.
|
25
|
+
# :skip_configure - skips the configure step
|
25
26
|
#
|
26
27
|
# === Block
|
27
28
|
# You can also pass a block that if it returns true, it will not
|
@@ -34,7 +35,7 @@ module Pawnee
|
|
34
35
|
installed = false
|
35
36
|
if options[:bin_file]
|
36
37
|
# Check if the bin file is installed
|
37
|
-
installed = exec(options[:bin_file]).strip != ''
|
38
|
+
installed = exec("which #{options[:bin_file]}").strip != ''
|
38
39
|
else
|
39
40
|
raise "You must pass :bin_file or a block to compile" unless block_given?
|
40
41
|
installed = yield()
|
@@ -76,7 +77,7 @@ module Pawnee
|
|
76
77
|
|
77
78
|
download(url)
|
78
79
|
extract
|
79
|
-
configure
|
80
|
+
configure unless options[:skip_configure]
|
80
81
|
make
|
81
82
|
make_install
|
82
83
|
end
|
@@ -108,7 +109,7 @@ module Pawnee
|
|
108
109
|
# action_name<String>:: An action name (used to explain what is happening)
|
109
110
|
def run_with_failure_handler(command, action_name)
|
110
111
|
base.say_status action_name.downcase, ''
|
111
|
-
stdout, stderr, exit_code, exit_status = base.exec(command, true)
|
112
|
+
stdout, stderr, exit_code, exit_status = base.exec(command, :with_codes => true)
|
112
113
|
|
113
114
|
if exit_code != 0
|
114
115
|
base.say_status :error, "Unable to #{action_name}, see output below", :red
|
@@ -121,7 +122,7 @@ module Pawnee
|
|
121
122
|
|
122
123
|
# Runs ./configure on the files
|
123
124
|
def configure
|
124
|
-
run_with_failure_handler("cd #{@extracted_path} ; ./configure #{options[:
|
125
|
+
run_with_failure_handler("cd #{@extracted_path} ; ./configure #{options[:config_options] || ''}", 'configure')
|
125
126
|
end
|
126
127
|
|
127
128
|
# Runs make
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Pawnee
|
2
|
+
module Actions
|
3
|
+
# Adds a :once option that will only do the action the first
|
4
|
+
# time it is run (it will check for the text before it injects
|
5
|
+
# it each time)
|
6
|
+
def insert_into_file(destination, *args, &block)
|
7
|
+
if block_given?
|
8
|
+
data, config = block, args.shift
|
9
|
+
else
|
10
|
+
data, config = args.shift, args.shift
|
11
|
+
end
|
12
|
+
|
13
|
+
if config[:once]
|
14
|
+
if destination_files.binread(destination)[data]
|
15
|
+
# Don't run again, the text is already in place
|
16
|
+
return
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
action InjectIntoFile.new(self, destination, data, config)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -31,7 +31,7 @@ module Pawnee
|
|
31
31
|
def installed_package_version(package_name)
|
32
32
|
packages = nil
|
33
33
|
as_root do
|
34
|
-
packages = exec("dpkg -l")
|
34
|
+
packages = exec("dpkg -l", :no_pty => true)
|
35
35
|
end
|
36
36
|
|
37
37
|
packages.split(/\n/).grep(/^ii /).each do |package|
|
@@ -55,17 +55,33 @@ module Pawnee
|
|
55
55
|
# package_name<String>:: The name of package to be installed
|
56
56
|
# version<String>:: The version of the package
|
57
57
|
def install_package(package_name, version=nil)
|
58
|
+
update_package_list
|
59
|
+
|
58
60
|
if package_installed?(package_name)
|
59
61
|
say_status "package already installed", package_name
|
60
62
|
else
|
61
63
|
package_name = "#{package_name}=#{version}" if version
|
64
|
+
track_modification!
|
62
65
|
as_root do
|
63
|
-
exec("apt-get -y install #{package_name}")
|
66
|
+
exec("DEBIAN_FRONTEND=noninteractive apt-get -q -y install #{package_name}", :no_pty => true)
|
64
67
|
end
|
65
68
|
say_status "installed package", package_name.gsub('=', ' ')
|
66
69
|
end
|
67
70
|
end
|
68
71
|
|
72
|
+
# Updates the package manager to the most recent list of
|
73
|
+
# packages. Also only runs this once per group of operations
|
74
|
+
# to prevent this from happening too much.
|
75
|
+
def update_package_list
|
76
|
+
# TODO: this needs to be per server
|
77
|
+
unless defined?(@@packages_updated)
|
78
|
+
@@packages_updated = true
|
79
|
+
as_root do
|
80
|
+
exec('DEBIAN_FRONTEND=noninteractive apt-get -q -y update', :no_pty => true)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
69
85
|
# Installs a set of packages, use install_package if you
|
70
86
|
# wish to specify a version
|
71
87
|
#
|
@@ -75,9 +91,22 @@ module Pawnee
|
|
75
91
|
# packages<Array>:: An array of strings of package names
|
76
92
|
def install_packages(*package_names)
|
77
93
|
packages = nil
|
94
|
+
# # TODO: pull in versions and use this to get a better
|
95
|
+
#
|
96
|
+
# as_root do
|
97
|
+
# packages = exec("dpkg --get-selections", :no_pty => true)
|
98
|
+
# end
|
99
|
+
#
|
100
|
+
# installed_package_names = []
|
101
|
+
# packages.split(/\n/).each do |package|
|
102
|
+
# name, version = package.split(/\s+/)
|
103
|
+
# installed_package_names << name
|
104
|
+
# end
|
105
|
+
|
106
|
+
|
78
107
|
as_root do
|
79
|
-
|
80
|
-
packages = exec("dpkg -l")
|
108
|
+
update_package_list
|
109
|
+
packages = exec("dpkg -l", :no_pty => true)
|
81
110
|
end
|
82
111
|
|
83
112
|
installed_package_names = []
|
@@ -97,9 +126,10 @@ module Pawnee
|
|
97
126
|
end
|
98
127
|
|
99
128
|
if need_to_install_packages.size > 0
|
129
|
+
track_modification!
|
100
130
|
as_root do
|
101
131
|
say_status "installing packages", need_to_install_packages.join(', ')
|
102
|
-
exec("apt-get -y install #{need_to_install_packages.join(' ')}")
|
132
|
+
exec("DEBIAN_FRONTEND=noninteractive apt-get -q -y install #{need_to_install_packages.join(' ')}", :no_pty => true)
|
103
133
|
end
|
104
134
|
end
|
105
135
|
end
|
@@ -112,7 +142,7 @@ module Pawnee
|
|
112
142
|
if package_installed?(package_name)
|
113
143
|
say_status "removed package", package_name
|
114
144
|
as_root do
|
115
|
-
exec("apt-get -y remove #{package_name}")
|
145
|
+
exec("DEBIAN_FRONTEND=noninteractive apt-get -q -y remove #{package_name}", :no_pty => true)
|
116
146
|
end
|
117
147
|
else
|
118
148
|
say_status "package not removed", package_name
|
@@ -40,8 +40,8 @@ module Pawnee
|
|
40
40
|
#
|
41
41
|
#
|
42
42
|
class User < BaseModel
|
43
|
-
define_attribute_methods [:login, :uid, :gid, :groups, :comment, :shell, :password]
|
44
|
-
change_attr_accessor [:login, :uid, :gid, :groups, :comment, :shell, :password]
|
43
|
+
define_attribute_methods [:login, :uid, :gid, :groups, :comment, :shell, :password, :home]
|
44
|
+
change_attr_accessor [:login, :uid, :gid, :groups, :comment, :shell, :password, :home]
|
45
45
|
|
46
46
|
attr_accessor :base
|
47
47
|
|
@@ -66,52 +66,99 @@ module Pawnee
|
|
66
66
|
return base.run(*args)
|
67
67
|
end
|
68
68
|
|
69
|
+
def passwd_data(find_user)
|
70
|
+
passwd_data = base.destination_files.binread('/etc/passwd')
|
71
|
+
|
72
|
+
if passwd_data
|
73
|
+
passwd_data.split(/\n/).each do |line|
|
74
|
+
user, *_, home, shell = line.split(':')
|
75
|
+
|
76
|
+
if user == find_user
|
77
|
+
return home, shell
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
return nil, nil
|
83
|
+
end
|
84
|
+
|
85
|
+
def home_for_user(find_user)
|
86
|
+
home, shell = passwd_data(find_user)
|
87
|
+
return home
|
88
|
+
end
|
89
|
+
|
90
|
+
def shell_for_user(find_user)
|
91
|
+
home, shell = passwd_data(find_user)
|
92
|
+
return shell
|
93
|
+
end
|
94
|
+
|
69
95
|
# Pull in the current (starting) state of the attributes
|
70
96
|
# for the User model
|
71
97
|
def read_from_system
|
72
|
-
@uid, stderr, exit_code, _ = exec("id -u #{login}", true)
|
98
|
+
@uid, stderr, exit_code, _ = exec("id -u #{login}", :with_codes => true, :log_stderr => false, :no_pty => true)
|
73
99
|
@uid = @uid.strip
|
74
100
|
if exit_code == 0
|
75
101
|
# The login exists, load in more data
|
76
|
-
@gid = exec("id -g #{login}").strip
|
77
|
-
|
102
|
+
@gid = exec("id -g #{login}", :log_stderr => false, :no_pty => true).strip
|
103
|
+
|
104
|
+
@groups = exec("groups #{login}", :no_pty => true).gsub(/^[^:]+[:]/, '').strip.split(/ /).sort
|
105
|
+
@home = home_for_user(login)
|
106
|
+
|
107
|
+
# TODO: Load in existing shell
|
108
|
+
@shell = shell_for_user(login)
|
78
109
|
self.new_record = false
|
79
110
|
|
80
111
|
# Reject any ones we just changed, so its as if we did a find with these
|
81
112
|
@changed_attributes = @changed_attributes.reject {|k,v| [:uid, :gid, :groups, :login].include?(k.to_sym) }
|
113
|
+
@original_groups_value = @groups
|
82
114
|
else
|
83
115
|
# No user
|
84
116
|
@uid = nil
|
117
|
+
@groups ||= []
|
118
|
+
@shell ||= '/bin/bash'
|
119
|
+
self.shell_will_change!
|
85
120
|
self.new_record = true
|
86
121
|
end
|
87
122
|
end
|
88
123
|
|
89
124
|
# Write any changes out
|
90
125
|
def save
|
126
|
+
# Since groups is an array, we have to manually check to see if
|
127
|
+
# its changed, because people can do << to it
|
128
|
+
if @original_groups_value != @groups
|
129
|
+
# Mark as changed
|
130
|
+
self.groups_will_change!
|
131
|
+
|
132
|
+
@original_groups_value = @groups
|
133
|
+
end
|
134
|
+
|
91
135
|
if changed?
|
92
136
|
raise "A login must be specified" unless login
|
93
137
|
|
94
138
|
if new_record?
|
95
139
|
# Just create a new user
|
96
140
|
command = ["useradd"]
|
97
|
-
base.say_status :create_user, login
|
141
|
+
base.say_status :create_user, login, :green
|
98
142
|
else
|
99
143
|
# Modify an existing user
|
100
144
|
command = ["usermod"]
|
101
|
-
base.say_status :update_user, login
|
145
|
+
base.say_status :update_user, login, :green
|
102
146
|
end
|
103
147
|
|
104
148
|
# Set options
|
105
149
|
command << "-u #{uid}" if uid && uid_changed?
|
106
150
|
command << "-g #{gid}" if gid && gid_changed?
|
107
|
-
command << "-G #{groups.join(',')}" if groups && groups_changed?
|
151
|
+
command << "-G #{groups.join(',')}" if groups && groups_changed? && groups.size != 0
|
108
152
|
command << "-c #{comment.inspect}" if comment && comment_changed?
|
109
153
|
command << "-s #{shell.inspect}" if shell && shell_changed?
|
110
154
|
command << "-p #{password.inspect}" if password && password_changed?
|
155
|
+
|
156
|
+
# TODO: If update, we need to make the directory first to move things to
|
157
|
+
command << "-m -d #{home.inspect}" if home && home_changed?
|
111
158
|
command << login
|
112
159
|
|
113
160
|
base.as_root do
|
114
|
-
base.exec(command.join(' '))
|
161
|
+
base.exec(command.join(' '), :no_pty => true)
|
115
162
|
end
|
116
163
|
else
|
117
164
|
base.say_status :user_exists, login, :blue
|
@@ -121,7 +168,7 @@ module Pawnee
|
|
121
168
|
def destroy
|
122
169
|
self.new_record = true
|
123
170
|
base.as_root do
|
124
|
-
base.exec("userdel #{login}")
|
171
|
+
base.exec("userdel #{login}", :no_pty => true)
|
125
172
|
end
|
126
173
|
end
|
127
174
|
end
|
data/lib/pawnee/pawnee/base.rb
CHANGED
@@ -9,6 +9,7 @@ require 'active_support/core_ext/hash/deep_merge'
|
|
9
9
|
require 'pawnee/roles'
|
10
10
|
require 'pawnee/invocation'
|
11
11
|
require 'pawnee/modified'
|
12
|
+
require 'pawnee/ssh_connection'
|
12
13
|
|
13
14
|
module Pawnee
|
14
15
|
# The pawnee gem provides the Pawnee::Base class, which includes actions
|
@@ -21,6 +22,7 @@ module Pawnee
|
|
21
22
|
include Pawnee::Actions
|
22
23
|
include Pawnee::Invocation
|
23
24
|
include Pawnee::Modified
|
25
|
+
include Pawnee::SshConnection
|
24
26
|
include Roles
|
25
27
|
|
26
28
|
attr_accessor :server
|
@@ -113,7 +115,7 @@ module Pawnee
|
|
113
115
|
|
114
116
|
# Guess the gem name based on the class name
|
115
117
|
def self.gem_name
|
116
|
-
self.name.gsub(/[:][:]Base$/, '').gsub(/^[^:]+[:][:]/, '').gsub('
|
118
|
+
self.name.gsub(/[:][:]Base$/, '').gsub(/^[^:]+[:][:]/, '').gsub(/([A-Z]+)([A-Z][a-z])/,'\1-\2').gsub(/([a-z\d])([A-Z])/,'\1-\2').downcase
|
117
119
|
end
|
118
120
|
|
119
121
|
no_tasks {
|
@@ -122,6 +124,10 @@ module Pawnee
|
|
122
124
|
def invoke_task(task, *args) #:nodoc:
|
123
125
|
current = @_invocations[self.class]
|
124
126
|
|
127
|
+
# Default force for actions in options
|
128
|
+
# TODO: Should this get set in invoke?
|
129
|
+
options[:force] ||= true
|
130
|
+
|
125
131
|
unless current.include?(task.name)
|
126
132
|
current << task.name
|
127
133
|
|
@@ -178,9 +184,15 @@ module Pawnee
|
|
178
184
|
# Whenever say is used, also print out the server name
|
179
185
|
def say(*args)
|
180
186
|
text = args[0]
|
181
|
-
text = "[#{server}]:\t" + text
|
187
|
+
text = "[#{server}]:\t" + text.to_s if server
|
182
188
|
super(text, *args[1..-1])
|
183
189
|
end
|
190
|
+
|
191
|
+
def say_status(*args)
|
192
|
+
text = args[0]
|
193
|
+
text = "[#{server}]:\t" + text.to_s if server
|
194
|
+
super(text, *args[1..-1])
|
195
|
+
end
|
184
196
|
}
|
185
197
|
|
186
198
|
private
|
@@ -220,7 +232,7 @@ module Pawnee
|
|
220
232
|
super(subclass)
|
221
233
|
|
222
234
|
# Make sure cli has been loaded at this point
|
223
|
-
require 'pawnee/cli'
|
235
|
+
require 'pawnee/cli' unless defined?(Pawnee) && defined?(Pawnee::CLI)
|
224
236
|
|
225
237
|
# Skip the main CLI class
|
226
238
|
return if subclass == Pawnee::CLI
|
@@ -240,6 +252,7 @@ module Pawnee
|
|
240
252
|
subclass.role(class_name)
|
241
253
|
end
|
242
254
|
|
255
|
+
|
243
256
|
def self.recipes
|
244
257
|
@recipes
|
245
258
|
end
|
@@ -271,6 +284,8 @@ module Pawnee
|
|
271
284
|
def self.method_added(meth)
|
272
285
|
super
|
273
286
|
|
287
|
+
require 'pawnee/cli' unless defined?(Pawnee) && defined?(Pawnee::CLI)
|
288
|
+
|
274
289
|
# Take all of the setup options and copy them to the main
|
275
290
|
# CLI setup task
|
276
291
|
meth = meth.to_s
|
data/lib/pawnee/pawnee/cli.rb
CHANGED
@@ -33,17 +33,18 @@ module Pawnee
|
|
33
33
|
method_option :bin, :type => :boolean, :default => false, :aliases => '-b', :banner => "Generate a binary for your library."
|
34
34
|
def gem(name)
|
35
35
|
# Prefix all gems with pawnee-
|
36
|
-
|
37
|
-
folder_name = name
|
38
|
-
target = File.join(Dir.pwd,
|
39
|
-
constant_name = name.split('
|
40
|
-
|
36
|
+
dir_name = 'pawnee-' + name.chomp("/") # remove trailing slash if present
|
37
|
+
folder_name = "pawnee/" + name
|
38
|
+
target = File.join(Dir.pwd, dir_name)
|
39
|
+
constant_name = "Pawnee::" + name.split('-').map{|q| q[0..0].upcase + q[1..-1] }.join('')
|
40
|
+
puts constant_name
|
41
41
|
constant_array = constant_name.split('::')
|
42
|
+
puts constant_array.inspect
|
42
43
|
git_user_name = `git config user.name`.chomp
|
43
44
|
git_user_email = `git config user.email`.chomp
|
44
45
|
opts = {
|
45
46
|
# Don't require the pawnee- when requring though
|
46
|
-
:name => name
|
47
|
+
:name => name,
|
47
48
|
:constant_name => constant_name,
|
48
49
|
:constant_array => constant_array,
|
49
50
|
:author => git_user_name.empty? ? "TODO: Write your name" : git_user_name,
|
@@ -54,11 +55,12 @@ module Pawnee
|
|
54
55
|
template(File.join("newgem/LICENSE.tt"), File.join(target, "LICENSE"), opts)
|
55
56
|
template(File.join("newgem/README.md.tt"), File.join(target, "README.md"), opts)
|
56
57
|
template(File.join("newgem/gitignore.tt"), File.join(target, ".gitignore"), opts)
|
57
|
-
template(File.join("newgem/newgem.gemspec.tt"), File.join(target, "#{
|
58
|
-
template(File.join("newgem/lib/
|
58
|
+
template(File.join("newgem/newgem.gemspec.tt"), File.join(target, "#{dir_name}.gemspec"), opts)
|
59
|
+
template(File.join("newgem/lib/newgem.rb.tt"), File.join(target, "lib/#{dir_name}.rb"), opts)
|
59
60
|
template(File.join("newgem/lib/pawnee/newgem/version.rb.tt"), File.join(target, "lib/#{folder_name}/version.rb"), opts)
|
60
61
|
template(File.join("newgem/lib/pawnee/newgem/base.rb.tt"), File.join(target, "lib/#{folder_name}/base.rb"), opts)
|
61
62
|
template(File.join("newgem/spec/spec_helper.rb.tt"), File.join(target, "spec/spec_helper.rb"), opts)
|
63
|
+
template(File.join("newgem/spec/base_spec.rb.tt"), File.join(target, "spec/base_spec.rb"), opts)
|
62
64
|
template(File.join("newgem/spec/vagrant/Vagrantfile.tt"), File.join(target, "spec/vagrant/Vagrantfile"), opts)
|
63
65
|
template(File.join("newgem/spec/vagrant/vagrant.rb.tt"), File.join(target, "spec/vagrant/vagrant.rb"), opts)
|
64
66
|
if options[:bin]
|
data/lib/pawnee/pawnee/setup.rb
CHANGED
@@ -3,16 +3,16 @@ require 'thor'
|
|
3
3
|
# Add setup to the base class
|
4
4
|
module Pawnee
|
5
5
|
class Base < Thor
|
6
|
-
if defined?(Rails)
|
6
|
+
if defined?(Rails) && defined?(Rails::Railtie)
|
7
7
|
class Railtie < Rails::Railtie
|
8
8
|
end
|
9
9
|
end
|
10
10
|
|
11
11
|
def self.setup(gem_name)
|
12
12
|
# Setup the railtie
|
13
|
-
require "
|
13
|
+
require "pawnee/#{gem_name.gsub(/^pawnee[-]/, '')}/base"
|
14
14
|
|
15
|
-
if defined?(Rails)
|
15
|
+
if defined?(Rails) && defined?(Rails::Railtie)
|
16
16
|
Railtie.initializer "#{gem_name}.configure_rails_initialization" do
|
17
17
|
gem_recipie_name = gem_name.gsub(/^pawnee[-]/, '')
|
18
18
|
require "#{gem_recipie_name}/base"
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Pawnee
|
2
|
+
module SshConnection
|
3
|
+
# Reconnects to the remote server (using net/ssh).
|
4
|
+
# This is useful since often things in linux don't take effect
|
5
|
+
# until the user creates a new login shell (adding a user to
|
6
|
+
# a group for example)
|
7
|
+
def reconnect!
|
8
|
+
host = self.destination_connection.host
|
9
|
+
options = self.destination_connection.options
|
10
|
+
user = options[:user]
|
11
|
+
|
12
|
+
# Close the existing connection
|
13
|
+
self.destination_connection.close
|
14
|
+
|
15
|
+
# Reconnect
|
16
|
+
new_connection = Net::SSH.start(host, user, options)
|
17
|
+
|
18
|
+
# Copy the instance variables to the old conection so we can keep using
|
19
|
+
# the same session without reassigning references
|
20
|
+
self.destination_connection.instance_variables.each do |variable_name|
|
21
|
+
value = new_connection.instance_variable_get(variable_name)
|
22
|
+
self.destination_connection.instance_variable_set(variable_name, value)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
File without changes
|
@@ -12,7 +12,7 @@ Gem::Specification.new do |gem|
|
|
12
12
|
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
13
13
|
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
14
14
|
gem.name = "pawnee-<%=config[:name]%>"
|
15
|
-
gem.require_paths = ["lib
|
15
|
+
gem.require_paths = ["lib"]
|
16
16
|
gem.add_runtime_dependency 'pawnee'
|
17
17
|
|
18
18
|
# Pawnee development dependencies - versions for these will
|
@@ -0,0 +1,12 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'pawnee/<%=config[:name]%>/base'
|
3
|
+
|
4
|
+
describe Pawnee::<%=config[:name].capitalize %>::Base do
|
5
|
+
it "should install <%=config[:name]%>" do
|
6
|
+
connection = VagrantManager.connect
|
7
|
+
|
8
|
+
Pawnee::Base.invoke_roles(:setup, ['<%=config[:name]%>'], {:servers => [connection], :roles => ['<%=config[:name]%>']})
|
9
|
+
|
10
|
+
connection.close unless connection.closed?
|
11
|
+
end
|
12
|
+
end
|
@@ -10,16 +10,11 @@ describe "compile actions" do
|
|
10
10
|
end
|
11
11
|
|
12
12
|
it 'should install a package' do
|
13
|
-
@base.
|
14
|
-
@base.as_root do
|
15
|
-
@base.exec('rm /usr/local/sbin/nginx')
|
16
|
-
end
|
13
|
+
@base.exec('which redis-server').should == ''
|
17
14
|
|
18
|
-
@base.
|
15
|
+
@base.compile('http://redis.googlecode.com/files/redis-2.4.15.tar.gz', '/home/vagrant/redis-server/', {:skip_configure => true, :bin_file => 'redis-server'})
|
19
16
|
|
20
|
-
@base.
|
21
|
-
|
22
|
-
@base.exec('which nginx').should_not == ''
|
17
|
+
@base.exec('which redis-server').should_not == ''
|
23
18
|
end
|
24
19
|
|
25
20
|
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'pawnee/base'
|
3
|
+
|
4
|
+
|
5
|
+
# NOTE: These are designed to run in order on vagrant
|
6
|
+
describe "inject into file" do
|
7
|
+
before do
|
8
|
+
@base = Pawnee::Base.new
|
9
|
+
@base.destination_connection = VagrantManager.connect
|
10
|
+
end
|
11
|
+
|
12
|
+
it "should only inject once if the once option is specified" do
|
13
|
+
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
data/spec/actions/user_spec.rb
CHANGED
@@ -10,7 +10,7 @@ describe "user actions" do
|
|
10
10
|
end
|
11
11
|
|
12
12
|
def user_exists?(login)
|
13
|
-
_, _, exit_code, _ = @base.exec("id -u #{login}", true)
|
13
|
+
_, _, exit_code, _ = @base.exec("id -u #{login}", :with_codes => true)
|
14
14
|
return exit_code == 0
|
15
15
|
end
|
16
16
|
|
@@ -32,8 +32,8 @@ describe "user actions" do
|
|
32
32
|
end
|
33
33
|
|
34
34
|
it "should modify a user" do
|
35
|
-
# @base.should_receive(:exec).any_number_of_times.ordered.with('id -u blue', true).and_return(["1002\n", '', 0, nil])
|
36
|
-
# @base.should_receive(:exec).any_number_of_times.ordered.with('id -u blue', true).and_return(["1002\n", '', 0, nil])
|
35
|
+
# @base.should_receive(:exec).any_number_of_times.ordered.with('id -u blue', :with_codes => true).and_return(["1002\n", '', 0, nil])
|
36
|
+
# @base.should_receive(:exec).any_number_of_times.ordered.with('id -u blue', :with_codes => true).and_return(["1002\n", '', 0, nil])
|
37
37
|
# @base.should_receive(:exec).any_number_of_times.ordered.with('id -g blue').and_return("1002\n")
|
38
38
|
# @base.should_receive(:exec).any_number_of_times.ordered.with('groups blue').and_return("blue: blue")
|
39
39
|
# @base.should_receive(:exec).once.ordered.with('useradd -c "comment" blue').and_return('')
|
@@ -44,6 +44,9 @@ describe "user actions" do
|
|
44
44
|
)
|
45
45
|
end
|
46
46
|
|
47
|
+
# TODO: Test when there is no groups
|
48
|
+
# TODO: Test default shell
|
49
|
+
|
47
50
|
it "should delete a user" do
|
48
51
|
user_exists?('blue').should == true
|
49
52
|
|
data/spec/base_spec.rb
CHANGED
@@ -106,7 +106,7 @@ describe Pawnee::Base do
|
|
106
106
|
'servers' => [
|
107
107
|
{'domain' => 'test1.com', 'roles' => ['red']},
|
108
108
|
{'domain' => 'test2.com', 'roles' => ['blue', 'red']}
|
109
|
-
]
|
109
|
+
], 'force' => true
|
110
110
|
}
|
111
111
|
|
112
112
|
Pawnee::Base.should_receive(:config_options).at_least(:once).and_return(config_options)
|
@@ -130,7 +130,7 @@ describe Pawnee::Base do
|
|
130
130
|
'servers' => [
|
131
131
|
{'domain' => 'test1.com', 'roles' => ['red']},
|
132
132
|
{'domain' => 'test2.com', 'roles' => ['red']}
|
133
|
-
]
|
133
|
+
], 'force' => true
|
134
134
|
}
|
135
135
|
|
136
136
|
Pawnee::Base.should_receive(:config_options).at_least(:once).and_return(options)
|
@@ -151,7 +151,7 @@ describe Pawnee::Base do
|
|
151
151
|
'servers' => [
|
152
152
|
{'domain' => 'test1.com', 'roles' => ['red']},
|
153
153
|
{'domain' => 'test2.com', 'roles' => ['red', 'blue']}
|
154
|
-
]
|
154
|
+
], 'force' => true
|
155
155
|
}
|
156
156
|
|
157
157
|
Pawnee::Base.should_receive(:config_options).at_least(:once).and_return(options)
|
data/spec/spec_helper.rb
CHANGED
@@ -20,7 +20,7 @@ RSpec.configure do |config|
|
|
20
20
|
unless ENV['TRAVIS']
|
21
21
|
# Rollback the server
|
22
22
|
puts "Roll back test server"
|
23
|
-
`cd spec/vagrant/ ; BUNDLE_GEMFILE=../../Gemfile bundle exec vagrant sandbox rollback`
|
23
|
+
# `cd spec/vagrant/ ; BUNDLE_GEMFILE=../../Gemfile bundle exec vagrant sandbox rollback`
|
24
24
|
end
|
25
25
|
end
|
26
26
|
end
|
data/spec/vagrant/.vagrant
CHANGED
@@ -1 +1 @@
|
|
1
|
-
{"active":{"default":"
|
1
|
+
{"active":{"default":"c90bb8aa-bba5-4bdf-98e8-5097a58829c8"}}
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pawnee
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.3
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-06-
|
12
|
+
date: 2012-06-26 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: bundler
|
@@ -258,6 +258,7 @@ files:
|
|
258
258
|
- lib/pawnee/pawnee/actions.rb
|
259
259
|
- lib/pawnee/pawnee/actions/base_model.rb
|
260
260
|
- lib/pawnee/pawnee/actions/compile.rb
|
261
|
+
- lib/pawnee/pawnee/actions/inject_into_file.rb
|
261
262
|
- lib/pawnee/pawnee/actions/package.rb
|
262
263
|
- lib/pawnee/pawnee/actions/user.rb
|
263
264
|
- lib/pawnee/pawnee/base.rb
|
@@ -268,16 +269,17 @@ files:
|
|
268
269
|
- lib/pawnee/pawnee/railtie.rb
|
269
270
|
- lib/pawnee/pawnee/roles.rb
|
270
271
|
- lib/pawnee/pawnee/setup.rb
|
272
|
+
- lib/pawnee/pawnee/ssh_connection.rb
|
271
273
|
- lib/pawnee/pawnee/templates/newgem/Gemfile.tt
|
272
274
|
- lib/pawnee/pawnee/templates/newgem/LICENSE.tt
|
273
275
|
- lib/pawnee/pawnee/templates/newgem/README.md.tt
|
274
276
|
- lib/pawnee/pawnee/templates/newgem/Rakefile.tt
|
275
|
-
- lib/pawnee/pawnee/templates/newgem/bin/newgem.tt
|
276
277
|
- lib/pawnee/pawnee/templates/newgem/gitignore.tt
|
277
|
-
- lib/pawnee/pawnee/templates/newgem/lib/
|
278
|
+
- lib/pawnee/pawnee/templates/newgem/lib/newgem.rb.tt
|
278
279
|
- lib/pawnee/pawnee/templates/newgem/lib/pawnee/newgem/base.rb.tt
|
279
280
|
- lib/pawnee/pawnee/templates/newgem/lib/pawnee/newgem/version.rb.tt
|
280
281
|
- lib/pawnee/pawnee/templates/newgem/newgem.gemspec.tt
|
282
|
+
- lib/pawnee/pawnee/templates/newgem/spec/base_spec.rb.tt
|
281
283
|
- lib/pawnee/pawnee/templates/newgem/spec/spec_helper.rb.tt
|
282
284
|
- lib/pawnee/pawnee/templates/newgem/spec/vagrant/Vagrantfile.tt
|
283
285
|
- lib/pawnee/pawnee/templates/newgem/spec/vagrant/vagrant.rb.tt
|
@@ -285,6 +287,7 @@ files:
|
|
285
287
|
- pawnee.gemspec
|
286
288
|
- spec/actions/compile_spec.rb
|
287
289
|
- spec/actions/file_spec.rb
|
290
|
+
- spec/actions/inject_into_file_spec.rb
|
288
291
|
- spec/actions/package_spec.rb
|
289
292
|
- spec/actions/user_spec.rb
|
290
293
|
- spec/base_spec.rb
|
@@ -307,7 +310,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
307
310
|
version: '0'
|
308
311
|
segments:
|
309
312
|
- 0
|
310
|
-
hash:
|
313
|
+
hash: 2154589448393807289
|
311
314
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
312
315
|
none: false
|
313
316
|
requirements:
|
@@ -316,7 +319,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
316
319
|
version: '0'
|
317
320
|
segments:
|
318
321
|
- 0
|
319
|
-
hash:
|
322
|
+
hash: 2154589448393807289
|
320
323
|
requirements: []
|
321
324
|
rubyforge_project:
|
322
325
|
rubygems_version: 1.8.22
|
@@ -326,6 +329,7 @@ summary: Better server provisioing
|
|
326
329
|
test_files:
|
327
330
|
- spec/actions/compile_spec.rb
|
328
331
|
- spec/actions/file_spec.rb
|
332
|
+
- spec/actions/inject_into_file_spec.rb
|
329
333
|
- spec/actions/package_spec.rb
|
330
334
|
- spec/actions/user_spec.rb
|
331
335
|
- spec/base_spec.rb
|