diff options
author | Lamont Granquist <lamont@scriptkiddie.org> | 2015-12-02 19:37:36 -0800 |
---|---|---|
committer | Lamont Granquist <lamont@scriptkiddie.org> | 2015-12-02 19:37:36 -0800 |
commit | 98d553ced4bde95210fac82006c9be24ddb8f817 (patch) | |
tree | 84354ce72351f2c7aacabd4bdee1be63addf2725 | |
parent | 2a610564a8a42208adf2158a7c5c0657b243d58a (diff) | |
parent | 2046cb8e519817619472384296328f9cdcbb5c16 (diff) | |
download | chef-98d553ced4bde95210fac82006c9be24ddb8f817.tar.gz |
Merge pull request #4196 from chef/lcg/dpkg-multipackage
multipackage dpkg_package and bonus fixes
42 files changed, 1662 insertions, 114 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index 6919283413..899fa979e8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -54,6 +54,7 @@ * [**Nolan Davidson**](https://github.com/nsdavidson) [pr#4014](https://github.com/chef/chef/pull/4014) Adding ksh resource +* [pr#4196](https://github.com/chef/chef/pull/4196) multipackage dpkg_package and bonus fixes * [pr#4185](https://github.com/chef/chef/pull/4185) dpkg provider cleanup * [pr#4165](https://github.com/chef/chef/pull/4165) Multipackage internal API improvements * [pr#4081](https://github.com/chef/chef/pull/4081) RFC-037: add `chef_version` and `ohai_version` metadata diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index c27984101b..44dcc64894 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -34,4 +34,10 @@ not designed to be a general solution to performance issues inside of chef-clien This debugging feature will mostly be useful to people who are already Ruby experts. +## `dpkg_package` now accepts an array of packages +Similar to the `yum_package` and `apt_package` resources, the `dpkg_package` resource now handles an Array of package names (and +also array of versions and array of sources). + +Some edge conditions in the `:remove` and `:purge` actions in `dpkg_package` were also fixed and the `:purge` action will now +purge packages that were previously removed (`apt_package` still does not do this). diff --git a/lib/chef/mixin/get_source_from_package.rb b/lib/chef/mixin/get_source_from_package.rb index 2ed251854a..cb5583b431 100644 --- a/lib/chef/mixin/get_source_from_package.rb +++ b/lib/chef/mixin/get_source_from_package.rb @@ -1,5 +1,5 @@ # Author:: Lamont Granquist (<lamont@opscode.com>) -# Copyright:: Copyright (c) 2008 Opscode, Inc. +# Copyright:: Copyright (c) 2008-2015 Chef Software, Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -27,6 +27,12 @@ class Chef module Mixin module GetSourceFromPackage + # FIXME: this is some bad code that I wrote a long time ago. + # - it does too much in the initializer + # - it mutates the new_resource + # - it does not support multipackage arrays + # this code is deprecated, check out the :use_package_names_for_source + # subclass directive instead def initialize(new_resource, run_context) super return if new_resource.package_name.is_a?(Array) @@ -40,4 +46,3 @@ class Chef end end end - diff --git a/lib/chef/mixin/subclass_directive.rb b/lib/chef/mixin/subclass_directive.rb new file mode 100644 index 0000000000..0f386b6cb2 --- /dev/null +++ b/lib/chef/mixin/subclass_directive.rb @@ -0,0 +1,37 @@ +# +# Author:: Adam Jacob (<adam@opscode.com>) +# Copyright:: Copyright (c) 2008-2015 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. +# + +class Chef + module Mixin + module SubclassDirective + def subclass_directive(sym) + define_singleton_method sym do + instance_variable_set(:"@#{sym}", true) + end + + define_singleton_method :"#{sym}?" do + !!instance_variable_get(:"@#{sym}") + end + + define_method :"#{sym}?" do + self.class.send(:"#{sym}?") + end + end + end + end +end diff --git a/lib/chef/provider/package.rb b/lib/chef/provider/package.rb index 888b171fa4..abb181c571 100644 --- a/lib/chef/provider/package.rb +++ b/lib/chef/provider/package.rb @@ -18,6 +18,7 @@ require 'chef/mixin/shell_out' require 'chef/mixin/command' +require 'chef/mixin/subclass_directive' require 'chef/log' require 'chef/file_cache' require 'chef/platform' @@ -27,6 +28,12 @@ class Chef class Package < Chef::Provider include Chef::Mixin::Command include Chef::Mixin::ShellOut + extend Chef::Mixin::SubclassDirective + + # subclasses declare this if they want all their arguments as arrays of packages and names + subclass_directive :use_multipackage_api + # subclasses declare this if they want sources (filenames) pulled from their package names + subclass_directive :use_package_name_for_source # # Hook that subclasses use to populate the candidate_version(s) @@ -44,6 +51,8 @@ class Chef end def check_resource_semantics! + # FIXME: this is not universally true and subclasses are needing to override this and no-ops it. It should be turned into + # another "subclass_directive" and the apt and yum providers should declare that they need this behavior. if new_resource.package_name.is_a?(Array) && new_resource.source != nil raise Chef::Exceptions::InvalidResourceSpecification, "You may not specify both multipackage and source" end @@ -211,7 +220,7 @@ class Chef # @todo use composition rather than inheritance def multipackage_api_adapter(name, version) - if supports_arrays? + if use_multipackage_api? yield [name].flatten, [version].flatten else yield name, version @@ -242,7 +251,7 @@ class Chef raise( Chef::Exceptions::UnsupportedAction, "#{self.to_s} does not support :reconfig" ) end - # this is heavily used by subclasses + # used by subclasses. deprecated. use #a_to_s instead. def expand_options(options) options ? " #{options}" : "" end @@ -298,24 +307,6 @@ class Chef [ thing ].flatten end - class << self - attr_accessor :supports_arrays - - def supports_arrays? - !!@supports_arrays - end - - private - - def use_multipackage_api - @supports_arrays = true - end - end - - def supports_arrays? - self.class.supports_arrays? - end - private # Returns the package names which need to be modified. If the resource was called with an array of packages @@ -528,6 +519,16 @@ class Chef end args end + + # Helper for sublcasses to convert an array of string args into a string. It + # will compact nil or empty strings in the array and will join the array elements + # with spaces, without introducing any double spaces for nil/empty elements. + # + # @param args [String] variable number of string arguments + # @return [String] nicely concatenated string or empty string + def a_to_s(*args) + args.reject {|i| i.nil? || i == "" }.join(" ") + end end end end diff --git a/lib/chef/provider/package/dpkg.rb b/lib/chef/provider/package/dpkg.rb index 2de6226bb9..35b6f4beee 100644 --- a/lib/chef/provider/package/dpkg.rb +++ b/lib/chef/provider/package/dpkg.rb @@ -19,31 +19,40 @@ require 'chef/provider/package' require 'chef/mixin/command' require 'chef/resource/package' -require 'chef/mixin/get_source_from_package' class Chef class Provider class Package class Dpkg < Chef::Provider::Package + DPKG_REMOVED = /^Status: deinstall ok config-files/ DPKG_INSTALLED = /^Status: install ok installed/ DPKG_VERSION = /^Version: (.+)$/ provides :dpkg_package, os: "linux" - include Chef::Mixin::GetSourceFromPackage + use_multipackage_api + use_package_name_for_source + + # semantics of dpkg properties: + # + # new_resource.name is always an array for this resource + # new_resource.package_name is always an array for this resource + # new_resource.source is always an array and may be [ nil ] for this resource. properly use #sources or + # #name_sources to also get the automatic package-name-to-source-conversion. this will never be nil? + # def define_resource_requirements super requirements.assert(:install, :upgrade) do |a| - a.assertion { !new_resource.source.nil? } + a.assertion { !sources.compact.empty? } a.failure_message Chef::Exceptions::Package, "#{new_resource} the source property is required for action :install or :upgrade" end requirements.assert(:install, :upgrade) do |a| - a.assertion { source_file_exist? } - a.failure_message Chef::Exceptions::Package, "#{new_resource} source file does not exist: #{new_resource.source}" - a.whyrun "Assuming it would have been previously created." + a.assertion { source_files_exist? } + a.failure_message Chef::Exceptions::Package, "#{new_resource} source file(s) do not exist: #{missing_sources}" + a.whyrun "Assuming they would have been previously created." end end @@ -51,11 +60,11 @@ class Chef @current_resource = Chef::Resource::Package.new(new_resource.name) current_resource.package_name(new_resource.package_name) - if source_file_exist? + if source_files_exist? @candidate_version = get_candidate_version current_resource.package_name(get_package_name) # if the source file exists then our package_name is right - current_resource.version(get_current_version) + current_resource.version(get_current_version_from(current_package_name_array)) elsif !installing? # we can't do this if we're installing with no source, because our package_name # is probably not right. @@ -65,31 +74,26 @@ class Chef # # we don't error here on the dpkg command since we'll handle the exception or # the why-run message in define_resource_requirements. - current_resource.version(get_current_version) + current_resource.version(get_current_version_from(current_package_name_array)) end current_resource end def install_package(name, version) - Chef::Log.info("#{new_resource} installing #{new_resource.source}") - run_noninteractive( - "dpkg -i#{expand_options(new_resource.options)} #{new_resource.source}" - ) + sources = name.map { |n| name_sources[n] } + Chef::Log.info("#{new_resource} installing package(s): #{name.join(' ')}") + run_noninteractive("dpkg -i", new_resource.options, *sources) end def remove_package(name, version) - Chef::Log.info("#{new_resource} removing #{new_resource.package_name}") - run_noninteractive( - "dpkg -r#{expand_options(new_resource.options)} #{new_resource.package_name}" - ) + Chef::Log.info("#{new_resource} removing package(s): #{name.join(' ')}") + run_noninteractive("dpkg -r", new_resource.options, *name) end def purge_package(name, version) - Chef::Log.info("#{new_resource} purging #{new_resource.package_name}") - run_noninteractive( - "dpkg -P#{expand_options(new_resource.options)} #{new_resource.package_name}" - ) + Chef::Log.info("#{new_resource} purging packages(s): #{name.join(' ')}") + run_noninteractive("dpkg -P", new_resource.options, *name) end def upgrade_package(name, version) @@ -98,22 +102,29 @@ class Chef def preseed_package(preseed_file) Chef::Log.info("#{new_resource} pre-seeding package installation instructions") - run_noninteractive("debconf-set-selections #{preseed_file}") + run_noninteractive("debconf-set-selections", *preseed_file) end def reconfig_package(name, version) Chef::Log.info("#{new_resource} reconfiguring") - run_noninteractive("dpkg-reconfigure #{name}") + run_noninteractive("dpkg-reconfigure", *name) + end + + # Override the superclass check. Multiple sources are required here. + def check_resource_semantics! end private - def get_current_version - Chef::Log.debug("#{new_resource} checking install state") - status = shell_out_with_timeout("dpkg -s #{current_resource.package_name}") + def read_current_version_of_package(package_name) + Chef::Log.debug("#{new_resource} checking install state of #{package_name}") + status = shell_out_with_timeout("dpkg -s #{package_name}") package_installed = false status.stdout.each_line do |line| case line + when DPKG_REMOVED + # if we are 'purging' then we consider 'removed' to be 'installed' + package_installed = true if action == :purge when DPKG_INSTALLED package_installed = true when DPKG_VERSION @@ -126,34 +137,124 @@ class Chef return nil end + def get_current_version_from(array) + array.map do |name| + read_current_version_of_package(name) + end + end + # Runs command via shell_out_with_timeout with magic environment to disable - # interactive prompts. Command is run with default localization rather - # than forcing locale to "C", so command output may not be stable. - def run_noninteractive(command) - shell_out_with_timeout!(command, :env => { "DEBIAN_FRONTEND" => "noninteractive" }) + # interactive prompts. + def run_noninteractive(*command) + shell_out_with_timeout!(a_to_s(*command), :env => { "DEBIAN_FRONTEND" => "noninteractive" }) + end + + # Returns true if all sources exist. Returns false if any do not, or if no + # sources were specified. + # + # @return [Boolean] True if all sources exist + def source_files_exist? + sources.all? {|s| s && ::File.exist?(s) } end - def source_file_exist? - new_resource.source && ::File.exist?(new_resource.source) + # Helper to return all the nanes of the missing sources for error messages. + # + # @return [Array<String>] Array of missing sources + def missing_sources + sources.select {|s| s.nil? || !::File.exist?(s) } + end + + def current_package_name_array + [ current_resource.package_name ].flatten + end + + def source_array + if new_resource.source.nil? + package_name_array.map { nil } + else + [ new_resource.source ].flatten + end + end + + # Helper to construct Array of sources. If the new_resource.source is nil it + # will return an array filled will nil the same size as the package_name array + # For all the nil source values, if a file exists on the filesystem that + # matches the package name it will use that name as the source. + # + # @return [Array] Array of normalized sources with package_names converted to sources + def sources + @sources ||= + begin + source_array.each_with_index.map do |source, i| + package_name = package_name_array[i] + # we require at least one '/' in the package_name to avoid dpkg_package 'foo' breaking due to a random 'foo' file in cwd + if use_package_name_for_source? && source.nil? && package_name.match(/#{::File::SEPARATOR}/) && ::File.exist?(package_name) + Chef::Log.debug("No package source specified, but #{package_name} exists on filesystem, using #{package_name} as source.") + package_name + else + source + end + end + end + end + + # Helper to construct Hash of names-to-sources. + # + # @return [Hash] Mapping of package names to sources + def name_sources + @name_sources = + begin + Hash[*package_name_array.zip(sources).flatten] + end + end + + # Helper to construct Hash of names-to-package-information. + # + # @return [Hash] Mapping of package names to package information + def name_pkginfo + @name_pkginfo ||= + begin + pkginfos = sources.map do |src| + Chef::Log.debug("#{new_resource} checking #{src} dpkg status") + status = shell_out_with_timeout!("dpkg-deb -W #{src}") + status.stdout + end + Hash[*package_name_array.zip(pkginfos).flatten] + end + end + + def name_candidate_version + @name_candidate_version ||= + begin + Hash[name_pkginfo.map {|k, v| [k, v ? v.split("\t")[1].strip : nil] }] + end end - def pkginfo - @pkginfo ||= + def name_package_name + @name_package_name ||= begin - Chef::Log.debug("#{new_resource} checking dpkg status") - status = shell_out_with_timeout!("dpkg-deb -W #{new_resource.source}") - status.stdout.split("\t") + Hash[name_pkginfo.map {|k, v| [k, v ? v.split("\t")[0] : nil] }] end end + # Return candidate version array from pkg-deb -W against the source file(s). + # + # @return [Array] Array of candidate versions read from the source files def get_candidate_version - pkginfo[1].strip unless pkginfo.empty? + package_name_array.map { |name| name_candidate_version[name] } end + # Return package names from the candidate source file(s). + # + # @return [Array] Array of actual package names read from the source files def get_package_name - pkginfo[0] unless pkginfo.empty? + package_name_array.map { |name| name_package_name[name] } end + # Since upgrade just calls install, this is a helper to determine + # if our action means that we'll be calling install_package. + # + # @return [Boolean] true if we're doing :install or :upgrade def installing? [:install, :upgrade].include?(action) end diff --git a/lib/chef/resource/dpkg_package.rb b/lib/chef/resource/dpkg_package.rb index 38adf24cf6..9288c18632 100644 --- a/lib/chef/resource/dpkg_package.rb +++ b/lib/chef/resource/dpkg_package.rb @@ -1,6 +1,6 @@ # # Author:: Adam Jacob (<adam@opscode.com>) -# Copyright:: Copyright (c) 2008 Opscode, Inc. +# Copyright:: Copyright (c) 2008-2015 Chef Software, Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -17,14 +17,15 @@ # require 'chef/resource/package' -require 'chef/provider/package/dpkg' class Chef class Resource class DpkgPackage < Chef::Resource::Package - provides :dpkg_package, os: "linux" + resource_name :dpkg_package + + property :source, [String, Array, nil] end end end diff --git a/spec/data/apt/chef-integration-test2-1.0/debian/README.Debian b/spec/data/apt/chef-integration-test2-1.0/debian/README.Debian new file mode 100644 index 0000000000..13f5dff153 --- /dev/null +++ b/spec/data/apt/chef-integration-test2-1.0/debian/README.Debian @@ -0,0 +1,6 @@ +chef-integration-test2 for Debian +--------------------------------- + +<possible notes regarding this package - if none, delete this file> + + -- Lamont Granquist <lamont@coredump.scriptkiddie.lan> Mon, 23 Nov 2015 12:57:22 -0800 diff --git a/spec/data/apt/chef-integration-test2-1.0/debian/README.source b/spec/data/apt/chef-integration-test2-1.0/debian/README.source new file mode 100644 index 0000000000..086a592106 --- /dev/null +++ b/spec/data/apt/chef-integration-test2-1.0/debian/README.source @@ -0,0 +1,10 @@ +chef-integration-test2 for Debian +--------------------------------- + +<this file describes information about the source package, see Debian policy +manual section 4.14. You WILL either need to modify or delete this file> + + + + -- Lamont Granquist <lamont@coredump.scriptkiddie.lan> Mon, 23 Nov 2015 12:57:22 -0800 + diff --git a/spec/data/apt/chef-integration-test2-1.0/debian/changelog b/spec/data/apt/chef-integration-test2-1.0/debian/changelog new file mode 100644 index 0000000000..63e92728de --- /dev/null +++ b/spec/data/apt/chef-integration-test2-1.0/debian/changelog @@ -0,0 +1,5 @@ +chef-integration-test2 (1.0-1) unstable; urgency=low + + * Initial release (Closes: #nnnn) <nnnn is the bug number of your ITP> + + -- Lamont Granquist <lamont@coredump.scriptkiddie.lan> Mon, 23 Nov 2015 12:57:22 -0800 diff --git a/spec/data/apt/chef-integration-test2-1.0/debian/chef-integration-test2.cron.d.ex b/spec/data/apt/chef-integration-test2-1.0/debian/chef-integration-test2.cron.d.ex new file mode 100644 index 0000000000..7590a38aa3 --- /dev/null +++ b/spec/data/apt/chef-integration-test2-1.0/debian/chef-integration-test2.cron.d.ex @@ -0,0 +1,4 @@ +# +# Regular cron jobs for the chef-integration-test2 package +# +0 4 * * * root [ -x /usr/bin/chef-integration-test2_maintenance ] && /usr/bin/chef-integration-test2_maintenance diff --git a/spec/data/apt/chef-integration-test2-1.0/debian/chef-integration-test2.default.ex b/spec/data/apt/chef-integration-test2-1.0/debian/chef-integration-test2.default.ex new file mode 100644 index 0000000000..b5ba987ece --- /dev/null +++ b/spec/data/apt/chef-integration-test2-1.0/debian/chef-integration-test2.default.ex @@ -0,0 +1,10 @@ +# Defaults for chef-integration-test2 initscript +# sourced by /etc/init.d/chef-integration-test2 +# installed at /etc/default/chef-integration-test2 by the maintainer scripts + +# +# This is a POSIX shell fragment +# + +# Additional options that are passed to the Daemon. +DAEMON_OPTS="" diff --git a/spec/data/apt/chef-integration-test2-1.0/debian/chef-integration-test2.doc-base.EX b/spec/data/apt/chef-integration-test2-1.0/debian/chef-integration-test2.doc-base.EX new file mode 100644 index 0000000000..84c8f9dd28 --- /dev/null +++ b/spec/data/apt/chef-integration-test2-1.0/debian/chef-integration-test2.doc-base.EX @@ -0,0 +1,20 @@ +Document: chef-integration-test2 +Title: Debian chef-integration-test2 Manual +Author: <insert document author here> +Abstract: This manual describes what chef-integration-test2 is + and how it can be used to + manage online manuals on Debian systems. +Section: unknown + +Format: debiandoc-sgml +Files: /usr/share/doc/chef-integration-test2/chef-integration-test2.sgml.gz + +Format: postscript +Files: /usr/share/doc/chef-integration-test2/chef-integration-test2.ps.gz + +Format: text +Files: /usr/share/doc/chef-integration-test2/chef-integration-test2.text.gz + +Format: HTML +Index: /usr/share/doc/chef-integration-test2/html/index.html +Files: /usr/share/doc/chef-integration-test2/html/*.html diff --git a/spec/data/apt/chef-integration-test2-1.0/debian/compat b/spec/data/apt/chef-integration-test2-1.0/debian/compat new file mode 100644 index 0000000000..ec635144f6 --- /dev/null +++ b/spec/data/apt/chef-integration-test2-1.0/debian/compat @@ -0,0 +1 @@ +9 diff --git a/spec/data/apt/chef-integration-test2-1.0/debian/conffiles b/spec/data/apt/chef-integration-test2-1.0/debian/conffiles new file mode 100644 index 0000000000..ac4307eadf --- /dev/null +++ b/spec/data/apt/chef-integration-test2-1.0/debian/conffiles @@ -0,0 +1 @@ +/usr/share/doc/chef-integration-test2/copyright diff --git a/spec/data/apt/chef-integration-test2-1.0/debian/control b/spec/data/apt/chef-integration-test2-1.0/debian/control new file mode 100644 index 0000000000..f8b66fcb5a --- /dev/null +++ b/spec/data/apt/chef-integration-test2-1.0/debian/control @@ -0,0 +1,15 @@ +Source: chef-integration-test2 +Section: unknown +Priority: optional +Maintainer: Lamont Granquist <lamont@coredump.scriptkiddie.lan> +Build-Depends: debhelper (>= 8.0.0) +Standards-Version: 3.9.4 +Homepage: <insert the upstream URL, if relevant> +#Vcs-Git: git://git.debian.org/collab-maint/chef-integration-test2.git +#Vcs-Browser: http://git.debian.org/?p=collab-maint/chef-integration-test2.git;a=summary + +Package: chef-integration-test2 +Architecture: any +Depends: ${shlibs:Depends}, ${misc:Depends} +Description: <insert up to 60 chars description> + <insert long description, indented with spaces> diff --git a/spec/data/apt/chef-integration-test2-1.0/debian/copyright b/spec/data/apt/chef-integration-test2-1.0/debian/copyright new file mode 100644 index 0000000000..dd891763ec --- /dev/null +++ b/spec/data/apt/chef-integration-test2-1.0/debian/copyright @@ -0,0 +1,38 @@ +Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ +Upstream-Name: chef-integration-test2 +Source: <url://example.com> + +Files: * +Copyright: <years> <put author's name and email here> + <years> <likewise for another author> +License: <special license> + <Put the license of the package here indented by 1 space> + <This follows the format of Description: lines in control file> + . + <Including paragraphs> + +# If you want to use GPL v2 or later for the /debian/* files use +# the following clauses, or change it to suit. Delete these two lines +Files: debian/* +Copyright: 2015 Lamont Granquist <lamont@coredump.scriptkiddie.lan> +License: GPL-2+ + This package is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + . + This package is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + . + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/> + . + On Debian systems, the complete text of the GNU General + Public License version 2 can be found in "/usr/share/common-licenses/GPL-2". + +# Please also look if there are files or directories which have a +# different copyright/license attached and list them here. +# Please avoid to pick license terms that are more restrictive than the +# packaged work, as it may make Debian's contributions unacceptable upstream. diff --git a/spec/data/apt/chef-integration-test2-1.0/debian/docs b/spec/data/apt/chef-integration-test2-1.0/debian/docs new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/spec/data/apt/chef-integration-test2-1.0/debian/docs diff --git a/spec/data/apt/chef-integration-test2-1.0/debian/init.d.ex b/spec/data/apt/chef-integration-test2-1.0/debian/init.d.ex new file mode 100644 index 0000000000..a776222376 --- /dev/null +++ b/spec/data/apt/chef-integration-test2-1.0/debian/init.d.ex @@ -0,0 +1,166 @@ +#!/bin/sh +### BEGIN INIT INFO +# Provides: chef-integration-test2 +# Required-Start: $local_fs $network $remote_fs $syslog +# Required-Stop: $local_fs $network $remote_fs $syslog +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +# Short-Description: <Enter a short description of the software> +# Description: <Enter a long description of the software> +# <...> +# <...> +### END INIT INFO + +# Author: Lamont Granquist <lamont@coredump.scriptkiddie.lan> + +# Do NOT "set -e" + +# PATH should only include /usr/* if it runs after the mountnfs.sh script +PATH=/sbin:/usr/sbin:/bin:/usr/bin +DESC="chef-integration-test2" +NAME=chef-integration-test2 +DAEMON=/usr/sbin/chef-integration-test2 +DAEMON_ARGS="" +PIDFILE=/var/run/$NAME.pid +SCRIPTNAME=/etc/init.d/$NAME + +# Exit if the package is not installed +[ -x "$DAEMON" ] || exit 0 + +# Read configuration variable file if it is present +[ -r /etc/default/$NAME ] && . /etc/default/$NAME + +# Load the VERBOSE setting and other rcS variables +. /lib/init/vars.sh + +# Define LSB log_* functions. +# Depend on lsb-base (>= 3.2-14) to ensure that this file is present +# and status_of_proc is working. +. /lib/lsb/init-functions + +# +# Function that starts the daemon/service +# +do_start() +{ + # Return + # 0 if daemon has been started + # 1 if daemon was already running + # 2 if daemon could not be started + start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON --test > /dev/null \ + || return 1 + start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON -- \ + $DAEMON_ARGS \ + || return 2 + # The above code will not work for interpreted scripts, use the next + # six lines below instead (Ref: #643337, start-stop-daemon(8) ) + #start-stop-daemon --start --quiet --pidfile $PIDFILE --startas $DAEMON \ + # --name $NAME --test > /dev/null \ + # || return 1 + #start-stop-daemon --start --quiet --pidfile $PIDFILE --startas $DAEMON \ + # --name $NAME -- $DAEMON_ARGS \ + # || return 2 + + # Add code here, if necessary, that waits for the process to be ready + # to handle requests from services started subsequently which depend + # on this one. As a last resort, sleep for some time. +} + +# +# Function that stops the daemon/service +# +do_stop() +{ + # Return + # 0 if daemon has been stopped + # 1 if daemon was already stopped + # 2 if daemon could not be stopped + # other if a failure occurred + start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --pidfile $PIDFILE --name $NAME + RETVAL="$?" + [ "$RETVAL" = 2 ] && return 2 + # Wait for children to finish too if this is a daemon that forks + # and if the daemon is only ever run from this initscript. + # If the above conditions are not satisfied then add some other code + # that waits for the process to drop all resources that could be + # needed by services started subsequently. A last resort is to + # sleep for some time. + start-stop-daemon --stop --quiet --oknodo --retry=0/30/KILL/5 --exec $DAEMON + [ "$?" = 2 ] && return 2 + # Many daemons don't delete their pidfiles when they exit. + rm -f $PIDFILE + return "$RETVAL" +} + +# +# Function that sends a SIGHUP to the daemon/service +# +do_reload() { + # + # If the daemon can reload its configuration without + # restarting (for example, when it is sent a SIGHUP), + # then implement that here. + # + start-stop-daemon --stop --signal 1 --quiet --pidfile $PIDFILE --name $NAME + return 0 +} + +case "$1" in + start) + [ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME" + do_start + case "$?" in + 0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;; + 2) [ "$VERBOSE" != no ] && log_end_msg 1 ;; + esac + ;; + stop) + [ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME" + do_stop + case "$?" in + 0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;; + 2) [ "$VERBOSE" != no ] && log_end_msg 1 ;; + esac + ;; + status) + status_of_proc "$DAEMON" "$NAME" && exit 0 || exit $? + ;; + #reload|force-reload) + # + # If do_reload() is not implemented then leave this commented out + # and leave 'force-reload' as an alias for 'restart'. + # + #log_daemon_msg "Reloading $DESC" "$NAME" + #do_reload + #log_end_msg $? + #;; + restart|force-reload) + # + # If the "reload" option is implemented then remove the + # 'force-reload' alias + # + log_daemon_msg "Restarting $DESC" "$NAME" + do_stop + case "$?" in + 0|1) + do_start + case "$?" in + 0) log_end_msg 0 ;; + 1) log_end_msg 1 ;; # Old process is still running + *) log_end_msg 1 ;; # Failed to start + esac + ;; + *) + # Failed to stop + log_end_msg 1 + ;; + esac + ;; + *) + #echo "Usage: $SCRIPTNAME {start|stop|restart|reload|force-reload}" >&2 + echo "Usage: $SCRIPTNAME {start|stop|status|restart|force-reload}" >&2 + exit 3 + ;; +esac + +: diff --git a/spec/data/apt/chef-integration-test2-1.0/debian/manpage.1.ex b/spec/data/apt/chef-integration-test2-1.0/debian/manpage.1.ex new file mode 100644 index 0000000000..b05b3bc906 --- /dev/null +++ b/spec/data/apt/chef-integration-test2-1.0/debian/manpage.1.ex @@ -0,0 +1,56 @@ +.\" Hey, EMACS: -*- nroff -*- +.\" (C) Copyright 2015 Lamont Granquist <lamont@coredump.scriptkiddie.lan>, +.\" +.\" First parameter, NAME, should be all caps +.\" Second parameter, SECTION, should be 1-8, maybe w/ subsection +.\" other parameters are allowed: see man(7), man(1) +.TH CHEF-INTEGRATION-TEST2 SECTION "November 23, 2015" +.\" Please adjust this date whenever revising the manpage. +.\" +.\" Some roff macros, for reference: +.\" .nh disable hyphenation +.\" .hy enable hyphenation +.\" .ad l left justify +.\" .ad b justify to both left and right margins +.\" .nf disable filling +.\" .fi enable filling +.\" .br insert line break +.\" .sp <n> insert n+1 empty lines +.\" for manpage-specific macros, see man(7) +.SH NAME +chef-integration-test2 \- program to do something +.SH SYNOPSIS +.B chef-integration-test2 +.RI [ options ] " files" ... +.br +.B bar +.RI [ options ] " files" ... +.SH DESCRIPTION +This manual page documents briefly the +.B chef-integration-test2 +and +.B bar +commands. +.PP +.\" TeX users may be more comfortable with the \fB<whatever>\fP and +.\" \fI<whatever>\fP escape sequences to invode bold face and italics, +.\" respectively. +\fBchef-integration-test2\fP is a program that... +.SH OPTIONS +These programs follow the usual GNU command line syntax, with long +options starting with two dashes (`-'). +A summary of options is included below. +For a complete description, see the Info files. +.TP +.B \-h, \-\-help +Show summary of options. +.TP +.B \-v, \-\-version +Show version of program. +.SH SEE ALSO +.BR bar (1), +.BR baz (1). +.br +The programs are documented fully by +.IR "The Rise and Fall of a Fooish Bar" , +available via the Info system. diff --git a/spec/data/apt/chef-integration-test2-1.0/debian/manpage.sgml.ex b/spec/data/apt/chef-integration-test2-1.0/debian/manpage.sgml.ex new file mode 100644 index 0000000000..f74dbe0b86 --- /dev/null +++ b/spec/data/apt/chef-integration-test2-1.0/debian/manpage.sgml.ex @@ -0,0 +1,154 @@ +<!doctype refentry PUBLIC "-//OASIS//DTD DocBook V4.1//EN" [ + +<!-- Process this file with docbook-to-man to generate an nroff manual + page: `docbook-to-man manpage.sgml > manpage.1'. You may view + the manual page with: `docbook-to-man manpage.sgml | nroff -man | + less'. A typical entry in a Makefile or Makefile.am is: + +manpage.1: manpage.sgml + docbook-to-man $< > $@ + + + The docbook-to-man binary is found in the docbook-to-man package. + Please remember that if you create the nroff version in one of the + debian/rules file targets (such as build), you will need to include + docbook-to-man in your Build-Depends control field. + + --> + + <!-- Fill in your name for FIRSTNAME and SURNAME. --> + <!ENTITY dhfirstname "<firstname>FIRSTNAME</firstname>"> + <!ENTITY dhsurname "<surname>SURNAME</surname>"> + <!-- Please adjust the date whenever revising the manpage. --> + <!ENTITY dhdate "<date>November 23, 2015</date>"> + <!-- SECTION should be 1-8, maybe w/ subsection other parameters are + allowed: see man(7), man(1). --> + <!ENTITY dhsection "<manvolnum>SECTION</manvolnum>"> + <!ENTITY dhemail "<email>lamont@coredump.scriptkiddie.lan</email>"> + <!ENTITY dhusername "Lamont Granquist"> + <!ENTITY dhucpackage "<refentrytitle>CHEF-INTEGRATION-TEST2</refentrytitle>"> + <!ENTITY dhpackage "chef-integration-test2"> + + <!ENTITY debian "<productname>Debian</productname>"> + <!ENTITY gnu "<acronym>GNU</acronym>"> + <!ENTITY gpl "&gnu; <acronym>GPL</acronym>"> +]> + +<refentry> + <refentryinfo> + <address> + &dhemail; + </address> + <author> + &dhfirstname; + &dhsurname; + </author> + <copyright> + <year>2003</year> + <holder>&dhusername;</holder> + </copyright> + &dhdate; + </refentryinfo> + <refmeta> + &dhucpackage; + + &dhsection; + </refmeta> + <refnamediv> + <refname>&dhpackage;</refname> + + <refpurpose>program to do something</refpurpose> + </refnamediv> + <refsynopsisdiv> + <cmdsynopsis> + <command>&dhpackage;</command> + + <arg><option>-e <replaceable>this</replaceable></option></arg> + + <arg><option>--example <replaceable>that</replaceable></option></arg> + </cmdsynopsis> + </refsynopsisdiv> + <refsect1> + <title>DESCRIPTION</title> + + <para>This manual page documents briefly the + <command>&dhpackage;</command> and <command>bar</command> + commands.</para> + + <para>This manual page was written for the &debian; distribution + because the original program does not have a manual page. + Instead, it has documentation in the &gnu; + <application>Info</application> format; see below.</para> + + <para><command>&dhpackage;</command> is a program that...</para> + + </refsect1> + <refsect1> + <title>OPTIONS</title> + + <para>These programs follow the usual &gnu; command line syntax, + with long options starting with two dashes (`-'). A summary of + options is included below. For a complete description, see the + <application>Info</application> files.</para> + + <variablelist> + <varlistentry> + <term><option>-h</option> + <option>--help</option> + </term> + <listitem> + <para>Show summary of options.</para> + </listitem> + </varlistentry> + <varlistentry> + <term><option>-v</option> + <option>--version</option> + </term> + <listitem> + <para>Show version of program.</para> + </listitem> + </varlistentry> + </variablelist> + </refsect1> + <refsect1> + <title>SEE ALSO</title> + + <para>bar (1), baz (1).</para> + + <para>The programs are documented fully by <citetitle>The Rise and + Fall of a Fooish Bar</citetitle> available via the + <application>Info</application> system.</para> + </refsect1> + <refsect1> + <title>AUTHOR</title> + + <para>This manual page was written by &dhusername; &dhemail; for + the &debian; system (and may be used by others). Permission is + granted to copy, distribute and/or modify this document under + the terms of the &gnu; General Public License, Version 2 any + later version published by the Free Software Foundation. + </para> + <para> + On Debian systems, the complete text of the GNU General Public + License can be found in /usr/share/common-licenses/GPL. + </para> + + </refsect1> +</refentry> + +<!-- Keep this comment at the end of the file +Local variables: +mode: sgml +sgml-omittag:t +sgml-shorttag:t +sgml-minimize-attributes:nil +sgml-always-quote-attributes:t +sgml-indent-step:2 +sgml-indent-data:t +sgml-parent-document:nil +sgml-default-dtd-file:nil +sgml-exposed-tags:nil +sgml-local-catalogs:nil +sgml-local-ecat-files:nil +End: +--> diff --git a/spec/data/apt/chef-integration-test2-1.0/debian/manpage.xml.ex b/spec/data/apt/chef-integration-test2-1.0/debian/manpage.xml.ex new file mode 100644 index 0000000000..4ad8c86fc8 --- /dev/null +++ b/spec/data/apt/chef-integration-test2-1.0/debian/manpage.xml.ex @@ -0,0 +1,291 @@ +<?xml version='1.0' encoding='UTF-8'?> +<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" +"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [ + +<!-- + +`xsltproc -''-nonet \ + -''-param man.charmap.use.subset "0" \ + -''-param make.year.ranges "1" \ + -''-param make.single.year.ranges "1" \ + /usr/share/xml/docbook/stylesheet/docbook-xsl/manpages/docbook.xsl \ + manpage.xml' + +A manual page <package>.<section> will be generated. You may view the +manual page with: nroff -man <package>.<section> | less'. A typical entry +in a Makefile or Makefile.am is: + +DB2MAN = /usr/share/sgml/docbook/stylesheet/xsl/docbook-xsl/manpages/docbook.xsl +XP = xsltproc -''-nonet -''-param man.charmap.use.subset "0" + +manpage.1: manpage.xml + $(XP) $(DB2MAN) $< + +The xsltproc binary is found in the xsltproc package. The XSL files are in +docbook-xsl. A description of the parameters you can use can be found in the +docbook-xsl-doc-* packages. Please remember that if you create the nroff +version in one of the debian/rules file targets (such as build), you will need +to include xsltproc and docbook-xsl in your Build-Depends control field. +Alternatively use the xmlto command/package. That will also automatically +pull in xsltproc and docbook-xsl. + +Notes for using docbook2x: docbook2x-man does not automatically create the +AUTHOR(S) and COPYRIGHT sections. In this case, please add them manually as +<refsect1> ... </refsect1>. + +To disable the automatic creation of the AUTHOR(S) and COPYRIGHT sections +read /usr/share/doc/docbook-xsl/doc/manpages/authors.html. This file can be +found in the docbook-xsl-doc-html package. + +Validation can be done using: `xmllint -''-noout -''-valid manpage.xml` + +General documentation about man-pages and man-page-formatting: +man(1), man(7), http://www.tldp.org/HOWTO/Man-Page/ + +--> + + <!-- Fill in your name for FIRSTNAME and SURNAME. --> + <!ENTITY dhfirstname "FIRSTNAME"> + <!ENTITY dhsurname "SURNAME"> + <!-- dhusername could also be set to "&dhfirstname; &dhsurname;". --> + <!ENTITY dhusername "Lamont Granquist"> + <!ENTITY dhemail "lamont@coredump.scriptkiddie.lan"> + <!-- SECTION should be 1-8, maybe w/ subsection other parameters are + allowed: see man(7), man(1) and + http://www.tldp.org/HOWTO/Man-Page/q2.html. --> + <!ENTITY dhsection "SECTION"> + <!-- TITLE should be something like "User commands" or similar (see + http://www.tldp.org/HOWTO/Man-Page/q2.html). --> + <!ENTITY dhtitle "chef-integration-test2 User Manual"> + <!ENTITY dhucpackage "CHEF-INTEGRATION-TEST2"> + <!ENTITY dhpackage "chef-integration-test2"> +]> + +<refentry> + <refentryinfo> + <title>&dhtitle;</title> + <productname>&dhpackage;</productname> + <authorgroup> + <author> + <firstname>&dhfirstname;</firstname> + <surname>&dhsurname;</surname> + <contrib>Wrote this manpage for the Debian system.</contrib> + <address> + <email>&dhemail;</email> + </address> + </author> + </authorgroup> + <copyright> + <year>2007</year> + <holder>&dhusername;</holder> + </copyright> + <legalnotice> + <para>This manual page was written for the Debian system + (and may be used by others).</para> + <para>Permission is granted to copy, distribute and/or modify this + document under the terms of the GNU General Public License, + Version 2 or (at your option) any later version published by + the Free Software Foundation.</para> + <para>On Debian systems, the complete text of the GNU General Public + License can be found in + <filename>/usr/share/common-licenses/GPL</filename>.</para> + </legalnotice> + </refentryinfo> + <refmeta> + <refentrytitle>&dhucpackage;</refentrytitle> + <manvolnum>&dhsection;</manvolnum> + </refmeta> + <refnamediv> + <refname>&dhpackage;</refname> + <refpurpose>program to do something</refpurpose> + </refnamediv> + <refsynopsisdiv> + <cmdsynopsis> + <command>&dhpackage;</command> + <!-- These are several examples, how syntaxes could look --> + <arg choice="plain"><option>-e <replaceable>this</replaceable></option></arg> + <arg choice="opt"><option>--example=<parameter>that</parameter></option></arg> + <arg choice="opt"> + <group choice="req"> + <arg choice="plain"><option>-e</option></arg> + <arg choice="plain"><option>--example</option></arg> + </group> + <replaceable class="option">this</replaceable> + </arg> + <arg choice="opt"> + <group choice="req"> + <arg choice="plain"><option>-e</option></arg> + <arg choice="plain"><option>--example</option></arg> + </group> + <group choice="req"> + <arg choice="plain"><replaceable>this</replaceable></arg> + <arg choice="plain"><replaceable>that</replaceable></arg> + </group> + </arg> + </cmdsynopsis> + <cmdsynopsis> + <command>&dhpackage;</command> + <!-- Normally the help and version options make the programs stop + right after outputting the requested information. --> + <group choice="opt"> + <arg choice="plain"> + <group choice="req"> + <arg choice="plain"><option>-h</option></arg> + <arg choice="plain"><option>--help</option></arg> + </group> + </arg> + <arg choice="plain"> + <group choice="req"> + <arg choice="plain"><option>-v</option></arg> + <arg choice="plain"><option>--version</option></arg> + </group> + </arg> + </group> + </cmdsynopsis> + </refsynopsisdiv> + <refsect1 id="description"> + <title>DESCRIPTION</title> + <para>This manual page documents briefly the + <command>&dhpackage;</command> and <command>bar</command> + commands.</para> + <para>This manual page was written for the Debian distribution + because the original program does not have a manual page. + Instead, it has documentation in the GNU <citerefentry> + <refentrytitle>info</refentrytitle> + <manvolnum>1</manvolnum> + </citerefentry> format; see below.</para> + <para><command>&dhpackage;</command> is a program that...</para> + </refsect1> + <refsect1 id="options"> + <title>OPTIONS</title> + <para>The program follows the usual GNU command line syntax, + with long options starting with two dashes (`-'). A summary of + options is included below. For a complete description, see the + <citerefentry> + <refentrytitle>info</refentrytitle> + <manvolnum>1</manvolnum> + </citerefentry> files.</para> + <variablelist> + <!-- Use the variablelist.term.separator and the + variablelist.term.break.after parameters to + control the term elements. --> + <varlistentry> + <term><option>-e <replaceable>this</replaceable></option></term> + <term><option>--example=<replaceable>that</replaceable></option></term> + <listitem> + <para>Does this and that.</para> + </listitem> + </varlistentry> + <varlistentry> + <term><option>-h</option></term> + <term><option>--help</option></term> + <listitem> + <para>Show summary of options.</para> + </listitem> + </varlistentry> + <varlistentry> + <term><option>-v</option></term> + <term><option>--version</option></term> + <listitem> + <para>Show version of program.</para> + </listitem> + </varlistentry> + </variablelist> + </refsect1> + <refsect1 id="files"> + <title>FILES</title> + <variablelist> + <varlistentry> + <term><filename>/etc/foo.conf</filename></term> + <listitem> + <para>The system-wide configuration file to control the + behaviour of <application>&dhpackage;</application>. See + <citerefentry> + <refentrytitle>foo.conf</refentrytitle> + <manvolnum>5</manvolnum> + </citerefentry> for further details.</para> + </listitem> + </varlistentry> + <varlistentry> + <term><filename>${HOME}/.foo.conf</filename></term> + <listitem> + <para>The per-user configuration file to control the + behaviour of <application>&dhpackage;</application>. See + <citerefentry> + <refentrytitle>foo.conf</refentrytitle> + <manvolnum>5</manvolnum> + </citerefentry> for further details.</para> + </listitem> + </varlistentry> + </variablelist> + </refsect1> + <refsect1 id="environment"> + <title>ENVIRONMENT</title> + <variablelist> + <varlistentry> + <term><envar>FOO_CONF</envar></term> + <listitem> + <para>If used, the defined file is used as configuration + file (see also <xref linkend="files"/>).</para> + </listitem> + </varlistentry> + </variablelist> + </refsect1> + <refsect1 id="diagnostics"> + <title>DIAGNOSTICS</title> + <para>The following diagnostics may be issued + on <filename class="devicefile">stderr</filename>:</para> + <variablelist> + <varlistentry> + <term><errortext>Bad configuration file. Exiting.</errortext></term> + <listitem> + <para>The configuration file seems to contain a broken configuration + line. Use the <option>--verbose</option> option, to get more info. + </para> + </listitem> + </varlistentry> + </variablelist> + <para><command>&dhpackage;</command> provides some return codes, that can + be used in scripts:</para> + <segmentedlist> + <segtitle>Code</segtitle> + <segtitle>Diagnostic</segtitle> + <seglistitem> + <seg><errorcode>0</errorcode></seg> + <seg>Program exited successfully.</seg> + </seglistitem> + <seglistitem> + <seg><errorcode>1</errorcode></seg> + <seg>The configuration file seems to be broken.</seg> + </seglistitem> + </segmentedlist> + </refsect1> + <refsect1 id="bugs"> + <!-- Or use this section to tell about upstream BTS. --> + <title>BUGS</title> + <para>The program is currently limited to only work + with the <package>foobar</package> library.</para> + <para>The upstreams <acronym>BTS</acronym> can be found + at <ulink url="http://bugzilla.foo.tld"/>.</para> + </refsect1> + <refsect1 id="see_also"> + <title>SEE ALSO</title> + <!-- In alpabetical order. --> + <para><citerefentry> + <refentrytitle>bar</refentrytitle> + <manvolnum>1</manvolnum> + </citerefentry>, <citerefentry> + <refentrytitle>baz</refentrytitle> + <manvolnum>1</manvolnum> + </citerefentry>, <citerefentry> + <refentrytitle>foo.conf</refentrytitle> + <manvolnum>5</manvolnum> + </citerefentry></para> + <para>The programs are documented fully by <citetitle>The Rise and + Fall of a Fooish Bar</citetitle> available via the <citerefentry> + <refentrytitle>info</refentrytitle> + <manvolnum>1</manvolnum> + </citerefentry> system.</para> + </refsect1> +</refentry> + diff --git a/spec/data/apt/chef-integration-test2-1.0/debian/menu.ex b/spec/data/apt/chef-integration-test2-1.0/debian/menu.ex new file mode 100644 index 0000000000..6d075924cf --- /dev/null +++ b/spec/data/apt/chef-integration-test2-1.0/debian/menu.ex @@ -0,0 +1,2 @@ +?package(chef-integration-test2):needs="X11|text|vc|wm" section="Applications/see-menu-manual"\ + title="chef-integration-test2" command="/usr/bin/chef-integration-test2" diff --git a/spec/data/apt/chef-integration-test2-1.0/debian/postinst.ex b/spec/data/apt/chef-integration-test2-1.0/debian/postinst.ex new file mode 100644 index 0000000000..6604d5f775 --- /dev/null +++ b/spec/data/apt/chef-integration-test2-1.0/debian/postinst.ex @@ -0,0 +1,39 @@ +#!/bin/sh +# postinst script for chef-integration-test2 +# +# see: dh_installdeb(1) + +set -e + +# summary of how this script can be called: +# * <postinst> `configure' <most-recently-configured-version> +# * <old-postinst> `abort-upgrade' <new version> +# * <conflictor's-postinst> `abort-remove' `in-favour' <package> +# <new-version> +# * <postinst> `abort-remove' +# * <deconfigured's-postinst> `abort-deconfigure' `in-favour' +# <failed-install-package> <version> `removing' +# <conflicting-package> <version> +# for details, see http://www.debian.org/doc/debian-policy/ or +# the debian-policy package + + +case "$1" in + configure) + ;; + + abort-upgrade|abort-remove|abort-deconfigure) + ;; + + *) + echo "postinst called with unknown argument \`$1'" >&2 + exit 1 + ;; +esac + +# dh_installdeb will replace this with shell code automatically +# generated by other debhelper scripts. + +#DEBHELPER# + +exit 0 diff --git a/spec/data/apt/chef-integration-test2-1.0/debian/postrm.ex b/spec/data/apt/chef-integration-test2-1.0/debian/postrm.ex new file mode 100644 index 0000000000..7cc62c867b --- /dev/null +++ b/spec/data/apt/chef-integration-test2-1.0/debian/postrm.ex @@ -0,0 +1,37 @@ +#!/bin/sh +# postrm script for chef-integration-test2 +# +# see: dh_installdeb(1) + +set -e + +# summary of how this script can be called: +# * <postrm> `remove' +# * <postrm> `purge' +# * <old-postrm> `upgrade' <new-version> +# * <new-postrm> `failed-upgrade' <old-version> +# * <new-postrm> `abort-install' +# * <new-postrm> `abort-install' <old-version> +# * <new-postrm> `abort-upgrade' <old-version> +# * <disappearer's-postrm> `disappear' <overwriter> +# <overwriter-version> +# for details, see http://www.debian.org/doc/debian-policy/ or +# the debian-policy package + + +case "$1" in + purge|remove|upgrade|failed-upgrade|abort-install|abort-upgrade|disappear) + ;; + + *) + echo "postrm called with unknown argument \`$1'" >&2 + exit 1 + ;; +esac + +# dh_installdeb will replace this with shell code automatically +# generated by other debhelper scripts. + +#DEBHELPER# + +exit 0 diff --git a/spec/data/apt/chef-integration-test2-1.0/debian/preinst.ex b/spec/data/apt/chef-integration-test2-1.0/debian/preinst.ex new file mode 100644 index 0000000000..d871e0e9b0 --- /dev/null +++ b/spec/data/apt/chef-integration-test2-1.0/debian/preinst.ex @@ -0,0 +1,35 @@ +#!/bin/sh +# preinst script for chef-integration-test2 +# +# see: dh_installdeb(1) + +set -e + +# summary of how this script can be called: +# * <new-preinst> `install' +# * <new-preinst> `install' <old-version> +# * <new-preinst> `upgrade' <old-version> +# * <old-preinst> `abort-upgrade' <new-version> +# for details, see http://www.debian.org/doc/debian-policy/ or +# the debian-policy package + + +case "$1" in + install|upgrade) + ;; + + abort-upgrade) + ;; + + *) + echo "preinst called with unknown argument \`$1'" >&2 + exit 1 + ;; +esac + +# dh_installdeb will replace this with shell code automatically +# generated by other debhelper scripts. + +#DEBHELPER# + +exit 0 diff --git a/spec/data/apt/chef-integration-test2-1.0/debian/prerm.ex b/spec/data/apt/chef-integration-test2-1.0/debian/prerm.ex new file mode 100644 index 0000000000..0fb0dc480c --- /dev/null +++ b/spec/data/apt/chef-integration-test2-1.0/debian/prerm.ex @@ -0,0 +1,38 @@ +#!/bin/sh +# prerm script for chef-integration-test2 +# +# see: dh_installdeb(1) + +set -e + +# summary of how this script can be called: +# * <prerm> `remove' +# * <old-prerm> `upgrade' <new-version> +# * <new-prerm> `failed-upgrade' <old-version> +# * <conflictor's-prerm> `remove' `in-favour' <package> <new-version> +# * <deconfigured's-prerm> `deconfigure' `in-favour' +# <package-being-installed> <version> `removing' +# <conflicting-package> <version> +# for details, see http://www.debian.org/doc/debian-policy/ or +# the debian-policy package + + +case "$1" in + remove|upgrade|deconfigure) + ;; + + failed-upgrade) + ;; + + *) + echo "prerm called with unknown argument \`$1'" >&2 + exit 1 + ;; +esac + +# dh_installdeb will replace this with shell code automatically +# generated by other debhelper scripts. + +#DEBHELPER# + +exit 0 diff --git a/spec/data/apt/chef-integration-test2-1.0/debian/rules b/spec/data/apt/chef-integration-test2-1.0/debian/rules new file mode 100755 index 0000000000..79fd842dca --- /dev/null +++ b/spec/data/apt/chef-integration-test2-1.0/debian/rules @@ -0,0 +1,8 @@ +#!/usr/bin/make -f +# -*- makefile -*- + +# Uncomment this to turn on verbose mode. +#export DH_VERBOSE=1 + +%: + dh $@ diff --git a/spec/data/apt/chef-integration-test2-1.0/debian/source/format b/spec/data/apt/chef-integration-test2-1.0/debian/source/format new file mode 100644 index 0000000000..163aaf8d82 --- /dev/null +++ b/spec/data/apt/chef-integration-test2-1.0/debian/source/format @@ -0,0 +1 @@ +3.0 (quilt) diff --git a/spec/data/apt/chef-integration-test2-1.0/debian/watch.ex b/spec/data/apt/chef-integration-test2-1.0/debian/watch.ex new file mode 100644 index 0000000000..0c5a2e0c17 --- /dev/null +++ b/spec/data/apt/chef-integration-test2-1.0/debian/watch.ex @@ -0,0 +1,23 @@ +# Example watch control file for uscan +# Rename this file to "watch" and then you can run the "uscan" command +# to check for upstream updates and more. +# See uscan(1) for format + +# Compulsory line, this is a version 3 file +version=3 + +# Uncomment to examine a Webpage +# <Webpage URL> <string match> +#http://www.example.com/downloads.php chef-integration-test2-(.*)\.tar\.gz + +# Uncomment to examine a Webserver directory +#http://www.example.com/pub/chef-integration-test2-(.*)\.tar\.gz + +# Uncommment to examine a FTP server +#ftp://ftp.example.com/pub/chef-integration-test2-(.*)\.tar\.gz debian uupdate + +# Uncomment to find new files on sourceforge, for devscripts >= 2.9 +# http://sf.net/chef-integration-test2/chef-integration-test2-(.*)\.tar\.gz + +# Uncomment to find new files on GooglePages +# http://example.googlepages.com/foo.html chef-integration-test2-(.*)\.tar\.gz diff --git a/spec/data/apt/chef-integration-test2_1.0-1.debian.tar.gz b/spec/data/apt/chef-integration-test2_1.0-1.debian.tar.gz Binary files differnew file mode 100644 index 0000000000..d4abcfca62 --- /dev/null +++ b/spec/data/apt/chef-integration-test2_1.0-1.debian.tar.gz diff --git a/spec/data/apt/chef-integration-test2_1.0-1.dsc b/spec/data/apt/chef-integration-test2_1.0-1.dsc new file mode 100644 index 0000000000..43e5ff1057 --- /dev/null +++ b/spec/data/apt/chef-integration-test2_1.0-1.dsc @@ -0,0 +1,20 @@ +Format: 3.0 (quilt) +Source: chef-integration-test2 +Binary: chef-integration-test2 +Architecture: any +Version: 1.0-1 +Maintainer: Lamont Granquist <lamont@coredump.scriptkiddie.lan> +Homepage: <insert the upstream URL, if relevant> +Standards-Version: 3.9.4 +Build-Depends: debhelper (>= 8.0.0) +Package-List: + chef-integration-test2 deb unknown optional +Checksums-Sha1: + 755c304197c6559128aed206ea70643fec2bb90d 248 chef-integration-test2_1.0.orig.tar.gz + 147e8003463c5b54862a84367ab8f9559306da60 9737 chef-integration-test2_1.0-1.debian.tar.gz +Checksums-Sha256: + 8b206a7b3d422290bc8d82bd700cb89f1c6e3962b96be6a3955c7a0159f9031c 248 chef-integration-test2_1.0.orig.tar.gz + b0b4f3423dc8934f41543352ab3f4bd3e647fdfc490f825426fd71103403d4bc 9737 chef-integration-test2_1.0-1.debian.tar.gz +Files: + f1f7d7bbe63ad631d25d707f564a8d33 248 chef-integration-test2_1.0.orig.tar.gz + ad45e1006026dbbe60edcbb7520e9379 9737 chef-integration-test2_1.0-1.debian.tar.gz diff --git a/spec/data/apt/chef-integration-test2_1.0-1_amd64.changes b/spec/data/apt/chef-integration-test2_1.0-1_amd64.changes new file mode 100644 index 0000000000..2596a2b2ec --- /dev/null +++ b/spec/data/apt/chef-integration-test2_1.0-1_amd64.changes @@ -0,0 +1,31 @@ +Format: 1.8 +Date: Mon, 23 Nov 2015 12:57:22 -0800 +Source: chef-integration-test2 +Binary: chef-integration-test2 +Architecture: source amd64 +Version: 1.0-1 +Distribution: unstable +Urgency: low +Maintainer: Lamont Granquist <lamont@coredump.scriptkiddie.lan> +Changed-By: Lamont Granquist <lamont@coredump.scriptkiddie.lan> +Description: + chef-integration-test2 - <insert up to 60 chars description> +Changes: + chef-integration-test2 (1.0-1) unstable; urgency=low + . + * Initial release (Closes: #nnnn) <nnnn is the bug number of your ITP> +Checksums-Sha1: + 496f99763cf1363587a218530839b888c9f21352 950 chef-integration-test2_1.0-1.dsc + 755c304197c6559128aed206ea70643fec2bb90d 248 chef-integration-test2_1.0.orig.tar.gz + 147e8003463c5b54862a84367ab8f9559306da60 9737 chef-integration-test2_1.0-1.debian.tar.gz + 9f6e72d07f4e7f7b835e81bf34890ecfdec57b30 2258 chef-integration-test2_1.0-1_amd64.deb +Checksums-Sha256: + 3535259d2a747b4c9595d86db41691cf7408d6cfe409fda2d11c538c19d39925 950 chef-integration-test2_1.0-1.dsc + 8b206a7b3d422290bc8d82bd700cb89f1c6e3962b96be6a3955c7a0159f9031c 248 chef-integration-test2_1.0.orig.tar.gz + b0b4f3423dc8934f41543352ab3f4bd3e647fdfc490f825426fd71103403d4bc 9737 chef-integration-test2_1.0-1.debian.tar.gz + 42df491d0a3c3a077b6c808fffc93557f9b4747b2443a1c1da16ddda873730a4 2258 chef-integration-test2_1.0-1_amd64.deb +Files: + 67b83ba0dcd7b8a3e061c38b9d70d0af 950 unknown optional chef-integration-test2_1.0-1.dsc + f1f7d7bbe63ad631d25d707f564a8d33 248 unknown optional chef-integration-test2_1.0.orig.tar.gz + ad45e1006026dbbe60edcbb7520e9379 9737 unknown optional chef-integration-test2_1.0-1.debian.tar.gz + 9932a1f0074e1b218c057b7f7f7a1399 2258 unknown optional chef-integration-test2_1.0-1_amd64.deb diff --git a/spec/data/apt/chef-integration-test2_1.0-1_amd64.deb b/spec/data/apt/chef-integration-test2_1.0-1_amd64.deb Binary files differnew file mode 100644 index 0000000000..4856df5236 --- /dev/null +++ b/spec/data/apt/chef-integration-test2_1.0-1_amd64.deb diff --git a/spec/data/apt/chef-integration-test2_1.0.orig.tar.gz b/spec/data/apt/chef-integration-test2_1.0.orig.tar.gz Binary files differnew file mode 100644 index 0000000000..18f7aa17d6 --- /dev/null +++ b/spec/data/apt/chef-integration-test2_1.0.orig.tar.gz diff --git a/spec/functional/resource/dpkg_package_spec.rb b/spec/functional/resource/dpkg_package_spec.rb new file mode 100644 index 0000000000..8d67a1fa03 --- /dev/null +++ b/spec/functional/resource/dpkg_package_spec.rb @@ -0,0 +1,336 @@ +# +# Copyright:: Copyright (c) 2014-2015 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' +require 'chef/mixin/shell_out' + +describe Chef::Resource::DpkgPackage, :requires_root, :debian_family_only do + include Chef::Mixin::ShellOut + + let(:apt_data) { File.join(CHEF_SPEC_DATA, "apt") } + + let(:test1_0) { File.join(apt_data, "chef-integration-test_1.0-1_amd64.deb") } + let(:test1_1) { File.join(apt_data, "chef-integration-test_1.1-1_amd64.deb") } + let(:test2_0) { File.join(apt_data, "chef-integration-test2_1.0-1_amd64.deb") } + + let(:run_context) { + node = TEST_NODE.dup + events = Chef::EventDispatch::Dispatcher.new + Chef::RunContext.new(node, {}, events) + } + + let(:dpkg_package) { Chef::Resource::DpkgPackage.new(test1_0, run_context)} + + before(:each) do + shell_out("dpkg -P chef-integration-test chef-integration-test2") + end + + # handles setting the name property after the initializer runs + def set_dpkg_package_name(name) + dpkg_package.name name + dpkg_package.package_name name + end + + def should_be_purged_or_removed(package, action) + if action == :purge + shell_out!("dpkg -s #{package}", returns: [1]) + else + expect(shell_out("dpkg -s #{package}").stdout).to match(/deinstall ok config-files/) + end + end + + shared_examples_for "common behavior for upgrade or install" do + it "installs a package when given only the filename as a name argument (no source)" do + dpkg_package.run_action(action) + expect(dpkg_package).to be_updated_by_last_action + shell_out!('dpkg -s chef-integration-test') + end + + it "installs a package when given the name and a source argument" do + set_dpkg_package_name "chef-integration-test" + dpkg_package.source test1_0 + dpkg_package.run_action(action) + expect(dpkg_package).to be_updated_by_last_action + shell_out!('dpkg -s chef-integration-test') + end + + it "installs a package when given a different name and a source argument" do + set_dpkg_package_name "some other name" + dpkg_package.source test1_0 + dpkg_package.run_action(action) + expect(dpkg_package).to be_updated_by_last_action + shell_out!('dpkg -s chef-integration-test') + end + + it "installs a package when given a path as a package_name and no source" do + set_dpkg_package_name "chef-integration-test" + dpkg_package.package_name test1_0 + dpkg_package.run_action(action) + expect(dpkg_package).to be_updated_by_last_action + shell_out!('dpkg -s chef-integration-test') + end + + it "raises an error when the name is not a path and the source is not given" do + set_dpkg_package_name "chef-integration-test" + dpkg_package.package_name "chef-integration-test" + expect { dpkg_package.run_action(action) }.to raise_error(Chef::Exceptions::Package) + end + + it "raises an error when passed a package_name that does not exist" do + set_dpkg_package_name File.join(test1_0, "make.it.fail") + expect { dpkg_package.run_action(action) }.to raise_error(Chef::Exceptions::Package) + end + + it "raises an error when passed a source that does not exist" do + set_dpkg_package_name "chef-integration-test" + dpkg_package.source File.join(test1_0, "make.it.fail") + expect { dpkg_package.run_action(action) }.to raise_error(Chef::Exceptions::Package) + end + + it "should not install an already installed package" do + shell_out!("dpkg -i #{test1_0}") + dpkg_package.run_action(action) + expect(dpkg_package).not_to be_updated_by_last_action + shell_out!('dpkg -s chef-integration-test') + end + + it "should handle a multipackage install" do + set_dpkg_package_name [ test1_0, test2_0 ] + dpkg_package.run_action(action) + expect(dpkg_package).to be_updated_by_last_action + shell_out!('dpkg -s chef-integration-test') + shell_out!('dpkg -s chef-integration-test2') + end + + it "should not update multipackages that are up-to-date" do + shell_out!("dpkg -i #{test1_0} #{test2_0}") + set_dpkg_package_name [ test1_0, test2_0 ] + dpkg_package.run_action(action) + expect(dpkg_package).not_to be_updated_by_last_action + shell_out!('dpkg -s chef-integration-test') + shell_out!('dpkg -s chef-integration-test2') + end + + it "should install the second if the first is installed" do + shell_out!("dpkg -i #{test1_0}") + set_dpkg_package_name [ test1_0, test2_0 ] + dpkg_package.run_action(action) + expect(dpkg_package).to be_updated_by_last_action + shell_out!('dpkg -s chef-integration-test') + shell_out!('dpkg -s chef-integration-test2') + end + + it "should install the first if the second is installed" do + shell_out!("dpkg -i #{test2_0}") + set_dpkg_package_name [ test1_0, test2_0 ] + dpkg_package.run_action(action) + expect(dpkg_package).to be_updated_by_last_action + shell_out!('dpkg -s chef-integration-test') + shell_out!('dpkg -s chef-integration-test2') + end + end + + context "action :install" do + let(:action) { :install } + it_behaves_like "common behavior for upgrade or install" + + it "should not upgrade a package" do + shell_out!("dpkg -i #{test1_0}") + set_dpkg_package_name test1_1 + dpkg_package.run_action(action) + expect(dpkg_package).not_to be_updated_by_last_action + end + + it "should not upgrade on a multipackage install" do + shell_out!("dpkg -i #{test1_0} #{test2_0}") + set_dpkg_package_name [ test1_1, test2_0 ] + dpkg_package.run_action(action) + expect(dpkg_package).not_to be_updated_by_last_action + end + end + + context "action :upgrade" do + let(:action) { :upgrade } + it_behaves_like "common behavior for upgrade or install" + + it "should upgrade a package" do + shell_out!("dpkg -i #{test1_0}") + set_dpkg_package_name test1_1 + dpkg_package.run_action(action) + expect(dpkg_package).to be_updated_by_last_action + end + + it "should upgrade on a multipackage install" do + shell_out!("dpkg -i #{test1_0} #{test2_0}") + set_dpkg_package_name [ test1_1, test2_0 ] + dpkg_package.run_action(action) + expect(dpkg_package).to be_updated_by_last_action + end + end + + shared_examples_for "common behavior for remove or purge" do + it "should remove a package that is installed when the name is a source" do + shell_out!("dpkg -i #{test1_0}") + dpkg_package.run_action(action) + expect(dpkg_package).to be_updated_by_last_action + expect(shell_out('dpkg -s chef-integration-test').exitstatus).to eql(1) + end + + it "should do nothing if the package is not installed when the name is a source" do + dpkg_package.run_action(action) + expect(dpkg_package).not_to be_updated_by_last_action + expect(shell_out('dpkg -s chef-integration-test').exitstatus).to eql(1) + end + + it "should remove a package that is installed when the name is the package name and source is nil" do + shell_out!("dpkg -i #{test1_0}") + set_dpkg_package_name "chef-integration-test" + dpkg_package.run_action(action) + expect(dpkg_package).to be_updated_by_last_action + expect(shell_out('dpkg -s chef-integration-test').exitstatus).to eql(1) + end + + it "should do nothing if the package is not installed when the name is the package name and the source is nil" do + set_dpkg_package_name "chef-integration-test" + dpkg_package.run_action(action) + expect(dpkg_package).not_to be_updated_by_last_action + expect(shell_out('dpkg -s chef-integration-test').exitstatus).to eql(1) + end + + it "should remove a package that is installed when the name is changed but the source is a package" do + shell_out!("dpkg -i #{test1_0}") + set_dpkg_package_name "some other name" + dpkg_package.source test1_0 + dpkg_package.run_action(action) + expect(dpkg_package).to be_updated_by_last_action + expect(shell_out('dpkg -s chef-integration-test').exitstatus).to eql(1) + end + + it "should do nothing if the package is not installed when the name is changed but the source is a package" do + set_dpkg_package_name "some other name" + dpkg_package.source test1_0 + dpkg_package.run_action(action) + expect(dpkg_package).not_to be_updated_by_last_action + expect(shell_out('dpkg -s chef-integration-test').exitstatus).to eql(1) + end + + it "should remove a package if the name is a file that does not exist, but the source exists" do + shell_out!("dpkg -i #{test1_0}") + dpkg_package.name "whatever" + dpkg_package.package_name File.join(test1_0, "make.it.fail") + dpkg_package.source test1_0 + dpkg_package.run_action(action) + expect(dpkg_package).to be_updated_by_last_action + expect(shell_out('dpkg -s chef-integration-test').exitstatus).to eql(1) + end + + it "should do nothing if the package is not installed when the name is a file that does not exist, but the source exists" do + set_dpkg_package_name "some other name" + dpkg_package.name "whatever" + dpkg_package.package_name File.join(test1_0, "make.it.fail") + dpkg_package.source test1_0 + dpkg_package.run_action(action) + expect(dpkg_package).not_to be_updated_by_last_action + expect(shell_out('dpkg -s chef-integration-test').exitstatus).to eql(1) + end + + it "should remove a package if the package_name is correct, but the source does not exist" do + shell_out!("dpkg -i #{test1_0}") + dpkg_package.name "whatever" + dpkg_package.package_name "chef-integration-test" + dpkg_package.source File.join(test1_0, "make.it.fail") + dpkg_package.run_action(action) + expect(dpkg_package).to be_updated_by_last_action + shell_out!('dpkg -s chef-integration-test', returns: [1]) + end + + it "should do nothing if the package_name is correct, but the source does not exist, and the package is not installed" do + dpkg_package.name "whatever" + dpkg_package.package_name "chef-integration-test" + dpkg_package.source File.join(test1_0, "make.it.fail") + dpkg_package.run_action(action) + expect(dpkg_package).not_to be_updated_by_last_action + expect(shell_out('dpkg -s chef-integration-test').exitstatus).to eql(1) + end + + it "should remove both packages when called with two" do + shell_out!("dpkg -i #{test1_0} #{test2_0}") + set_dpkg_package_name [ "chef-integration-test", "chef-integration-test2" ] + dpkg_package.run_action(action) + expect(dpkg_package).to be_updated_by_last_action + shell_out!('dpkg -s chef-integration-test', returns: [1]) + should_be_purged_or_removed('chef-integration-test2', action) + end + + it "should remove a package when only the first one is installed" do + shell_out!("dpkg -i #{test1_0}") + set_dpkg_package_name [ "chef-integration-test", "chef-integration-test2" ] + dpkg_package.run_action(action) + expect(dpkg_package).to be_updated_by_last_action + shell_out!('dpkg -s chef-integration-test', returns: [1]) + shell_out!('dpkg -s chef-integration-test2', returns: [1]) + end + + it "should remove a package when only the second one is installed" do + shell_out!("dpkg -i #{test2_0}") + set_dpkg_package_name [ "chef-integration-test", "chef-integration-test2" ] + dpkg_package.run_action(action) + expect(dpkg_package).to be_updated_by_last_action + shell_out!('dpkg -s chef-integration-test', returns: [1]) + should_be_purged_or_removed('chef-integration-test2', action) + end + + it "should do nothing when both packages are not installed" do + set_dpkg_package_name [ "chef-integration-test", "chef-integration-test2" ] + dpkg_package.run_action(action) + expect(dpkg_package).not_to be_updated_by_last_action + shell_out!('dpkg -s chef-integration-test', returns: [1]) + shell_out!('dpkg -s chef-integration-test2', returns: [1]) + end + + end + + context "action :remove" do + let(:action) { :remove } + it_behaves_like "common behavior for remove or purge" + + it "should not remove a removed package when the name is a source" do + # the "test2" file has a conffile declared in it + shell_out!("dpkg -i #{test2_0}") + shell_out!("dpkg -r chef-integration-test2") + set_dpkg_package_name "chef-integration-test2" + dpkg_package.run_action(action) + expect(dpkg_package).not_to be_updated_by_last_action + shell_out!('dpkg -s chef-integration-test2') # its still 'installed' + end + end + + context "action :purge" do + let(:action) { :purge } + it_behaves_like "common behavior for remove or purge" + + it "should purge a removed package when the name is a source" do + # the "test2" file has a conffile declared in it + shell_out!("dpkg -i #{test2_0}") + shell_out!("dpkg -r chef-integration-test2") + set_dpkg_package_name "chef-integration-test2" + dpkg_package.run_action(action) + expect(dpkg_package).to be_updated_by_last_action + expect(shell_out('dpkg -s chef-integration-test2').exitstatus).to eql(1) + end + end +end diff --git a/spec/functional/resource/package_spec.rb b/spec/functional/resource/package_spec.rb index 8d37b072e8..25ec872b9b 100644 --- a/spec/functional/resource/package_spec.rb +++ b/spec/functional/resource/package_spec.rb @@ -1,7 +1,7 @@ # encoding: UTF-8 # # Author:: Daniel DeLeo (<dan@opscode.com>) -# Copyright:: Copyright (c) 2013 Opscode, Inc. +# Copyright:: Copyright (c) 2013-2015 Chef Software, Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 5ebd9cb896..7b3b61cad0 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -1,6 +1,6 @@ # # Author:: Adam Jacob (<adam@opscode.com>) -# Copyright:: Copyright (c) 2008 Opscode, Inc. +# Copyright:: Copyright (c) 2008-2015 Chef Software, Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -94,8 +94,10 @@ test_node.automatic['platform_family'] = (OHAI_SYSTEM['platform_family'] || 'unk test_node.automatic['platform'] = (OHAI_SYSTEM['platform'] || 'unknown_platform').dup.freeze test_node.automatic['platform_version'] = (OHAI_SYSTEM['platform_version'] || 'unknown_platform_version').dup.freeze TEST_NODE = test_node.freeze +TEST_OS = TEST_NODE['os'] TEST_PLATFORM = TEST_NODE['platform'] TEST_PLATFORM_VERSION = TEST_NODE['platform_version'] +TEST_PLATFORM_FAMILY = TEST_NODE['platform_family'] RSpec.configure do |config| config.include(Matchers) @@ -145,6 +147,7 @@ RSpec.configure do |config| config.filter_run_excluding :system_windows_service_gem_only => true unless system_windows_service_gem? config.filter_run_excluding :unix_only => true unless unix? config.filter_run_excluding :aix_only => true unless aix? + config.filter_run_excluding :debian_family_only => true unless debian_family? config.filter_run_excluding :supports_cloexec => true unless supports_cloexec? config.filter_run_excluding :selinux_only => true unless selinux_enabled? config.filter_run_excluding :ruby_20_only => true unless ruby_20? diff --git a/spec/support/platform_helpers.rb b/spec/support/platform_helpers.rb index 9c6c3fdf72..2fc4a02cf1 100644 --- a/spec/support/platform_helpers.rb +++ b/spec/support/platform_helpers.rb @@ -143,6 +143,10 @@ def freebsd? !!(RUBY_PLATFORM =~ /freebsd/) end +def debian_family? + !!(ohai[:platform_family] == "debian") +end + def aix? !!(RUBY_PLATFORM =~ /aix/) end diff --git a/spec/unit/mixin/subclass_directive_spec.rb b/spec/unit/mixin/subclass_directive_spec.rb new file mode 100644 index 0000000000..552f26c0c1 --- /dev/null +++ b/spec/unit/mixin/subclass_directive_spec.rb @@ -0,0 +1,45 @@ +# +# Copyright:: Copyright (c) 2015 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' + +class SubclassDirectiveParent + extend Chef::Mixin::SubclassDirective + + subclass_directive :behave_differently +end + +class SubclassDirectiveChild < SubclassDirectiveParent + behave_differently +end + +class ChildWithoutDirective < SubclassDirectiveParent +end + +describe Chef::Mixin::Uris do + let (:child) { SubclassDirectiveChild.new } + + let (:other_child) { ChildWithoutDirective.new } + + it "the child instance has the directive set" do + expect(child.behave_differently?).to be true + end + + it "a child that does not declare it does not have it set" do + expect(other_child.behave_differently?).to be false + end +end diff --git a/spec/unit/provider/package/dpkg_spec.rb b/spec/unit/provider/package/dpkg_spec.rb index 2ded8313c0..15b2903a0e 100644 --- a/spec/unit/provider/package/dpkg_spec.rb +++ b/spec/unit/provider/package/dpkg_spec.rb @@ -1,4 +1,3 @@ -# # Author:: Bryan McLellan (btm@loftninjas.org) # Copyright:: Copyright (c) 2009 Bryan McLellan # License:: Apache License, Version 2.0 @@ -25,7 +24,7 @@ describe Chef::Provider::Package::Dpkg do let(:package) { "wget" } let(:source) { "/tmp/wget_1.11.4-1ubuntu1_amd64.deb" } let(:new_resource) do - new_resource = Chef::Resource::Package.new(package) + new_resource = Chef::Resource::DpkgPackage.new(package) new_resource.source source new_resource end @@ -52,8 +51,8 @@ Conflicts: wget-ssl end before(:each) do - allow(provider).to receive(:shell_out!).with("dpkg-deb -W #{new_resource.source}", timeout: 900).and_return(dpkg_deb_status) - allow(provider).to receive(:shell_out).with("dpkg -s #{package}", timeout: 900).and_return(dpkg_s_status) + allow(provider).to receive(:shell_out!).with("dpkg-deb -W #{source}", timeout: 900).and_return(dpkg_deb_status) + allow(provider).to receive(:shell_out).with("dpkg -s #{package}", timeout: 900).and_return(double(stdout: "", exitstatus: -1)) allow(::File).to receive(:exist?).with(source).and_return(true) end @@ -112,16 +111,16 @@ Conflicts: wget-ssl it "should create a current resource with the name of the new_resource" do provider.load_current_resource - expect(provider.current_resource.package_name).to eq("wget") + expect(provider.current_resource.package_name).to eq(["wget"]) end describe 'gets the source package version from dpkg-deb' do def check_version(version) status = double(:stdout => "wget\t#{version}", :exitstatus => 0) - expect(provider).to receive(:shell_out!).with("dpkg-deb -W #{new_resource.source}", timeout: 900).and_return(status) + expect(provider).to receive(:shell_out!).with("dpkg-deb -W #{source}", timeout: 900).and_return(status) provider.load_current_resource - expect(provider.current_resource.package_name).to eq("wget") - expect(provider.candidate_version).to eq(version) + expect(provider.current_resource.package_name).to eq(["wget"]) + expect(provider.candidate_version).to eq([version]) end it 'if short version provided' do @@ -146,7 +145,7 @@ Conflicts: wget-ssl it "gets the source package name from dpkg-deb correctly" do provider.load_current_resource - expect(provider.current_resource.package_name).to eq("f.o.o-pkg++2") + expect(provider.current_resource.package_name).to eq(["f.o.o-pkg++2"]) end end @@ -157,21 +156,22 @@ Conflicts: wget-ssl it "gets the source package version from dpkg-deb correctly when the package version has `~', `-', `+' or `.' characters" do provider.load_current_resource - expect(provider.candidate_version).to eq('1.2.3+3141592-1ubuntu1~lucid') + expect(provider.candidate_version).to eq(['1.2.3+3141592-1ubuntu1~lucid']) end end - it "should raise an exception if the source is not set but we are installing" do - new_resource = Chef::Resource::Package.new("wget") - provider.new_resource = new_resource - provider.load_current_resource - provider.define_resource_requirements - expect { provider.run_action(:install)}.to raise_error(Chef::Exceptions::Package) + describe "when the source is not set" do + let(:source) { nil } + + it "should raise an exception if the source is not set but we are installing" do + expect { provider.run_action(:install)}.to raise_error(Chef::Exceptions::Package) + end end it "should return the current version installed if found by dpkg" do + allow(provider).to receive(:shell_out).with("dpkg -s #{package}", timeout: 900).and_return(dpkg_s_status) provider.load_current_resource - expect(provider.current_resource.version).to eq("1.11.4-1ubuntu1") + expect(provider.current_resource.version).to eq(["1.11.4-1ubuntu1"]) end it "should raise an exception if dpkg fails to run" do @@ -184,72 +184,73 @@ Conflicts: wget-ssl describe Chef::Provider::Package::Dpkg, "install and upgrade" do it "should run dpkg -i with the package source" do expect(provider).to receive(:run_noninteractive).with( - "dpkg -i /tmp/wget_1.11.4-1ubuntu1_amd64.deb" + "dpkg -i", nil, "/tmp/wget_1.11.4-1ubuntu1_amd64.deb" ) - provider.install_package("wget", "1.11.4-1ubuntu1") + provider.load_current_resource + provider.run_action(:install) end it "should run dpkg -i if the package is a path and the source is nil" do - new_resource.name = "/tmp/wget_1.11.4-1ubuntu1_amd64.deb" + new_resource.name "/tmp/wget_1.11.4-1ubuntu1_amd64.deb" expect(provider).to receive(:run_noninteractive).with( - "dpkg -i /tmp/wget_1.11.4-1ubuntu1_amd64.deb" + "dpkg -i", nil, "/tmp/wget_1.11.4-1ubuntu1_amd64.deb" ) - provider.install_package("/tmp/wget_1.11.4-1ubuntu1_amd64.deb", "1.11.4-1ubuntu1") + provider.run_action(:install) end it "should run dpkg -i if the package is a path and the source is nil for an upgrade" do - new_resource.name = "/tmp/wget_1.11.4-1ubuntu1_amd64.deb" + new_resource.name "/tmp/wget_1.11.4-1ubuntu1_amd64.deb" expect(provider).to receive(:run_noninteractive).with( - "dpkg -i /tmp/wget_1.11.4-1ubuntu1_amd64.deb" + "dpkg -i", nil, "/tmp/wget_1.11.4-1ubuntu1_amd64.deb" ) - provider.upgrade_package("/tmp/wget_1.11.4-1ubuntu1_amd64.deb", "1.11.4-1ubuntu1") + provider.run_action(:upgrade) end it "should run dpkg -i with the package source and options if specified" do + new_resource.options "--force-yes" expect(provider).to receive(:run_noninteractive).with( - "dpkg -i --force-yes /tmp/wget_1.11.4-1ubuntu1_amd64.deb" + "dpkg -i", "--force-yes", "/tmp/wget_1.11.4-1ubuntu1_amd64.deb" ) - allow(new_resource).to receive(:options).and_return("--force-yes") - - provider.install_package("wget", "1.11.4-1ubuntu1") + provider.run_action(:install) end + it "should upgrade by running install_package" do - expect(provider).to receive(:install_package).with("wget", "1.11.4-1ubuntu1") - provider.upgrade_package("wget", "1.11.4-1ubuntu1") + expect(provider).to receive(:install_package).with(["wget"], ["1.11.4-1ubuntu1"]) + provider.upgrade_package(["wget"], ["1.11.4-1ubuntu1"]) end end describe Chef::Provider::Package::Dpkg, "remove and purge" do it "should run dpkg -r to remove the package" do expect(provider).to receive(:run_noninteractive).with( - "dpkg -r wget" + "dpkg -r", nil, "wget" ) - provider.remove_package("wget", "1.11.4-1ubuntu1") + provider.remove_package(["wget"], ["1.11.4-1ubuntu1"]) end it "should run dpkg -r to remove the package with options if specified" do expect(provider).to receive(:run_noninteractive).with( - "dpkg -r --force-yes wget" + "dpkg -r", "--force-yes", "wget" ) allow(new_resource).to receive(:options).and_return("--force-yes") - provider.remove_package("wget", "1.11.4-1ubuntu1") + provider.remove_package(["wget"], ["1.11.4-1ubuntu1"]) end it "should run dpkg -P to purge the package" do expect(provider).to receive(:run_noninteractive).with( - "dpkg -P wget" + "dpkg -P", nil, "wget" ) - provider.purge_package("wget", "1.11.4-1ubuntu1") + provider.purge_package(["wget"], ["1.11.4-1ubuntu1"]) end it "should run dpkg -P to purge the package with options if specified" do expect(provider).to receive(:run_noninteractive).with( - "dpkg -P --force-yes wget" + "dpkg -P", "--force-yes", "wget" ) allow(new_resource).to receive(:options).and_return("--force-yes") - provider.purge_package("wget", "1.11.4-1ubuntu1") + provider.purge_package(["wget"], ["1.11.4-1ubuntu1"]) end end end diff --git a/spec/unit/provider/package_spec.rb b/spec/unit/provider/package_spec.rb index 9e4384820a..f77c2b5d0d 100644 --- a/spec/unit/provider/package_spec.rb +++ b/spec/unit/provider/package_spec.rb @@ -453,17 +453,13 @@ describe "Subclass with use_multipackage_api" do provider end - it "should have supports_arrays class accessor" do - expect(MyPackageProvider.supports_arrays).to be true - MyPackageProvider.supports_arrays = false - expect(MyPackageProvider.supports_arrays).to be false - # class variables are global state, so better set it back... - MyPackageProvider.supports_arrays = true + it "has use_multipackage_api? methods on the class and instance" do + expect(MyPackageProvider.use_multipackage_api?).to be true + expect(provider.use_multipackage_api?).to be true end - it "has supports_arrays? methods on the class and instance" do - expect(MyPackageProvider.supports_arrays?).to be true - expect(provider.supports_arrays?).to be true + it "offers a_to_s to subclasses to convert an array of strings to a single string" do + expect(provider.send(:a_to_s, "a", nil, "b", "", "c", " ", "d e", "f-g")).to eq("a b c d e f-g") end it "when user passes string to package_name, passes arrays to install_package" do |