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.
@@ -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
@@ -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(/^\s+/, '')
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
@@ -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)
@@ -1,3 +1,5 @@
1
1
  module KnifeSolo
2
- VERSION = '0.0.3'
2
+ def self.version
3
+ '0.0.4'
4
+ end
3
5
  end
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.3
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-08-01 00:00:00.000000000Z
12
+ date: 2011-10-07 00:00:00.000000000Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rake
16
- requirement: &70346489903680 !ruby/object:Gem::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: *70346489903680
24
+ version_requirements: *70138524107880
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: mocha
27
- requirement: &70346489903000 !ruby/object:Gem::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: *70346489903000
35
+ version_requirements: *70138524105520
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: virtualbox
38
- requirement: &70346489902460 !ruby/object:Gem::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: *70346489902460
46
+ version_requirements: *70138524103420
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: chef
49
- requirement: &70346489901760 !ruby/object:Gem::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: *70346489901760
57
+ version_requirements: *70138524099600
58
58
  - !ruby/object:Gem::Dependency
59
59
  name: net-ssh
60
- requirement: &70346489901160 !ruby/object:Gem::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: *70346489901160
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/data_bags_patch.rb
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