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.
@@ -1,24 +1,39 @@
1
- # 0.1.0: In progress
1
+ # 0.1.0: January 12, 2013
2
2
 
3
- ## Goals
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]: http://github.com/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
@@ -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
- Knife-solo is a gem plugin for Chef's knife utility. It currently adds 5 subcommands to knife:
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 - ignored).join("\n")
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
- class InclFieldRange < FieldRange
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.has_key?(self.text_value)
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
@@ -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 ||= ["/opt/chef/embedded/bin", "/opt/opscode/embedded/bin"]
14
- OMNIBUS_EMBEDDED_GEM_PATHS ||= ["/opt/chef/embedded/lib/ruby/gems/1.9.1", "/opt/opscode/embedded/lib/ruby/gems/1.9.1"]
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 => '--skip-chef-check',
33
- :boolean => true,
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 => '--sync-only',
38
- :boolean => false,
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 => '-W',
43
- :long => '--why-run',
44
- :boolean => true,
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)}}
@@ -23,8 +23,6 @@ class Chef
23
23
  end
24
24
  end
25
25
 
26
- private
27
-
28
26
  def create_cupboards(base, dirs)
29
27
  dirs.each do |dir|
30
28
  cupboard_dir = File.join(base, dir)
@@ -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 => "--omnibus-version VERSION",
25
- :description => "The version of Omnibus to install"
24
+ :long => '--omnibus-version VERSION',
25
+ :description => 'The version of Omnibus to install'
26
26
 
27
27
  option :omnibus_url,
28
- :long => "--omnibus-url URL",
29
- :description => "URL to download install.sh from"
28
+ :long => '--omnibus-url URL',
29
+ :description => 'URL to download install.sh from'
30
30
 
31
31
  option :omnibus_options,
32
- :long => "--omnibus-options \"-r -n\"",
33
- :description => "Pass options to the install.sh script"
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 which curl 2>/dev/null; then
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[:options]}" if prepare.config[:options]
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 || perepare.run_command("lsb_release -d -s").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 => "omnibus", :version => "RHEL5"}
90
+ {:type => "yum_omnibus", :version => "RHEL5"}
89
91
  when %r{CentOS.*? 6}
90
- {:type => "omnibus", :version => "RHEL6"}
92
+ {:type => "yum_omnibus", :version => "RHEL6"}
91
93
  when %r{Red Hat Enterprise.*? 5}
92
- {:type => "omnibus", :version => "RHEL5"}
94
+ {:type => "yum_omnibus", :version => "RHEL5"}
93
95
  when %r{Red Hat Enterprise.*? 6}
94
- {:type => "omnibus", :version => "RHEL6"}
96
+ {:type => "yum_omnibus", :version => "RHEL6"}
95
97
  when %r{Fedora release.*? 15}
96
- {:type => "omnibus", :version => "FC15"}
98
+ {:type => "yum_omnibus", :version => "FC15"}
97
99
  when %r{Fedora release.*? 16}
98
- {:type => "omnibus", :version => "FC16"}
100
+ {:type => "yum_omnibus", :version => "FC16"}
99
101
  when %r{Fedora release.*? 17}
100
- {:type => "omnibus", :version => "FC17"}
102
+ {:type => "yum_omnibus", :version => "FC17"}
101
103
  when %r{Scientific Linux.*? 5}
102
- {:type => "omnibus", :version => "RHEL5"}
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]}
@@ -1,5 +1,5 @@
1
1
  module KnifeSolo
2
2
  def self.version
3
- '0.1.0.pre1'
3
+ '0.1.0'
4
4
  end
5
5
  end
@@ -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 => "-N NAME",
16
- :long => "--node-name NAME",
17
- :description => "The Chef node name for your new node"
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 => "-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 => []
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 => "-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 => {}
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 => "-F CONFIG_FILE",
26
- :long => "--ssh-config-file CONFIG_FILE",
27
- :description => "Alternate location for ssh config file"
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 => "-P PASSWORD",
31
- :long => "--ssh-password PASSWORD",
32
- :description => "The ssh password"
30
+ :short => '-P PASSWORD',
31
+ :long => '--ssh-password PASSWORD',
32
+ :description => 'The ssh password'
33
33
 
34
34
  option :ssh_identity,
35
- :short => "-i FILE",
36
- :long => "--ssh-identity FILE",
37
- :description => "The ssh identity file"
35
+ :short => '-i FILE',
36
+ :long => '--ssh-identity FILE',
37
+ :description => 'The ssh identity file'
38
38
 
39
39
  option :ssh_port,
40
- :short => "-p PORT",
41
- :long => "--ssh-port PORT",
42
- :description => "The ssh port"
40
+ :short => '-p PORT',
41
+ :long => '--ssh-port PORT',
42
+ :description => 'The ssh port'
43
43
 
44
44
  option :startup_script,
45
- :short => "-s FILE",
46
- :long => "--startup-script FILE",
47
- :description => "The startup script on the remote server containing variable definitions"
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
 
@@ -8,7 +8,6 @@ module Apache2Bootstrap
8
8
 
9
9
  def test_apache2
10
10
  write_cheffile
11
- system "librarian-chef install >> #{log_file}"
12
11
  assert_subcommand "bootstrap --run-list=recipe[apache2]"
13
12
  assert_match default_apache_message, http_response
14
13
  end
@@ -11,16 +11,15 @@ module Apache2Cook
11
11
  end
12
12
 
13
13
  def http_response
14
- Net::HTTP.get(URI.parse("http://"+server.public_ip_address))
14
+ Net::HTTP.get(URI.parse("http://#{server.public_ip_address}"))
15
15
  end
16
16
 
17
17
  def default_apache_message
18
- /It works!/
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
@@ -9,10 +9,6 @@ class Centos5_6Test < IntegrationTest
9
9
  "ami-3fe42456"
10
10
  end
11
11
 
12
- def default_apache_message
13
- /Apache 2 Test Page/
14
- end
15
-
16
12
  include EmptyCook
17
13
  include Apache2Cook
18
14
  include EncryptedDataBag
@@ -1,9 +1,8 @@
1
1
  require 'rubygems'
2
- require 'bundler'
2
+ require 'bundler/setup'
3
3
 
4
- Bundler.require
5
4
  require 'minitest/parallel'
6
- Bundler.require(:test)
5
+ require 'minitest/autorun'
7
6
 
8
7
  require 'pathname'
9
8
  $base_dir = Pathname.new(__FILE__).dirname
@@ -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
@@ -1,4 +1,5 @@
1
1
  require 'yaml'
2
+ require 'fog'
2
3
 
3
4
  # A custom runner that serves as a common point for EC2 control
4
5
  class EC2Runner < MiniTest::Unit
@@ -1,7 +1,7 @@
1
1
  require 'rubygems'
2
- require 'bundler'
2
+ require 'bundler/setup'
3
3
 
4
- Bundler.require
5
- Bundler.require(:test)
4
+ require 'minitest/autorun'
5
+ require 'mocha/setup'
6
6
 
7
7
  require 'support/test_case'
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.pre1
5
- prerelease: 6
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: 2012-12-28 00:00:00.000000000 Z
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: chef
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.10.10
54
- type: :runtime
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.10.10
77
+ version: '0'
62
78
  - !ruby/object:Gem::Dependency
63
- name: net-ssh
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: 2.1.3
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: 2.3.0
73
- type: :runtime
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: 2.1.3
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: 2.3.0
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/search_patch.rb
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: 1.3.1
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