chef 12.2.1-x86-mingw32 → 12.3.0.rc.0-x86-mingw32

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 (70) hide show
  1. checksums.yaml +4 -4
  2. data/ext/win32-eventlog/Rakefile +10 -6
  3. data/lib/chef.rb +1 -0
  4. data/lib/chef/application/apply.rb +5 -0
  5. data/lib/chef/application/client.rb +10 -0
  6. data/lib/chef/application/knife.rb +5 -1
  7. data/lib/chef/application/solo.rb +5 -0
  8. data/lib/chef/chef_class.rb +130 -0
  9. data/lib/chef/client.rb +15 -7
  10. data/lib/chef/config.rb +13 -0
  11. data/lib/chef/event_loggers/windows_eventlog.rb +11 -5
  12. data/lib/chef/http.rb +13 -3
  13. data/lib/chef/http/basic_client.rb +21 -4
  14. data/lib/chef/http/socketless_chef_zero_client.rb +207 -0
  15. data/lib/chef/knife.rb +3 -0
  16. data/lib/chef/knife/bootstrap.rb +1 -1
  17. data/lib/chef/knife/core/status_presenter.rb +12 -11
  18. data/lib/chef/knife/ssh.rb +3 -1
  19. data/lib/chef/knife/status.rb +32 -7
  20. data/lib/chef/local_mode.rb +13 -3
  21. data/lib/chef/mixin/provides.rb +32 -0
  22. data/lib/chef/platform/provider_priority_map.rb +16 -7
  23. data/lib/chef/platform/resource_priority_map.rb +37 -0
  24. data/lib/chef/policy_builder/expand_node_object.rb +14 -0
  25. data/lib/chef/policy_builder/policyfile.rb +0 -1
  26. data/lib/chef/provider.rb +5 -20
  27. data/lib/chef/provider/package/rubygems.rb +4 -1
  28. data/lib/chef/provider/service/macosx.rb +66 -30
  29. data/lib/chef/provider_resolver.rb +10 -5
  30. data/lib/chef/resource.rb +5 -39
  31. data/lib/chef/resource/gem_package.rb +5 -0
  32. data/lib/chef/resource/link.rb +1 -1
  33. data/lib/chef/resource/macosx_service.rb +59 -0
  34. data/lib/chef/resource/remote_file.rb +0 -4
  35. data/lib/chef/resource_resolver.rb +101 -0
  36. data/lib/chef/rest.rb +4 -5
  37. data/lib/chef/search/query.rb +1 -1
  38. data/lib/chef/server_api.rb +1 -0
  39. data/lib/chef/version.rb +1 -1
  40. data/spec/data/lwrp/providers/buck_passer.rb +2 -1
  41. data/spec/data/lwrp/resources/bar.rb +1 -1
  42. data/spec/data/{big_json.json → nested.json} +2 -2
  43. data/spec/functional/event_loggers/windows_eventlog_spec.rb +14 -0
  44. data/spec/functional/resource/execute_spec.rb +1 -1
  45. data/spec/integration/client/client_spec.rb +12 -1
  46. data/spec/integration/client/ipv6_spec.rb +1 -1
  47. data/spec/integration/knife/common_options_spec.rb +3 -3
  48. data/spec/integration/recipes/lwrp_inline_resources_spec.rb +1 -1
  49. data/spec/integration/solo/solo_spec.rb +7 -5
  50. data/spec/unit/application/client_spec.rb +10 -0
  51. data/spec/unit/chef_class_spec.rb +91 -0
  52. data/spec/unit/client_spec.rb +13 -0
  53. data/spec/unit/http/basic_client_spec.rb +43 -6
  54. data/spec/unit/http/socketless_chef_zero_client_spec.rb +174 -0
  55. data/spec/unit/http_spec.rb +14 -0
  56. data/spec/unit/json_compat_spec.rb +7 -20
  57. data/spec/unit/knife/ssh_spec.rb +18 -0
  58. data/spec/unit/knife/status_spec.rb +69 -3
  59. data/spec/unit/knife_spec.rb +5 -0
  60. data/spec/unit/provider/package/rubygems_spec.rb +19 -0
  61. data/spec/unit/provider/service/macosx_spec.rb +230 -203
  62. data/spec/unit/provider_resolver_spec.rb +1 -0
  63. data/spec/unit/recipe_spec.rb +48 -0
  64. data/spec/unit/resource/link_spec.rb +15 -0
  65. data/spec/unit/resource_spec.rb +6 -6
  66. data/spec/unit/rest_spec.rb +9 -0
  67. data/spec/unit/search/query_spec.rb +24 -0
  68. data/spec/unit/shell_spec.rb +3 -1
  69. metadata +16 -9
  70. data/spec/data/big_json_plus_one.json +0 -2
@@ -20,6 +20,7 @@ require 'spec_helper'
20
20
 
21
21
  require 'chef/http'
22
22
  require 'chef/http/basic_client'
23
+ require 'chef/http/socketless_chef_zero_client'
23
24
 
24
25
  class Chef::HTTP
25
26
  public :create_url
@@ -27,6 +28,19 @@ end
27
28
 
28
29
  describe Chef::HTTP do
29
30
 
31
+ context "when given a chefzero:// URL" do
32
+
33
+ let(:uri) { URI("chefzero://localhost:1") }
34
+
35
+ subject(:http) { Chef::HTTP.new(uri) }
36
+
37
+ it "uses the SocketlessChefZeroClient to handle requests" do
38
+ expect(http.http_client).to be_a_kind_of(Chef::HTTP::SocketlessChefZeroClient)
39
+ expect(http.http_client.url).to eq(uri)
40
+ end
41
+
42
+ end
43
+
30
44
  describe "create_url" do
31
45
 
32
46
  it 'should return a correctly formatted url 1/3 CHEF-5261' do
@@ -72,32 +72,19 @@ describe Chef::JSONCompat do
72
72
  end
73
73
  end
74
74
 
75
- describe "with a file with 300 or less nested entries" do
76
- let(:json) { IO.read(File.join(CHEF_SPEC_DATA, 'big_json.json')) }
75
+ # On FreeBSD 10.1 i386 rspec fails with a SystemStackError loading the expect line with more that 252 entries
76
+ # https://github.com/chef/chef/issues/3101
77
+ describe "with the file with 252 or less nested entries" do
78
+ let(:json) { IO.read(File.join(CHEF_SPEC_DATA, 'nested.json')) }
77
79
  let(:hash) { Chef::JSONCompat.from_json(json) }
78
80
 
79
- describe "when a big json file is loaded" do
81
+ describe "when the 252 json file is loaded" do
80
82
  it "should create a Hash from the file" do
81
83
  expect(hash).to be_kind_of(Hash)
82
84
  end
83
85
 
84
- it "should has 'test' as a 300th nested value" do
85
- expect(hash['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']).to eq('test')
86
- end
87
- end
88
- end
89
-
90
- describe "with a file with more than 300 nested entries" do
91
- let(:json) { IO.read(File.join(CHEF_SPEC_DATA, 'big_json_plus_one.json')) }
92
- let(:hash) { Chef::JSONCompat.from_json(json, {:max_nesting => 301}) }
93
-
94
- describe "when a big json file is loaded" do
95
- it "should create a Hash from the file" do
96
- expect(hash).to be_kind_of(Hash)
97
- end
98
-
99
- it "should has 'test' as a 301st nested value" do
100
- expect(hash['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']).to eq('test')
86
+ it "should has 'test' as a 252 nested value" do
87
+ expect(hash['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']).to eq('test')
101
88
  end
102
89
  end
103
90
  end
@@ -96,6 +96,24 @@ describe Chef::Knife::Ssh do
96
96
  should_return_specified_attributes
97
97
  end
98
98
 
99
+ context "when cloud hostnames are available but empty" do
100
+ before do
101
+ @node_foo.automatic_attrs[:cloud][:public_hostname] = ''
102
+ @node_bar.automatic_attrs[:cloud][:public_hostname] = ''
103
+ end
104
+
105
+ it "returns an array of fqdns" do
106
+ configure_query([@node_foo, @node_bar])
107
+ expect(@knife).to receive(:session_from_list).with([
108
+ ['foo.example.org', nil],
109
+ ['bar.example.org', nil]
110
+ ])
111
+ @knife.configure_session
112
+ end
113
+
114
+ should_return_specified_attributes
115
+ end
116
+
99
117
  it "should raise an error if no host are found" do
100
118
  configure_query([ ])
101
119
  expect(@knife.ui).to receive(:fatal)
@@ -24,15 +24,81 @@ describe Chef::Knife::Status do
24
24
  n.automatic_attrs["fqdn"] = "foobar"
25
25
  n.automatic_attrs["ohai_time"] = 1343845969
26
26
  end
27
- query = double("Chef::Search::Query")
28
- allow(query).to receive(:search).and_yield(node)
29
- allow(Chef::Search::Query).to receive(:new).and_return(query)
27
+ allow(Time).to receive(:now).and_return(Time.at(1428573420))
28
+ @query = double("Chef::Search::Query")
29
+ allow(@query).to receive(:search).and_yield(node)
30
+ allow(Chef::Search::Query).to receive(:new).and_return(@query)
30
31
  @knife = Chef::Knife::Status.new
31
32
  @stdout = StringIO.new
32
33
  allow(@knife.ui).to receive(:stdout).and_return(@stdout)
33
34
  end
34
35
 
35
36
  describe "run" do
37
+ let(:opts) {{filter_result:
38
+ { name: ["name"], ipaddress: ["ipaddress"], ohai_time: ["ohai_time"],
39
+ ec2: ["ec2"], run_list: ["run_list"], platform: ["platform"],
40
+ platform_version: ["platform_version"], chef_environment: ["chef_environment"]}}}
41
+
42
+ it "should default to searching for everything" do
43
+ expect(@query).to receive(:search).with(:node, "*:*", opts)
44
+ @knife.run
45
+ end
46
+
47
+ it "should filter healthy nodes" do
48
+ @knife.config[:hide_healthy] = true
49
+ expect(@query).to receive(:search).with(:node, "NOT ohai_time:[1428569820 TO 1428573420]", opts)
50
+ @knife.run
51
+ end
52
+
53
+ it "should filter by environment" do
54
+ @knife.config[:environment] = "production"
55
+ expect(@query).to receive(:search).with(:node, "chef_environment:production", opts)
56
+ @knife.run
57
+ end
58
+
59
+ it "should filter by environment and health" do
60
+ @knife.config[:environment] = "production"
61
+ @knife.config[:hide_healthy] = true
62
+ expect(@query).to receive(:search).with(:node, "chef_environment:production NOT ohai_time:[1428569820 TO 1428573420]", opts)
63
+ @knife.run
64
+ end
65
+
66
+ it "should not use partial search with long output" do
67
+ @knife.config[:long_output] = true
68
+ expect(@query).to receive(:search).with(:node, "*:*", {})
69
+ @knife.run
70
+ end
71
+
72
+ context "with a custom query" do
73
+ before :each do
74
+ @knife.instance_variable_set(:@name_args, ["name:my_custom_name"])
75
+ end
76
+
77
+ it "should allow a custom query to be specified" do
78
+ expect(@query).to receive(:search).with(:node, "name:my_custom_name", opts)
79
+ @knife.run
80
+ end
81
+
82
+ it "should filter healthy nodes" do
83
+ @knife.config[:hide_healthy] = true
84
+ expect(@query).to receive(:search).with(:node, "name:my_custom_name NOT ohai_time:[1428569820 TO 1428573420]", opts)
85
+ @knife.run
86
+ end
87
+
88
+ it "should filter by environment" do
89
+ @knife.config[:environment] = "production"
90
+ expect(@query).to receive(:search).with(:node, "name:my_custom_name AND chef_environment:production", opts)
91
+ @knife.run
92
+ end
93
+
94
+ it "should filter by environment and health" do
95
+ @knife.config[:environment] = "production"
96
+ @knife.config[:hide_healthy] = true
97
+ expect(@query).to receive(:search).with(:node, "name:my_custom_name AND chef_environment:production NOT ohai_time:[1428569820 TO 1428573420]", opts)
98
+ @knife.run
99
+ end
100
+ end
101
+
36
102
  it "should not colorize output unless it's writing to a tty" do
37
103
  @knife.run
38
104
  expect(@stdout.string.match(/foobar/)).not_to be_nil
@@ -271,6 +271,11 @@ describe Chef::Knife do
271
271
  expect(knife_command.config[:opt_with_default]).to eq("from-cli")
272
272
  end
273
273
 
274
+ it "merges `listen` config to Chef::Config" do
275
+ Chef::Knife.run(%w[test yourself --no-listen], Chef::Application::Knife.options)
276
+ expect(Chef::Config[:listen]).to be(false)
277
+ end
278
+
274
279
  context "verbosity is greater than zero" do
275
280
  let(:fake_config) { "/does/not/exist/knife.rb" }
276
281
 
@@ -547,6 +547,25 @@ describe Chef::Provider::Package::Rubygems do
547
547
  expect(@new_resource).to be_updated_by_last_action
548
548
  end
549
549
 
550
+ it "installs the gem with rubygems.org as an added source" do
551
+ @new_resource.gem_binary('/foo/bar')
552
+ @new_resource.source('http://mirror.ops.rhcloud.com/mirror/ruby')
553
+ expected ="/foo/bar install rspec-core -q --no-rdoc --no-ri -v \"#{@spec_version}\" --source=#{@new_resource.source} --source=https://rubygems.org"
554
+ expect(@provider).to receive(:shell_out!).with(expected, :env => nil)
555
+ @provider.run_action(:install)
556
+ expect(@new_resource).to be_updated_by_last_action
557
+ end
558
+
559
+ it "installs the gem with cleared sources and explict source when specified" do
560
+ @new_resource.gem_binary('/foo/bar')
561
+ @new_resource.source('http://mirror.ops.rhcloud.com/mirror/ruby')
562
+ @new_resource.clear_sources(true)
563
+ expected ="/foo/bar install rspec-core -q --no-rdoc --no-ri -v \"#{@spec_version}\" --clear-sources --source=#{@new_resource.source}"
564
+ expect(@provider).to receive(:shell_out!).with(expected, :env => nil)
565
+ @provider.run_action(:install)
566
+ expect(@new_resource).to be_updated_by_last_action
567
+ end
568
+
550
569
  context "when no version is given" do
551
570
  let(:target_version) { nil }
552
571
 
@@ -58,248 +58,275 @@ describe Chef::Provider::Service::Macosx do
58
58
  </plist>
59
59
  XML
60
60
 
61
- ["redis-server", "io.redis.redis-server"].each do |service_name|
62
- before do
63
- allow(Dir).to receive(:glob).and_return(["/Users/igor/Library/LaunchAgents/io.redis.redis-server.plist"], [])
64
- allow(provider).to receive(:shell_out!).
65
- with("launchctl list", {:group => 1001, :user => 101}).
66
- and_return(double("Status", :stdout => launchctl_stdout))
67
- allow(provider).to receive(:shell_out).
68
- with(/launchctl list /,
69
- {:group => nil, :user => nil}).
70
- and_return(double("Status",
71
- :stdout => launchctl_stdout, :exitstatus => 0))
72
- allow(provider).to receive(:shell_out!).
73
- with(/plutil -convert xml1 -o/).
74
- and_return(double("Status", :stdout => plutil_stdout))
75
-
76
- allow(File).to receive(:stat).and_return(double("stat", :gid => 1001, :uid => 101))
77
- end
78
-
79
- context "#{service_name}" do
80
- let(:new_resource) { Chef::Resource::Service.new(service_name) }
81
- let!(:current_resource) { Chef::Resource::Service.new(service_name) }
82
-
83
- describe "#load_current_resource" do
84
-
85
- # CHEF-5223 "you can't glob for a file that hasn't been converged
86
- # onto the node yet."
87
- context "when the plist doesn't exist" do
88
-
89
- def run_resource_setup_for_action(action)
90
- new_resource.action(action)
91
- provider.action = action
92
- provider.load_current_resource
93
- provider.define_resource_requirements
94
- provider.process_resource_requirements
95
- end
96
-
97
- before do
98
- allow(Dir).to receive(:glob).and_return([])
99
- allow(provider).to receive(:shell_out!).
100
- with(/plutil -convert xml1 -o/).
101
- and_raise(Mixlib::ShellOut::ShellCommandFailed)
102
- end
103
-
104
- it "works for action :nothing" do
105
- expect { run_resource_setup_for_action(:nothing) }.not_to raise_error
106
- end
107
-
108
- it "works for action :start" do
109
- expect { run_resource_setup_for_action(:start) }.not_to raise_error
110
- end
111
-
112
- it "errors if action is :enable" do
113
- expect { run_resource_setup_for_action(:enable) }.to raise_error(Chef::Exceptions::Service)
114
- end
115
-
116
- it "errors if action is :disable" do
117
- expect { run_resource_setup_for_action(:disable) }.to raise_error(Chef::Exceptions::Service)
61
+ ["Daemon", "Agent"].each do |service_type|
62
+ ["redis-server", "io.redis.redis-server"].each do |service_name|
63
+ ["10.9", "10.10"].each do |platform_version|
64
+ let(:plist) {'/Library/LaunchDaemons/io.redis.redis-server.plist'}
65
+ let(:session) { StringIO.new }
66
+ if service_type == 'Agent'
67
+ let(:plist) {'/Library/LaunchAgents/io.redis.redis-server.plist'}
68
+ let(:session) {'-S Aqua '}
69
+ let(:su_cmd) {'su igor -c'}
70
+ if platform_version != "10.10"
71
+ let(:su_cmd) {'su -l igor -c'}
118
72
  end
119
73
  end
120
-
121
- context "when launchctl returns pid in service list" do
122
- let(:launchctl_stdout) { StringIO.new <<-SVC_LIST }
123
- 12761 - 0x100114220.old.machinit.thing
124
- 7777 - io.redis.redis-server
125
- - - com.lol.stopped-thing
126
- SVC_LIST
127
-
128
- before do
129
- provider.load_current_resource
130
- end
131
-
132
- it "sets resource running state to true" do
133
- expect(provider.current_resource.running).to be_truthy
134
- end
135
-
136
- it "sets resouce enabled state to true" do
137
- expect(provider.current_resource.enabled).to be_truthy
138
- end
74
+ let(:service_label) {'io.redis.redis-server'}
75
+ before do
76
+ allow(Dir).to receive(:glob).and_return([plist], [])
77
+ allow(Etc).to receive(:getlogin).and_return('igor')
78
+ allow(node).to receive(:[]).with("platform_version").and_return(platform_version)
79
+ cmd = "launchctl list #{service_label}"
80
+ allow(provider).to receive(:shell_out_with_systems_locale).
81
+ with(/(#{su_cmd} '#{cmd}'|#{cmd})/).
82
+ and_return(double("Status",
83
+ :stdout => launchctl_stdout, :exitstatus => 0))
84
+ allow(File).to receive(:exists?).and_return([true], [])
85
+ allow(provider).to receive(:shell_out_with_systems_locale!).
86
+ with(/plutil -convert xml1 -o/).
87
+ and_return(double("Status", :stdout => plutil_stdout))
139
88
  end
140
89
 
141
- describe "running unsupported actions" do
142
- let(:launchctl_stdout) { StringIO.new <<-SVC_LIST }
143
- 12761 - 0x100114220.old.machinit.thing
144
- 7777 - io.redis.redis-server
145
- - - com.lol.stopped-thing
90
+ context "#{service_name} that is a #{service_type} running Osx #{platform_version}" do
91
+ let(:new_resource) { Chef::Resource::MacosxService.new(service_name) }
92
+ let!(:current_resource) { Chef::Resource::MacosxService.new(service_name) }
93
+
94
+ describe "#load_current_resource" do
95
+
96
+ # CHEF-5223 "you can't glob for a file that hasn't been converged
97
+ # onto the node yet."
98
+ context "when the plist doesn't exist" do
99
+
100
+ def run_resource_setup_for_action(action)
101
+ new_resource.action(action)
102
+ provider.action = action
103
+ provider.load_current_resource
104
+ provider.define_resource_requirements
105
+ provider.process_resource_requirements
106
+ end
107
+
108
+ before do
109
+ allow(Dir).to receive(:glob).and_return([])
110
+ allow(File).to receive(:exists?).and_return([true], [])
111
+ allow(provider).to receive(:shell_out!).
112
+ with(/plutil -convert xml1 -o/).
113
+ and_raise(Mixlib::ShellOut::ShellCommandFailed)
114
+ end
115
+
116
+ it "works for action :nothing" do
117
+ expect { run_resource_setup_for_action(:nothing) }.not_to raise_error
118
+ end
119
+
120
+ it "works for action :start" do
121
+ expect { run_resource_setup_for_action(:start) }.not_to raise_error
122
+ end
123
+
124
+ it "errors if action is :enable" do
125
+ expect { run_resource_setup_for_action(:enable) }.to raise_error(Chef::Exceptions::Service)
126
+ end
127
+
128
+ it "errors if action is :disable" do
129
+ expect { run_resource_setup_for_action(:disable) }.to raise_error(Chef::Exceptions::Service)
130
+ end
131
+ end
132
+
133
+ context "when launchctl returns pid in service list" do
134
+ let(:launchctl_stdout) { StringIO.new <<-SVC_LIST }
135
+ {
136
+ "LimitLoadToSessionType" = "System";
137
+ "Label" = "io.redis.redis-server";
138
+ "TimeOut" = 30;
139
+ "OnDemand" = false;
140
+ "LastExitStatus" = 0;
141
+ "PID" = 62803;
142
+ "Program" = "do_some.sh";
143
+ "ProgramArguments" = (
144
+ "path/to/do_something.sh";
145
+ "-f";
146
+ );
147
+ };
146
148
  SVC_LIST
147
149
 
148
- before do
149
- allow(Dir).to receive(:glob).and_return(["/Users/igor/Library/LaunchAgents/io.redis.redis-server.plist"], [])
150
- end
151
- it "should throw an exception when reload action is attempted" do
152
- expect {provider.run_action(:reload)}.to raise_error(Chef::Exceptions::UnsupportedAction)
153
- end
154
- end
155
- context "when launchctl returns empty service pid" do
156
- let(:launchctl_stdout) { StringIO.new <<-SVC_LIST }
157
- 12761 - 0x100114220.old.machinit.thing
158
- - - io.redis.redis-server
159
- - - com.lol.stopped-thing
160
- SVC_LIST
161
-
162
- before do
163
- provider.load_current_resource
164
- end
150
+ before do
151
+ provider.load_current_resource
152
+ end
165
153
 
166
- it "sets resource running state to false" do
167
- expect(provider.current_resource.running).to be_falsey
168
- end
154
+ it "sets resource running state to true" do
155
+ expect(provider.current_resource.running).to be_truthy
156
+ end
169
157
 
170
- it "sets resouce enabled state to true" do
171
- expect(provider.current_resource.enabled).to be_truthy
172
- end
173
- end
158
+ it "sets resouce enabled state to true" do
159
+ expect(provider.current_resource.enabled).to be_truthy
160
+ end
161
+ end
174
162
 
175
- context "when launchctl doesn't return service entry at all" do
176
- let(:launchctl_stdout) { StringIO.new <<-SVC_LIST }
177
- 12761 - 0x100114220.old.machinit.thing
178
- - - com.lol.stopped-thing
179
- SVC_LIST
163
+ describe "running unsupported actions" do
164
+ before do
165
+ allow(Dir).to receive(:glob).and_return(["#{plist}"], [])
166
+ allow(File).to receive(:exists?).and_return([true], [])
167
+ end
168
+ it "should throw an exception when reload action is attempted" do
169
+ expect {provider.run_action(:reload)}.to raise_error(Chef::Exceptions::UnsupportedAction)
170
+ end
171
+ end
172
+ context "when launchctl returns empty service pid" do
173
+ let(:launchctl_stdout) { StringIO.new <<-SVC_LIST }
174
+ {
175
+ "LimitLoadToSessionType" = "System";
176
+ "Label" = "io.redis.redis-server";
177
+ "TimeOut" = 30;
178
+ "OnDemand" = false;
179
+ "LastExitStatus" = 0;
180
+ "Program" = "do_some.sh";
181
+ "ProgramArguments" = (
182
+ "path/to/do_something.sh";
183
+ "-f";
184
+ );
185
+ };
186
+ SVC_LIST
180
187
 
181
- it "sets service running state to false" do
182
- provider.load_current_resource
183
- expect(provider.current_resource.running).to be_falsey
184
- end
188
+ before do
189
+ provider.load_current_resource
190
+ end
185
191
 
186
- context "and plist for service is not available" do
187
- before do
188
- allow(Dir).to receive(:glob).and_return([])
189
- provider.load_current_resource
190
- end
192
+ it "sets resource running state to false" do
193
+ expect(provider.current_resource.running).to be_falsey
194
+ end
191
195
 
192
- it "sets resouce enabled state to false" do
193
- expect(provider.current_resource.enabled).to be_falsey
196
+ it "sets resouce enabled state to true" do
197
+ expect(provider.current_resource.enabled).to be_truthy
198
+ end
194
199
  end
195
- end
196
200
 
197
- context "and plist for service is available" do
198
- before do
199
- allow(Dir).to receive(:glob).and_return(["/Users/igor/Library/LaunchAgents/io.redis.redis-server.plist"], [])
200
- provider.load_current_resource
201
- end
201
+ context "when launchctl doesn't return service entry at all" do
202
+ let(:launchctl_stdout) { StringIO.new <<-SVC_LIST }
203
+ Could not find service "io.redis.redis-server" in domain for system
204
+ SVC_LIST
202
205
 
203
- it "sets resouce enabled state to true" do
204
- expect(provider.current_resource.enabled).to be_truthy
206
+ it "sets service running state to false" do
207
+ provider.load_current_resource
208
+ expect(provider.current_resource.running).to be_falsey
209
+ end
210
+
211
+ context "and plist for service is not available" do
212
+ before do
213
+ allow(Dir).to receive(:glob).and_return([])
214
+ provider.load_current_resource
215
+ end
216
+
217
+ it "sets resouce enabled state to false" do
218
+ expect(provider.current_resource.enabled).to be_falsey
219
+ end
220
+ end
221
+
222
+ context "and plist for service is available" do
223
+ before do
224
+ allow(Dir).to receive(:glob).and_return(["#{plist}"], [])
225
+ provider.load_current_resource
226
+ end
227
+
228
+ it "sets resouce enabled state to true" do
229
+ expect(provider.current_resource.enabled).to be_truthy
230
+ end
231
+ end
232
+
233
+ describe "and several plists match service name" do
234
+ it "throws exception" do
235
+ allow(Dir).to receive(:glob).and_return(["#{plist}",
236
+ "/Users/wtf/something.plist"])
237
+ provider.load_current_resource
238
+ provider.define_resource_requirements
239
+ expect { provider.process_resource_requirements }.to raise_error(Chef::Exceptions::Service)
240
+ end
241
+ end
205
242
  end
206
243
  end
207
-
208
- describe "and several plists match service name" do
209
- it "throws exception" do
210
- allow(Dir).to receive(:glob).and_return(["/Users/igor/Library/LaunchAgents/io.redis.redis-server.plist",
211
- "/Users/wtf/something.plist"])
244
+ describe "#start_service" do
245
+ before do
246
+ allow(Chef::Resource::MacosxService).to receive(:new).and_return(current_resource)
212
247
  provider.load_current_resource
213
- provider.define_resource_requirements
214
- expect { provider.process_resource_requirements }.to raise_error(Chef::Exceptions::Service)
248
+ allow(current_resource).to receive(:running).and_return(false)
215
249
  end
216
- end
217
- end
218
- end
219
- describe "#start_service" do
220
- before do
221
- allow(Chef::Resource::Service).to receive(:new).and_return(current_resource)
222
- provider.load_current_resource
223
- allow(current_resource).to receive(:running).and_return(false)
224
- end
225
250
 
226
- it "calls the start command if one is specified and service is not running" do
227
- allow(new_resource).to receive(:start_command).and_return("cowsay dirty")
251
+ it "calls the start command if one is specified and service is not running" do
252
+ allow(new_resource).to receive(:start_command).and_return("cowsay dirty")
228
253
 
229
- expect(provider).to receive(:shell_out_with_systems_locale!).with("cowsay dirty")
230
- provider.start_service
231
- end
254
+ expect(provider).to receive(:shell_out_with_systems_locale!).with("cowsay dirty")
255
+ provider.start_service
256
+ end
232
257
 
233
- it "shows warning message if service is already running" do
234
- allow(current_resource).to receive(:running).and_return(true)
235
- expect(Chef::Log).to receive(:debug).with("service[#{service_name}] already running, not starting")
258
+ it "shows warning message if service is already running" do
259
+ allow(current_resource).to receive(:running).and_return(true)
260
+ expect(Chef::Log).to receive(:debug).with("macosx_service[#{service_name}] already running, not starting")
236
261
 
237
- provider.start_service
238
- end
262
+ provider.start_service
263
+ end
239
264
 
240
- it "starts service via launchctl if service found" do
241
- expect(provider).to receive(:shell_out_with_systems_locale!).
242
- with("launchctl load -w '/Users/igor/Library/LaunchAgents/io.redis.redis-server.plist'",
243
- :group => 1001, :user => 101).
244
- and_return(0)
265
+ it "starts service via launchctl if service found" do
266
+ cmd = 'launchctl load -w ' + session + plist
267
+ expect(provider).to receive(:shell_out_with_systems_locale).
268
+ with(/(#{su_cmd} .#{cmd}.|#{cmd})/).
269
+ and_return(0)
245
270
 
246
- provider.start_service
247
- end
248
- end
271
+ provider.start_service
272
+ end
273
+ end
249
274
 
250
- describe "#stop_service" do
251
- before do
252
- allow(Chef::Resource::Service).to receive(:new).and_return(current_resource)
275
+ describe "#stop_service" do
276
+ before do
277
+ allow(Chef::Resource::MacosxService).to receive(:new).and_return(current_resource)
253
278
 
254
- provider.load_current_resource
255
- allow(current_resource).to receive(:running).and_return(true)
256
- end
279
+ provider.load_current_resource
280
+ allow(current_resource).to receive(:running).and_return(true)
281
+ end
257
282
 
258
- it "calls the stop command if one is specified and service is running" do
259
- allow(new_resource).to receive(:stop_command).and_return("kill -9 123")
283
+ it "calls the stop command if one is specified and service is running" do
284
+ allow(new_resource).to receive(:stop_command).and_return("kill -9 123")
260
285
 
261
- expect(provider).to receive(:shell_out_with_systems_locale!).with("kill -9 123")
262
- provider.stop_service
263
- end
286
+ expect(provider).to receive(:shell_out_with_systems_locale!).with("kill -9 123")
287
+ provider.stop_service
288
+ end
264
289
 
265
- it "shows warning message if service is not running" do
266
- allow(current_resource).to receive(:running).and_return(false)
267
- expect(Chef::Log).to receive(:debug).with("service[#{service_name}] not running, not stopping")
290
+ it "shows warning message if service is not running" do
291
+ allow(current_resource).to receive(:running).and_return(false)
292
+ expect(Chef::Log).to receive(:debug).with("macosx_service[#{service_name}] not running, not stopping")
268
293
 
269
- provider.stop_service
270
- end
294
+ provider.stop_service
295
+ end
271
296
 
272
- it "stops the service via launchctl if service found" do
273
- expect(provider).to receive(:shell_out_with_systems_locale!).
274
- with("launchctl unload '/Users/igor/Library/LaunchAgents/io.redis.redis-server.plist'",
275
- :group => 1001, :user => 101).
276
- and_return(0)
297
+ it "stops the service via launchctl if service found" do
298
+ cmd = 'launchctl unload -w '+ plist
299
+ expect(provider).to receive(:shell_out_with_systems_locale).
300
+ with(/(#{su_cmd} .#{cmd}.|#{cmd})/).
301
+ and_return(0)
277
302
 
278
- provider.stop_service
279
- end
280
- end
303
+ provider.stop_service
304
+ end
305
+ end
281
306
 
282
- describe "#restart_service" do
283
- before do
284
- allow(Chef::Resource::Service).to receive(:new).and_return(current_resource)
307
+ describe "#restart_service" do
308
+ before do
309
+ allow(Chef::Resource::Service).to receive(:new).and_return(current_resource)
285
310
 
286
- provider.load_current_resource
287
- allow(current_resource).to receive(:running).and_return(true)
288
- allow(provider).to receive(:sleep)
289
- end
311
+ provider.load_current_resource
312
+ allow(current_resource).to receive(:running).and_return(true)
313
+ allow(provider).to receive(:sleep)
314
+ end
290
315
 
291
- it "issues a command if given" do
292
- allow(new_resource).to receive(:restart_command).and_return("reload that thing")
316
+ it "issues a command if given" do
317
+ allow(new_resource).to receive(:restart_command).and_return("reload that thing")
293
318
 
294
- expect(provider).to receive(:shell_out_with_systems_locale!).with("reload that thing")
295
- provider.restart_service
296
- end
319
+ expect(provider).to receive(:shell_out_with_systems_locale!).with("reload that thing")
320
+ provider.restart_service
321
+ end
297
322
 
298
- it "stops and then starts service" do
299
- expect(provider).to receive(:stop_service)
300
- expect(provider).to receive(:start_service);
323
+ it "stops and then starts service" do
324
+ expect(provider).to receive(:unload_service)
325
+ expect(provider).to receive(:load_service);
301
326
 
302
- provider.restart_service
327
+ provider.restart_service
328
+ end
329
+ end
303
330
  end
304
331
  end
305
332
  end