diff options
-rw-r--r-- | lib/chef/resource/dmg_package.rb | 47 | ||||
-rw-r--r-- | lib/chef/resource/homebrew_cask.rb | 58 | ||||
-rw-r--r-- | lib/chef/resource/homebrew_tap.rb | 51 | ||||
-rw-r--r-- | spec/unit/mixin/homebrew_user_spec.rb | 6 | ||||
-rw-r--r-- | spec/unit/resource/homebrew_cask_spec.rb | 35 | ||||
-rw-r--r-- | spec/unit/resource/homebrew_tap_spec.rb | 39 |
6 files changed, 180 insertions, 56 deletions
diff --git a/lib/chef/resource/dmg_package.rb b/lib/chef/resource/dmg_package.rb index e427784990..cdfe764643 100644 --- a/lib/chef/resource/dmg_package.rb +++ b/lib/chef/resource/dmg_package.rb @@ -1,6 +1,6 @@ # # Author:: Joshua Timberman (<jtimberman@chef.io>) -# Copyright:: 2011-2017, Chef Software, Inc. +# Copyright:: 2011-2018, Chef Software, Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -21,46 +21,63 @@ class Chef class Resource class DmgPackage < Chef::Resource resource_name :dmg_package - provides :dmg_package - description "" + description "Use the dmg_package resourceto install a DMG 'Package'. The resource will retrieve the"\ + " DMG file from a remote URL, mount it using OS X's hdid, copy the application (.app directory)"\ + " to the specified destination (/Applications), and detach the image using hdiutil. The dmg file"\ + "will be stored in the Chef::Config[:file_cache_path]." introduced "14.0" property :app, String, + description: "The name of the application used by default for the /Volumes directory and the .app directory copied to /Applications.", name_property: true - property :source, String + property :source, String, + description: "The remote URL for the dmg to download if specified." - property :file, String + property :file, String, + description: "The local dmg full file path." - property :owner, String + property :owner, String, + description: "The owner that should own the package installation." property :destination, String, + description: "The directory to copy the .app into.", default: "/Applications" - property :checksum, String + property :checksum, String, + description: "The sha256 checksum of the dmg to download" - property :volumes_dir, String + property :volumes_dir, String, + description: "The Directory under /Volumes where the dmg is mounted as not all dmgs are mounted into a /Volumes location matching the name of the dmg." - property :dmg_name, String + property :dmg_name, String, + description: "The name of the dmg if it is not the same as app, or if the name has spaces." property :type, String, + description: "The type of package.", + equal_to: %w{app pkg mpkg}, default: "app" - property :installed, [true, false], + property :installed, [TrueClass, FalseClass], default: false, desired_state: false - property :package_id, String + property :package_id, String, + description: "The package id registered with pkgutil when a pkg or mpkg is installed" - property :dmg_passphrase, String + property :dmg_passphrase, String, + description: "Specify a passphrase to use to unencrypt the dmg while mounting." - property :accept_eula, [true, false], + property :accept_eula, [TrueClass, FalseClass], + description: "Specify whether to accept the EULA. Certain dmgs require acceptance of EULA before mounting.", default: false property :headers, [Hash, nil], + description: "Allows custom HTTP headers (like cookies) to be set on the remote_file resource.", default: nil - property :allow_untrusted, [true, false], + property :allow_untrusted, [TrueClass, FalseClass], + description: "Allows packages with untrusted certs to be installed.", default: false load_current_value do |new_resource| @@ -76,6 +93,8 @@ class Chef end action :install do + description "Installs the application." + unless current_resource.installed volumes_dir = new_resource.volumes_dir ? new_resource.volumes_dir : new_resource.app diff --git a/lib/chef/resource/homebrew_cask.rb b/lib/chef/resource/homebrew_cask.rb index 9a053c0a68..d10ecb04c9 100644 --- a/lib/chef/resource/homebrew_cask.rb +++ b/lib/chef/resource/homebrew_cask.rb @@ -24,51 +24,73 @@ class Chef class Resource class HomebrewCask < Chef::Resource resource_name :homebrew_cask - provides :homebrew_cask - description "" + description "Use the homebrew_cask resource to install binaries distributed via the Homebrew package manager." introduced "14.0" include Chef::Mixin::HomebrewUser - property :name, String, + property :cask_name, String, + description: "Cask name to override the resource name.", regex: %r{^[\w/-]+$}, name_property: true - property :options, String + property :options, String, + description: "Options to pass to the brew CLI during installation." - property :install_cask, [true, false], + property :install_cask, [TrueClass, FalseClass], + description: "Auto install cask tap if necessary.", default: true + property :homebrew_path, String, + description: "The path to the homebrew binary.", + default: "/usr/local/bin/brew" + + property :owner, String, + description: "The owner of the homebrew installation.", + default: lazy { Chef::Mixin::HomebrewUser.find_homebrew_username } + action :install do + description "Install an application packaged as a Homebrew cask." + homebrew_tap "caskroom/cask" if new_resource.install_cask - declare_resource(:execute, "installing cask #{new_resource.name}") do - command "/usr/local/bin/brew cask install #{new_resource.name} #{new_resource.options}" - user find_homebrew_uid - environment lazy { { "HOME" => ::Dir.home(find_homebrew_uid), "USER" => find_homebrew_uid } } - not_if { casked? } + unless casked? + converge_by("install cask #{new_resource.name} #{new_resource.options}") do + shell_out!("#{new_resource.homebrew_path} cask install #{new_resource.name} #{new_resource.options}", + user: new_resource.owner, + env: { "HOME" => ::Dir.home(new_resource.owner), "USER" => new_resource.owner }, + cwd: ::Dir.home(new_resource.owner)) + end end end - action :uninstall do + action :remove do + description "Remove an application packaged as a Homebrew cask." + homebrew_tap "caskroom/cask" if new_resource.install_cask - declare_resource(:execute, "uninstalling cask #{new_resource.name}") do - command "/usr/local/bin/brew cask uninstall #{new_resource.name}" - user find_homebrew_uid - environment lazy { { "HOME" => ::Dir.home(find_homebrew_uid), "USER" => find_homebrew_uid } } - only_if { casked? } + if casked? + converge_by("uninstall cask #{new_resource.name}") do + shell_out!("#{new_resource.homebrew_path} cask uninstall #{new_resource.name}", + user: new_resource.owner, + env: { "HOME" => ::Dir.home(new_resource.owner), "USER" => new_resource.owner }, + cwd: ::Dir.home(new_resource.owner)) + end end end action_class do alias_method :action_cask, :action_install - alias_method :action_uncask, :action_uninstall + alias_method :action_uncask, :action_remove + alias_method :action_uninstall, :action_remove def casked? unscoped_name = new_resource.name.split("/").last - shell_out("/usr/local/bin/brew cask list 2>/dev/null", user: find_homebrew_uid).stdout.split.include?(unscoped_name) + shell_out!('#{new_resource.homebrew_path} cask list 2>/dev/null', + user: new_resource.owner, + env: { "HOME" => ::Dir.home(new_resource.owner), "USER" => new_resource.owner }, + cwd: ::Dir.home(new_resource.owner)).stdout.split.include?(unscoped_name) end end end diff --git a/lib/chef/resource/homebrew_tap.rb b/lib/chef/resource/homebrew_tap.rb index ad58f73dd3..8ce72e0861 100644 --- a/lib/chef/resource/homebrew_tap.rb +++ b/lib/chef/resource/homebrew_tap.rb @@ -24,49 +24,62 @@ class Chef class Resource class HomebrewTap < Chef::Resource resource_name :homebrew_tap - provides :homebrew_tap - description "" + description "Use the homebrew_tap resource to add additional formula repositories to the Homebrew package manager." introduced "14.0" include Chef::Mixin::HomebrewUser - property :name, String, + property :tap_name, String, + description: "Optional tap name to override the resource name", + validation_message: "Homebrew tap names must be in the form REPO/TAP", regex: %r{^[\w-]+(?:\/[\w-]+)+$}, name_property: true - property :url, String + property :url, String, + description: "URL to the tap." property :full, [TrueClass, FalseClass], + description: "Perform a full clone rather than a shallow clone on the tap.", default: false + property :homebrew_path, String, + description: "The path to the homebrew binary.", + default: "/usr/local/bin/brew" + + property :owner, String, + description: "The owner of the homebrew installation", + default: lazy { Chef::Mixin::HomebrewUser.find_homebrew_username } + action :tap do + description "Add a Homebrew tap." + unless tapped?(new_resource.name) - declare_resource(:execute, "tapping #{new_resource.name}") do - command "/usr/local/bin/brew tap #{new_resource.full ? '--full' : ''} #{new_resource.name} #{new_resource.url || ''}" - environment lazy { { "HOME" => ::Dir.home(find_homebrew_uid), "USER" => find_homebrew_uid } } - not_if "/usr/local/bin/brew tap | grep #{new_resource.name}" - user find_homebrew_uid + converge_by("tap #{new_resource.name}") do + shell_out!("#{new_resource.homebrew_path} tap #{new_resource.full ? '--full' : ''} #{new_resource.name} #{new_resource.url || ''}", + user: new_resource.owner, + env: { "HOME" => ::Dir.home(new_resource.owner), "USER" => new_resource.owner }, + cwd: ::Dir.home(new_resource.owner)) end end end action :untap do + description "Remove a Homebrew tap." + if tapped?(new_resource.name) - declare_resource(:execute, "untapping #{new_resource.name}") do - command "/usr/local/bin/brew untap #{new_resource.name}" - environment lazy { { "HOME" => ::Dir.home(find_homebrew_uid), "USER" => find_homebrew_uid } } - only_if "/usr/local/bin/brew tap | grep #{new_resource.name}" - user find_homebrew_uid + converge_by("untap #{new_resource.name}") do + shell_out!("#{new_resource.homebrew_path} untap #{new_resource.name}", + user: new_resource.owner, + env: { "HOME" => ::Dir.home(new_resource.owner), "USER" => new_resource.owner }, + cwd: ::Dir.home(new_resource.owner)) end end end - action_class do - def tapped?(name) - tap_dir = name.gsub("/", "/homebrew-") - ::File.directory?("/usr/local/Homebrew/Library/Taps/#{tap_dir}") - end + def tapped?(name) + tap_dir = name.gsub("/", "/homebrew-") + ::File.directory?("/usr/local/Homebrew/Library/Taps/#{tap_dir}") end end end diff --git a/spec/unit/mixin/homebrew_user_spec.rb b/spec/unit/mixin/homebrew_user_spec.rb index c9a6e6e909..67d79719aa 100644 --- a/spec/unit/mixin/homebrew_user_spec.rb +++ b/spec/unit/mixin/homebrew_user_spec.rb @@ -1,7 +1,7 @@ # # Author:: Joshua Timberman (<joshua@chef.io>) # -# Copyright 2014-2016, Chef Software, Inc <legal@chef.io> +# Copyright 2014-2018, Chef Software, Inc <legal@chef.io> # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -23,10 +23,6 @@ class ExampleHomebrewUser end describe Chef::Mixin::HomebrewUser do - before(:each) do - node.default["homebrew"]["owner"] = nil - end - let(:homebrew_user) { ExampleHomebrewUser.new } let(:node) { Chef::Node.new } diff --git a/spec/unit/resource/homebrew_cask_spec.rb b/spec/unit/resource/homebrew_cask_spec.rb new file mode 100644 index 0000000000..9b04a0328d --- /dev/null +++ b/spec/unit/resource/homebrew_cask_spec.rb @@ -0,0 +1,35 @@ +# +# Copyright:: Copyright 2018, Chef Software, Inc. +# License:: Apache License, Version 2.0 +# +# 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_helper" + +describe Chef::Resource::HomebrewCask do + + let(:resource) { Chef::Resource::HomebrewCask.new("myapp") } + + it "has a resource name of :homebrew_cask" do + expect(resource.resource_name).to eql(:homebrew_cask) + end + + it "has a default action of install" do + expect(resource.action).to eql([:install]) + end + + it "the cask_name property is the name property" do + expect(resource.cask_name).to eql("myapp") + end +end diff --git a/spec/unit/resource/homebrew_tap_spec.rb b/spec/unit/resource/homebrew_tap_spec.rb new file mode 100644 index 0000000000..2b93c11c28 --- /dev/null +++ b/spec/unit/resource/homebrew_tap_spec.rb @@ -0,0 +1,39 @@ +# +# Copyright:: Copyright 2018, Chef Software, Inc. +# License:: Apache License, Version 2.0 +# +# 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_helper" + +describe Chef::Resource::HomebrewTap do + + let(:resource) { Chef::Resource::HomebrewTap.new("user/mytap") } + + it "has a resource name of :homebrew_tap" do + expect(resource.resource_name).to eql(:homebrew_tap) + end + + it "has a default action of tap" do + expect(resource.action).to eql([:tap]) + end + + it "the tap_name property is the name property" do + expect(resource.tap_name).to eql("user/mytap") + end + + it "fails if tap_name isn't in the USER/TAP format" do + expect { resource.tap_name "mytap" }.to raise_error(ArgumentError) + end +end |