kitchen-scribe 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -10,9 +10,10 @@ It performs two main functions.
10
10
 
11
11
  1. _Documenting changes_. It pulls the configuration of all your environements, roles, and nodes then saves them into json files in the place of your choosing and commits the changes to a local git repository. It can also pull/push them to a remote repostory for safekeeping.
12
12
 
13
- 2. _Making precise changes_. It can perform precise updates on your environments, roles and nodes by using json data structure describing the change. *[This feature is still being tested and it's not available through rubygems yet. If you would like to try it please install it driectly from the github repo]*
13
+ 2. _Making precise changes_. It can perform precise updates on your environments, roles and nodes by using json data structure describing the change.
14
14
 
15
- The philosophy behind using scribe to update your environments, roles an nodes is that you may want to make prepare some changes in advance, be able to test them and then have them applied to the final setup. Also it might be important to isolate those changes in a clear way so people who are not familiar with chef don't have to edit a huge json object to get them in. Lastly you can now automate applying your changes as well, and automation is what Chef is all about in the end:).
15
+
16
+ The philosophy behind using scribe to update your environments, roles an nodes is that you may want to prepare some changes in advance, be able to test them and then have them applied to the final setup. Also it might be important to isolate those changes in a clear way so people who are not familiar with chef don't have to edit a huge json object to get them in. Lastly, you can now automate applying your changes as well, and automation is what Chef is all about in the end:).
16
17
 
17
18
  The plugin is still in the beta stage, I've tested it manualy to some extent, but I'm sure there are things I missed. Please submit any bugs you find through the github issue system and I promiss to take care of them as soon as possible.
18
19
 
@@ -38,6 +38,9 @@ class Chef
38
38
  }
39
39
 
40
40
  ENVIRONMENT_ADJUSTMENT_TEMPLATE = {
41
+ "action" => "merge",
42
+ "type" => "environment",
43
+ "search" => "name:my_environment_name",
41
44
  "adjustment" => { "default_attributes" => { },
42
45
  "override_attributes" => { },
43
46
  "cookbook_versions" => { }
@@ -45,6 +48,9 @@ class Chef
45
48
  }
46
49
 
47
50
  ROLE_ADJUSTMENT_TEMPLATE = {
51
+ "action" => "merge",
52
+ "type" => "role",
53
+ "search" => "name:my_role_name",
48
54
  "adjustment" => { "default_attributes" => { },
49
55
  "override_attributes" => { },
50
56
  "run_list" => [ ]
@@ -52,8 +58,11 @@ class Chef
52
58
  }
53
59
 
54
60
  NODE_ADJUSTMENT_TEMPLATE = {
55
- "adjustment" => { "attributes" => { },
56
- "run_list" => [ ]
61
+ "action" => "merge",
62
+ "type" => "node",
63
+ "search" => "name:my_node_name",
64
+ "adjustment" => { "normal" => { },
65
+ "run_list" => [ ],
57
66
  }
58
67
  }
59
68
 
@@ -192,15 +201,29 @@ class Chef
192
201
  def apply_adjustment(adjustment)
193
202
  query = adjustment["search"].include?(":") ? adjustment["search"] : "name:" + adjustment["search"]
194
203
  Chef::Search::Query.new.search(adjustment["type"], query ) do |result|
195
- result_hash = result.to_hash
196
- key = result_hash["chef_type"] + ":" + result_hash["name"]
197
- if changes.has_key? key
198
- result_hash = changes[key]["adjusted"]
199
- else
200
- changes.store(key, { "original" => result_hash })
201
- end
202
- changes[key].store("adjusted", send(("action_" + adjustment["action"]).to_sym, result_hash, adjustment["adjustment"]))
204
+ key = result.class.name.downcase + ":" + result.name
205
+ prepared_hash = prepare_adjustment_subject(key, result)
206
+ changes[key].store("adjusted", send(("action_" + adjustment["action"]).to_sym, prepared_hash, adjustment["adjustment"]))
207
+ end
208
+ end
209
+
210
+ def prepare_adjustment_subject(key, chef_object)
211
+ prepared_hash = prepare_object_hash(chef_object)
212
+ if changes.has_key? key
213
+ prepared_hash = changes[key]["adjusted"]
214
+ else
215
+ changes.store(key, { "original" => prepared_hash })
216
+ end
217
+ prepared_hash
218
+ end
219
+
220
+ def prepare_object_hash(chef_object)
221
+ prepared_hash = chef_object.to_hash
222
+ if prepared_hash["chef_type"] == "node"
223
+ prepared_hash.keep_if { |key, value| ["name","chef_type","chef_environment","run_list"].include? key }
224
+ prepared_hash.merge!({ "normal" => chef_object.normal_attrs })
203
225
  end
226
+ prepared_hash
204
227
  end
205
228
 
206
229
  def write_adjustments
@@ -132,7 +132,7 @@ class Chef
132
132
 
133
133
  def fetch_nodes
134
134
  Chef::Node.list(true).each do |name, n|
135
- node_hash = {"name" => name, "env" => n.chef_environment, "attribiutes" => n.normal_attrs, "run_list" => n.run_list}
135
+ node_hash = {"name" => name, "env" => n.chef_environment, "normal" => n.normal_attrs, "run_list" => n.run_list}
136
136
  save_to_file("nodes",name, node_hash)
137
137
  end
138
138
  end
@@ -1,4 +1,4 @@
1
1
  module KitchenScribe
2
- VERSION = "0.2.0"
2
+ VERSION = "0.3.0"
3
3
  MAJOR, MINOR, TINY = VERSION.split('.')
4
4
  end
@@ -28,10 +28,6 @@ describe Chef::Knife::ScribeAdjust do
28
28
  @scribe.should respond_to(:action_merge)
29
29
  end
30
30
 
31
- it "responds to #action_hash_only_merge" do
32
- @scribe.should respond_to(:action_hash_only_merge)
33
- end
34
-
35
31
  it "responds to #action_overwrite" do
36
32
  @scribe.should respond_to(:action_overwrite)
37
33
  end
@@ -614,11 +610,7 @@ describe Chef::Knife::ScribeAdjust do
614
610
  Chef::Search::Query.stub(:new).and_return(@query)
615
611
  @chef_obj = double("chef_object")
616
612
  @chef_obj.stub(:to_hash).and_return( { "name" => "test_name", "chef_type" => "test_type", "a" => 3, "c" => 3 } )
617
- chef_obj_class = double("chef_object_class")
618
- json_create_return_obj = double("final_chef_object")
619
- json_create_return_obj.stub(:save)
620
- chef_obj_class.stub(:json_create).and_return(json_create_return_obj)
621
- @chef_obj.stub(:class).and_return(chef_obj_class)
613
+ @chef_obj.stub(:name).and_return("test_name")
622
614
  @query.stub(:search).and_yield(@chef_obj)
623
615
  end
624
616
 
@@ -644,35 +636,90 @@ describe Chef::Knife::ScribeAdjust do
644
636
  end
645
637
  end
646
638
 
647
- it "checks if the a change to a given object is already pending" do
648
- @scribe.changes.should_receive(:has_key?).with(@chef_obj.to_hash["chef_type"] + ":" + @chef_obj.to_hash["name"])
639
+ it "saves the changed version in the changes hash" do
640
+ adjusted_hash = @chef_obj.to_hash.dup.merge({ "a" => "b" })
641
+ changes_hash = { "original" => @chef_obj.to_hash, "adjusted" => adjusted_hash }
642
+ @scribe.changes[@chef_obj.class.name.downcase + ":" + @chef_obj.name] = changes_hash
643
+ adjusted_hash = @scribe.send(("action_" + @adjustment["action"]).to_sym, adjusted_hash, @adjustment["adjustment"])
644
+ changes_hash.should_receive(:store).with("adjusted", adjusted_hash).and_call_original
649
645
  @scribe.apply_adjustment(@adjustment)
650
646
  end
647
+ end
648
+
649
+ describe "#prepare_adjustment_subject" do
650
+ before(:each) do
651
+ @chef_obj = double("chef_object")
652
+ @chef_obj.stub(:to_hash).and_return( { "name" => "test_name", "chef_type" => "test_type", "a" => 3, "c" => 3 } )
653
+ @key = "test_type:test_name"
654
+ end
655
+
656
+ it "checks if the a change to a given object is already pending" do
657
+ @scribe.changes.should_receive(:has_key?).with(@key)
658
+ @scribe.prepare_adjustment_subject(@key, @chef_obj)
659
+ end
651
660
 
652
661
  describe "if the key doesn't exist" do
653
662
  it "saves the original in the changes hash" do
654
- @scribe.changes.should_receive(:store).with(@chef_obj.to_hash["chef_type"] + ":" + @chef_obj.to_hash["name"],
663
+ @scribe.changes.should_receive(:store).with(@key,
655
664
  { "original" => @chef_obj.to_hash }
656
665
  ).and_call_original
657
- @scribe.apply_adjustment(@adjustment)
666
+ @scribe.prepare_adjustment_subject(@key, @chef_obj)
667
+ end
668
+
669
+ it "prepares the object hash" do
670
+ @scribe.should_receive(:prepare_object_hash).with(@chef_obj)
671
+ @scribe.prepare_adjustment_subject(@key, @chef_obj)
672
+ end
673
+
674
+ it "returns the prepared object hash" do
675
+ @scribe.prepare_adjustment_subject(@key, @chef_obj).should == @chef_obj.to_hash
658
676
  end
659
677
  end
660
678
 
661
- it "applies each subsequent adjustment to the already adjusted version" do
662
- adjusted_hash = @chef_obj.to_hash.dup.merge({"a" => "b"})
663
- changes_hash = { "original" => @chef_obj.to_hash, "adjusted" => adjusted_hash }
664
- @scribe.changes[@chef_obj.to_hash["chef_type"] + ":" + @chef_obj.to_hash["name"]] = changes_hash
665
- @scribe.should_receive(("action_" + @adjustment["action"]).to_sym).with(adjusted_hash, @adjustment["adjustment"])
666
- @scribe.apply_adjustment(@adjustment)
679
+ describe "if the key already exists" do
680
+ before(:each) do
681
+ @adjusted_hash = @chef_obj.to_hash.dup.merge({"a" => "b"})
682
+ changes_hash = { "original" => @chef_obj.to_hash, "adjusted" => @adjusted_hash }
683
+ @scribe.changes[@key] = changes_hash
684
+ end
685
+
686
+ it "it returns the previously adjusted version" do
687
+ @scribe.prepare_adjustment_subject(@key, @chef_obj).should == @adjusted_hash
688
+ end
667
689
  end
690
+ end
668
691
 
669
- it "saves the changed version in the changes hash" do
670
- adjusted_hash = @chef_obj.to_hash.dup.merge({ "a" => "b" })
671
- changes_hash = { "original" => @chef_obj.to_hash, "adjusted" => adjusted_hash }
672
- @scribe.changes[@chef_obj.to_hash["chef_type"] + ":" + @chef_obj.to_hash["name"]] = changes_hash
673
- adjusted_hash = @scribe.send(("action_" + @adjustment["action"]).to_sym, adjusted_hash, @adjustment["adjustment"])
674
- changes_hash.should_receive(:store).with("adjusted", adjusted_hash).and_call_original
675
- @scribe.apply_adjustment(@adjustment)
692
+ describe "#prepare_object_hash" do
693
+ describe "if object isn't a node" do
694
+ before(:each) do
695
+ @chef_obj = double("chef_object")
696
+ @chef_obj.stub(:to_hash).and_return( { "name" => "test_name", "chef_type" => "test_type", "a" => 3, "c" => 3 } )
697
+ end
698
+
699
+ it "returns the object converted to hash" do
700
+ @scribe.prepare_object_hash(@chef_obj).should == @chef_obj.to_hash
701
+ end
702
+ end
703
+
704
+ describe "if object is a node" do
705
+ before(:each) do
706
+ @chef_obj = double("chef_object")
707
+ @node_data = { "name" => "test_name",
708
+ "chef_type" => "node",
709
+ "a" => 3,
710
+ "c" => 3,
711
+ "chef_environment" => "test_env",
712
+ "run_list" => "blah"
713
+ }
714
+ @chef_obj.stub(:to_hash).and_return( @node_data)
715
+ @chef_obj.stub(:normal_attrs).and_return({"nx" => "ny"})
716
+ @prepared_data = @node_data.select { |key, value| ["name","chef_type","chef_environment","run_list"].include? key }
717
+ @prepared_data.merge!({"normal" => {"nx" => "ny"}})
718
+ end
719
+
720
+ it "keeps only the relevant information" do
721
+ @scribe.prepare_object_hash(@chef_obj).should == @prepared_data
722
+ end
676
723
  end
677
724
  end
678
725
 
@@ -398,13 +398,13 @@ describe Chef::Knife::ScribeCopy do
398
398
  @node1.stub(:chef_environment) { "chef_environment1" }
399
399
  @node1.stub(:normal_attrs) { { :attr1 => "val1" } }
400
400
  @node1.stub(:run_list) { ["cookbook1", "cookbook2"] }
401
- @serialized_node1 = {"name" => @node1.name, "env" => @node1.chef_environment, "attribiutes" => @node1.normal_attrs, "run_list" => @node1.run_list}
401
+ @serialized_node1 = {"name" => @node1.name, "env" => @node1.chef_environment, "normal" => @node1.normal_attrs, "run_list" => @node1.run_list}
402
402
  @node2 = { :test2 => :value2 }
403
403
  @node2.stub(:name) { "node_name2" }
404
404
  @node2.stub(:chef_environment) { "chef_environment2" }
405
405
  @node2.stub(:normal_attrs) { { :attrA => "valA" } }
406
406
  @node2.stub(:run_list) { ["cookbookA", "cookbookB"] }
407
- @serialized_node2 = {"name" => @node2.name, "env" => @node2.chef_environment, "attribiutes" => @node2.normal_attrs, "run_list" => @node2.run_list}
407
+ @serialized_node2 = {"name" => @node2.name, "env" => @node2.chef_environment, "normal" => @node2.normal_attrs, "run_list" => @node2.run_list}
408
408
  Chef::Node.stub(:list) { { @node1.name => @node1, @node2.name => @node2 } }
409
409
  end
410
410
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kitchen-scribe
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-05-14 00:00:00.000000000 Z
12
+ date: 2013-07-25 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: chef