knife-solo 0.1.0.pre1 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|