knife_sous 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (48) hide show
  1. data/.gitignore +1 -0
  2. data/.ruby-version +1 -0
  3. data/Gemfile +9 -0
  4. data/Gemfile.lock +106 -0
  5. data/Guardfile +6 -0
  6. data/README.md +51 -0
  7. data/Rakefile +16 -0
  8. data/knife_sous.gemspec +28 -0
  9. data/lib/chef/knife/sous_bootstrap.rb +31 -0
  10. data/lib/chef/knife/sous_clean.rb +30 -0
  11. data/lib/chef/knife/sous_cook.rb +31 -0
  12. data/lib/chef/knife/sous_init.rb +39 -0
  13. data/lib/chef/knife/sous_list.rb +22 -0
  14. data/lib/chef/knife/sous_prepare.rb +31 -0
  15. data/lib/knife_sous/configure_command.rb +12 -0
  16. data/lib/knife_sous/dsl_definitions.rb +29 -0
  17. data/lib/knife_sous/dsl_wrapper.rb +8 -0
  18. data/lib/knife_sous/mixins/hash_mixins.rb +14 -0
  19. data/lib/knife_sous/namespace.rb +19 -0
  20. data/lib/knife_sous/namespace_presenter.rb +27 -0
  21. data/lib/knife_sous/node.rb +47 -0
  22. data/lib/knife_sous/node_command.rb +36 -0
  23. data/lib/knife_sous/node_presenter.rb +13 -0
  24. data/lib/knife_sous/processor_command.rb +52 -0
  25. data/lib/knife_sous.rb +3 -0
  26. data/lib/templates/nodes.example.rb +32 -0
  27. data/spec/lib/chef/knife/sous_bootstrap_spec.rb +42 -0
  28. data/spec/lib/chef/knife/sous_clean_spec.rb +41 -0
  29. data/spec/lib/chef/knife/sous_cook_spec.rb +52 -0
  30. data/spec/lib/chef/knife/sous_init_spec.rb +56 -0
  31. data/spec/lib/chef/knife/sous_list_spec.rb +33 -0
  32. data/spec/lib/chef/knife/sous_prepare_spec.rb +42 -0
  33. data/spec/lib/knife_sous/configure_command_spec.rb +27 -0
  34. data/spec/lib/knife_sous/dsl_definitions_spec.rb +52 -0
  35. data/spec/lib/knife_sous/dsl_wrapper_spec.rb +12 -0
  36. data/spec/lib/knife_sous/mixins/hash_mixins_spec.rb +23 -0
  37. data/spec/lib/knife_sous/namespace_presenter_spec.rb +57 -0
  38. data/spec/lib/knife_sous/namespace_spec.rb +59 -0
  39. data/spec/lib/knife_sous/node_presenter_spec.rb +18 -0
  40. data/spec/lib/knife_sous/node_spec.rb +63 -0
  41. data/spec/lib/knife_sous/processor_command_spec.rb +135 -0
  42. data/spec/spec_helper.rb +14 -0
  43. data/spec/support/fixtures/nodes.rb +20 -0
  44. data/spec/support/knife_command_helpers.rb +11 -0
  45. data/spec/support/shared_examples/collection.rb +24 -0
  46. data/spec/support/shared_examples/dsl_wrapper.rb +11 -0
  47. data/spec/support/shared_examples/node_command.rb +66 -0
  48. metadata +178 -0
data/.gitignore ADDED
@@ -0,0 +1 @@
1
+ tmp
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ ruby-1.9.3-p362@knife_sous
data/Gemfile ADDED
@@ -0,0 +1,9 @@
1
+ source "http://rubygems.org"
2
+
3
+ gemspec
4
+
5
+ gem 'guard'
6
+ gem 'guard-rspec'
7
+ gem 'pry'
8
+ gem 'rb-fsevent'
9
+
data/Gemfile.lock ADDED
@@ -0,0 +1,106 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ knife_sous (0.0.1)
5
+ knife-solo (~> 0.2.0)
6
+
7
+ GEM
8
+ remote: http://rubygems.org/
9
+ specs:
10
+ archive-tar-minitar (0.5.2)
11
+ chef (11.4.0)
12
+ erubis
13
+ highline (>= 1.6.9)
14
+ json (>= 1.4.4, <= 1.7.7)
15
+ mixlib-authentication (>= 1.3.0)
16
+ mixlib-cli (~> 1.3.0)
17
+ mixlib-config (>= 1.1.2)
18
+ mixlib-log (>= 1.3.0)
19
+ mixlib-shellout
20
+ net-ssh (~> 2.6)
21
+ net-ssh-multi (~> 1.1.0)
22
+ ohai (>= 0.6.0)
23
+ rest-client (>= 1.0.4, < 1.7.0)
24
+ yajl-ruby (~> 1.1)
25
+ coderay (1.0.8)
26
+ diff-lcs (1.1.3)
27
+ erubis (2.7.0)
28
+ guard (1.6.2)
29
+ listen (>= 0.6.0)
30
+ lumberjack (>= 1.0.2)
31
+ pry (>= 0.9.10)
32
+ terminal-table (>= 1.4.3)
33
+ thor (>= 0.14.6)
34
+ guard-rspec (2.4.0)
35
+ guard (>= 1.1)
36
+ rspec (~> 2.11)
37
+ highline (1.6.15)
38
+ ipaddress (0.8.0)
39
+ json (1.7.7)
40
+ knife-solo (0.2.0)
41
+ chef (>= 10.12)
42
+ librarian (~> 0.0.20)
43
+ net-ssh (>= 2.2.2, < 3.0)
44
+ librarian (0.0.26)
45
+ archive-tar-minitar (>= 0.5.2)
46
+ chef (>= 0.10)
47
+ highline
48
+ thor (~> 0.15)
49
+ listen (0.7.2)
50
+ lumberjack (1.0.2)
51
+ method_source (0.8.1)
52
+ mime-types (1.21)
53
+ mixlib-authentication (1.3.0)
54
+ mixlib-log
55
+ mixlib-cli (1.3.0)
56
+ mixlib-config (1.1.2)
57
+ mixlib-log (1.4.1)
58
+ mixlib-shellout (1.1.0)
59
+ net-ssh (2.6.5)
60
+ net-ssh-gateway (1.2.0)
61
+ net-ssh (>= 2.6.5)
62
+ net-ssh-multi (1.1)
63
+ net-ssh (>= 2.1.4)
64
+ net-ssh-gateway (>= 0.99.0)
65
+ ohai (6.16.0)
66
+ ipaddress
67
+ mixlib-cli
68
+ mixlib-config
69
+ mixlib-log
70
+ mixlib-shellout
71
+ systemu
72
+ yajl-ruby
73
+ pry (0.9.11.4)
74
+ coderay (~> 1.0.5)
75
+ method_source (~> 0.8)
76
+ slop (~> 3.4)
77
+ rake (10.0.3)
78
+ rb-fsevent (0.9.3)
79
+ rest-client (1.6.7)
80
+ mime-types (>= 1.16)
81
+ rspec (2.12.0)
82
+ rspec-core (~> 2.12.0)
83
+ rspec-expectations (~> 2.12.0)
84
+ rspec-mocks (~> 2.12.0)
85
+ rspec-core (2.12.2)
86
+ rspec-expectations (2.12.1)
87
+ diff-lcs (~> 1.1.3)
88
+ rspec-mocks (2.12.1)
89
+ slop (3.4.3)
90
+ systemu (2.5.2)
91
+ terminal-table (1.4.5)
92
+ thor (0.17.0)
93
+ yajl-ruby (1.1.0)
94
+
95
+ PLATFORMS
96
+ ruby
97
+
98
+ DEPENDENCIES
99
+ bundler (~> 1.1)
100
+ guard
101
+ guard-rspec
102
+ knife_sous!
103
+ pry
104
+ rake (~> 10.0.0)
105
+ rb-fsevent
106
+ rspec (~> 2.12.0)
data/Guardfile ADDED
@@ -0,0 +1,6 @@
1
+
2
+ guard 'rspec', cli: '--color' do
3
+ watch(%r{^spec/.+_spec\.rb$})
4
+ watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
5
+ watch('spec/spec_helper.rb') { "spec" }
6
+ end
data/README.md ADDED
@@ -0,0 +1,51 @@
1
+ # Knife Sous
2
+
3
+ A Chef Knife plugin which uses a DSL to configure and manage
4
+ [knife-solo](http://matschaffer.github.com/knife-solo/) nodes.
5
+
6
+ ## Usage
7
+
8
+ Simply ensure the gem is installed using:
9
+
10
+ gem install knife_sous
11
+
12
+ Or add this to your Gemfile if you use bundler:
13
+
14
+ gem 'knife_sous'
15
+
16
+ Having the gem installed will add Knife subcommands. Run `knife sous` with no
17
+ arguments to see a list of available commands.
18
+
19
+
20
+ ## Configure
21
+
22
+ Node configuration is done in `nodes/nodes.rb`. It uses a DSL similar to Rake.
23
+ You can namespace your nodes however you want. Example `nodes.rb`:
24
+
25
+ ```rb
26
+ namespace :production do |prod|
27
+ prod.namespace :web do |web|
28
+ web.node :nodetastic,
29
+ node_config: 'nodes/some_node.json',
30
+ hostname: 12.34.56.78,
31
+ user: 'deploy',
32
+ ssh_port: 1234
33
+ end
34
+ end
35
+ prod.namespace :db do |db|
36
+ db.node :database_node, node_config: 'nodes/database.json', hostname: 123.456.78
37
+ end
38
+ end
39
+
40
+ node :vagrant, node_config:'nodes/some_node.json'
41
+
42
+ ```
43
+
44
+ ## Contributing
45
+
46
+ 1. Fork it
47
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
48
+ 3. Commit your changes (`git commit -am 'Added some feature'`)
49
+ 4. Push to the branch (`git push origin my-new-feature`)
50
+ 5. Create new Pull Request
51
+
data/Rakefile ADDED
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env rake
2
+
3
+ require 'rubygems'
4
+ require 'bundler/setup'
5
+ require 'bundler/gem_tasks'
6
+ require 'rspec/core/rake_task'
7
+
8
+ desc 'Default: run unit tests.'
9
+ task :default => :spec
10
+
11
+ desc "Run all specs"
12
+ RSpec::Core::RakeTask.new do |t|
13
+ t.pattern = 'spec/**/*_spec.rb'
14
+ t.rspec_opts = '--color'
15
+ end
16
+
@@ -0,0 +1,28 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+
4
+ Gem::Specification.new do |s|
5
+ s.authors = "Shaun Dern"
6
+ s.email = "shaun@substantail.com"
7
+
8
+ s.name = 'knife_sous'
9
+ s.version = "0.0.1"
10
+ s.description = %q{Knife plugin for managing knife-solo nodes}
11
+ s.summary = %q{A Chef Knife plugin which uses a DSL to configure and
12
+ manage knife solo nodes. Run knife solo commands on one or multiple nodes.}
13
+ s.homepage = %q{http://github.com/substantial/knife_sous}
14
+ s.license = "MIT"
15
+
16
+ s.rubyforge_project = "knife_sous"
17
+
18
+ s.files = `git ls-files`.split("\n")
19
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
20
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
21
+ s.require_paths = ["lib"]
22
+
23
+ s.add_development_dependency "rspec", "~> 2.12.0"
24
+ s.add_development_dependency "rake", "~> 10.0.0"
25
+ s.add_development_dependency "bundler", "~> 1.1"
26
+ s.add_dependency "knife-solo", "~> 0.2.0"
27
+ end
28
+
@@ -0,0 +1,31 @@
1
+ require 'chef/knife'
2
+ require 'knife_sous/processor_command'
3
+ require 'knife_sous/configure_command'
4
+ require 'knife_sous/node_command'
5
+
6
+ class Chef
7
+ class Knife
8
+ class SousBootstrap < Knife
9
+ include KnifeSous::ProcessorCommand
10
+ include KnifeSous::ConfigureCommand
11
+ include KnifeSous::NodeCommand
12
+
13
+ deps do
14
+ require 'chef/knife/solo_bootstrap'
15
+ end
16
+
17
+ banner "knife sous bootstrap [NAMESPACE] NODE"
18
+
19
+ def solo_bootstrap_node(node)
20
+ solo_bootstrap_command = configure_command(Chef::Knife::SoloBootstrap.new, node)
21
+ Chef::Knife::SoloBootstrap.load_deps
22
+ solo_bootstrap_command.name_args << node.hostname
23
+ solo_bootstrap_command.name_args << node.node_config
24
+ solo_bootstrap_command.run
25
+ end
26
+
27
+ alias_method :solo_command, :solo_bootstrap_node
28
+ end
29
+ end
30
+ end
31
+
@@ -0,0 +1,30 @@
1
+ require 'chef/knife'
2
+ require 'knife_sous/processor_command'
3
+ require 'knife_sous/configure_command'
4
+ require 'knife_sous/node_command'
5
+
6
+ class Chef
7
+ class Knife
8
+ class SousClean < Knife
9
+ include KnifeSous::ProcessorCommand
10
+ include KnifeSous::ConfigureCommand
11
+ include KnifeSous::NodeCommand
12
+
13
+ deps do
14
+ require 'chef/knife/solo_clean'
15
+ end
16
+
17
+ banner "knife sous clean [NAMESPACE] NODE"
18
+
19
+ def solo_clean_node(node)
20
+ solo_cook_command = configure_command(Chef::Knife::SoloClean.new, node)
21
+ Chef::Knife::SoloClean.load_deps
22
+ solo_cook_command.name_args << node.hostname
23
+ solo_cook_command.run
24
+ end
25
+
26
+ alias_method :solo_command, :solo_clean_node
27
+ end
28
+ end
29
+ end
30
+
@@ -0,0 +1,31 @@
1
+ require 'chef/knife'
2
+ require 'knife_sous/processor_command'
3
+ require 'knife_sous/configure_command'
4
+ require 'knife_sous/node_command'
5
+
6
+ class Chef
7
+ class Knife
8
+ class SousCook < Knife
9
+ include KnifeSous::ProcessorCommand
10
+ include KnifeSous::ConfigureCommand
11
+ include KnifeSous::NodeCommand
12
+
13
+ deps do
14
+ require 'chef/knife/solo_cook'
15
+ end
16
+
17
+ banner "knife sous cook [NAMESPACE] NODE"
18
+
19
+ def solo_cook_node(node)
20
+ solo_cook_command = configure_command(Chef::Knife::SoloCook.new, node)
21
+ Chef::Knife::SoloCook.load_deps
22
+ solo_cook_command.name_args << node.hostname
23
+ solo_cook_command.name_args << node.node_config
24
+ solo_cook_command.run
25
+ end
26
+
27
+ alias_method :solo_command, :solo_cook_node
28
+ end
29
+ end
30
+ end
31
+
@@ -0,0 +1,39 @@
1
+ require 'chef/knife'
2
+ require 'knife_sous/processor_command'
3
+
4
+ class Chef
5
+ class Knife
6
+ class SousInit < Knife
7
+ include KnifeSous::ProcessorCommand
8
+
9
+ banner "knife sous init [DIRECTORY]"
10
+
11
+ def node_manifest_example_path
12
+ File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'templates', 'nodes.example.rb'))
13
+ end
14
+
15
+ def run
16
+ unless name_args.empty?
17
+ target = File.expand_path(name_args.first)
18
+ else
19
+ target = File.expand_path(Dir.pwd, File.join('nodes'))
20
+ end
21
+ copy_template(target)
22
+ end
23
+
24
+ def copy_template(location)
25
+ FileUtils.mkdir_p(location)
26
+
27
+ target_file = File.join(location, 'nodes.example.rb' )
28
+
29
+ unless File.exists?(target_file)
30
+ FileUtils.cp(node_manifest_example_path, target_file)
31
+ ui.msg "Example nodes.rb copied to #{target_file}"
32
+ else
33
+ ui.error "File already exists: #{target_file}"
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
39
+
@@ -0,0 +1,22 @@
1
+ require 'chef/knife'
2
+ require 'knife_sous/processor_command'
3
+ require 'knife_sous/namespace_presenter'
4
+
5
+ class Chef
6
+ class Knife
7
+ class SousList < Knife
8
+ include KnifeSous::ProcessorCommand
9
+
10
+ banner "knife sous list"
11
+
12
+ def run
13
+ present_nodes
14
+ end
15
+
16
+ def present_nodes
17
+ ui.output(KnifeSous::NamespacePresenter.new(root_namespace).present)
18
+ end
19
+ end
20
+ end
21
+ end
22
+
@@ -0,0 +1,31 @@
1
+ require 'chef/knife'
2
+ require 'knife_sous/processor_command'
3
+ require 'knife_sous/configure_command'
4
+ require 'knife_sous/node_command'
5
+
6
+ class Chef
7
+ class Knife
8
+ class SousPrepare < Knife
9
+ include KnifeSous::ProcessorCommand
10
+ include KnifeSous::ConfigureCommand
11
+ include KnifeSous::NodeCommand
12
+
13
+ deps do
14
+ require 'chef/knife/solo_prepare'
15
+ end
16
+
17
+ banner "knife sous prepare [NAMESPACE] NODE"
18
+
19
+ def solo_prepare_node(node)
20
+ solo_cook_command = configure_command(Chef::Knife::SoloPrepare.new, node)
21
+ Chef::Knife::SoloPrepare.load_deps
22
+ solo_cook_command.name_args << node.hostname
23
+ solo_cook_command.name_args << node.node_config
24
+ solo_cook_command.run
25
+ end
26
+
27
+ alias_method :solo_command, :solo_prepare_node
28
+ end
29
+ end
30
+ end
31
+
@@ -0,0 +1,12 @@
1
+ module KnifeSous
2
+ module ConfigureCommand
3
+
4
+ module_function
5
+
6
+ def configure_command(command, node)
7
+ command.config.merge!(node.config)
8
+ command
9
+ end
10
+ end
11
+ end
12
+
@@ -0,0 +1,29 @@
1
+ require 'knife_sous/namespace'
2
+ require 'knife_sous/node'
3
+
4
+ module KnifeSous
5
+ module DSL
6
+ def self.included(base)
7
+ base.class_eval do
8
+ base.extend Forwardable
9
+ def_delegators :children, :<<, :first, :last, :[], :map, :each, :to_a, :keep_if, :empty?
10
+ end
11
+ end
12
+
13
+ def children
14
+ @children ||= []
15
+ end
16
+
17
+ def namespace(name, &block)
18
+ namespace = Namespace.new(name)
19
+ namespace.evaluate_block(&block)
20
+ children << namespace
21
+ end
22
+
23
+ def node(name, args={})
24
+ node = Node.new(name, args)
25
+ children << node
26
+ end
27
+ end
28
+ end
29
+
@@ -0,0 +1,8 @@
1
+ module KnifeSous
2
+ module DSLWrapper
3
+ def evaluate_block(&block)
4
+ yield self if block_given?
5
+ end
6
+ end
7
+ end
8
+
@@ -0,0 +1,14 @@
1
+ module KnifeSous
2
+ module HashMixins
3
+
4
+ module_function
5
+
6
+ def normalize_hash(hash)
7
+ Hash[hash.map{ |k, v| [sanitize_key(k), v.to_s] }]
8
+ end
9
+
10
+ def sanitize_key(key)
11
+ key.to_s.downcase.gsub(/-/, '_').to_sym
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,19 @@
1
+ require 'knife_sous/node'
2
+
3
+ require 'knife_sous/dsl_definitions'
4
+ require 'knife_sous/dsl_wrapper'
5
+
6
+
7
+ module KnifeSous
8
+ class Namespace
9
+ include DSL
10
+ include DSLWrapper
11
+
12
+ attr_reader :name
13
+
14
+ def initialize(name)
15
+ @name = name.to_s
16
+ end
17
+ end
18
+ end
19
+
@@ -0,0 +1,27 @@
1
+ require 'knife_sous/node_presenter'
2
+
3
+ module KnifeSous
4
+ class NamespacePresenter
5
+ attr_reader :namespace
6
+
7
+ def initialize(namespace)
8
+ @namespace = namespace
9
+ end
10
+
11
+ def present
12
+ return @namespace.name if @namespace.empty?
13
+
14
+ nodes = ""
15
+ @namespace.each do |child|
16
+ nodes << "#{@namespace.name} #{presenter(child).present}".lstrip
17
+ end
18
+ nodes
19
+ end
20
+
21
+ def presenter(item)
22
+ klass = item.is_a?(Node) ? NodePresenter : NamespacePresenter
23
+ klass.new(item)
24
+ end
25
+ end
26
+ end
27
+
@@ -0,0 +1,47 @@
1
+ require 'knife_sous/dsl_wrapper'
2
+ require 'knife_sous/mixins/hash_mixins'
3
+
4
+ module KnifeSous
5
+ class Node
6
+ include KnifeSous::HashMixins
7
+
8
+ attr_reader :name, :config
9
+
10
+ def initialize(name, config_args={})
11
+ @name = name.to_s
12
+ @config = {}
13
+ update_config(config_args)
14
+ end
15
+
16
+ def update_config(other_config={})
17
+ config = convert_aliases(normalize_hash(other_config))
18
+ @config.merge!(config)
19
+ end
20
+
21
+ def convert_aliases(config_hash = {})
22
+ config_aliases.each do |key, value|
23
+ if config_hash.has_key?(key)
24
+ config_hash[value] = config_hash[key]
25
+ config_hash.delete(key)
26
+ end
27
+ end
28
+ config_hash
29
+ end
30
+
31
+ def node_name
32
+ @config[:node_name] || @name
33
+ end
34
+
35
+ def method_missing(method_name, *args, &block)
36
+ @config[method_name.to_sym]
37
+ end
38
+
39
+ def config_aliases
40
+ {
41
+ ssh_config_file: :ssh_config,
42
+ ip: :hostname
43
+ }
44
+ end
45
+ end
46
+ end
47
+
@@ -0,0 +1,36 @@
1
+ module KnifeSous
2
+ module NodeCommand
3
+
4
+ def search_for_target
5
+ result = search(name_args)
6
+ if result.nil?
7
+ ui.error "Can't find node. Run `knife sous list` to see nodes"
8
+ exit 1
9
+ end
10
+ result
11
+ end
12
+
13
+ def run
14
+ check_args
15
+ search_result = search_for_target
16
+ process_result(search_result)
17
+ end
18
+
19
+ def process_result(result)
20
+ if result.is_a? KnifeSous::Namespace
21
+ result.each { |child| process_result(child) }
22
+ else
23
+ solo_command(result)
24
+ end
25
+ end
26
+
27
+ def check_args
28
+ unless name_args.size > 0
29
+ ui.fatal "You need to specificy a node or namespace"
30
+ show_usage
31
+ exit 1
32
+ end
33
+ end
34
+ end
35
+ end
36
+
@@ -0,0 +1,13 @@
1
+ module KnifeSous
2
+ class NodePresenter
3
+ attr_reader :node
4
+
5
+ def initialize(node)
6
+ @node = node
7
+ end
8
+
9
+ def present
10
+ "#{@node.name}\n"
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,52 @@
1
+ require 'knife_sous/namespace'
2
+
3
+ module KnifeSous
4
+ module ProcessorCommand
5
+ def self.included(other)
6
+ other.class_eval do
7
+ option :node_manifest_file,
8
+ :long => '--node-manifest-file NODE_MANIFEST_FILE',
9
+ :description => 'Alternate location for node manifest config file',
10
+ :default => File.join("nodes", "nodes.rb")
11
+ end
12
+ end
13
+
14
+ def validate_config!
15
+ unless File.exists?(manifest_file_path)
16
+ ui.fatal("Couldn't find #{manifest_file_path}")
17
+ exit 1
18
+ end
19
+ unless File.readable?(manifest_file_path)
20
+ ui.fatal("Can't read #{manifest_file_path}")
21
+ exit 1
22
+ end
23
+ true
24
+ end
25
+
26
+ def search(target_qualifiers = [])
27
+ namespace = root_namespace
28
+ target_qualifiers.each do |target_qualifier|
29
+ return nil if namespace.nil?
30
+ namespace = namespace.keep_if { |item| item.name == target_qualifier }.first
31
+ end
32
+ namespace
33
+ end
34
+
35
+ def root_namespace
36
+ @root_namespace ||= process_config
37
+ end
38
+
39
+ def manifest_file_path
40
+ config[:node_manifest_file] ||= default_config[:node_manifest_file]
41
+ @manifest_file_path ||= File.expand_path(File.join(Dir.pwd, config[:node_manifest_file]))
42
+ end
43
+
44
+ def process_config
45
+ validate_config!
46
+ root_namespace = Namespace.new('')
47
+ root_namespace.instance_eval(File.read(manifest_file_path), manifest_file_path)
48
+ root_namespace
49
+ end
50
+ end
51
+ end
52
+
data/lib/knife_sous.rb ADDED
@@ -0,0 +1,3 @@
1
+
2
+ require 'chef/knife/sous_list'
3
+