knife-solo 0.0.3 → 0.0.4
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/chef/knife/cook.rb +10 -1
- data/lib/chef/knife/kitchen.rb +2 -1
- data/lib/chef/knife/patches/parser.rb +211 -0
- data/lib/chef/knife/patches/search_patch.rb +81 -0
- data/lib/chef/knife/prepare.rb +0 -2
- data/lib/knife-solo/info.rb +3 -1
- metadata +14 -19
- data/lib/chef/knife/patches/data_bags_patch.rb +0 -42
data/lib/chef/knife/cook.rb
CHANGED
@@ -27,6 +27,8 @@ class Chef
|
|
27
27
|
|
28
28
|
add_patches
|
29
29
|
|
30
|
+
check_chef_version
|
31
|
+
|
30
32
|
logging_arg = "-l debug" if config[:verbosity] > 0
|
31
33
|
stream_command <<-BASH
|
32
34
|
sudo chef-solo -c #{chef_path}/solo.rb \
|
@@ -64,7 +66,6 @@ class Chef
|
|
64
66
|
Array(Chef::Config.cookbook_path).first + "/chef_solo_patches/libraries"
|
65
67
|
end
|
66
68
|
|
67
|
-
# TODO (mat): Let rsync write to /var/chef-solo with sudo somehow
|
68
69
|
def rsync_kitchen
|
69
70
|
system %Q{rsync -rlP --rsh="ssh #{ssh_args}" --delete --exclude '.*' ./ :#{chef_path}}
|
70
71
|
end
|
@@ -75,6 +76,14 @@ class Chef
|
|
75
76
|
system %Q{rsync -rlP --rsh="ssh #{ssh_args}" #{patch} :#{patch_path}}
|
76
77
|
end
|
77
78
|
end
|
79
|
+
|
80
|
+
def check_chef_version
|
81
|
+
constraint = "~>0.10.4"
|
82
|
+
result = run_command <<-BASH
|
83
|
+
ruby -rubygems -e "gem 'chef', '#{constraint}'"
|
84
|
+
BASH
|
85
|
+
raise "The chef gem on #{host} is out of date. Please run `#{$0} prepare #{ssh_args}` to upgrade Chef to #{constraint}." unless result.success?
|
86
|
+
end
|
78
87
|
end
|
79
88
|
end
|
80
89
|
end
|
data/lib/chef/knife/kitchen.rb
CHANGED
@@ -16,11 +16,12 @@ class Chef
|
|
16
16
|
mkdir name + "/site-cookbooks"
|
17
17
|
mkdir name + "/cookbooks"
|
18
18
|
File.open(name + "/solo.rb", 'w') do |f|
|
19
|
-
f << <<-RUBY.gsub(
|
19
|
+
f << <<-RUBY.gsub(/^ {12}/, '')
|
20
20
|
file_cache_path "/tmp/chef-solo"
|
21
21
|
data_bag_path "/tmp/chef-solo/data_bags"
|
22
22
|
cookbook_path [ "/tmp/chef-solo/site-cookbooks",
|
23
23
|
"/tmp/chef-solo/cookbooks" ]
|
24
|
+
role_path "/tmp/chef-solo/roles"
|
24
25
|
RUBY
|
25
26
|
end
|
26
27
|
end
|
@@ -0,0 +1,211 @@
|
|
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
|
+
require 'treetop'
|
21
|
+
require 'chef/solr_query/query_transform'
|
22
|
+
|
23
|
+
# mock QueryTransform such that we can access the location of the lucene grammar
|
24
|
+
class Chef
|
25
|
+
class SolrQuery
|
26
|
+
class QueryTransform
|
27
|
+
def self.base_path
|
28
|
+
class_variable_get(:@@base_path)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def build_flat_hash(hsh, prefix="")
|
35
|
+
result = {}
|
36
|
+
hsh.each_pair do |key, value|
|
37
|
+
if value.kind_of?(Hash)
|
38
|
+
result.merge!(build_flat_hash(value, "#{prefix}#{key}_"))
|
39
|
+
else
|
40
|
+
result[prefix+key] = value
|
41
|
+
end
|
42
|
+
end
|
43
|
+
result
|
44
|
+
end
|
45
|
+
|
46
|
+
module Lucene
|
47
|
+
|
48
|
+
class Term < Treetop::Runtime::SyntaxNode
|
49
|
+
# compares a query value and a value, tailing '*'-wildcards are handled correctly.
|
50
|
+
# Value can either be a string or an array, all other objects are converted
|
51
|
+
# to a string and than checked.
|
52
|
+
def match( value )
|
53
|
+
if value.is_a?(Array)
|
54
|
+
value.any?{ |x| self.match(x) }
|
55
|
+
else
|
56
|
+
File.fnmatch(self.text_value, value.to_s)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
class Field < Treetop::Runtime::SyntaxNode
|
62
|
+
# simple field -> value matches, supporting tailing '*'-wildcards in keys
|
63
|
+
# as well as in values
|
64
|
+
def match( item )
|
65
|
+
keys = self.elements[0].match(item)
|
66
|
+
if keys.nil?
|
67
|
+
false
|
68
|
+
else
|
69
|
+
keys.any?{ |key| self.elements[1].match(item[key]) }
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
# we don't support range matches
|
75
|
+
# range of integers would be easy to implement
|
76
|
+
# but string ranges are hard
|
77
|
+
class FiledRange < Treetop::Runtime::SyntaxNode
|
78
|
+
end
|
79
|
+
|
80
|
+
class InclFieldRange < FieldRange
|
81
|
+
end
|
82
|
+
|
83
|
+
class ExclFieldRange < FieldRange
|
84
|
+
end
|
85
|
+
|
86
|
+
class RangeValue < Treetop::Runtime::SyntaxNode
|
87
|
+
end
|
88
|
+
|
89
|
+
class FieldName < Treetop::Runtime::SyntaxNode
|
90
|
+
def match( item )
|
91
|
+
if self.text_value.count("_") > 0
|
92
|
+
item.merge!(build_flat_hash(item))
|
93
|
+
end
|
94
|
+
if self.text_value.end_with?("*")
|
95
|
+
part = self.text_value.chomp("*")
|
96
|
+
item.keys.collect{ |key| key.start_with?(part)? key: nil}.compact
|
97
|
+
else
|
98
|
+
if item.has_key?(self.text_value)
|
99
|
+
[self.text_value,]
|
100
|
+
else
|
101
|
+
nil
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
class Body < Treetop::Runtime::SyntaxNode
|
108
|
+
def match( item )
|
109
|
+
self.elements[0].match( item )
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
class Group < Treetop::Runtime::SyntaxNode
|
114
|
+
def match( item )
|
115
|
+
self.elements[0].match(item)
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
class BinaryOp < Treetop::Runtime::SyntaxNode
|
120
|
+
def match( item )
|
121
|
+
self.elements[1].match(
|
122
|
+
self.elements[0].match(item),
|
123
|
+
self.elements[2].match(item)
|
124
|
+
)
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
class OrOperator < Treetop::Runtime::SyntaxNode
|
129
|
+
def match( cond1, cond2 )
|
130
|
+
cond1 or cond2
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
class AndOperator < Treetop::Runtime::SyntaxNode
|
135
|
+
def match( cond1, cond2 )
|
136
|
+
cond1 and cond2
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
# we don't support fuzzy string matching
|
141
|
+
class FuzzyOp < Treetop::Runtime::SyntaxNode
|
142
|
+
end
|
143
|
+
|
144
|
+
class BoostOp < Treetop::Runtime::SyntaxNode
|
145
|
+
end
|
146
|
+
|
147
|
+
class FuzzyParam < Treetop::Runtime::SyntaxNode
|
148
|
+
end
|
149
|
+
|
150
|
+
class UnaryOp < Treetop::Runtime::SyntaxNode
|
151
|
+
def match( item )
|
152
|
+
self.elements[0].match(
|
153
|
+
self.elements[1].match(item)
|
154
|
+
)
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
class NotOperator < Treetop::Runtime::SyntaxNode
|
159
|
+
def match( cond )
|
160
|
+
not cond
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
class RequiredOperator < Treetop::Runtime::SyntaxNode
|
165
|
+
end
|
166
|
+
|
167
|
+
class ProhibitedOperator < Treetop::Runtime::SyntaxNode
|
168
|
+
end
|
169
|
+
|
170
|
+
class Phrase < Treetop::Runtime::SyntaxNode
|
171
|
+
# a quoted ::Term
|
172
|
+
def match( value )
|
173
|
+
self.elements[0].match(value)
|
174
|
+
end
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
class Query
|
179
|
+
# initialize the parser by using the grammar shipped with chef
|
180
|
+
@@grammar = File.join(Chef::SolrQuery::QueryTransform.base_path, "lucene.treetop")
|
181
|
+
Treetop.load(@@grammar)
|
182
|
+
@@parser = LuceneParser.new
|
183
|
+
|
184
|
+
def self.parse(data)
|
185
|
+
# parse the query into a query tree
|
186
|
+
if data.nil?
|
187
|
+
data = "*:*"
|
188
|
+
end
|
189
|
+
tree = @@parser.parse(data)
|
190
|
+
if tree.nil?
|
191
|
+
msg = "Parse error at offset: #{@@parser.index}\n"
|
192
|
+
msg += "Reason: #{@@parser.failure_reason}"
|
193
|
+
raise "Query #{data} is not supported: #{msg}"
|
194
|
+
end
|
195
|
+
self.clean_tree(tree)
|
196
|
+
tree
|
197
|
+
end
|
198
|
+
|
199
|
+
private
|
200
|
+
|
201
|
+
def self.clean_tree(root_node)
|
202
|
+
# remove all SyntaxNode elements from the tree, we don't need them as
|
203
|
+
# the related ruby class already knowns what to do.
|
204
|
+
return if root_node.elements.nil?
|
205
|
+
root_node.elements.delete_if do |node|
|
206
|
+
node.class.name == "Treetop::Runtime::SyntaxNode"
|
207
|
+
end
|
208
|
+
root_node.elements.each { |node| self.clean_tree(node) }
|
209
|
+
end
|
210
|
+
end
|
211
|
+
|
@@ -0,0 +1,81 @@
|
|
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
|
data/lib/chef/knife/prepare.rb
CHANGED
@@ -30,7 +30,6 @@ class Chef
|
|
30
30
|
@packages.join(' ')
|
31
31
|
end
|
32
32
|
|
33
|
-
# TODO (mat): integration test this, not a gem install
|
34
33
|
def emerge_gem_install
|
35
34
|
ui.msg("Installing required packages...")
|
36
35
|
run_command("sudo USE='-test' ACCEPT_KEYWORDS='~amd64' emerge -u chef")
|
@@ -51,7 +50,6 @@ class Chef
|
|
51
50
|
raise result.stderr unless result.success? || result.stdout.match(installed)
|
52
51
|
end
|
53
52
|
|
54
|
-
# TODO (mat): integration test this, will probably break without sudo
|
55
53
|
def rpm_gem_install
|
56
54
|
ui.msg("Installing required packages...")
|
57
55
|
@packages = %w(ruby ruby-shadow gcc gcc-c++ ruby-devel wget rsync)
|
data/lib/knife-solo/info.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: knife-solo
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.4
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2011-
|
12
|
+
date: 2011-10-07 00:00:00.000000000Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rake
|
16
|
-
requirement: &
|
16
|
+
requirement: &70138524107880 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
@@ -21,10 +21,10 @@ dependencies:
|
|
21
21
|
version: '0'
|
22
22
|
type: :development
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *70138524107880
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: mocha
|
27
|
-
requirement: &
|
27
|
+
requirement: &70138524105520 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ! '>='
|
@@ -32,10 +32,10 @@ dependencies:
|
|
32
32
|
version: '0'
|
33
33
|
type: :development
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *70138524105520
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
37
|
name: virtualbox
|
38
|
-
requirement: &
|
38
|
+
requirement: &70138524103420 !ruby/object:Gem::Requirement
|
39
39
|
none: false
|
40
40
|
requirements:
|
41
41
|
- - ! '>='
|
@@ -43,10 +43,10 @@ dependencies:
|
|
43
43
|
version: '0'
|
44
44
|
type: :development
|
45
45
|
prerelease: false
|
46
|
-
version_requirements: *
|
46
|
+
version_requirements: *70138524103420
|
47
47
|
- !ruby/object:Gem::Dependency
|
48
48
|
name: chef
|
49
|
-
requirement: &
|
49
|
+
requirement: &70138524099600 !ruby/object:Gem::Requirement
|
50
50
|
none: false
|
51
51
|
requirements:
|
52
52
|
- - ~>
|
@@ -54,10 +54,10 @@ dependencies:
|
|
54
54
|
version: 0.10.0
|
55
55
|
type: :runtime
|
56
56
|
prerelease: false
|
57
|
-
version_requirements: *
|
57
|
+
version_requirements: *70138524099600
|
58
58
|
- !ruby/object:Gem::Dependency
|
59
59
|
name: net-ssh
|
60
|
-
requirement: &
|
60
|
+
requirement: &70138524098780 !ruby/object:Gem::Requirement
|
61
61
|
none: false
|
62
62
|
requirements:
|
63
63
|
- - ~>
|
@@ -65,7 +65,7 @@ dependencies:
|
|
65
65
|
version: 2.1.3
|
66
66
|
type: :runtime
|
67
67
|
prerelease: false
|
68
|
-
version_requirements: *
|
68
|
+
version_requirements: *70138524098780
|
69
69
|
description: Handles bootstrapping, running chef solo, rsyncing cookbooks etc
|
70
70
|
email: mat@schaffer.me
|
71
71
|
executables: []
|
@@ -74,7 +74,8 @@ extra_rdoc_files: []
|
|
74
74
|
files:
|
75
75
|
- lib/chef/knife/cook.rb
|
76
76
|
- lib/chef/knife/kitchen.rb
|
77
|
-
- lib/chef/knife/patches/
|
77
|
+
- lib/chef/knife/patches/parser.rb
|
78
|
+
- lib/chef/knife/patches/search_patch.rb
|
78
79
|
- lib/chef/knife/prepare.rb
|
79
80
|
- lib/knife-solo/info.rb
|
80
81
|
- lib/knife-solo/kitchen_command.rb
|
@@ -92,18 +93,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
92
93
|
- - ! '>='
|
93
94
|
- !ruby/object:Gem::Version
|
94
95
|
version: '0'
|
95
|
-
segments:
|
96
|
-
- 0
|
97
|
-
hash: -2883154116349428333
|
98
96
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
99
97
|
none: false
|
100
98
|
requirements:
|
101
99
|
- - ! '>='
|
102
100
|
- !ruby/object:Gem::Version
|
103
101
|
version: '0'
|
104
|
-
segments:
|
105
|
-
- 0
|
106
|
-
hash: -2883154116349428333
|
107
102
|
requirements: []
|
108
103
|
rubyforge_project: nowarning
|
109
104
|
rubygems_version: 1.8.6
|
@@ -1,42 +0,0 @@
|
|
1
|
-
# Taken from Vagrant's patch: https://gist.github.com/867960
|
2
|
-
# based on Brian Akins's patch: http://lists.opscode.com/sympa/arc/chef/2011-02/msg00000.html
|
3
|
-
if Chef::Config[:solo]
|
4
|
-
class Chef
|
5
|
-
module Mixin
|
6
|
-
module Language
|
7
|
-
def data_bag(bag)
|
8
|
-
@solo_data_bags = {} if @solo_data_bags.nil?
|
9
|
-
unless @solo_data_bags[bag]
|
10
|
-
@solo_data_bags[bag] = {}
|
11
|
-
data_bag_path = Chef::Config[:data_bag_path]
|
12
|
-
Dir.glob(File.join(data_bag_path, bag, "*.json")).each do |f|
|
13
|
-
item = JSON.parse(IO.read(f))
|
14
|
-
@solo_data_bags[bag][item['id']] = item
|
15
|
-
end
|
16
|
-
end
|
17
|
-
@solo_data_bags[bag].keys
|
18
|
-
end
|
19
|
-
|
20
|
-
def data_bag_item(bag, item)
|
21
|
-
data_bag(bag) unless ( !@solo_data_bags.nil? && @solo_data_bags[bag])
|
22
|
-
@solo_data_bags[bag][item]
|
23
|
-
end
|
24
|
-
|
25
|
-
end
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
class Chef
|
30
|
-
class Recipe
|
31
|
-
def search(bag_name, query=nil)
|
32
|
-
Chef::Log.warn("Simplistic search patch, ignoring query of %s" % [query]) unless query.nil?
|
33
|
-
data_bag(bag_name.to_s).each do |bag_item_id|
|
34
|
-
bag_item = data_bag_item(bag_name.to_s, bag_item_id)
|
35
|
-
yield bag_item
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
end
|