pantry-chef 0.1

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.
Files changed (53) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +5 -0
  3. data/.travis.yml +16 -0
  4. data/Gemfile +15 -0
  5. data/LICENSE +20 -0
  6. data/README.md +49 -0
  7. data/Rakefile +18 -0
  8. data/lib/pantry/chef.rb +47 -0
  9. data/lib/pantry/chef/configure_chef.rb +59 -0
  10. data/lib/pantry/chef/list_cookbooks.rb +31 -0
  11. data/lib/pantry/chef/run.rb +30 -0
  12. data/lib/pantry/chef/run_chef_solo.rb +21 -0
  13. data/lib/pantry/chef/send_cookbooks.rb +23 -0
  14. data/lib/pantry/chef/sync_cookbooks.rb +84 -0
  15. data/lib/pantry/chef/sync_data_bags.rb +19 -0
  16. data/lib/pantry/chef/sync_environments.rb +19 -0
  17. data/lib/pantry/chef/sync_roles.rb +19 -0
  18. data/lib/pantry/chef/upload_cookbook.rb +110 -0
  19. data/lib/pantry/chef/upload_data_bag.rb +37 -0
  20. data/lib/pantry/chef/upload_environment.rb +28 -0
  21. data/lib/pantry/chef/upload_role.rb +28 -0
  22. data/lib/pantry/chef/version.rb +5 -0
  23. data/lib/pantry/init.rb +1 -0
  24. data/pantry-chef.gemspec +27 -0
  25. data/test/acceptance/chef/run_test.rb +69 -0
  26. data/test/acceptance/chef/upload_cookbook_test.rb +26 -0
  27. data/test/acceptance/chef/upload_data_bag_test.rb +36 -0
  28. data/test/acceptance/chef/upload_environment_test.rb +22 -0
  29. data/test/acceptance/chef/upload_role_test.rb +21 -0
  30. data/test/acceptance/test_helper.rb +25 -0
  31. data/test/fixtures/cookbooks/bad/recipes/default.rb +1 -0
  32. data/test/fixtures/cookbooks/mini/metadata.rb +5 -0
  33. data/test/fixtures/cookbooks/mini/recipes/default.rb +1 -0
  34. data/test/fixtures/data_bags/settings/test.json +0 -0
  35. data/test/fixtures/environments/test.rb +2 -0
  36. data/test/fixtures/roles/app.rb +2 -0
  37. data/test/fixtures/roles/app1.rb +2 -0
  38. data/test/root_dir/applications/pantry/chef/roles/app.rb +2 -0
  39. data/test/unit/chef/configure_chef_test.rb +64 -0
  40. data/test/unit/chef/list_cookbooks_test.rb +49 -0
  41. data/test/unit/chef/run_chef_solo_test.rb +29 -0
  42. data/test/unit/chef/run_test.rb +5 -0
  43. data/test/unit/chef/send_cookbooks_test.rb +44 -0
  44. data/test/unit/chef/sync_cookbooks_test.rb +40 -0
  45. data/test/unit/chef/sync_data_bags_test.rb +21 -0
  46. data/test/unit/chef/sync_environments_test.rb +21 -0
  47. data/test/unit/chef/sync_roles_test.rb +21 -0
  48. data/test/unit/chef/upload_cookbook_test.rb +132 -0
  49. data/test/unit/chef/upload_data_bag_test.rb +24 -0
  50. data/test/unit/chef/upload_environment_test.rb +11 -0
  51. data/test/unit/chef/upload_role_test.rb +11 -0
  52. data/test/unit/test_helper.rb +26 -0
  53. metadata +166 -0
@@ -0,0 +1,25 @@
1
+ require 'pantry/test/acceptance'
2
+ require 'pantry/chef'
3
+
4
+ Pantry.logger.disable!
5
+ #Pantry.config.log_level = :debug
6
+
7
+ class Minitest::Test
8
+
9
+ def setup
10
+ Pantry.config.root_dir = File.expand_path("../../root_dir", __FILE__)
11
+ clean_up_pantry_root
12
+ end
13
+
14
+ # Ensure Pantry.root is always clean for each test.
15
+ def clean_up_pantry_root
16
+ Dir["#{Pantry.root}/**/*"].each do |file|
17
+ FileUtils.rm_rf file
18
+ end
19
+ end
20
+
21
+ def fixture_path(file_path)
22
+ File.join(File.dirname(__FILE__), "..", "fixtures", file_path)
23
+ end
24
+
25
+ end
@@ -0,0 +1 @@
1
+ # Do nothing
@@ -0,0 +1,5 @@
1
+ name "mini"
2
+ description "The smallest cookbook possible"
3
+ version "1.0.0"
4
+
5
+ recipe "mini", "The basic recipe"
@@ -0,0 +1,2 @@
1
+ name "test"
2
+ description "Pantry test env"
@@ -0,0 +1,2 @@
1
+ name "app"
2
+ description "Application test role"
@@ -0,0 +1,2 @@
1
+ name "app1"
2
+ description "Application test role"
@@ -0,0 +1,2 @@
1
+ name "app"
2
+ description "Application test role"
@@ -0,0 +1,64 @@
1
+ require 'unit/test_helper'
2
+
3
+ describe Pantry::Chef::ConfigureChef do
4
+
5
+ fake_fs!
6
+
7
+ it "creates expected directory structure for chef file storage" do
8
+ command = Pantry::Chef::ConfigureChef.new
9
+ command.perform(Pantry::Message.new)
10
+
11
+ %w(cache cookbooks environments).each do |dir|
12
+ assert File.directory?(Pantry.root.join("chef", dir)),
13
+ "Did not create the chef #{dir} directory"
14
+ end
15
+ end
16
+
17
+ it "writes out chef/solo.rb pointing chef to the right locations" do
18
+ command = Pantry::Chef::ConfigureChef.new
19
+ command.perform(Pantry::Message.new)
20
+
21
+ solo_rb = Pantry.root.join("etc", "chef", "solo.rb")
22
+ assert File.exists?(solo_rb), "Did not write out a solo.rb file"
23
+
24
+ solo_contents = File.read(solo_rb)
25
+
26
+ assert_match %r|cookbook_path\s*"#{Pantry.root.join("chef", "cookbooks")}|,
27
+ solo_contents
28
+ assert_match %r|file_cache_path\s*"#{Pantry.root.join("chef", "cache")}|,
29
+ solo_contents
30
+ assert_match %r|role_path\s*"#{Pantry.root.join("chef", "roles")}|,
31
+ solo_contents
32
+ assert_match %r|environment_path\s*"#{Pantry.root.join("chef", "environments")}|,
33
+ solo_contents
34
+ assert_match %r|json_attribs\s*"#{Pantry.root.join("etc", "chef", "node.json")}"|,
35
+ solo_contents
36
+ end
37
+
38
+ it "writes out the node.json file with run list based on client roles" do
39
+ client = Pantry::Client.new(roles: %w(app db))
40
+
41
+ command = Pantry::Chef::ConfigureChef.new
42
+ command.client = client
43
+ command.perform(Pantry::Message.new)
44
+
45
+ node_json = File.read(Pantry.root.join("etc", "chef", "node.json"))
46
+
47
+ assert_match "role[app]", node_json
48
+ assert_match "role[db]", node_json
49
+ end
50
+
51
+ it "writes out the current environment of the Client if one exists" do
52
+ client = Pantry::Client.new(environment: "staging")
53
+
54
+ command = Pantry::Chef::ConfigureChef.new
55
+ command.client = client
56
+ command.perform(Pantry::Message.new)
57
+
58
+ solo_rb = Pantry.root.join("etc/chef/solo.rb")
59
+ solo_contents = File.read(solo_rb)
60
+
61
+ assert_match %|environment "staging"|, solo_contents
62
+ end
63
+
64
+ end
@@ -0,0 +1,49 @@
1
+ require 'unit/test_helper'
2
+
3
+ describe Pantry::Chef::ListCookbooks do
4
+
5
+ describe "#perform" do
6
+ fake_fs!
7
+
8
+ it "returns the list of cookbooks and latest version known" do
9
+ cookbooks = [
10
+ Pantry.root.join("chef", "cookbook-cache", "mini.tgz"),
11
+ Pantry.root.join("chef", "cookbook-cache", "ruby.tgz"),
12
+ Pantry.root.join("chef", "cookbook-cache", "pantry.tgz")
13
+ ]
14
+
15
+ cookbooks.each do|c|
16
+ FileUtils.mkdir_p(File.dirname(c))
17
+ FileUtils.touch(c)
18
+ end
19
+
20
+ Pantry.stubs(:file_checksum).returns("deadbeef")
21
+
22
+ command = Pantry::Chef::ListCookbooks.new
23
+ cookbook_list = command.perform(Pantry::Message.new)
24
+
25
+ assert_equal [
26
+ ["mini", 0, "deadbeef"],
27
+ ["pantry", 0, "deadbeef"],
28
+ ["ruby", 0, "deadbeef"]
29
+ ], cookbook_list
30
+ end
31
+ end
32
+
33
+ describe "#receive_server_response" do
34
+ mock_ui!
35
+
36
+ it "displays the list alphabetical order" do
37
+ message = Pantry::Message.new
38
+ message << ["pantry", 0, "deadbeef"]
39
+ message << ["ruby", 0, "deadbeef"]
40
+ message << ["mini", 0, "deadbeef"]
41
+
42
+ command = Pantry::Chef::ListCookbooks.new
43
+ command.receive_server_response(message)
44
+
45
+ assert_equal "mini\npantry\nruby\n", stdout
46
+ end
47
+ end
48
+
49
+ end
@@ -0,0 +1,29 @@
1
+ require 'unit/test_helper'
2
+
3
+ describe Pantry::Chef::RunChefSolo do
4
+
5
+ it "executes the chef-solo command, returning outputs" do
6
+ config_file = Pantry.root.join(*%w(etc chef solo.rb))
7
+ Open3.expects(:capture3).with("chef-solo --config #{config_file}").
8
+ returns(["chef ran", "error", 0])
9
+
10
+ command = Pantry::Chef::RunChefSolo.new
11
+ stdout, stderr, status = command.perform(Pantry::Message.new)
12
+
13
+ assert_equal "chef ran", stdout
14
+ assert_equal "error", stderr
15
+ assert_equal 0, status
16
+ end
17
+
18
+ it "returns error message if chef-solo not found on the system" do
19
+ Open3.expects(:capture3).raises(Errno::ENOENT, "Can't find LOLZ")
20
+
21
+ command = Pantry::Chef::RunChefSolo.new
22
+ stdout, stderr, status = command.perform(Pantry::Message.new)
23
+
24
+ assert_equal "", stdout
25
+ assert_equal "No such file or directory - Can't find LOLZ", stderr
26
+ assert_equal 1, status
27
+ end
28
+
29
+ end
@@ -0,0 +1,5 @@
1
+ require 'unit/test_helper'
2
+
3
+ describe Pantry::Chef::Run do
4
+
5
+ end
@@ -0,0 +1,44 @@
1
+ require 'unit/test_helper'
2
+
3
+ describe Pantry::Chef::SendCookbooks do
4
+
5
+ fake_fs!
6
+
7
+ describe "#perform" do
8
+
9
+ it "takes the list of receivers and builds senders, passing in the proper cookbook file" do
10
+ message = Pantry::Message.new
11
+ message << ["mini", "receiver_ident", "file_uuid"]
12
+ message << ["pantry", "receiver_ident2", "file_uuid2"]
13
+
14
+ cookbooks = [
15
+ Pantry.root.join("chef", "cookbook-cache", "mini.tgz"),
16
+ Pantry.root.join("chef", "cookbook-cache", "pantry.tgz")
17
+ ]
18
+
19
+ cookbooks.each do|c|
20
+ FileUtils.mkdir_p(File.dirname(c))
21
+ FileUtils.touch(c)
22
+ end
23
+
24
+ server = mock
25
+ server.expects(:send_file).with(
26
+ Pantry.root.join("chef", "cookbook-cache", "mini.tgz"),
27
+ "receiver_ident",
28
+ "file_uuid"
29
+ )
30
+
31
+ server.expects(:send_file).with(
32
+ Pantry.root.join("chef", "cookbook-cache", "pantry.tgz"),
33
+ "receiver_ident2",
34
+ "file_uuid2"
35
+ )
36
+
37
+ command = Pantry::Chef::SendCookbooks.new
38
+ command.server = server
39
+ command.perform(message)
40
+ end
41
+
42
+ end
43
+
44
+ end
@@ -0,0 +1,40 @@
1
+ require 'unit/test_helper'
2
+
3
+ describe Pantry::Chef::SyncCookbooks do
4
+
5
+ describe "#perform" do
6
+
7
+ it "requests to the server a list of cookbooks it should have" do
8
+ client = stub_everything
9
+ client.expects(:send_request).with do |message|
10
+ assert_equal "Chef::ListCookbooks", message.type
11
+ end.returns(mock(:value => Pantry::Message.new))
12
+
13
+ command = Pantry::Chef::SyncCookbooks.new
14
+ command.client = client
15
+ command.perform(Pantry::Message.new)
16
+ end
17
+
18
+ it "fires off receivers for each cookbook in the list and waits for downloads to finish" do
19
+ client = stub_everything
20
+ message = Pantry::Message.new
21
+ message << ["cookbook1", 0, "checksum1"]
22
+
23
+ client.stubs(:send_request).returns(stub(:value => message)).times(2)
24
+
25
+ client.expects(:receive_file).with(0, "checksum1").returns(
26
+ receive_info = Pantry::Communication::FileService::ReceivingFile.new(0, "checksum1", 1, 1)
27
+ )
28
+
29
+ receive_info.expects(:wait_for_finish)
30
+
31
+ command = Pantry::Chef::SyncCookbooks.new
32
+ command.client = client
33
+ command.perform(Pantry::Message.new)
34
+ end
35
+
36
+ it "deletes cookbooks stored locally not in the list (?)"
37
+
38
+ end
39
+
40
+ end
@@ -0,0 +1,21 @@
1
+ require 'unit/test_helper'
2
+
3
+ describe Pantry::Chef::SyncDataBags do
4
+
5
+ it "reads from the server directory for chef" do
6
+ cmd = Pantry::Chef::SyncDataBags.new
7
+ cmd.client = Pantry::ClientInfo.new(application: "pantry")
8
+
9
+ dir = cmd.server_directory(Pathname.new(""))
10
+ assert_equal "applications/pantry/chef/data_bags", dir.to_s
11
+ end
12
+
13
+ it "writes to the client's local chef dir" do
14
+ cmd = Pantry::Chef::SyncDataBags.new
15
+
16
+ dir = cmd.client_directory(Pathname.new(""))
17
+ assert_equal "chef/data_bags", dir.to_s
18
+ end
19
+
20
+ end
21
+
@@ -0,0 +1,21 @@
1
+ require 'unit/test_helper'
2
+
3
+ describe Pantry::Chef::SyncEnvironments do
4
+
5
+ it "reads from the server directory for chef" do
6
+ cmd = Pantry::Chef::SyncEnvironments.new
7
+ cmd.client = Pantry::ClientInfo.new(application: "pantry")
8
+
9
+ dir = cmd.server_directory(Pathname.new(""))
10
+ assert_equal "applications/pantry/chef/environments", dir.to_s
11
+ end
12
+
13
+ it "writes to the client's local chef dir" do
14
+ cmd = Pantry::Chef::SyncEnvironments.new
15
+
16
+ dir = cmd.client_directory(Pathname.new(""))
17
+ assert_equal "chef/environments", dir.to_s
18
+ end
19
+
20
+ end
21
+
@@ -0,0 +1,21 @@
1
+ require 'unit/test_helper'
2
+
3
+ describe Pantry::Chef::SyncRoles do
4
+
5
+ it "reads from the server directory for chef" do
6
+ cmd = Pantry::Chef::SyncRoles.new
7
+ cmd.client = Pantry::ClientInfo.new(application: "pantry")
8
+
9
+ dir = cmd.server_directory(Pathname.new(""))
10
+ assert_equal "applications/pantry/chef/roles", dir.to_s
11
+ end
12
+
13
+ it "writes to the client's local chef dir" do
14
+ cmd = Pantry::Chef::SyncRoles.new
15
+
16
+ dir = cmd.client_directory(Pathname.new(""))
17
+ assert_equal "chef/roles", dir.to_s
18
+ end
19
+
20
+ end
21
+
@@ -0,0 +1,132 @@
1
+ require 'unit/test_helper'
2
+
3
+ describe Pantry::Chef::UploadCookbook do
4
+
5
+ mock_ui!
6
+
7
+ def build_command(cookbook_name)
8
+ @command ||=
9
+ Pantry::Chef::UploadCookbook.new(fixture_path("cookbooks/#{cookbook_name}"))
10
+ end
11
+
12
+ describe "#prepare_message" do
13
+
14
+ after do
15
+ File.unlink(@command.cookbook_tarball) if @command && @command.cookbook_tarball
16
+ end
17
+
18
+ it "figures out name of the requested cookbook" do
19
+ command = build_command("mini")
20
+ message = command.prepare_message({})
21
+
22
+ assert_not_nil message, "Did not return a message"
23
+ assert_equal "mini", message[:cookbook_name]
24
+ end
25
+
26
+ it "tars up the cookbook, noting the size and a checksum of the file" do
27
+ command = build_command("mini")
28
+ message = command.prepare_message({})
29
+
30
+ assert message[:cookbook_size] > 0, "Did not calculate a size of the tarball"
31
+ assert_not_nil message[:cookbook_checksum], "Did not calculate a checksum"
32
+
33
+ assert_not_nil command.cookbook_tarball, "Did not save a pointer to the tarball"
34
+ assert File.exists?(command.cookbook_tarball), "No tarball found on the file system"
35
+ end
36
+
37
+ it "errors out if no metadata file" do
38
+ assert_raises Pantry::Chef::MissingMetadata do
39
+ command = build_command("bad")
40
+ command.prepare_message({})
41
+ end
42
+ end
43
+
44
+ it "errors if it can't find the cookbook" do
45
+ assert_raises Pantry::Chef::UnknownCookbook do
46
+ command = build_command("nonexist")
47
+ command.prepare_message({})
48
+ end
49
+ end
50
+ end
51
+
52
+ describe "#perform" do
53
+
54
+ let(:incoming_message) do
55
+ m = command.to_message
56
+ m[:cookbook_name] = "testing"
57
+ m[:cookbook_size] = 100
58
+ m[:cookbook_checksum] = "123abc"
59
+ m
60
+ end
61
+
62
+ let(:command) { build_command("mini") }
63
+
64
+ let(:receiver_info) {
65
+ stub(
66
+ :file_uuid => "abc123",
67
+ :receiver_uuid => "receiver",
68
+ :on_complete => nil
69
+ )
70
+ }
71
+
72
+ it "ensures a place exists for the uploaded cookbook to go" do
73
+ command.server_or_client = stub(:receive_file => receiver_info)
74
+ response = command.perform(incoming_message)
75
+
76
+ assert File.directory?(Pantry.root.join("chef", "cookbooks")),
77
+ "Did not create directory for the testing cookbook"
78
+ end
79
+
80
+ it "responds successfully and fires off a file upload receiver" do
81
+ server_mock = mock
82
+ server_mock.expects(:receive_file).with(100, "123abc").returns(receiver_info)
83
+
84
+ command.server_or_client = server_mock
85
+
86
+ response = command.perform(incoming_message)
87
+
88
+ assert_equal [true, "receiver", "abc123"], response
89
+ end
90
+
91
+ end
92
+
93
+ describe "#receive_server_response" do
94
+
95
+ let(:command) { build_command("mini") }
96
+
97
+ it "triggers a file upload actor with the cookbook tarball and message UUID" do
98
+ client = mock
99
+ client.expects(:send_file).with do |file, receiver_uuid|
100
+ assert File.exists?(file), "Did not find the file"
101
+ assert_equal "abc123", receiver_uuid
102
+ end.returns(mock(:wait_for_finish))
103
+
104
+ command.server_or_client = client
105
+ command.prepare_message({})
106
+
107
+ response_message = Pantry::Message.new
108
+ response_message.body << "true"
109
+ response_message.body << "abc123"
110
+
111
+ command.receive_server_response(response_message)
112
+ end
113
+
114
+ it "fails out with a message and cleans up if the server response with an error" do
115
+ client = mock
116
+ client.expects(:send_file).never
117
+
118
+ command.server_or_client = client
119
+ command.prepare_message({})
120
+
121
+ response_message = Pantry::Message.new
122
+ response_message << "false"
123
+ response_message << "Unable to Upload Reason"
124
+
125
+ command.receive_server_response(response_message)
126
+
127
+ assert_match /ERROR: Unable to Upload Reason/, stdout
128
+ end
129
+
130
+ end
131
+
132
+ end