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
@@ -0,0 +1,32 @@
1
+ # def vagrant_ssh_config_file
2
+ # @vagrant_ssh_config_file ||=begin
3
+ # config_file = Tempfile.new('vagrant_ssh_config')
4
+ # config_file.write(`vagrant ssh-config`)
5
+ # config_file.close
6
+ # at_exit { config_file.delete }
7
+ # config_file
8
+ # end
9
+ # @vagrant_ssh_config_file.path
10
+ # end
11
+ #
12
+ # def default_node_options
13
+ # {
14
+ # user: 'deploy',
15
+ # node_config: 'nodes/server.json'
16
+ # }
17
+ # end
18
+ #
19
+ # node :vagrant, node_config: 'nodes/something.json',
20
+ # hostname: 'default',
21
+ # ssh_config: vagrant_ssh_config_file
22
+ #
23
+ # namespace :production do |prod|
24
+ # prod.node :node_awesome, default_options.merge!(hostname: '00.12.34.56')
25
+ # prod.namespace :web do |web|
26
+ # web.node :nodetastic,
27
+ # hostname: "12.34.56.789",
28
+ # ssh_port: 22,
29
+ # identity_file: "path/to/identity"
30
+ # end
31
+ # end
32
+ #
@@ -0,0 +1,42 @@
1
+ require 'spec_helper'
2
+
3
+ describe Chef::Knife::SousBootstrap do
4
+ include KnifeCommandHelpers
5
+
6
+ describe "#banner" do
7
+ it "should have display how to use command" do
8
+ command.banner.should == 'knife sous bootstrap [NAMESPACE] NODE'
9
+ end
10
+ end
11
+ it_should_behave_like "a node command" do
12
+ let(:node_command) { command }
13
+ end
14
+
15
+ describe "#solo_bootstrap_node" do
16
+ let(:node) { KnifeSous::Node.new('nodetastic') }
17
+ let(:cmd) { command }
18
+ let(:solo_bootstrap_command) { Chef::Knife::SoloBootstrap.new }
19
+
20
+ before do
21
+ Chef::Knife::SoloBootstrap.stub(new: solo_bootstrap_command)
22
+ solo_bootstrap_command.stub(:run)
23
+ cmd.stub(configure_command: solo_bootstrap_command)
24
+ node.update_config(
25
+ node_config: '/path/to/node/config',
26
+ hostname: 'host_ip'
27
+ )
28
+ end
29
+
30
+ it "should provide name to args and run" do
31
+ solo_bootstrap_command.should_receive(:run)
32
+ cmd.solo_bootstrap_node(node)
33
+
34
+ solo_bootstrap_command.name_args.should == %w[host_ip /path/to/node/config]
35
+ end
36
+ end
37
+
38
+ def command(*args)
39
+ knife_command(Chef::Knife::SousBootstrap, *args)
40
+ end
41
+ end
42
+
@@ -0,0 +1,41 @@
1
+ require 'spec_helper'
2
+
3
+ describe Chef::Knife::SousClean do
4
+ include KnifeCommandHelpers
5
+
6
+ describe "#banner" do
7
+ it "should have display how to use command" do
8
+ command.banner.should == 'knife sous clean [NAMESPACE] NODE'
9
+ end
10
+ end
11
+ it_should_behave_like "a node command" do
12
+ let(:node_command) { command }
13
+ end
14
+
15
+ describe "#solo_clean_node" do
16
+ let(:node) { KnifeSous::Node.new('nodetastic') }
17
+ let(:cmd) { command }
18
+ let(:solo_clean_command) { Chef::Knife::SoloClean.new }
19
+
20
+ before do
21
+ Chef::Knife::SoloClean.stub(new: solo_clean_command)
22
+ solo_clean_command.stub(:run)
23
+ cmd.stub(configure_command: solo_clean_command)
24
+ node.update_config(
25
+ hostname: 'host_ip'
26
+ )
27
+ end
28
+
29
+ it "should provide name to args and run" do
30
+ solo_clean_command.should_receive(:run)
31
+ cmd.solo_clean_node(node)
32
+
33
+ solo_clean_command.name_args.should == %w[host_ip]
34
+ end
35
+ end
36
+
37
+ def command(*args)
38
+ knife_command(Chef::Knife::SousClean, *args)
39
+ end
40
+ end
41
+
@@ -0,0 +1,52 @@
1
+ require 'spec_helper'
2
+
3
+ describe Chef::Knife::SousCook do
4
+ include KnifeCommandHelpers
5
+
6
+ describe "#banner" do
7
+ it "should have display how to use command" do
8
+ command.banner.should == 'knife sous cook [NAMESPACE] NODE'
9
+ end
10
+ end
11
+
12
+ describe "#check_args" do
13
+ it "should print error, show usage and exit if no args are passed in" do
14
+ cmd = command
15
+ cmd.ui.should_receive(:fatal).with("You need to specificy a node or namespace")
16
+ cmd.should_receive(:show_usage)
17
+ lambda { cmd.check_args}.should raise_error SystemExit
18
+ end
19
+ end
20
+
21
+ it_should_behave_like "a node command" do
22
+ let(:node_command) { command }
23
+ end
24
+
25
+ describe "#solo_cook_node" do
26
+ let(:node) { KnifeSous::Node.new('nodetastic') }
27
+ let(:cmd) { command }
28
+ let(:solo_cook_command) { Chef::Knife::SoloCook.new }
29
+
30
+ before do
31
+ Chef::Knife::SoloCook.stub(new: solo_cook_command)
32
+ solo_cook_command.stub(:run)
33
+ cmd.stub(configure_command: solo_cook_command)
34
+ node.update_config(
35
+ node_config: '/path/to/node/config',
36
+ hostname: 'host_ip'
37
+ )
38
+ end
39
+
40
+ it "should provide name to args and run" do
41
+ solo_cook_command.should_receive(:run)
42
+ cmd.solo_cook_node(node)
43
+
44
+ solo_cook_command.name_args.should == %w[host_ip /path/to/node/config]
45
+ end
46
+ end
47
+
48
+ def command(*args)
49
+ knife_command(Chef::Knife::SousCook, *args)
50
+ end
51
+ end
52
+
@@ -0,0 +1,56 @@
1
+ require 'spec_helper'
2
+
3
+ describe Chef::Knife::SousInit do
4
+ include KnifeCommandHelpers
5
+
6
+ describe "#banner" do
7
+ it "should have display how to use command" do
8
+ command.banner.should == 'knife sous init [DIRECTORY]'
9
+ end
10
+ end
11
+
12
+ describe "#copy_template" do
13
+ before do
14
+ FileUtils.stub(:mkdir_p)
15
+ end
16
+
17
+ it "should copy template to location if location is empty" do
18
+ cmd = command
19
+ File.stub(exists?: false)
20
+ cmd.stub(node_manifest_example_path: 'example location')
21
+
22
+ FileUtils.should_receive(:cp).with('example location', 'some/location/nodes.example.rb')
23
+ cmd.ui.should_receive(:msg).with("Example nodes.rb copied to some/location/nodes.example.rb")
24
+
25
+ cmd.copy_template('some/location')
26
+ end
27
+
28
+ it "should print an error and shouldn't copy if file already exists at destination" do
29
+ cmd = command
30
+ File.stub(exists?: true)
31
+ FileUtils.should_not_receive(:cp)
32
+ cmd.ui.should_receive(:error).with("File already exists: some/location/nodes.example.rb")
33
+ cmd.copy_template('some/location')
34
+ end
35
+ end
36
+
37
+ describe "#run" do
38
+ it "should copy example config to default location, if no location specified" do
39
+ cmd = command
40
+ cmd.should_receive(:copy_template).with(File.expand_path(Dir.pwd, File.join('nodes')))
41
+ cmd.run
42
+ end
43
+
44
+ it "should copy the example config to specified location" do
45
+ cmd = command
46
+ cmd.should_receive(:copy_template).with(File.expand_path("some/path"))
47
+ cmd.name_args << 'some/path'
48
+ cmd.run
49
+ end
50
+ end
51
+
52
+ def command(*args)
53
+ knife_command(Chef::Knife::SousInit, *args)
54
+ end
55
+ end
56
+
@@ -0,0 +1,33 @@
1
+ require 'spec_helper'
2
+
3
+ describe Chef::Knife::SousList do
4
+ include KnifeCommandHelpers
5
+
6
+ describe "#banner" do
7
+ it "should have display how to use command" do
8
+ command.banner.should == 'knife sous list'
9
+ end
10
+ end
11
+
12
+ describe "#run" do
13
+ it "should print out the list nodes" do
14
+ cmd = command
15
+ cmd.should_receive(:present_nodes)
16
+ cmd.run
17
+ end
18
+ end
19
+
20
+ describe "#present_nodes" do
21
+ it "should output presented nodes" do
22
+ cmd = command
23
+ cmd.config[:node_manifest_file] = 'spec/support/fixtures/nodes.rb'
24
+ cmd.ui.should_receive(:output).with("production node_awesome\nproduction web nodetastic\nvagrant\n")
25
+ cmd.present_nodes
26
+ end
27
+ end
28
+
29
+ def command(*args)
30
+ knife_command(Chef::Knife::SousList, *args)
31
+ end
32
+ end
33
+
@@ -0,0 +1,42 @@
1
+ require 'spec_helper'
2
+
3
+ describe Chef::Knife::SousPrepare do
4
+ include KnifeCommandHelpers
5
+
6
+ describe "#banner" do
7
+ it "should have display how to use command" do
8
+ command.banner.should == 'knife sous prepare [NAMESPACE] NODE'
9
+ end
10
+ end
11
+ it_should_behave_like "a node command" do
12
+ let(:node_command) { command }
13
+ end
14
+
15
+ describe "#solo_prepare_node" do
16
+ let(:node) { KnifeSous::Node.new('nodetastic') }
17
+ let(:cmd) { command }
18
+ let(:solo_prepare_command) { Chef::Knife::SoloPrepare.new }
19
+
20
+ before do
21
+ Chef::Knife::SoloPrepare.stub(new: solo_prepare_command)
22
+ solo_prepare_command.stub(:run)
23
+ cmd.stub(configure_command: solo_prepare_command)
24
+ node.update_config(
25
+ node_config: '/path/to/node/config',
26
+ hostname: 'host_ip'
27
+ )
28
+ end
29
+
30
+ it "should provide name to args and run" do
31
+ solo_prepare_command.should_receive(:run)
32
+ cmd.solo_prepare_node(node)
33
+
34
+ solo_prepare_command.name_args.should == %w[host_ip /path/to/node/config]
35
+ end
36
+ end
37
+
38
+ def command(*args)
39
+ knife_command(Chef::Knife::SousPrepare, *args)
40
+ end
41
+ end
42
+
@@ -0,0 +1,27 @@
1
+ require 'spec_helper'
2
+
3
+ class DummyCommand < Chef::Knife
4
+ end
5
+
6
+ describe KnifeSous::ConfigureCommand do
7
+ include KnifeCommandHelpers
8
+
9
+ describe "#configure_command" do
10
+ it "should be configured for a given node" do
11
+ node = KnifeSous::Node.new('some node',
12
+ foo: 'bar',
13
+ ssh_password: 'some_password')
14
+
15
+ cmd = command
16
+ KnifeSous::ConfigureCommand.configure_command(cmd, node)
17
+
18
+ cmd.config[:ssh_password].should == 'some_password'
19
+ cmd.config[:foo].should == 'bar'
20
+ end
21
+ end
22
+
23
+ def command(*args)
24
+ knife_command(DummyCommand, *args)
25
+ end
26
+ end
27
+
@@ -0,0 +1,52 @@
1
+ require 'spec_helper'
2
+
3
+ class DummyClass
4
+ include KnifeSous::DSL
5
+ end
6
+
7
+ describe KnifeSous::DSL do
8
+ it_should_behave_like "a collection object" do
9
+ let(:collection) { DummyClass.new }
10
+ end
11
+
12
+ describe "#namespace" do
13
+ let(:some_block) { Proc.new { } }
14
+ let(:dummy_class) { DummyClass.new }
15
+
16
+ it "should instantiate a Namespace" do
17
+ namespace = KnifeSous::Namespace.new('stuff')
18
+ KnifeSous::Namespace.stub(new: namespace)
19
+ KnifeSous::Namespace.should_receive(:new).with('some name')
20
+ dummy_class.namespace('some name', &some_block)
21
+ end
22
+
23
+ it "should have the Namespace evaluate the passed in block" do
24
+ namespace = KnifeSous::Namespace.new('stuff')
25
+ KnifeSous::Namespace.stub(new: namespace)
26
+ namespace.should_receive(:evaluate_block).with(&some_block)
27
+ dummy_class.namespace('some name', &some_block)
28
+ end
29
+
30
+ it "should add the Namespace to the collection" do
31
+ dummy_class.namespace('some name', &some_block)
32
+ dummy_class.first.should be_a KnifeSous::Namespace
33
+ end
34
+ end
35
+
36
+ describe "#node" do
37
+ let(:dummy_class) { DummyClass.new }
38
+
39
+ it "should instantiate a Node" do
40
+ node = KnifeSous::Node.new('stuff')
41
+ KnifeSous::Node.stub(new: node)
42
+ KnifeSous::Node.should_receive(:new).with('some name', {config: 'stuff'})
43
+ dummy_class.node('some name', config: 'stuff' )
44
+ end
45
+
46
+ it "should add the Node to the collection" do
47
+ dummy_class.node('some name')
48
+ dummy_class.first.should be_a KnifeSous::Node
49
+ end
50
+ end
51
+ end
52
+
@@ -0,0 +1,12 @@
1
+ require 'spec_helper'
2
+
3
+ class DummyClass
4
+ include KnifeSous::DSLWrapper
5
+ end
6
+
7
+ describe KnifeSous::DSLWrapper do
8
+ it_should_behave_like "dsl wrapper" do
9
+ let(:klass) { DummyClass.new }
10
+ end
11
+ end
12
+
@@ -0,0 +1,23 @@
1
+ require 'spec_helper'
2
+
3
+ describe KnifeSous::HashMixins do
4
+
5
+ subject { KnifeSous::HashMixins }
6
+
7
+ describe "#sanitize_key"do
8
+ it "should return a lowercase, snake_case, symbol" do
9
+ subject.sanitize_key('SoMEthing-Ridic_uLous!').should == :something_ridic_ulous!
10
+ end
11
+ end
12
+
13
+ describe "#normalize_hash" do
14
+ it "should sanitize each key" do
15
+ subject.normalize_hash('GroS-key' => 'foo', OtherKey: 'bar').keys.should =~ [:gros_key, :otherkey]
16
+ end
17
+
18
+ it "should convert every value to string" do
19
+ subject.normalize_hash(number: 5, bar: 'baz').should == { number: '5', bar: 'baz' }
20
+ end
21
+ end
22
+ end
23
+
@@ -0,0 +1,57 @@
1
+ require 'spec_helper'
2
+
3
+ describe KnifeSous::NamespacePresenter do
4
+ describe "#initialize" do
5
+ it "should keep track of the namespace" do
6
+ namespace = 'namespace'
7
+ KnifeSous::NamespacePresenter.new(namespace).namespace.should == 'namespace'
8
+ end
9
+ end
10
+
11
+ describe "#presenter" do
12
+ it "should return a NodePresenter if item is a Node" do
13
+ root_namespace_presenter = KnifeSous::NamespacePresenter.new('foo namespace')
14
+ some_node = KnifeSous::Node.new('some node')
15
+ root_namespace_presenter.presenter(some_node).should be_a KnifeSous::NodePresenter
16
+ end
17
+
18
+ it "should return a NamespacePresenter if item is a Namespace" do
19
+ root_namespace_presenter = KnifeSous::NamespacePresenter.new('foo namespace')
20
+ some_namespace = KnifeSous::Namespace.new('some node')
21
+ root_namespace_presenter.presenter(some_namespace).should be_a KnifeSous::NamespacePresenter
22
+ end
23
+ end
24
+
25
+ describe "#present" do
26
+ it "should present its own name" do
27
+ namespace = KnifeSous::Namespace.new("some namespace")
28
+ KnifeSous::NamespacePresenter.new(namespace).present.should == "some namespace"
29
+ end
30
+
31
+ it "should present each of its children" do
32
+ root_namespace = KnifeSous::Namespace.new("")
33
+ namespaceA = KnifeSous::Namespace.new(:namespace_a)
34
+ namespaceB = KnifeSous::Namespace.new(:namespace_b)
35
+
36
+ node1 = KnifeSous::Node.new(:node_1)
37
+ node2 = KnifeSous::Node.new(:node_2)
38
+ node3 = KnifeSous::Node.new(:node_3)
39
+ node4 = KnifeSous::Node.new(:node_4)
40
+
41
+ root_namespace << namespaceA
42
+ namespaceA << node1
43
+ namespaceA << node2
44
+ namespaceA << namespaceB
45
+ namespaceB << node3
46
+ root_namespace << node4
47
+
48
+ KnifeSous::NamespacePresenter.new(root_namespace).present.should ==<<-TEXT
49
+ namespace_a node_1
50
+ namespace_a node_2
51
+ namespace_a namespace_b node_3
52
+ node_4
53
+ TEXT
54
+ end
55
+ end
56
+ end
57
+
@@ -0,0 +1,59 @@
1
+ require 'spec_helper'
2
+
3
+ describe KnifeSous::Namespace do
4
+ let(:namespace) { KnifeSous::Namespace.new("some namespace name") }
5
+
6
+ it_should_behave_like "a collection object" do
7
+ let(:collection) { namespace }
8
+ end
9
+
10
+ it_should_behave_like "dsl wrapper" do
11
+ let(:klass) { namespace }
12
+ end
13
+
14
+ describe "#initialize" do
15
+ it "should set the name" do
16
+ KnifeSous::Namespace.new("some namespace name").name.should == 'some namespace name'
17
+ end
18
+
19
+ it "should convert symbols to strings" do
20
+ KnifeSous::Namespace.new(:foo_bar).name.should == 'foo_bar'
21
+ end
22
+ end
23
+
24
+ describe "root namespace" do
25
+ it "should instance_eval DSL from file" do
26
+ root_namespace = KnifeSous::Namespace.new('')
27
+ root_namespace.instance_eval do
28
+ namespace :production do |prod|
29
+ prod.node :node_awesome
30
+ prod.namespace :web do |web|
31
+ web.node :web_node
32
+ end
33
+ end
34
+ node :vagrant, node_config: 'nodes/some_node.json', ssh_config: 'vagrant config'
35
+ end
36
+
37
+ prod_namespace = root_namespace[0]
38
+ prod_namespace.should be_a KnifeSous::Namespace
39
+ prod_namespace.name.should == 'production'
40
+
41
+ vagrant_node = root_namespace[1]
42
+ vagrant_node.should be_a KnifeSous::Node
43
+ vagrant_node.name.should == 'vagrant'
44
+
45
+ node_awesome = prod_namespace[0]
46
+ node_awesome.should be_a KnifeSous::Node
47
+ node_awesome.name.should == 'node_awesome'
48
+
49
+ web_namespace = prod_namespace[1]
50
+ web_namespace.should be_a KnifeSous::Namespace
51
+ web_namespace.name.should == 'web'
52
+
53
+ web_node = web_namespace[0]
54
+ web_node.should be_a KnifeSous::Node
55
+ web_node.name.should == 'web_node'
56
+ end
57
+ end
58
+ end
59
+
@@ -0,0 +1,18 @@
1
+ require 'spec_helper'
2
+
3
+ describe KnifeSous::NodePresenter do
4
+ describe "#initialize" do
5
+ it "should keep track of the node" do
6
+ node = 'node'
7
+ KnifeSous::NodePresenter.new(node).node.should == 'node'
8
+ end
9
+ end
10
+
11
+ describe "#present" do
12
+ it "should present the node name and a newline" do
13
+ node = KnifeSous::Node.new('Awesome node')
14
+ KnifeSous::NodePresenter.new(node).present.should == "Awesome node\n"
15
+ end
16
+ end
17
+ end
18
+
@@ -0,0 +1,63 @@
1
+ require 'spec_helper'
2
+
3
+ describe KnifeSous::Node do
4
+ describe "#initialize" do
5
+ it "should set the name that was passed in" do
6
+ KnifeSous::Node.new('Node-Fuu').name.should == 'Node-Fuu'
7
+ end
8
+
9
+ it "should convert symbols to strings" do
10
+ KnifeSous::Node.new(:node_tastic).name.should == 'node_tastic'
11
+ end
12
+
13
+ it "should accept config arguments as a hash" do
14
+ options_hash = {ssh_config: 'stuff', other_something: 'foo' }
15
+ KnifeSous::Node.new(:node_tastic, options_hash).config.should == options_hash
16
+ end
17
+ end
18
+
19
+ describe "#node_name" do
20
+ it "should set the node name" do
21
+ node = KnifeSous::Node.new('some node', node_name: 'node_tastic')
22
+ node.node_name.should == 'node_tastic'
23
+ end
24
+
25
+ it "should default to the node name" do
26
+ node = KnifeSous::Node.new('some node')
27
+ node.node_name.should == 'some node'
28
+ end
29
+ end
30
+
31
+ describe "#update_config" do
32
+ it "should merge config options" do
33
+ node = KnifeSous::Node.new(:node_tastic, foo: 'bar', baz: 'stuff')
34
+ node.update_config(baz: 'new stuff')
35
+ node.config.should == { foo: 'bar', baz: 'new stuff' }
36
+ end
37
+ end
38
+
39
+ describe "config hash" do
40
+ it "should sanitize hash keys" do
41
+ KnifeSous::Node.new(:node_tastic, 'fOO-BAr' => 'baz').config.keys.should =~ [:foo_bar]
42
+ end
43
+ end
44
+
45
+ describe "#method_missing" do
46
+ it "should try to access from config hash" do
47
+ KnifeSous::Node.new(:node_tastic, foo_bar: 'baz').foo_bar.should == 'baz'
48
+ end
49
+
50
+ it "should return nil if config doesn't exist" do
51
+ KnifeSous::Node.new(:node_tastic).foo_bar.should == nil
52
+ end
53
+ end
54
+
55
+ describe "#convert_aliases" do
56
+ it "should convert keys to their alias defined by #config_aliases" do
57
+ node = KnifeSous::Node.new(:foo)
58
+ node.stub(config_aliases: {foo: :bar})
59
+ node.convert_aliases(foo: 'baz').should == { bar: 'baz'}
60
+ end
61
+ end
62
+ end
63
+