knife-solo 0.1.0.pre1 → 0.1.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/CHANGELOG.md +29 -10
- data/README.rdoc +3 -6
- data/Rakefile +51 -3
- data/lib/chef/knife/patches/parser.rb +32 -20
- data/lib/chef/knife/patches/search.rb +110 -0
- data/lib/chef/knife/solo_cook.rb +23 -12
- data/lib/chef/knife/solo_init.rb +0 -2
- data/lib/chef/knife/solo_prepare.rb +6 -6
- data/lib/knife-solo/bootstraps.rb +3 -3
- data/lib/knife-solo/bootstraps/linux.rb +11 -9
- data/lib/knife-solo/info.rb +1 -1
- data/lib/knife-solo/node_config_command.rb +13 -13
- data/lib/knife-solo/ssh_command.rb +15 -15
- data/test/integration/cases/apache2_bootstrap.rb +0 -1
- data/test/integration/cases/apache2_cook.rb +2 -3
- data/test/integration/centos5_6_test.rb +0 -4
- data/test/integration_helper.rb +2 -3
- data/test/solo_cook_test.rb +16 -0
- data/test/support/ec2_runner.rb +1 -0
- data/test/test_helper.rb +3 -3
- metadata +93 -18
- data/lib/chef/knife/patches/search_patch.rb +0 -81
data/CHANGELOG.md
CHANGED
@@ -1,24 +1,39 @@
|
|
1
|
-
# 0.1.0:
|
1
|
+
# 0.1.0: January 12, 2013
|
2
2
|
|
3
|
-
##
|
4
|
-
|
5
|
-
* Cleaner bootstrap code
|
6
|
-
* Local integration testing
|
7
|
-
* Compatibility with plugins like knife-ec2
|
8
|
-
|
9
|
-
# Not released yet
|
3
|
+
## Changes and new features
|
10
4
|
|
11
5
|
* Move all commands under "knife solo" namespace (#118)
|
12
6
|
- Rename `knife kitchen` to `knife solo init`
|
13
7
|
- Rename `knife wash_up` to `knife solo clean`
|
14
8
|
* Add `knife solo bootstrap` command (#120)
|
9
|
+
* OmniOS support (#144)
|
15
10
|
* Detect Fedora 17 (#141)
|
11
|
+
* Update chef-solo-search and add support of encrypted data bags (#127)
|
12
|
+
* Support Librarian (#36)
|
13
|
+
* Always install rsync from yum on RPM-based Linuxes (#157)
|
14
|
+
* Debian wheezy (7) support (#165)
|
15
|
+
|
16
|
+
## Fixes
|
17
|
+
|
16
18
|
* Improve help/error messages and validation (#142)
|
17
19
|
* Fix exit status of "cook" if chef-solo fails (#97)
|
20
|
+
* Fix option passing to the Omnibus installer (#163)
|
21
|
+
* Other fixes: SuSE omnibus #146, #155, #158, #160, #164
|
22
|
+
|
23
|
+
## Documentation
|
24
|
+
|
25
|
+
* Include documentation and tests in the gem (e01c23)
|
26
|
+
* [Home page](http://matschaffer.github.com/knife-solo/)
|
27
|
+
that reflects always the current release (#151)
|
18
28
|
|
19
29
|
## Thanks to our contributors!
|
20
30
|
|
21
31
|
* [Marek Hulan][ares]
|
32
|
+
* [Anton Orel][skyeagle]
|
33
|
+
* [Adam Carlile][Frozenproduce]
|
34
|
+
* [Chris Lundquist][ChrisLundquist]
|
35
|
+
* [Hiten Parmar][hrp]
|
36
|
+
* [Patrick Connolly][patcon]
|
22
37
|
|
23
38
|
# 0.0.15: November 29th, 2012
|
24
39
|
|
@@ -182,7 +197,9 @@ And a special thanks to [Teemu Matilainen][tmatilai] who is now on the list of d
|
|
182
197
|
* Generate node config on prepare
|
183
198
|
* Cook via rsync
|
184
199
|
|
200
|
+
[ChrisLundquist]:https://github.com/ChrisLundquist
|
185
201
|
[DrGonzo65]: https://github.com/DrGonzo65
|
202
|
+
[Frozenproduce]: https://github.com/Frozenproduce
|
186
203
|
[Motiejus]: https://github.com/Motiejus
|
187
204
|
[Nix-wie-weg]: https://github.com/Nix-wie-weg
|
188
205
|
[TylerRick]: https://github.com/TylerRick
|
@@ -195,10 +212,11 @@ And a special thanks to [Teemu Matilainen][tmatilai] who is now on the list of d
|
|
195
212
|
[davidsch]: https://github.com/davidsch
|
196
213
|
[deepak]: https://github.com/deepak
|
197
214
|
[fnichol]: https://github.com/fnichol
|
198
|
-
[funglaub]: https://github/funglaub
|
215
|
+
[funglaub]: https://github.com/funglaub
|
199
216
|
[gregf]: https://github.com/gregf
|
200
217
|
[gsterndale]: https://github.com/gsterndale
|
201
218
|
[hectcastro]: https://github.com/hectcastro
|
219
|
+
[hrp]: https://github.com/hrp
|
202
220
|
[jgarber]: https://github.com/jgarber
|
203
221
|
[jgrevich]: https://github.com/jgrevich
|
204
222
|
[natlownes]: https://github.com/natlownes
|
@@ -207,10 +225,11 @@ And a special thanks to [Teemu Matilainen][tmatilai] who is now on the list of d
|
|
207
225
|
[pferdefleisch]: https://github.com/pferdefleisch
|
208
226
|
[portertech]: https://github.com/portertech
|
209
227
|
[retr0h]: https://github.com/retr0h
|
210
|
-
[rmoriz]:
|
228
|
+
[rmoriz]: https://github.com/rmoriz
|
211
229
|
[rosstimson]: https://github.com/rosstimson
|
212
230
|
[rubiojr]: https://github.com/rubiojr
|
213
231
|
[ryandub]: https://github.com/ryandub
|
232
|
+
[skyeagle]: https://github.com/skyeagle
|
214
233
|
[tmatilai]: https://github.com/tmatilai
|
215
234
|
[vjpr]: https://github.com/vjpr
|
216
235
|
[zeph]: https://github.com/zeph
|
data/README.rdoc
CHANGED
@@ -1,11 +1,8 @@
|
|
1
1
|
= knife-solo
|
2
2
|
|
3
|
-
{<img src="https://secure.travis-ci.org/matschaffer/knife-solo.png" alt="Build Status" />}[http://travis-ci.org/matschaffer/knife-solo]
|
4
|
-
{<img src="https://codeclimate.com/badge.png" />}[https://codeclimate.com/github/matschaffer/knife-solo]
|
5
|
-
|
6
3
|
== DESCRIPTION:
|
7
4
|
|
8
|
-
|
5
|
+
knife-solo adds a handful of commands that aim to make working with chef-solo as powerful as chef-server. It currently adds 5 subcommands to knife:
|
9
6
|
|
10
7
|
- <tt>knife solo init</tt> is used to create a new directory structure (i.e. "kitchen") that fits with Chef's standard structure and can be used to build and store recipes.
|
11
8
|
|
@@ -27,13 +24,13 @@ Installation is a normal gem installation.
|
|
27
24
|
|
28
25
|
If you need to install from git run:
|
29
26
|
|
30
|
-
rake install
|
27
|
+
bundle && bundle exec rake install
|
31
28
|
|
32
29
|
=== Init command
|
33
30
|
|
34
31
|
The init command simply takes a name of the directory to store the kitchen structure. Use "." to initialize the current directory.
|
35
32
|
|
36
|
-
knife init mychefrepo
|
33
|
+
knife solo init mychefrepo
|
37
34
|
|
38
35
|
Currently the directory structure looks like this, but could change as development continues.
|
39
36
|
|
data/Rakefile
CHANGED
@@ -1,18 +1,63 @@
|
|
1
1
|
require 'bundler/gem_tasks'
|
2
2
|
require 'rake/testtask'
|
3
3
|
|
4
|
+
MANIFEST_IGNORES = %w[
|
5
|
+
.travis.yml
|
6
|
+
.gitignore
|
7
|
+
Gemfile
|
8
|
+
Gemfile.lock
|
9
|
+
Manifest.txt
|
10
|
+
README.md
|
11
|
+
knife-solo.gemspec
|
12
|
+
script/newb
|
13
|
+
script/test
|
14
|
+
]
|
15
|
+
|
4
16
|
desc 'Updates Manifest.txt with a list of files from git'
|
5
17
|
task :manifest do
|
6
18
|
git_files = `git ls-files`.split("\n")
|
7
|
-
ignored = %w(.gitignore Gemfile Gemfile.lock Manifest.txt knife-solo.gemspec script/newb script/test)
|
8
19
|
|
9
20
|
File.open('Manifest.txt', 'w') do |f|
|
10
|
-
f.puts (git_files -
|
21
|
+
f.puts (git_files - MANIFEST_IGNORES).join("\n")
|
11
22
|
end
|
12
23
|
end
|
13
|
-
|
14
24
|
task :release => :manifest
|
15
25
|
|
26
|
+
# Returns the parsed RDoc for a single file as HTML
|
27
|
+
# Somewhat gnarly, but does the job.
|
28
|
+
def parsed_rdoc file
|
29
|
+
options = RDoc::Options.new
|
30
|
+
options.template_dir = options.template_dir_for 'darkfish'
|
31
|
+
|
32
|
+
rdoc = RDoc::RDoc.current = RDoc::RDoc.new
|
33
|
+
rdoc.options = options
|
34
|
+
rdoc.generator = RDoc::Generator::Darkfish.new(options)
|
35
|
+
parsed = rdoc.parse_files([file])
|
36
|
+
parsed.first.description
|
37
|
+
end
|
38
|
+
|
39
|
+
desc 'Renerates gh-pages from project'
|
40
|
+
task 'gh-pages' do
|
41
|
+
require 'tmpdir'
|
42
|
+
gem 'rdoc'; require 'rdoc/rdoc'
|
43
|
+
|
44
|
+
Dir.mktmpdir do |clone|
|
45
|
+
sh "git clone -b gh-pages git@github.com:matschaffer/knife-solo.git #{clone}"
|
46
|
+
File.open(clone + "/index.html", 'w') do |f|
|
47
|
+
f.puts '---'
|
48
|
+
f.puts 'layout: default'
|
49
|
+
f.puts '---'
|
50
|
+
f.puts parsed_rdoc("README.rdoc")
|
51
|
+
end
|
52
|
+
rev = `git rev-parse HEAD`[0..7]
|
53
|
+
Dir.chdir(clone) do
|
54
|
+
sh "git commit --allow-empty -m 'Updated index from README.rdoc rev #{rev}' index.html"
|
55
|
+
sh "git push origin gh-pages"
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
task :release => 'gh-pages'
|
60
|
+
|
16
61
|
namespace :test do
|
17
62
|
Rake::TestTask.new(:integration) do |t|
|
18
63
|
t.libs << "test"
|
@@ -23,6 +68,9 @@ namespace :test do
|
|
23
68
|
t.libs << "test"
|
24
69
|
t.test_files = FileList['test/*_test.rb']
|
25
70
|
end
|
71
|
+
|
72
|
+
desc 'Run both unit and integration tests'
|
73
|
+
task :all => [:units, :integration]
|
26
74
|
end
|
27
75
|
|
28
76
|
desc "Alias for test:units"
|
@@ -70,22 +70,34 @@ module Lucene
|
|
70
70
|
end
|
71
71
|
end
|
72
72
|
end
|
73
|
-
|
73
|
+
|
74
74
|
# we don't support range matches
|
75
75
|
# range of integers would be easy to implement
|
76
76
|
# but string ranges are hard
|
77
77
|
class FiledRange < Treetop::Runtime::SyntaxNode
|
78
78
|
end
|
79
|
-
|
80
|
-
|
79
|
+
|
80
|
+
# we handle '[* TO *]' as a special case since it is common in
|
81
|
+
# cookbooks for matching the existence of keys
|
82
|
+
class InclFieldRange
|
83
|
+
def match(item)
|
84
|
+
field = self.elements[0].text_value
|
85
|
+
range_start = self.elements[1].transform
|
86
|
+
range_end = self.elements[2].transform
|
87
|
+
if range_start == "*" and range_end == "*"
|
88
|
+
!!item[field]
|
89
|
+
else
|
90
|
+
raise "Ranges not really supported yet"
|
91
|
+
end
|
92
|
+
end
|
81
93
|
end
|
82
|
-
|
94
|
+
|
83
95
|
class ExclFieldRange < FieldRange
|
84
96
|
end
|
85
|
-
|
97
|
+
|
86
98
|
class RangeValue < Treetop::Runtime::SyntaxNode
|
87
99
|
end
|
88
|
-
|
100
|
+
|
89
101
|
class FieldName < Treetop::Runtime::SyntaxNode
|
90
102
|
def match( item )
|
91
103
|
if self.text_value.count("_") > 0
|
@@ -95,7 +107,7 @@ module Lucene
|
|
95
107
|
part = self.text_value.chomp("*")
|
96
108
|
item.keys.collect{ |key| key.start_with?(part)? key: nil}.compact
|
97
109
|
else
|
98
|
-
if item
|
110
|
+
if item[self.text_value]
|
99
111
|
[self.text_value,]
|
100
112
|
else
|
101
113
|
nil
|
@@ -109,13 +121,13 @@ module Lucene
|
|
109
121
|
self.elements[0].match( item )
|
110
122
|
end
|
111
123
|
end
|
112
|
-
|
124
|
+
|
113
125
|
class Group < Treetop::Runtime::SyntaxNode
|
114
126
|
def match( item )
|
115
127
|
self.elements[0].match(item)
|
116
128
|
end
|
117
129
|
end
|
118
|
-
|
130
|
+
|
119
131
|
class BinaryOp < Treetop::Runtime::SyntaxNode
|
120
132
|
def match( item )
|
121
133
|
self.elements[1].match(
|
@@ -124,29 +136,29 @@ module Lucene
|
|
124
136
|
)
|
125
137
|
end
|
126
138
|
end
|
127
|
-
|
139
|
+
|
128
140
|
class OrOperator < Treetop::Runtime::SyntaxNode
|
129
141
|
def match( cond1, cond2 )
|
130
142
|
cond1 or cond2
|
131
143
|
end
|
132
144
|
end
|
133
|
-
|
145
|
+
|
134
146
|
class AndOperator < Treetop::Runtime::SyntaxNode
|
135
147
|
def match( cond1, cond2 )
|
136
148
|
cond1 and cond2
|
137
149
|
end
|
138
150
|
end
|
139
|
-
|
151
|
+
|
140
152
|
# we don't support fuzzy string matching
|
141
153
|
class FuzzyOp < Treetop::Runtime::SyntaxNode
|
142
154
|
end
|
143
|
-
|
155
|
+
|
144
156
|
class BoostOp < Treetop::Runtime::SyntaxNode
|
145
157
|
end
|
146
|
-
|
158
|
+
|
147
159
|
class FuzzyParam < Treetop::Runtime::SyntaxNode
|
148
160
|
end
|
149
|
-
|
161
|
+
|
150
162
|
class UnaryOp < Treetop::Runtime::SyntaxNode
|
151
163
|
def match( item )
|
152
164
|
self.elements[0].match(
|
@@ -154,19 +166,19 @@ module Lucene
|
|
154
166
|
)
|
155
167
|
end
|
156
168
|
end
|
157
|
-
|
169
|
+
|
158
170
|
class NotOperator < Treetop::Runtime::SyntaxNode
|
159
171
|
def match( cond )
|
160
172
|
not cond
|
161
173
|
end
|
162
174
|
end
|
163
|
-
|
175
|
+
|
164
176
|
class RequiredOperator < Treetop::Runtime::SyntaxNode
|
165
177
|
end
|
166
|
-
|
178
|
+
|
167
179
|
class ProhibitedOperator < Treetop::Runtime::SyntaxNode
|
168
180
|
end
|
169
|
-
|
181
|
+
|
170
182
|
class Phrase < Treetop::Runtime::SyntaxNode
|
171
183
|
# a quoted ::Term
|
172
184
|
def match( value )
|
@@ -195,7 +207,7 @@ class Query
|
|
195
207
|
self.clean_tree(tree)
|
196
208
|
tree
|
197
209
|
end
|
198
|
-
|
210
|
+
|
199
211
|
private
|
200
212
|
|
201
213
|
def self.clean_tree(root_node)
|
@@ -0,0 +1,110 @@
|
|
1
|
+
#
|
2
|
+
# Copyright 2011, edelight GmbH
|
3
|
+
#
|
4
|
+
# Authors:
|
5
|
+
# Markus Korn <markus.korn@edelight.de>
|
6
|
+
#
|
7
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
8
|
+
# you may not use this file except in compliance with the License.
|
9
|
+
# You may obtain a copy of the License at
|
10
|
+
#
|
11
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
12
|
+
#
|
13
|
+
# Unless required by applicable law or agreed to in writing, software
|
14
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
15
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
16
|
+
# See the License for the specific language governing permissions and
|
17
|
+
# limitations under the License.
|
18
|
+
#
|
19
|
+
|
20
|
+
if Chef::Config[:solo]
|
21
|
+
|
22
|
+
if (defined? require_relative).nil?
|
23
|
+
# defenition of 'require_relative' for ruby < 1.9, found on stackoverflow.com
|
24
|
+
def require_relative(relative_feature)
|
25
|
+
c = caller.first
|
26
|
+
fail "Can't parse #{c}" unless c.rindex(/:\d+(:in `.*')?$/)
|
27
|
+
file = $`
|
28
|
+
if /\A\((.*)\)/ =~ file # eval, etc.
|
29
|
+
raise LoadError, "require_relative is called in #{$1}"
|
30
|
+
end
|
31
|
+
absolute = File.expand_path(relative_feature, File.dirname(file))
|
32
|
+
require absolute
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
require_relative 'parser.rb'
|
37
|
+
|
38
|
+
class Chef
|
39
|
+
module Mixin
|
40
|
+
module Language
|
41
|
+
|
42
|
+
# Overwrite the search method of recipes to operate locally by using
|
43
|
+
# data found in data_bags.
|
44
|
+
# Only very basic lucene syntax is supported and also sorting the result
|
45
|
+
# is not implemented, if this search method does not support a given query
|
46
|
+
# an exception is raised.
|
47
|
+
# This search() method returns a block iterator or an Array, depending
|
48
|
+
# on how this method is called.
|
49
|
+
def search(obj, query=nil, sort=nil, start=0, rows=1000, &block)
|
50
|
+
if !sort.nil?
|
51
|
+
raise "Sorting search results is not supported"
|
52
|
+
end
|
53
|
+
@_query = Query.parse(query)
|
54
|
+
if @_query.nil?
|
55
|
+
raise "Query #{query} is not supported"
|
56
|
+
end
|
57
|
+
@_result = []
|
58
|
+
|
59
|
+
case obj
|
60
|
+
when :node
|
61
|
+
search_nodes(start, rows, &block)
|
62
|
+
when :role
|
63
|
+
search_roles(start, rows, &block)
|
64
|
+
else
|
65
|
+
search_data_bag(obj, start, rows, &block)
|
66
|
+
end
|
67
|
+
|
68
|
+
|
69
|
+
if block_given?
|
70
|
+
pos = 0
|
71
|
+
while (pos >= start and pos < (start + rows) and pos < @_result.size)
|
72
|
+
yield @_result[pos]
|
73
|
+
pos += 1
|
74
|
+
end
|
75
|
+
else
|
76
|
+
return @_result.slice(start, rows)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def search_nodes(start, rows, &block)
|
81
|
+
Dir.glob(File.join(Chef::Config[:data_bag_path], "node", "*.json")).map do |f|
|
82
|
+
# parse and hashify the node
|
83
|
+
node = JSON.parse(IO.read(f))
|
84
|
+
if @_query.match(node.to_hash)
|
85
|
+
@_result << node
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
def search_roles(start, rows, &block)
|
91
|
+
raise "Role searching not implemented"
|
92
|
+
end
|
93
|
+
|
94
|
+
def search_data_bag(bag_name, start, rows, &block)
|
95
|
+
secret_path = Chef::Config[:encrypted_data_bag_secret]
|
96
|
+
data_bag(bag_name.to_s).each do |bag_item_id|
|
97
|
+
if secret_path && secret = Chef::EncryptedDataBagItem.load_secret(secret_path)
|
98
|
+
bag_item = Chef::EncryptedDataBagItem.load(bag_name, bag_item_id, secret)
|
99
|
+
else
|
100
|
+
bag_item = data_bag_item(bag_name.to_s, bag_item_id)
|
101
|
+
end
|
102
|
+
if @_query.match(bag_item)
|
103
|
+
@_result << bag_item
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
data/lib/chef/knife/solo_cook.rb
CHANGED
@@ -10,8 +10,8 @@ class Chef
|
|
10
10
|
# Approach ported from spatula (https://github.com/trotter/spatula)
|
11
11
|
# Copyright 2009, Trotter Cashion
|
12
12
|
class SoloCook < Knife
|
13
|
-
OMNIBUS_EMBEDDED_PATHS ||= [
|
14
|
-
OMNIBUS_EMBEDDED_GEM_PATHS ||= [
|
13
|
+
OMNIBUS_EMBEDDED_PATHS ||= %w[/opt/chef/embedded/bin /opt/opscode/embedded/bin]
|
14
|
+
OMNIBUS_EMBEDDED_GEM_PATHS ||= %w[/opt/chef/embedded/lib/ruby/gems/1.9.1 /opt/opscode/embedded/lib/ruby/gems/1.9.1]
|
15
15
|
CHEF_VERSION_CONSTRAINT ||= ">=0.10.4"
|
16
16
|
|
17
17
|
include KnifeSolo::SshCommand
|
@@ -21,6 +21,8 @@ class Chef
|
|
21
21
|
|
22
22
|
deps do
|
23
23
|
require 'chef/cookbook/chefignore'
|
24
|
+
require 'librarian/action'
|
25
|
+
require 'librarian/chef'
|
24
26
|
require 'pathname'
|
25
27
|
KnifeSolo::SshCommand.load_deps
|
26
28
|
KnifeSolo::NodeConfigCommand.load_deps
|
@@ -29,20 +31,17 @@ class Chef
|
|
29
31
|
banner "knife solo cook [USER@]HOSTNAME [JSON] (options)"
|
30
32
|
|
31
33
|
option :skip_chef_check,
|
32
|
-
:long
|
33
|
-
:
|
34
|
-
:description => "Skip the version check on the Chef gem"
|
34
|
+
:long => '--skip-chef-check',
|
35
|
+
:description => 'Skip the version check on the Chef gem'
|
35
36
|
|
36
37
|
option :sync_only,
|
37
|
-
:long
|
38
|
-
:
|
39
|
-
:description => "Only sync the cookbook - do not run Chef"
|
38
|
+
:long => '--sync-only',
|
39
|
+
:description => 'Only sync the cookbook - do not run Chef'
|
40
40
|
|
41
41
|
option :why_run,
|
42
|
-
:short
|
43
|
-
:long
|
44
|
-
:
|
45
|
-
:description => "Enable whyrun mode"
|
42
|
+
:short => '-W',
|
43
|
+
:long => '--why-run',
|
44
|
+
:description => 'Enable whyrun mode'
|
46
45
|
|
47
46
|
def run
|
48
47
|
time('Run') do
|
@@ -50,6 +49,7 @@ class Chef
|
|
50
49
|
Chef::Config.from_file('solo.rb')
|
51
50
|
check_chef_version unless config[:skip_chef_check]
|
52
51
|
generate_node_config
|
52
|
+
librarian_install
|
53
53
|
rsync_kitchen
|
54
54
|
add_patches
|
55
55
|
cook unless config[:sync_only]
|
@@ -96,6 +96,17 @@ class Chef
|
|
96
96
|
ui.msg "#{msg} finished in #{Time.now - start} seconds"
|
97
97
|
end
|
98
98
|
|
99
|
+
def librarian_install
|
100
|
+
return unless File.exist? 'Cheffile'
|
101
|
+
Chef::Log.debug("Installing Librarian cookbooks")
|
102
|
+
Librarian::Action::Resolve.new(librarian_env).run
|
103
|
+
Librarian::Action::Install.new(librarian_env).run
|
104
|
+
end
|
105
|
+
|
106
|
+
def librarian_env
|
107
|
+
@librarian_env ||= Librarian::Chef::Environment.new
|
108
|
+
end
|
109
|
+
|
99
110
|
def rsync_kitchen
|
100
111
|
time('Rsync kitchen') do
|
101
112
|
cmd = %Q{rsync -rl --rsh="ssh #{ssh_args}" --delete #{rsync_exclude.collect{ |ignore| "--exclude #{ignore} " }.join} ./ :#{adjust_rsync_path(chef_path)}}
|
data/lib/chef/knife/solo_init.rb
CHANGED
@@ -21,16 +21,16 @@ class Chef
|
|
21
21
|
banner "knife solo prepare [USER@]HOSTNAME [JSON] (options)"
|
22
22
|
|
23
23
|
option :omnibus_version,
|
24
|
-
:long
|
25
|
-
:description =>
|
24
|
+
:long => '--omnibus-version VERSION',
|
25
|
+
:description => 'The version of Omnibus to install'
|
26
26
|
|
27
27
|
option :omnibus_url,
|
28
|
-
:long
|
29
|
-
:description =>
|
28
|
+
:long => '--omnibus-url URL',
|
29
|
+
:description => 'URL to download install.sh from'
|
30
30
|
|
31
31
|
option :omnibus_options,
|
32
|
-
:long
|
33
|
-
:description =>
|
32
|
+
:long => '--omnibus-options "OPTIONS"',
|
33
|
+
:description => 'Pass options to the install.sh script'
|
34
34
|
|
35
35
|
def run
|
36
36
|
validate!
|
@@ -57,7 +57,7 @@ module KnifeSolo
|
|
57
57
|
|
58
58
|
def http_client_get_url(url, file)
|
59
59
|
stream_command <<-BASH
|
60
|
-
if
|
60
|
+
if command -v curl >/dev/null 2>&1; then
|
61
61
|
curl -L -o #{file} #{url}
|
62
62
|
else
|
63
63
|
wget -O #{file} #{url}
|
@@ -73,7 +73,7 @@ module KnifeSolo
|
|
73
73
|
# `omnibus_version` is not provided.
|
74
74
|
install_command = "sudo bash #{file}"
|
75
75
|
install_command << " -v #{prepare.config[:omnibus_version]}" if prepare.config[:omnibus_version]
|
76
|
-
install_command << " #{prepare.config[:
|
76
|
+
install_command << " #{prepare.config[:omnibus_options]}" if prepare.config[:omnibus_options]
|
77
77
|
|
78
78
|
stream_command(install_command)
|
79
79
|
end
|
@@ -81,7 +81,7 @@ module KnifeSolo
|
|
81
81
|
def yum_omnibus_install
|
82
82
|
omnibus_install
|
83
83
|
# Make sure we have rsync on builds that don't include it by default
|
84
|
-
# (for example Scientific Linux minimal)
|
84
|
+
# (for example Scientific Linux minimal, CentOS minimal)
|
85
85
|
run_command("sudo yum -y install rsync")
|
86
86
|
end
|
87
87
|
|
@@ -2,7 +2,7 @@ module KnifeSolo::Bootstraps
|
|
2
2
|
class Linux < Base
|
3
3
|
|
4
4
|
def issue
|
5
|
-
prepare.run_command("cat /etc/issue").stdout.strip ||
|
5
|
+
prepare.run_command("cat /etc/issue").stdout.strip || prepare.run_command("lsb_release -d -s").stdout.strip
|
6
6
|
end
|
7
7
|
|
8
8
|
def x86?
|
@@ -76,6 +76,8 @@ module KnifeSolo::Bootstraps
|
|
76
76
|
{:type => if x86? then "debianoid_omnibus" else "debian_gem" end, :version => "lenny"}
|
77
77
|
when %r{Debian GNU/Linux 6}
|
78
78
|
{:type => if x86? then "debianoid_omnibus" else "debian_gem" end, :version => "squeeze"}
|
79
|
+
when %r{Debian GNU/Linux 7}
|
80
|
+
{:type => if x86? then "debianoid_omnibus" else "debian_gem" end, :version => "wheezy"}
|
79
81
|
when %r{Debian GNU/Linux wheezy}
|
80
82
|
{:type => "debian_gem", :version => "wheezy"}
|
81
83
|
when %r{Ubuntu}i
|
@@ -85,21 +87,21 @@ module KnifeSolo::Bootstraps
|
|
85
87
|
version = run_command("lsb_release -cs").stdout.strip
|
86
88
|
{:type => "debian_gem", :version => version}
|
87
89
|
when %r{CentOS.*? 5}
|
88
|
-
{:type => "
|
90
|
+
{:type => "yum_omnibus", :version => "RHEL5"}
|
89
91
|
when %r{CentOS.*? 6}
|
90
|
-
{:type => "
|
92
|
+
{:type => "yum_omnibus", :version => "RHEL6"}
|
91
93
|
when %r{Red Hat Enterprise.*? 5}
|
92
|
-
{:type => "
|
94
|
+
{:type => "yum_omnibus", :version => "RHEL5"}
|
93
95
|
when %r{Red Hat Enterprise.*? 6}
|
94
|
-
{:type => "
|
96
|
+
{:type => "yum_omnibus", :version => "RHEL6"}
|
95
97
|
when %r{Fedora release.*? 15}
|
96
|
-
{:type => "
|
98
|
+
{:type => "yum_omnibus", :version => "FC15"}
|
97
99
|
when %r{Fedora release.*? 16}
|
98
|
-
{:type => "
|
100
|
+
{:type => "yum_omnibus", :version => "FC16"}
|
99
101
|
when %r{Fedora release.*? 17}
|
100
|
-
{:type => "
|
102
|
+
{:type => "yum_omnibus", :version => "FC17"}
|
101
103
|
when %r{Scientific Linux.*? 5}
|
102
|
-
{:type => "
|
104
|
+
{:type => "yum_omnibus", :version => "RHEL5"}
|
103
105
|
when %r{Scientific Linux.*? 6}
|
104
106
|
{:type => "yum_omnibus", :version => "RHEL6"}
|
105
107
|
when %r{SUSE Linux Enterprise Server 1[12]}
|
data/lib/knife-solo/info.rb
CHANGED
@@ -12,23 +12,23 @@ module KnifeSolo
|
|
12
12
|
deps { KnifeSolo::NodeConfigCommand.load_deps } unless @dependency_loader
|
13
13
|
|
14
14
|
option :chef_node_name,
|
15
|
-
:short
|
16
|
-
:long
|
17
|
-
:description =>
|
15
|
+
:short => '-N NAME',
|
16
|
+
:long => '--node-name NAME',
|
17
|
+
:description => 'The Chef node name for your new node'
|
18
18
|
|
19
19
|
option :run_list,
|
20
|
-
:short
|
21
|
-
:long
|
22
|
-
:description =>
|
23
|
-
:proc
|
24
|
-
:default
|
20
|
+
:short => '-r RUN_LIST',
|
21
|
+
:long => '--run-list RUN_LIST',
|
22
|
+
:description => 'Comma separated list of roles/recipes to put to node config (if it does not exist)',
|
23
|
+
:proc => lambda { |o| o.split(/[\s,]+/) },
|
24
|
+
:default => []
|
25
25
|
|
26
26
|
option :first_boot_attributes,
|
27
|
-
:short
|
28
|
-
:long
|
29
|
-
:description =>
|
30
|
-
:proc
|
31
|
-
:default
|
27
|
+
:short => '-j JSON_ATTRIBS',
|
28
|
+
:long => '--json-attributes',
|
29
|
+
:description => 'A JSON string to be added to node config (if it does not exist)',
|
30
|
+
:proc => lambda { |o| JSON.parse(o) },
|
31
|
+
:default => {}
|
32
32
|
end
|
33
33
|
end
|
34
34
|
|
@@ -22,29 +22,29 @@ module KnifeSolo
|
|
22
22
|
deps { KnifeSolo::SshCommand.load_deps } unless @dependency_loader
|
23
23
|
|
24
24
|
option :ssh_config,
|
25
|
-
:short
|
26
|
-
:long
|
27
|
-
:description =>
|
25
|
+
:short => '-F CONFIG_FILE',
|
26
|
+
:long => '--ssh-config-file CONFIG_FILE',
|
27
|
+
:description => 'Alternate location for ssh config file'
|
28
28
|
|
29
29
|
option :ssh_password,
|
30
|
-
:short
|
31
|
-
:long
|
32
|
-
:description =>
|
30
|
+
:short => '-P PASSWORD',
|
31
|
+
:long => '--ssh-password PASSWORD',
|
32
|
+
:description => 'The ssh password'
|
33
33
|
|
34
34
|
option :ssh_identity,
|
35
|
-
:short
|
36
|
-
:long
|
37
|
-
:description =>
|
35
|
+
:short => '-i FILE',
|
36
|
+
:long => '--ssh-identity FILE',
|
37
|
+
:description => 'The ssh identity file'
|
38
38
|
|
39
39
|
option :ssh_port,
|
40
|
-
:short
|
41
|
-
:long
|
42
|
-
:description =>
|
40
|
+
:short => '-p PORT',
|
41
|
+
:long => '--ssh-port PORT',
|
42
|
+
:description => 'The ssh port'
|
43
43
|
|
44
44
|
option :startup_script,
|
45
|
-
:short
|
46
|
-
:long
|
47
|
-
:description =>
|
45
|
+
:short => '-s FILE',
|
46
|
+
:long => '--startup-script FILE',
|
47
|
+
:description => 'The startup script on the remote server containing variable definitions'
|
48
48
|
end
|
49
49
|
end
|
50
50
|
|
@@ -11,16 +11,15 @@ module Apache2Cook
|
|
11
11
|
end
|
12
12
|
|
13
13
|
def http_response
|
14
|
-
Net::HTTP.get(URI.parse("http
|
14
|
+
Net::HTTP.get(URI.parse("http://#{server.public_ip_address}"))
|
15
15
|
end
|
16
16
|
|
17
17
|
def default_apache_message
|
18
|
-
/
|
18
|
+
/Apache Server/
|
19
19
|
end
|
20
20
|
|
21
21
|
def test_apache2
|
22
22
|
write_cheffile
|
23
|
-
system "librarian-chef install >> #{log_file}"
|
24
23
|
write_nodefile(run_list: ["recipe[apache2]"])
|
25
24
|
assert_subcommand "cook"
|
26
25
|
assert_match default_apache_message, http_response
|
data/test/integration_helper.rb
CHANGED
data/test/solo_cook_test.rb
CHANGED
@@ -4,6 +4,7 @@ require 'support/validation_helper'
|
|
4
4
|
|
5
5
|
require 'chef/cookbook/chefignore'
|
6
6
|
require 'chef/knife/solo_cook'
|
7
|
+
require 'librarian/action/install'
|
7
8
|
|
8
9
|
class SuccessfulResult
|
9
10
|
def success?
|
@@ -38,6 +39,21 @@ class SoloCookTest < TestCase
|
|
38
39
|
end
|
39
40
|
end
|
40
41
|
|
42
|
+
def test_does_not_run_librarian_if_no_cheffile
|
43
|
+
in_kitchen do
|
44
|
+
Librarian::Action::Install.any_instance.expects(:run).never
|
45
|
+
command.librarian_install
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def test_runs_librarian_if_cheffile_found
|
50
|
+
in_kitchen do
|
51
|
+
File.open("Cheffile", 'w') {}
|
52
|
+
Librarian::Action::Install.any_instance.expects(:run)
|
53
|
+
command.librarian_install
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
41
57
|
def test_passes_node_name_to_chef_solo
|
42
58
|
assert_chef_solo_option "--node-name=mynode", "-N mynode"
|
43
59
|
end
|
data/test/support/ec2_runner.rb
CHANGED
data/test/test_helper.rb
CHANGED
metadata
CHANGED
@@ -1,16 +1,32 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: knife-solo
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.0
|
5
|
-
prerelease:
|
4
|
+
version: 0.1.0
|
5
|
+
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Mat Schaffer
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2013-01-12 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: bundler
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :development
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
14
30
|
- !ruby/object:Gem::Dependency
|
15
31
|
name: rake
|
16
32
|
requirement: !ruby/object:Gem::Requirement
|
@@ -44,43 +60,101 @@ dependencies:
|
|
44
60
|
- !ruby/object:Gem::Version
|
45
61
|
version: '0'
|
46
62
|
- !ruby/object:Gem::Dependency
|
47
|
-
name:
|
63
|
+
name: rdoc
|
48
64
|
requirement: !ruby/object:Gem::Requirement
|
49
65
|
none: false
|
50
66
|
requirements:
|
51
67
|
- - ! '>='
|
52
68
|
- !ruby/object:Gem::Version
|
53
|
-
version: 0
|
54
|
-
type: :
|
69
|
+
version: '0'
|
70
|
+
type: :development
|
55
71
|
prerelease: false
|
56
72
|
version_requirements: !ruby/object:Gem::Requirement
|
57
73
|
none: false
|
58
74
|
requirements:
|
59
75
|
- - ! '>='
|
60
76
|
- !ruby/object:Gem::Version
|
61
|
-
version: 0
|
77
|
+
version: '0'
|
62
78
|
- !ruby/object:Gem::Dependency
|
63
|
-
name:
|
79
|
+
name: fog
|
64
80
|
requirement: !ruby/object:Gem::Requirement
|
65
81
|
none: false
|
66
82
|
requirements:
|
67
83
|
- - ! '>='
|
68
84
|
- !ruby/object:Gem::Version
|
69
|
-
version:
|
70
|
-
|
85
|
+
version: '0'
|
86
|
+
type: :development
|
87
|
+
prerelease: false
|
88
|
+
version_requirements: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - ! '>='
|
71
92
|
- !ruby/object:Gem::Version
|
72
|
-
version:
|
73
|
-
|
93
|
+
version: '0'
|
94
|
+
- !ruby/object:Gem::Dependency
|
95
|
+
name: minitest
|
96
|
+
requirement: !ruby/object:Gem::Requirement
|
97
|
+
none: false
|
98
|
+
requirements:
|
99
|
+
- - ! '>='
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: '0'
|
102
|
+
type: :development
|
74
103
|
prerelease: false
|
75
104
|
version_requirements: !ruby/object:Gem::Requirement
|
76
105
|
none: false
|
77
106
|
requirements:
|
78
107
|
- - ! '>='
|
79
108
|
- !ruby/object:Gem::Version
|
80
|
-
version:
|
81
|
-
|
109
|
+
version: '0'
|
110
|
+
- !ruby/object:Gem::Dependency
|
111
|
+
name: parallel
|
112
|
+
requirement: !ruby/object:Gem::Requirement
|
113
|
+
none: false
|
114
|
+
requirements:
|
115
|
+
- - ! '>='
|
82
116
|
- !ruby/object:Gem::Version
|
83
|
-
version:
|
117
|
+
version: '0'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
none: false
|
122
|
+
requirements:
|
123
|
+
- - ! '>='
|
124
|
+
- !ruby/object:Gem::Version
|
125
|
+
version: '0'
|
126
|
+
- !ruby/object:Gem::Dependency
|
127
|
+
name: chef
|
128
|
+
requirement: !ruby/object:Gem::Requirement
|
129
|
+
none: false
|
130
|
+
requirements:
|
131
|
+
- - ~>
|
132
|
+
- !ruby/object:Gem::Version
|
133
|
+
version: '10.12'
|
134
|
+
type: :runtime
|
135
|
+
prerelease: false
|
136
|
+
version_requirements: !ruby/object:Gem::Requirement
|
137
|
+
none: false
|
138
|
+
requirements:
|
139
|
+
- - ~>
|
140
|
+
- !ruby/object:Gem::Version
|
141
|
+
version: '10.12'
|
142
|
+
- !ruby/object:Gem::Dependency
|
143
|
+
name: net-ssh
|
144
|
+
requirement: !ruby/object:Gem::Requirement
|
145
|
+
none: false
|
146
|
+
requirements:
|
147
|
+
- - ~>
|
148
|
+
- !ruby/object:Gem::Version
|
149
|
+
version: 2.2.2
|
150
|
+
type: :runtime
|
151
|
+
prerelease: false
|
152
|
+
version_requirements: !ruby/object:Gem::Requirement
|
153
|
+
none: false
|
154
|
+
requirements:
|
155
|
+
- - ~>
|
156
|
+
- !ruby/object:Gem::Version
|
157
|
+
version: 2.2.2
|
84
158
|
- !ruby/object:Gem::Dependency
|
85
159
|
name: librarian
|
86
160
|
requirement: !ruby/object:Gem::Requirement
|
@@ -110,7 +184,7 @@ files:
|
|
110
184
|
- lib/chef/knife/cook.rb
|
111
185
|
- lib/chef/knife/kitchen.rb
|
112
186
|
- lib/chef/knife/patches/parser.rb
|
113
|
-
- lib/chef/knife/patches/
|
187
|
+
- lib/chef/knife/patches/search.rb
|
114
188
|
- lib/chef/knife/prepare.rb
|
115
189
|
- lib/chef/knife/solo_bootstrap.rb
|
116
190
|
- lib/chef/knife/solo_clean.rb
|
@@ -184,9 +258,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
184
258
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
185
259
|
none: false
|
186
260
|
requirements:
|
187
|
-
- - ! '
|
261
|
+
- - ! '>='
|
188
262
|
- !ruby/object:Gem::Version
|
189
|
-
version:
|
263
|
+
version: '0'
|
190
264
|
requirements: []
|
191
265
|
rubyforge_project:
|
192
266
|
rubygems_version: 1.8.24
|
@@ -233,3 +307,4 @@ test_files:
|
|
233
307
|
- test/support/test_case.rb
|
234
308
|
- test/support/validation_helper.rb
|
235
309
|
- test/test_helper.rb
|
310
|
+
has_rdoc:
|
@@ -1,81 +0,0 @@
|
|
1
|
-
#
|
2
|
-
# Copyright 2011, edelight GmbH
|
3
|
-
#
|
4
|
-
# Authors:
|
5
|
-
# Markus Korn <markus.korn@edelight.de>
|
6
|
-
#
|
7
|
-
# Licensed under the Apache License, Version 2.0 (the "License");
|
8
|
-
# you may not use this file except in compliance with the License.
|
9
|
-
# You may obtain a copy of the License at
|
10
|
-
#
|
11
|
-
# http://www.apache.org/licenses/LICENSE-2.0
|
12
|
-
#
|
13
|
-
# Unless required by applicable law or agreed to in writing, software
|
14
|
-
# distributed under the License is distributed on an "AS IS" BASIS,
|
15
|
-
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
16
|
-
# See the License for the specific language governing permissions and
|
17
|
-
# limitations under the License.
|
18
|
-
#
|
19
|
-
|
20
|
-
if Chef::Config[:solo]
|
21
|
-
|
22
|
-
if (defined? require_relative).nil?
|
23
|
-
# defenition of 'require_relative' for ruby < 1.9, found on stackoverflow.com
|
24
|
-
def require_relative(relative_feature)
|
25
|
-
c = caller.first
|
26
|
-
fail "Can't parse #{c}" unless c.rindex(/:\d+(:in `.*')?$/)
|
27
|
-
file = $`
|
28
|
-
if /\A\((.*)\)/ =~ file # eval, etc.
|
29
|
-
raise LoadError, "require_relative is called in #{$1}"
|
30
|
-
end
|
31
|
-
absolute = File.expand_path(relative_feature, File.dirname(file))
|
32
|
-
require absolute
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
require_relative 'parser.rb'
|
37
|
-
|
38
|
-
class Chef
|
39
|
-
class Recipe
|
40
|
-
|
41
|
-
# Overwrite the search method of recipes to operate locally by using
|
42
|
-
# data found in data_bags.
|
43
|
-
# Only very basic lucene syntax is supported and also sorting the result
|
44
|
-
# is not implemented, if this search method does not support a given query
|
45
|
-
# an exception is raised.
|
46
|
-
# This search() method returns a block iterator or an Array, depending
|
47
|
-
# on how this method is called.
|
48
|
-
def search(bag_name, query=nil, sort=nil, start=0, rows=1000, &block)
|
49
|
-
if !sort.nil?
|
50
|
-
raise "Sorting search results is not supported"
|
51
|
-
end
|
52
|
-
@_query = Query.parse(query)
|
53
|
-
if @_query.nil?
|
54
|
-
raise "Query #{query} is not supported"
|
55
|
-
end
|
56
|
-
if block_given?
|
57
|
-
pos = 0
|
58
|
-
else
|
59
|
-
result = []
|
60
|
-
end
|
61
|
-
data_bag(bag_name.to_s).each do |bag_item_id|
|
62
|
-
bag_item = data_bag_item(bag_name.to_s, bag_item_id)
|
63
|
-
if @_query.match(bag_item)
|
64
|
-
if block_given?
|
65
|
-
if (pos >= start and pos < (start + rows))
|
66
|
-
yield bag_item
|
67
|
-
end
|
68
|
-
pos += 1
|
69
|
-
else
|
70
|
-
result << bag_item
|
71
|
-
end
|
72
|
-
end
|
73
|
-
end
|
74
|
-
if !block_given?
|
75
|
-
return result.slice(start, rows)
|
76
|
-
end
|
77
|
-
end
|
78
|
-
end
|
79
|
-
end
|
80
|
-
|
81
|
-
end
|