cookbooks/fb_launchd/spec/default_spec.rb (184 lines of code) (raw):

# vim: syntax=ruby:expandtab:shiftwidth=2:softtabstop=2:tabstop=2 # # Copyright (c) 2018-present, Facebook, Inc. # All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. require './spec/spec_helper.rb' # rubocop:disable Style/MultilineBlockChain recipe( 'fb_launchd::default', :supported => [:mac_os_x], :unsupported => [:centos7], ) do |tc| context 'on non-macOS' do it 'should raise an error' do expect do tc.chef_run(:step_into => ['fb_launchd']) do |node| allow(node).to receive(:macos?).and_return(false) end.converge(described_recipe) end.to raise_error(RuntimeError) end end context 'when performing a clean fb_launchd setup' do cached(:chef_run) do tc.chef_run(:step_into => ['fb_launchd']) do |node| allow(node).to receive(:macos?).and_return(true) end.converge(described_recipe) do |node| node.default['fb_launchd'] = { 'prefix' => 'com.facebook.managed', 'jobs' => { 'simple_daemon' => { 'program_arguments' => ['foo', '1', '2'], 'start_calendar_interval' => { 'Minute' => 15 }, }, 'complex_daemon' => { 'action' => 'create_if_missing', 'program' => '/usr/local/bin/foo', 'keep_alive' => true, 'limit_load_to_session_type' => ['Aqua'], }, 'simple_agent' => { 'program' => '/usr/local/bin/foo', 'start_calendar_interval' => { 'Minute' => 15 }, 'type' => 'agent', }, }, } end end it 'should enable daemons' do expect(chef_run).to enable_launchd( 'com.facebook.managed.simple_daemon', ).with( 'program_arguments' => ['foo', '1', '2'], 'start_calendar_interval' => { 'Minute' => 15 }, ) end it 'should create daemons with custom actions' do expect(chef_run).to create_if_missing_launchd( 'com.facebook.managed.complex_daemon', ).with( 'program' => '/usr/local/bin/foo', 'keep_alive' => true, 'limit_load_to_session_type' => ['Aqua'], ) end it 'should enable agents' do expect(chef_run).to enable_launchd( 'com.facebook.managed.simple_agent', ).with( 'program' => '/usr/local/bin/foo', 'start_calendar_interval' => { 'Minute' => 15 }, 'type' => 'agent', ) end end context 'when specifying a custom prefix' do let(:job_spec) do { 'prefix' => 'io.company', 'jobs' => { 'simple_daemon' => { 'program_arguments' => ['foo', '1', '2'], }, }, } end let(:chef_run) do tc.chef_run(:step_into => ['fb_launchd']) do |node| allow(node).to receive(:macos?).and_return(true) end end it 'should use the custom prefix' do chef_run.converge(described_recipe) do |node| node.default['fb_launchd'] = job_spec end expect(chef_run).to enable_launchd('io.company.simple_daemon').with( 'program_arguments' => ['foo', '1', '2'], ) end it 'should fail when the prefix ends with .' do job_spec['prefix'] = 'io.company.' expect do chef_run.converge(described_recipe) do |node| node.default['fb_launchd'] = job_spec end end.to raise_error(RuntimeError) end end context 'when using blacklisted attributes' do let(:launchd_spec) do { 'prefix' => 'com.facebook.managed', 'jobs' => { 'test' => { 'program' => '/usr/local/bin/foo', 'start_calendar_interval' => { 'Minute' => 15 }, }, }, } end let(:chef_run) do tc.chef_run(:step_into => ['fb_launchd']) do |node| allow(node).to receive(:macos?).and_return(true) end end it 'should fail when parsing label attribute' do launchd_spec['jobs']['test']['label'] = 'foo.bar.baz' expect do chef_run.converge(described_recipe) do |node| node.default['fb_launchd'] = launchd_spec end end.to raise_error(RuntimeError) end it 'should fail when parsing path attribute' do launchd_spec['jobs']['test']['path'] = '/Library/LaunchDaemons/foo.plist' expect do chef_run.converge(described_recipe) do |node| node.default['fb_launchd'] = launchd_spec end end.to raise_error(RuntimeError) end end context 'when removing unmanaged jobs' do cached(:chef_run) do tc.chef_run(:step_into => ['fb_launchd']) do |node| allow(node).to receive(:macos?).and_return(true) end.converge(described_recipe) do |node| node.default['fb_launchd'] = { 'prefix' => 'com.facebook.managed', 'jobs' => { 'test' => { 'program' => '/usr/local/bin/foo', 'start_calendar_interval' => { 'Minute' => 15 }, }, }, } end end before(:each) do allow(Dir).to receive(:glob).and_return( [ '/Library/LaunchDaemons/com.apple.daemon1.plist', '/Library/LaunchDaemons/com.company.daemon2.plist', '/Library/LaunchDaemons/com.facebook.managed.not_test.plist', ], [ '/Library/LaunchAgents/com.apple.agent1.plist', '/Library/LaunchAgents/com.facebook.managed.also_not_test.plist', ], ) end it 'should not remove non-prefixed launchds' do expect(chef_run).to delete_launchd('com.facebook.managed.not_test').with( 'path' => '/Library/LaunchDaemons/com.facebook.managed.not_test.plist', ) expect(chef_run).to delete_launchd( 'com.facebook.managed.also_not_test', ).with( 'path' => '/Library/LaunchAgents/com.facebook.managed.also_not_test.plist', ) end it 'should enable prefixed launchds' do expect(chef_run).to enable_launchd('com.facebook.managed.test').with( 'program' => '/usr/local/bin/foo', 'start_calendar_interval' => { 'Minute' => 15 }, ) end end end # rubocop:enable Style/MultilineBlockChain