summaryrefslogtreecommitdiff
path: root/lib/chef/resource/yum_package.rb
blob: 6d06465c342682c810f5aac38e072371fad5a2b0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
#
# Author:: AJ Christensen (<aj@chef.io>)
# Copyright:: Copyright (c) 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_relative "package"
require "chef-utils/dist"

class Chef
  class Resource
    class YumPackage < Chef::Resource::Package
      unified_mode true

      provides :yum_package
      provides :package, platform_family: "fedora_derived"

      description "Use the **yum_package** resource to install, upgrade, and remove packages with Yum"\
                  " for the Red Hat and CentOS platforms. The yum_package resource is able to resolve"\
                  " `provides` data for packages much like Yum can do when it is run from the command line."\
                  " This allows a variety of options for installing packages, like minimum versions,"\
                  " virtual provides, and library names."
      examples <<~DOC
        **Install an exact version**:

        ``` ruby
        yum_package 'netpbm = 10.35.58-8.el8'
        ```

        **Install a minimum version**:

        ``` ruby
        yum_package 'netpbm >= 10.35.58-8.el8'
        ```

        **Install a minimum version using the default action**:

        ``` ruby
        yum_package 'netpbm'
        ```

        **Install a version without worrying about the exact release**:

        ``` ruby
        yum_package 'netpbm-10.35*'
        ```


        **To install a package**:

        ``` ruby
        yum_package 'netpbm' do
          action :install
        end
        ```

        **To install a partial minimum version**:

        ``` ruby
        yum_package 'netpbm >= 10'
        ```

        **To install a specific architecture**:

        ``` ruby
        yum_package 'netpbm' do
          arch 'i386'
        end
        ```

        or:

        ``` ruby
        yum_package 'netpbm.x86_64'
        ```

        **To install a specific version-release**

        ``` ruby
        yum_package 'netpbm' do
          version '10.35.58-8.el8'
        end
        ```

        **Handle cookbook_file and yum_package resources in the same recipe**:

        When a **cookbook_file** resource and a **yum_package** resource are
        both called from within the same recipe, use the `flush_cache` attribute
        to dump the in-memory Yum cache, and then use the repository immediately
        to ensure that the correct package is installed:

        ``` ruby
        cookbook_file '/etc/yum.repos.d/custom.repo' do
          source 'custom'
          mode '0755'
        end

        yum_package 'pkg-that-is-only-in-custom-repo' do
          action :install
          flush_cache [ :before ]
        end
        ```
      DOC

      # XXX: the coercions here are due to the provider promiscuously updating the properties on the
      # new_resource which causes immutable modification exceptions when passed an immutable node array.
      #
      # <lecture>
      # THIS is why updating the new_resource in a provider is so terrible, and is equivalent to methods scribbling over
      # its own arguments as unintended side-effects (and why functional languages that don't allow modifications
      # of variables eliminate entire classes of bugs).
      # </lecture>
      property :package_name, [ String, Array ],
        description: "One of the following: the name of a package, the name of a package and its architecture, the name of a dependency.",
        identity: true, coerce: proc { |x| x.is_a?(Array) ? x.to_a : x }

      property :version, [ String, Array ],
        description: "The version of a package to be installed or upgraded. This property is ignored when using the `:upgrade` action.",
        coerce: proc { |x| x.is_a?(Array) ? x.to_a : x }

      property :arch, [ String, Array ],
        description: "The architecture of the package to be installed or upgraded. This value can also be passed as part of the package name.",
        coerce: proc { |x| x.is_a?(Array) ? x.to_a : x }

      property :flush_cache, Hash,
        description: "Flush the in-memory cache before or after a Yum operation that installs, upgrades, or removes a package. Accepts a Hash in the form: { :before => true/false, :after => true/false } or an Array in the form [ :before, :after ].\nYum automatically synchronizes remote metadata to a local cache. The #{ChefUtils::Dist::Infra::CLIENT} creates a copy of the local cache, and then stores it in-memory during the #{ChefUtils::Dist::Infra::CLIENT} run. The in-memory cache allows packages to be installed during the #{ChefUtils::Dist::Infra::CLIENT} run without the need to continue synchronizing the remote metadata to the local cache while the #{ChefUtils::Dist::Infra::CLIENT} run is in-progress.",
        default: { before: false, after: false },
        coerce: proc { |v|
          if v.is_a?(Hash)
            v
          elsif v.is_a?(Array)
            v.each_with_object({}) { |arg, obj| obj[arg] = true }
          elsif v.is_a?(TrueClass) || v.is_a?(FalseClass)
            { before: v, after: v }
          elsif v == :before
            { before: true, after: false }
          elsif v == :after
            { after: true, before: false }
          end
        }

      property :allow_downgrade, [ TrueClass, FalseClass ],
        description: "Allow downgrading a package to satisfy requested version requirements.",
        default: true,
        desired_state: false

      property :yum_binary, String,
        description: "The path to the yum binary."
    end
  end
end