Vendor the external cookbooks

Knife-Zero doesn't include Berkshelf support, so vendoring everything in
the repo is convenient again
This commit is contained in:
Greg Karékinian
2019-10-13 19:17:42 +02:00
parent f4bfe31ac1
commit a32f34b408
1245 changed files with 100630 additions and 0 deletions

View File

@@ -0,0 +1,29 @@
module ChefCompat
module CopiedFromChef
def self.extend_chef_module(chef_module, target)
target.instance_eval do
include chef_module
@chef_module = chef_module
def self.method_missing(name, *args, &block)
@chef_module.send(name, *args, &block)
end
def self.const_missing(name)
@chef_module.const_get(name)
end
end
end
# This patch to CopiedFromChef's ActionClass is necessary for the include to work
require 'chef/resource'
class Chef < ::Chef
class Resource < ::Chef::Resource
module ActionClass
def self.use_inline_resources
end
def self.include_resource_dsl(include_resource_dsl)
end
end
end
end
end
end

View File

@@ -0,0 +1,47 @@
#
# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE
#
# THIS IS A FILE AUTOGENERATED BY 'rake update' DO NOT EDIT!!!!
#
# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE
#
begin
require 'chef/constants'
rescue LoadError; end
require 'chef_compat/copied_from_chef'
class Chef
module ::ChefCompat
module CopiedFromChef
#
# Author:: John Keiser <jkeiser@chef.io>
# Copyright:: Copyright 2015-2016, 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 < (defined?(::Chef) ? ::Chef : Object)
NOT_PASSED = Object.new
def NOT_PASSED.to_s
"NOT_PASSED"
end
def NOT_PASSED.inspect
to_s
end
NOT_PASSED.freeze
end
end
end
end

View File

@@ -0,0 +1,40 @@
#
# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE
#
# THIS IS A FILE AUTOGENERATED BY 'rake update' DO NOT EDIT!!!!
#
# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE
#
begin
require 'chef/delayed_evaluator'
rescue LoadError; end
require 'chef_compat/copied_from_chef'
class Chef
module ::ChefCompat
module CopiedFromChef
#
# Author:: John Keiser <jkeiser@chef.io>
# Copyright:: Copyright 2015-2016, 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 < (defined?(::Chef) ? ::Chef : Object)
class DelayedEvaluator < (defined?(::Chef::DelayedEvaluator) ? ::Chef::DelayedEvaluator : Proc)
end
end
end
end
end

View File

@@ -0,0 +1,73 @@
#
# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE
#
# THIS IS A FILE AUTOGENERATED BY 'rake update' DO NOT EDIT!!!!
#
# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE
#
begin
require 'chef/dsl/core'
rescue LoadError; end
require 'chef_compat/copied_from_chef'
class Chef
module ::ChefCompat
module CopiedFromChef
#--
# Author:: Adam Jacob (<adam@chef.io>)
# Author:: Christopher Walters (<cw@chef.io>)
# Copyright:: Copyright 2008-2016 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 "chef_compat/copied_from_chef/chef/dsl/declare_resource"
require "chef_compat/copied_from_chef/chef/dsl/universal"
require "chef_compat/copied_from_chef/chef/mixin/notifying_block"
require "chef_compat/copied_from_chef/chef/mixin/lazy_module_include"
class Chef < (defined?(::Chef) ? ::Chef : Object)
module DSL
CopiedFromChef.extend_chef_module(::Chef::DSL, self) if defined?(::Chef::DSL)
# Part of a family of DSL mixins.
#
# Chef::DSL::Recipe mixes into Recipes and LWRP Providers.
# - this does not target core chef resources and providers.
# - this is restricted to recipe/resource/provider context where a resource collection exists.
# - cookbook authors should typically include modules into here.
#
# Chef::DSL::Core mixes into Recipes, LWRP Providers and Core Providers
# - this adds cores providers on top of the Recipe DSL.
# - this is restricted to recipe/resource/provider context where a resource collection exists.
# - core chef authors should typically include modules into here.
#
# Chef::DSL::Universal mixes into Recipes, LWRP Resources+Providers, Core Resources+Providers, and Attributes files.
# - this adds resources and attributes files.
# - do not add helpers which manipulate the resource collection.
# - this is for general-purpose stuff that is useful nearly everywhere.
# - it also pollutes the namespace of nearly every context, watch out.
#
module Core
CopiedFromChef.extend_chef_module(::Chef::DSL::Core, self) if defined?(::Chef::DSL::Core)
include Chef::DSL::Universal
include Chef::DSL::DeclareResource
include Chef::Mixin::NotifyingBlock
extend Chef::Mixin::LazyModuleInclude
end
end
end
end
end
end

View File

@@ -0,0 +1,315 @@
#
# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE
#
# THIS IS A FILE AUTOGENERATED BY 'rake update' DO NOT EDIT!!!!
#
# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE
#
begin
require 'chef/dsl/declare_resource'
rescue LoadError; end
require 'chef_compat/copied_from_chef'
class Chef
module ::ChefCompat
module CopiedFromChef
#--
# Author:: Adam Jacob (<adam@chef.io>)
# Author:: Christopher Walters
# Copyright:: Copyright 2008-2016 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 < (defined?(::Chef) ? ::Chef : Object)
module DSL
CopiedFromChef.extend_chef_module(::Chef::DSL, self) if defined?(::Chef::DSL)
module DeclareResource
CopiedFromChef.extend_chef_module(::Chef::DSL::DeclareResource, self) if defined?(::Chef::DSL::DeclareResource)
# Helper for switching run_contexts. Allows for using :parent or :root in place of
# passing the run_context. Executes the block in the run_context. Returns the return
# value of the passed block.
#
# @param rc [Chef::RunContext,Symbol] Either :root, :parent or a Chef::RunContext
#
# @return return value of the block
#
# @example
# # creates/returns a 'service[foo]' resource in the root run_context
# resource = with_run_context(:root)
# edit_resource(:service, "foo") do
# action :nothing
# end
# end
#
def with_run_context(rc)
raise ArgumentError, "with_run_context is useless without a block" unless block_given?
old_run_context = @run_context
@run_context =
case rc
when Chef::RunContext
rc
when :root
run_context.root_run_context
when :parent
run_context.parent_run_context
else
raise ArgumentError, "bad argument to run_context helper, must be :root, :parent, or a Chef::RunContext"
end
yield
ensure
@run_context = old_run_context
end
# Lookup a resource in the resource collection by name and delete it. This
# will raise Chef::Exceptions::ResourceNotFound if the resource is not found.
#
# @param type [Symbol] The type of resource (e.g. `:file` or `:package`)
# @param name [String] The name of the resource (e.g. '/x/y.txt' or 'apache2')
# @param run_context [Chef::RunContext] the run_context of the resource collection to operate on
#
# @return [Chef::Resource] The resource
#
# @example
# delete_resource!(:template, '/x/y.txy')
#
def delete_resource!(type, name, run_context: self.run_context)
run_context.resource_collection.delete("#{type}[#{name}]").tap do |resource|
# Purge any pending notifications too. This will not raise an exception
# if there are no notifications.
if resource
run_context.before_notification_collection.delete(resource.declared_key)
run_context.immediate_notification_collection.delete(resource.declared_key)
run_context.delayed_notification_collection.delete(resource.declared_key)
end
end
end
# Lookup a resource in the resource collection by name and delete it. Returns
# nil if the resource is not found and should not fail.
#
# @param type [Symbol] The type of resource (e.g. `:file` or `:package`)
# @param name [String] The name of the resource (e.g. '/x/y.txt' or 'apache2')
# @param run_context [Chef::RunContext] the run_context of the resource collection to operate on
#
# @return [Chef::Resource] The resource
#
# @example
# delete_resource(:template, '/x/y.txy')
#
def delete_resource(type, name, run_context: self.run_context)
delete_resource!(type, name, run_context: run_context)
rescue Chef::Exceptions::ResourceNotFound
nil
end
# Lookup a resource in the resource collection by name and edit the resource. If the resource is not
# found this will raise Chef::Exceptions::ResourceNotFound. This is the correct API to use for
# "chef_rewind" functionality.
#
# @param type [Symbol] The type of resource (e.g. `:file` or `:package`)
# @param name [String] The name of the resource (e.g. '/x/y.txt' or 'apache2')
# @param run_context [Chef::RunContext] the run_context of the resource collection to operate on
# @param resource_attrs_block A block that lets you set attributes of the
# resource (it is instance_eval'd on the resource instance).
#
# @return [Chef::Resource] The updated resource
#
# @example
# edit_resource!(:template, '/x/y.txy') do
# cookbook_name: cookbook_name
# end
#
def edit_resource!(type, name, created_at = nil, run_context: self.run_context, &resource_attrs_block)
resource = find_resource!(type, name, run_context: run_context)
if resource_attrs_block
if defined?(new_resource)
resource.instance_exec(new_resource, &resource_attrs_block)
else
resource.instance_exec(&resource_attrs_block)
end
end
resource
end
# Lookup a resource in the resource collection by name. If it exists,
# return it. If it does not exist, create it. This is a useful function
# for accumulator patterns. In CRUD terminology this is an "upsert" operation and is
# used to assert that the resource must exist with the specified properties.
#
# @param type [Symbol] The type of resource (e.g. `:file` or `:package`)
# @param name [String] The name of the resource (e.g. '/x/y.txt' or 'apache2')
# @param created_at [String] The caller of the resource. Use `caller[0]`
# to get the caller of your function. Defaults to the caller of this
# function.
# @param run_context [Chef::RunContext] the run_context of the resource collection to operate on
# @param resource_attrs_block A block that lets you set attributes of the
# resource (it is instance_eval'd on the resource instance).
#
# @return [Chef::Resource] The updated or created resource
#
# @example
# resource = edit_resource(:template, '/x/y.txy') do
# source "y.txy.erb"
# variables {}
# end
# resource.variables.merge!({ home: "/home/klowns" })
#
def edit_resource(type, name, created_at = nil, run_context: self.run_context, &resource_attrs_block)
edit_resource!(type, name, created_at, run_context: run_context, &resource_attrs_block)
rescue Chef::Exceptions::ResourceNotFound
declare_resource(type, name, created_at, run_context: run_context, &resource_attrs_block)
end
# Lookup a resource in the resource collection by name. If the resource is not
# found this will raise Chef::Exceptions::ResourceNotFound. This API is identical to the
# resources() call and while it is a synonym it is not intended to deprecate that call.
#
# @param type [Symbol] The type of resource (e.g. `:file` or `:package`)
# @param name [String] The name of the resource (e.g. '/x/y.txt' or 'apache2')
# @param run_context [Chef::RunContext] the run_context of the resource collection to operate on
#
# @return [Chef::Resource] The updated resource
#
# @example
# resource = find_resource!(:template, '/x/y.txy')
#
def find_resource!(type, name, run_context: self.run_context)
raise ArgumentError, "find_resource! does not take a block" if block_given?
run_context.resource_collection.find(type => name)
end
# Lookup a resource in the resource collection by name. If the resource is not found
# the will be no exception raised and the call will return nil. If a block is given and
# no resource is found it will create the resource using the block, if the resource is
# found then the block will not be applied. The block version is similar to create_if_missing
#
# @param type [Symbol] The type of resource (e.g. `:file` or `:package`)
# @param name [String] The name of the resource (e.g. '/x/y.txt' or 'apache2')
# @param run_context [Chef::RunContext] the run_context of the resource collection to operate on
#
# @return [Chef::Resource] The updated resource
#
# @example
# if ( find_resource(:template, '/x/y.txy') )
# # do something
# else
# # don't worry about the error
# end
#
# @example
# # this API can be used to return a resource from an outer run context, and will only create
# # an action :nothing service if one does not already exist.
# resource = with_run_context(:root) do
# find_resource(:service, 'whatever') do
# action :nothing
# end
# end
#
def find_resource(type, name, created_at: nil, run_context: self.run_context, &resource_attrs_block)
find_resource!(type, name, run_context: run_context)
rescue Chef::Exceptions::ResourceNotFound
if resource_attrs_block
declare_resource(type, name, created_at, run_context: run_context, &resource_attrs_block)
end # returns nil otherwise
end
# Instantiates a resource (via #build_resource), then adds it to the
# resource collection. Note that resource classes are looked up directly,
# so this will create the resource you intended even if the method name
# corresponding to that resource has been overridden.
#
# @param type [Symbol] The type of resource (e.g. `:file` or `:package`)
# @param name [String] The name of the resource (e.g. '/x/y.txt' or 'apache2')
# @param created_at [String] The caller of the resource. Use `caller[0]`
# to get the caller of your function. Defaults to the caller of this
# function.
# @param run_context [Chef::RunContext] the run_context of the resource collection to operate on
# @param resource_attrs_block A block that lets you set attributes of the
# resource (it is instance_eval'd on the resource instance).
#
# @return [Chef::Resource] The new resource.
#
# @example
# declare_resource(:file, '/x/y.txy', caller[0]) do
# action :delete
# end
# # Equivalent to
# file '/x/y.txt' do
# action :delete
# end
#
def declare_resource(type, name, created_at = nil, run_context: self.run_context, create_if_missing: false, &resource_attrs_block)
created_at ||= caller[0]
if create_if_missing
Chef::Log.deprecation "build_resource with a create_if_missing flag is deprecated, use edit_resource instead"
# midly goofy since we call edit_resource only to re-call ourselves, but that's why its deprecated...
return edit_resource(type, name, created_at, run_context: run_context, &resource_attrs_block)
end
resource = build_resource(type, name, created_at, &resource_attrs_block)
run_context.resource_collection.insert(resource, resource_type: type, instance_name: name)
resource
end
# Instantiate a resource of the given +type+ with the given +name+ and
# attributes as given in the +resource_attrs_block+.
#
# The resource is NOT added to the resource collection.
#
# @param type [Symbol] The type of resource (e.g. `:file` or `:package`)
# @param name [String] The name of the resource (e.g. '/x/y.txt' or 'apache2')
# @param created_at [String] The caller of the resource. Use `caller[0]`
# to get the caller of your function. Defaults to the caller of this
# function.
# @param run_context [Chef::RunContext] the run_context of the resource collection to operate on
# @param resource_attrs_block A block that lets you set attributes of the
# resource (it is instance_eval'd on the resource instance).
#
# @return [Chef::Resource] The new resource.
#
# @example
# build_resource(:file, '/x/y.txy', caller[0]) do
# action :delete
# end
#
def build_resource(type, name, created_at = nil, run_context: self.run_context, &resource_attrs_block)
created_at ||= caller[0]
# this needs to be lazy in order to avoid circular dependencies since ResourceBuilder
# will requires the entire provider+resolver universe
require "chef_compat/copied_from_chef/chef/resource_builder" unless defined?(Chef::ResourceBuilder)
Chef::ResourceBuilder.new(
type: type,
name: name,
created_at: created_at,
params: @params,
run_context: run_context,
cookbook_name: cookbook_name,
recipe_name: recipe_name,
enclosing_provider: self.is_a?(Chef::Provider) ? self : nil
).build(&resource_attrs_block)
end
end
end
end
end
end
end

View File

@@ -0,0 +1,292 @@
#
# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE
#
# THIS IS A FILE AUTOGENERATED BY 'rake update' DO NOT EDIT!!!!
#
# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE
#
begin
require 'chef/dsl/platform_introspection'
rescue LoadError; end
require 'chef_compat/copied_from_chef'
class Chef
module ::ChefCompat
module CopiedFromChef
#
# Author:: Adam Jacob (<adam@chef.io>)
# Copyright:: Copyright 2008-2016, 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 < (defined?(::Chef) ? ::Chef : Object)
module DSL
CopiedFromChef.extend_chef_module(::Chef::DSL, self) if defined?(::Chef::DSL)
# == Chef::DSL::PlatformIntrospection
# Provides the DSL for platform-dependent switch logic, such as
# #value_for_platform.
module PlatformIntrospection
CopiedFromChef.extend_chef_module(::Chef::DSL::PlatformIntrospection, self) if defined?(::Chef::DSL::PlatformIntrospection)
# Implementation class for determining platform dependent values
class PlatformDependentValue < (defined?(::Chef::DSL::PlatformIntrospection::PlatformDependentValue) ? ::Chef::DSL::PlatformIntrospection::PlatformDependentValue : Object)
# Create a platform dependent value object.
# === Arguments
# platform_hash (Hash) a hash of the same structure as Chef::Platform,
# like this:
# {
# :debian => {:default => 'the value for all debian'}
# [:centos, :redhat, :fedora] => {:default => "value for all EL variants"}
# :ubuntu => { :default => "default for ubuntu", '10.04' => "value for 10.04 only"},
# :default => "the default when nothing else matches"
# }
# * platforms can be specified as Symbols or Strings
# * multiple platforms can be grouped by using an Array as the key
# * values for platforms need to be Hashes of the form:
# {platform_version => value_for_that_version}
# * the exception to the above is the default value, which is given as
# :default => default_value
def initialize(platform_hash)
super if defined?(::Chef::DSL::PlatformIntrospection::PlatformDependentValue)
@values = {}
platform_hash.each { |platforms, value| set(platforms, value) }
end
def value_for_node(node)
platform, version = node[:platform].to_s, node[:platform_version].to_s
# Check if we match a version constraint via Chef::VersionConstraint::Platform and Chef::Version::Platform
matched_value = match_versions(node)
if @values.key?(platform) && @values[platform].key?(version)
@values[platform][version]
elsif matched_value
matched_value
elsif @values.key?(platform) && @values[platform].key?("default")
@values[platform]["default"]
elsif @values.key?("default")
@values["default"]
else
nil
end
end
private
def match_versions(node)
begin
platform, version = node[:platform].to_s, node[:platform_version].to_s
return nil unless @values.key?(platform)
node_version = Chef::Version::Platform.new(version)
key_matches = []
keys = @values[platform].keys
keys.each do |k|
begin
if Chef::VersionConstraint::Platform.new(k).include?(node_version)
key_matches << k
end
rescue Chef::Exceptions::InvalidVersionConstraint => e
Chef::Log.debug "Caught InvalidVersionConstraint. This means that a key in value_for_platform cannot be interpreted as a Chef::VersionConstraint::Platform."
Chef::Log.debug(e)
end
end
return @values[platform][version] if key_matches.include?(version)
case key_matches.length
when 0
return nil
when 1
return @values[platform][key_matches.first]
else
raise "Multiple matches detected for #{platform} with values #{@values}. The matches are: #{key_matches}"
end
rescue Chef::Exceptions::InvalidCookbookVersion => e
# Lets not break because someone passes a weird string like 'default' :)
Chef::Log.debug(e)
Chef::Log.debug "InvalidCookbookVersion exceptions are common and expected here: the generic constraint matcher attempted to match something which is not a constraint. Moving on to next version or constraint"
return nil
rescue Chef::Exceptions::InvalidPlatformVersion => e
Chef::Log.debug "Caught InvalidPlatformVersion, this means that Chef::Version::Platform does not know how to turn #{node_version} into an x.y.z format"
Chef::Log.debug(e)
return nil
end
end
def set(platforms, value)
if platforms.to_s == "default"
@values["default"] = value
else
assert_valid_platform_values!(platforms, value)
Array(platforms).each { |platform| @values[platform.to_s] = normalize_keys(value) }
value
end
end
def normalize_keys(hash)
hash.inject({}) do |h, key_value|
keys, value = *key_value
Array(keys).each do |key|
h[key.to_s] = value
end
h
end
end
def assert_valid_platform_values!(platforms, value)
unless value.kind_of?(Hash)
msg = "platform dependent values must be specified in the format :platform => {:version => value} "
msg << "you gave a value #{value.inspect} for platform(s) #{platforms}"
raise ArgumentError, msg
end
end
end
# Given a hash similar to the one we use for Platforms, select a value from the hash. Supports
# per platform defaults, along with a single base default. Arrays may be passed as hash keys and
# will be expanded.
#
# === Parameters
# platform_hash:: A platform-style hash.
#
# === Returns
# value:: Whatever the most specific value of the hash is.
def value_for_platform(platform_hash)
PlatformDependentValue.new(platform_hash).value_for_node(node)
end
# Given a list of platforms, returns true if the current recipe is being run on a node with
# that platform, false otherwise.
#
# === Parameters
# args:: A list of platforms. Each platform can be in string or symbol format.
#
# === Returns
# true:: If the current platform is in the list
# false:: If the current platform is not in the list
def platform?(*args)
has_platform = false
args.flatten.each do |platform|
has_platform = true if platform.to_s == node[:platform]
end
has_platform
end
# Implementation class for determining platform family dependent values
class PlatformFamilyDependentValue < (defined?(::Chef::DSL::PlatformIntrospection::PlatformFamilyDependentValue) ? ::Chef::DSL::PlatformIntrospection::PlatformFamilyDependentValue : Object)
# Create a platform family dependent value object.
# === Arguments
# platform_family_hash (Hash) a map of platform families to values.
# like this:
# {
# :rhel => "value for all EL variants"
# :fedora => "value for fedora variants fedora and amazon" ,
# [:fedora, :rhel] => "value for all known redhat variants"
# :debian => "value for debian variants including debian, ubuntu, mint" ,
# :default => "the default when nothing else matches"
# }
# * platform families can be specified as Symbols or Strings
# * multiple platform families can be grouped by using an Array as the key
# * values for platform families can be any object, with no restrictions. Some examples:
# - [:stop, :start]
# - "mysql-devel"
# - { :key => "value" }
def initialize(platform_family_hash)
super if defined?(::Chef::DSL::PlatformIntrospection::PlatformFamilyDependentValue)
@values = {}
@values["default"] = nil
platform_family_hash.each { |platform_families, value| set(platform_families, value) }
end
def value_for_node(node)
if node.key?(:platform_family)
platform_family = node[:platform_family].to_s
if @values.key?(platform_family)
@values[platform_family]
else
@values["default"]
end
else
@values["default"]
end
end
private
def set(platform_family, value)
if platform_family.to_s == "default"
@values["default"] = value
else
Array(platform_family).each { |family| @values[family.to_s] = value }
value
end
end
end
# Given a hash mapping platform families to values, select a value from the hash. Supports a single
# base default if platform family is not in the map. Arrays may be passed as hash keys and will be
# expanded
#
# === Parameters
# platform_family_hash:: A hash in the form { platform_family_name => value }
#
# === Returns
# value:: Whatever the most specific value of the hash is.
def value_for_platform_family(platform_family_hash)
PlatformFamilyDependentValue.new(platform_family_hash).value_for_node(node)
end
# Given a list of platform families, returns true if the current recipe is being run on a
# node within that platform family, false otherwise.
#
# === Parameters
# args:: A list of platform families. Each platform family can be in string or symbol format.
#
# === Returns
# true:: if the current node platform family is in the list.
# false:: if the current node platform family is not in the list.
def platform_family?(*args)
args.flatten.any? do |platform_family|
platform_family.to_s == node[:platform_family]
end
end
# Shamelessly stolen from https://github.com/sethvargo/chef-sugar/blob/master/lib/chef/sugar/docker.rb
# Given a node object, returns whether the node is a docker container.
#
# === Parameters
# node:: [Chef::Node] The node to check.
#
# === Returns
# true:: if the current node is a docker container
# false:: if the current node is not a docker container
def docker?(node = run_context.nil? ? nil : run_context.node)
# Using "File.exist?('/.dockerinit') || File.exist?('/.dockerenv')" makes Travis sad,
# and that makes us sad too.
node && node[:virtualization] && node[:virtualization][:systems] &&
node[:virtualization][:systems][:docker] && node[:virtualization][:systems][:docker] == "guest"
end
end
end
end
# **DEPRECATED**
# This used to be part of chef/mixin/language. Load the file to activate the deprecation code.
end
end
end

View File

@@ -0,0 +1,37 @@
#
# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE
#
# THIS IS A FILE AUTOGENERATED BY 'rake update' DO NOT EDIT!!!!
#
# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE
#
begin
require 'chef/dsl/recipe'
rescue LoadError; end
require 'chef_compat/copied_from_chef'
class Chef
module ::ChefCompat
module CopiedFromChef
require "chef_compat/copied_from_chef/chef/dsl/core"
require "chef_compat/copied_from_chef/chef/mixin/lazy_module_include"
class Chef < (defined?(::Chef) ? ::Chef : Object)
module DSL
CopiedFromChef.extend_chef_module(::Chef::DSL, self) if defined?(::Chef::DSL)
module Recipe
CopiedFromChef.extend_chef_module(::Chef::DSL::Recipe, self) if defined?(::Chef::DSL::Recipe)
include Chef::DSL::Core
extend Chef::Mixin::LazyModuleInclude
module FullDSL
CopiedFromChef.extend_chef_module(::Chef::DSL::Recipe::FullDSL, self) if defined?(::Chef::DSL::Recipe::FullDSL)
include Chef::DSL::Recipe
extend Chef::Mixin::LazyModuleInclude
end
end
end
end
require "chef_compat/copied_from_chef/chef/resource"
end
end
end

View File

@@ -0,0 +1,70 @@
#
# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE
#
# THIS IS A FILE AUTOGENERATED BY 'rake update' DO NOT EDIT!!!!
#
# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE
#
begin
require 'chef/dsl/universal'
rescue LoadError; end
require 'chef_compat/copied_from_chef'
class Chef
module ::ChefCompat
module CopiedFromChef
#--
# Author:: Adam Jacob (<adam@chef.io>)
# Author:: Christopher Walters (<cw@chef.io>)
# Copyright:: Copyright 2008-2016 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 "chef_compat/copied_from_chef/chef/dsl/platform_introspection"
require "chef_compat/copied_from_chef/chef/mixin/powershell_out"
class Chef < (defined?(::Chef) ? ::Chef : Object)
module DSL
CopiedFromChef.extend_chef_module(::Chef::DSL, self) if defined?(::Chef::DSL)
# Part of a family of DSL mixins.
#
# Chef::DSL::Recipe mixes into Recipes and LWRP Providers.
# - this does not target core chef resources and providers.
# - this is restricted to recipe/resource/provider context where a resource collection exists.
# - cookbook authors should typically include modules into here.
#
# Chef::DSL::Core mixes into Recipes, LWRP Providers and Core Providers
# - this adds cores providers on top of the Recipe DSL.
# - this is restricted to recipe/resource/provider context where a resource collection exists.
# - core chef authors should typically include modules into here.
#
# Chef::DSL::Universal mixes into Recipes, LWRP Resources+Providers, Core Resources+Providers, and Attributes files.
# - this adds resources and attributes files.
# - do not add helpers which manipulate the resource collection.
# - this is for general-purpose stuff that is useful nearly everywhere.
# - it also pollutes the namespace of nearly every context, watch out.
#
module Universal
CopiedFromChef.extend_chef_module(::Chef::DSL::Universal, self) if defined?(::Chef::DSL::Universal)
include Chef::DSL::PlatformIntrospection
include Chef::Mixin::PowershellOut
include Chef::Mixin::ShellOut
end
end
end
end
end
end

View File

@@ -0,0 +1,98 @@
#
# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE
#
# THIS IS A FILE AUTOGENERATED BY 'rake update' DO NOT EDIT!!!!
#
# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE
#
begin
require 'chef/mixin/lazy_module_include'
rescue LoadError; end
require 'chef_compat/copied_from_chef'
class Chef
module ::ChefCompat
module CopiedFromChef
#
# Copyright:: Copyright 2011-2016, 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 < (defined?(::Chef) ? ::Chef : Object)
module Mixin
CopiedFromChef.extend_chef_module(::Chef::Mixin, self) if defined?(::Chef::Mixin)
# If you have:
#
# module A
# extend LazyModuleInclude
# end
#
# module B
# include A
# end
#
# module C
# include B
# end
#
# module Monkeypatches
# def monkey
# puts "monkey!"
# end
# end
#
# A.send(:include, Monkeypatches)
#
# Then B and C and any classes that they're included in will also get the #monkey method patched into them.
#
module LazyModuleInclude
CopiedFromChef.extend_chef_module(::Chef::Mixin::LazyModuleInclude, self) if defined?(::Chef::Mixin::LazyModuleInclude)
# Most of the magick is in this hook which creates a closure over the parent class and then builds an
# "infector" module which infects all descendants and which is responsible for updating the list of
# descendants in the parent class.
def included(klass)
super
parent_klass = self
infector = Module.new do
define_method(:included) do |subklass|
super(subklass)
subklass.extend(infector)
parent_klass.descendants.push(subklass)
end
end
klass.extend(infector)
parent_klass.descendants.push(klass)
end
def descendants
@descendants ||= []
end
def include(*classes)
super
classes.each do |klass|
descendants.each do |descendant|
descendant.send(:include, klass)
end
end
end
end
end
end
end
end
end

View File

@@ -0,0 +1,74 @@
#
# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE
#
# THIS IS A FILE AUTOGENERATED BY 'rake update' DO NOT EDIT!!!!
#
# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE
#
begin
require 'chef/mixin/notifying_block'
rescue LoadError; end
require 'chef_compat/copied_from_chef'
class Chef
module ::ChefCompat
module CopiedFromChef
#--
# Author:: Lamont Granquist <lamont@chef.io>
# Copyright:: Copyright 2010-2016, 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 < (defined?(::Chef) ? ::Chef : Object)
module Mixin
CopiedFromChef.extend_chef_module(::Chef::Mixin, self) if defined?(::Chef::Mixin)
module NotifyingBlock
CopiedFromChef.extend_chef_module(::Chef::Mixin::NotifyingBlock, self) if defined?(::Chef::Mixin::NotifyingBlock)
def notifying_block(&block)
begin
subcontext = subcontext_block(&block)
Chef::Runner.new(subcontext).converge
ensure
# recipes don't have a new_resource
if respond_to?(:new_resource)
if subcontext && subcontext.resource_collection.any?(&:updated?)
new_resource.updated_by_last_action(true)
end
end
end
end
def subcontext_block(parent_context = nil, &block)
parent_context ||= @run_context
sub_run_context = parent_context.create_child
begin
outer_run_context = @run_context
@run_context = sub_run_context
instance_eval(&block)
ensure
@run_context = outer_run_context
end
sub_run_context
end
end
end
end
end
end
end

View File

@@ -0,0 +1,510 @@
#
# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE
#
# THIS IS A FILE AUTOGENERATED BY 'rake update' DO NOT EDIT!!!!
#
# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE
#
begin
require 'chef/mixin/params_validate'
rescue LoadError; end
require 'chef_compat/copied_from_chef'
class Chef
module ::ChefCompat
module CopiedFromChef
#
# Author:: Adam Jacob (<adam@chef.io>)
# Copyright:: Copyright 2008-2016, 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 "chef_compat/copied_from_chef/chef/constants"
require "chef_compat/copied_from_chef/chef/property"
require "chef_compat/copied_from_chef/chef/delayed_evaluator"
class Chef < (defined?(::Chef) ? ::Chef : Object)
module Mixin
CopiedFromChef.extend_chef_module(::Chef::Mixin, self) if defined?(::Chef::Mixin)
module ParamsValidate
CopiedFromChef.extend_chef_module(::Chef::Mixin::ParamsValidate, self) if defined?(::Chef::Mixin::ParamsValidate)
# Takes a hash of options, along with a map to validate them. Returns the original
# options hash, plus any changes that might have been made (through things like setting
# default values in the validation map)
#
# For example:
#
# validate({ :one => "neat" }, { :one => { :kind_of => String }})
#
# Would raise an exception if the value of :one above is not a kind_of? string. Valid
# map options are:
#
# @param opts [Hash<Symbol,Object>] Validation opts.
# @option opts [Object,Array] :is An object, or list of
# objects, that must match the value using Ruby's `===` operator
# (`opts[:is].any? { |v| v === value }`). (See #_pv_is.)
# @option opts [Object,Array] :equal_to An object, or list
# of objects, that must be equal to the value using Ruby's `==`
# operator (`opts[:is].any? { |v| v == value }`) (See #_pv_equal_to.)
# @option opts [Regexp,Array<Regexp>] :regex An object, or
# list of objects, that must match the value with `regex.match(value)`.
# (See #_pv_regex)
# @option opts [Class,Array<Class>] :kind_of A class, or
# list of classes, that the value must be an instance of. (See
# #_pv_kind_of.)
# @option opts [Hash<String,Proc>] :callbacks A hash of
# messages -> procs, all of which match the value. The proc must
# return a truthy or falsey value (true means it matches). (See
# #_pv_callbacks.)
# @option opts [Symbol,Array<Symbol>] :respond_to A method
# name, or list of method names, the value must respond to. (See
# #_pv_respond_to.)
# @option opts [Symbol,Array<Symbol>] :cannot_be A property,
# or a list of properties, that the value cannot have (such as `:nil` or
# `:empty`). The method with a questionmark at the end is called on the
# value (e.g. `value.empty?`). If the value does not have this method,
# it is considered valid (i.e. if you don't respond to `empty?` we
# assume you are not empty). (See #_pv_cannot_be.)
# @option opts [Proc] :coerce A proc which will be called to
# transform the user input to canonical form. The value is passed in,
# and the transformed value returned as output. Lazy values will *not*
# be passed to this method until after they are evaluated. Called in the
# context of the resource (meaning you can access other properties).
# (See #_pv_coerce.) (See #_pv_coerce.)
# @option opts [Boolean] :required `true` if this property
# must be present and not `nil`; `false` otherwise. This is checked
# after the resource is fully initialized. (See #_pv_required.)
# @option opts [Boolean] :name_property `true` if this
# property defaults to the same value as `name`. Equivalent to
# `default: lazy { name }`, except that #property_is_set? will
# return `true` if the property is set *or* if `name` is set. (See
# #_pv_name_property.)
# @option opts [Boolean] :name_attribute Same as `name_property`.
# @option opts [Object] :default The value this property
# will return if the user does not set one. If this is `lazy`, it will
# be run in the context of the instance (and able to access other
# properties). (See #_pv_default.)
#
def validate(opts, map)
map = map.validation_options if map.is_a?(Property)
#--
# validate works by taking the keys in the validation map, assuming it's a hash, and
# looking for _pv_:symbol as methods. Assuming it find them, it calls the right
# one.
#++
raise ArgumentError, "Options must be a hash" unless opts.kind_of?(Hash)
raise ArgumentError, "Validation Map must be a hash" unless map.kind_of?(Hash)
map.each do |key, validation|
unless key.kind_of?(Symbol) || key.kind_of?(String)
raise ArgumentError, "Validation map keys must be symbols or strings!"
end
case validation
when true
_pv_required(opts, key)
when false
true
when Hash
validation.each do |check, carg|
check_method = "_pv_#{check}"
if self.respond_to?(check_method, true)
self.send(check_method, opts, key, carg)
else
raise ArgumentError, "Validation map has unknown check: #{check}"
end
end
end
end
opts
end
def lazy(&block)
DelayedEvaluator.new(&block)
end
def set_or_return(symbol, value, validation)
property = SetOrReturnProperty.new(name: symbol, **validation)
property.call(self, value)
end
private
def explicitly_allows_nil?(key, validation)
validation.has_key?(:is) && _pv_is({ key => nil }, key, validation[:is], raise_error: false)
end
# Return the value of a parameter, or nil if it doesn't exist.
def _pv_opts_lookup(opts, key)
if opts.has_key?(key.to_s)
opts[key.to_s]
elsif opts.has_key?(key.to_sym)
opts[key.to_sym]
else
nil
end
end
# Raise an exception if the parameter is not found.
def _pv_required(opts, key, is_required = true, explicitly_allows_nil = false)
if is_required
return true if opts.has_key?(key.to_s) && (explicitly_allows_nil || !opts[key.to_s].nil?)
return true if opts.has_key?(key.to_sym) && (explicitly_allows_nil || !opts[key.to_sym].nil?)
raise Exceptions::ValidationFailed, "Required argument #{key.inspect} is missing!"
end
true
end
#
# List of things values must be equal to.
#
# Uses Ruby's `==` to evaluate (equal_to == value). At least one must
# match for the value to be valid.
#
# `nil` passes this validation automatically.
#
# @return [Array,nil] List of things values must be equal to, or nil if
# equal_to is unspecified.
#
def _pv_equal_to(opts, key, to_be)
value = _pv_opts_lookup(opts, key)
unless value.nil?
to_be = Array(to_be)
to_be.each do |tb|
return true if value == tb
end
raise Exceptions::ValidationFailed, "Option #{key} must be equal to one of: #{to_be.join(", ")}! You passed #{value.inspect}."
end
end
#
# List of things values must be instances of.
#
# Uses value.kind_of?(kind_of) to evaluate. At least one must match for
# the value to be valid.
#
# `nil` automatically passes this validation.
#
def _pv_kind_of(opts, key, to_be)
value = _pv_opts_lookup(opts, key)
unless value.nil?
to_be = Array(to_be)
to_be.each do |tb|
return true if value.kind_of?(tb)
end
raise Exceptions::ValidationFailed, "Option #{key} must be a kind of #{to_be}! You passed #{value.inspect}."
end
end
#
# List of method names values must respond to.
#
# Uses value.respond_to?(respond_to) to evaluate. At least one must match
# for the value to be valid.
#
def _pv_respond_to(opts, key, method_name_list)
value = _pv_opts_lookup(opts, key)
unless value.nil?
Array(method_name_list).each do |method_name|
unless value.respond_to?(method_name)
raise Exceptions::ValidationFailed, "Option #{key} must have a #{method_name} method!"
end
end
end
end
#
# List of things that must not be true about the value.
#
# Calls `value.<thing>?` All responses must be false for the value to be
# valid.
# Values which do not respond to <thing>? are considered valid (because if
# a value doesn't respond to `:readable?`, then it probably isn't
# readable.)
#
# @example
# ```ruby
# property :x, cannot_be: [ :nil, :empty ]
# x [ 1, 2 ] #=> valid
# x 1 #=> valid
# x [] #=> invalid
# x nil #=> invalid
# ```
#
def _pv_cannot_be(opts, key, predicate_method_base_name)
value = _pv_opts_lookup(opts, key)
if !value.nil?
Array(predicate_method_base_name).each do |method_name|
predicate_method = :"#{method_name}?"
if value.respond_to?(predicate_method)
if value.send(predicate_method)
raise Exceptions::ValidationFailed, "Option #{key} cannot be #{predicate_method_base_name}"
end
end
end
end
end
#
# The default value for a property.
#
# When the property is not assigned, this will be used.
#
# If this is a lazy value, it will either be passed the resource as a value,
# or if the lazy proc does not take parameters, it will be run in the
# context of the instance with instance_eval.
#
# @example
# ```ruby
# property :x, default: 10
# ```
#
# @example
# ```ruby
# property :x
# property :y, default: lazy { x+2 }
# ```
#
# @example
# ```ruby
# property :x
# property :y, default: lazy { |r| r.x+2 }
# ```
#
def _pv_default(opts, key, default_value)
value = _pv_opts_lookup(opts, key)
if value.nil?
default_value = default_value.freeze if !default_value.is_a?(DelayedEvaluator)
opts[key] = default_value
end
end
#
# List of regexes values that must match.
#
# Uses regex.match() to evaluate. At least one must match for the value to
# be valid.
#
# `nil` passes regex validation automatically.
#
# @example
# ```ruby
# property :x, regex: [ /abc/, /xyz/ ]
# ```
#
def _pv_regex(opts, key, regex)
value = _pv_opts_lookup(opts, key)
if !value.nil?
Array(regex).flatten.each do |r|
return true if r.match(value.to_s)
end
raise Exceptions::ValidationFailed, "Option #{key}'s value #{value} does not match regular expression #{regex.inspect}"
end
end
#
# List of procs we pass the value to.
#
# All procs must return true for the value to be valid. If any procs do
# not return true, the key will be used for the message: `"Property x's
# value :y <message>"`.
#
# @example
# ```ruby
# property :x, callbacks: { "is bigger than 10" => proc { |v| v <= 10 }, "is not awesome" => proc { |v| !v.awesome }}
# ```
#
def _pv_callbacks(opts, key, callbacks)
raise ArgumentError, "Callback list must be a hash!" unless callbacks.kind_of?(Hash)
value = _pv_opts_lookup(opts, key)
if !value.nil?
callbacks.each do |message, zeproc|
unless zeproc.call(value)
raise Exceptions::ValidationFailed, "Option #{key}'s value #{value} #{message}!"
end
end
end
end
#
# Allows a parameter to default to the value of the resource name.
#
# @example
# ```ruby
# property :x, name_property: true
# ```
#
def _pv_name_property(opts, key, is_name_property = true)
if is_name_property
if opts[key].nil?
raise CannotValidateStaticallyError, "name_property cannot be evaluated without a resource." if self == Chef::Mixin::ParamsValidate
opts[key] = self.instance_variable_get(:"@name")
end
end
end
alias :_pv_name_attribute :_pv_name_property
#
# List of valid things values can be.
#
# Uses Ruby's `===` to evaluate (is === value). At least one must match
# for the value to be valid.
#
# If a proc is passed, it is instance_eval'd in the resource, passed the
# value, and must return a truthy or falsey value.
#
# @example Class
# ```ruby
# property :x, String
# x 'valid' #=> valid
# x 1 #=> invalid
# x nil #=> invalid
#
# @example Value
# ```ruby
# property :x, [ :a, :b, :c, nil ]
# x :a #=> valid
# x nil #=> valid
# ```
#
# @example Regex
# ```ruby
# property :x, /bar/
# x 'foobar' #=> valid
# x 'foo' #=> invalid
# x nil #=> invalid
# ```
#
# @example Proc
# ```ruby
# property :x, proc { |x| x > y }
# property :y, default: 2
# x 3 #=> valid
# x 1 #=> invalid
# ```
#
# @example Property
# ```ruby
# type = Property.new(is: String)
# property :x, type
# x 'foo' #=> valid
# x 1 #=> invalid
# x nil #=> invalid
# ```
#
# @example RSpec Matcher
# ```ruby
# include RSpec::Matchers
# property :x, a_string_matching /bar/
# x 'foobar' #=> valid
# x 'foo' #=> invalid
# x nil #=> invalid
# ```
#
def _pv_is(opts, key, to_be, raise_error: true)
return true if !opts.has_key?(key.to_s) && !opts.has_key?(key.to_sym)
value = _pv_opts_lookup(opts, key)
to_be = [ to_be ].flatten(1)
errors = []
passed = to_be.any? do |tb|
case tb
when Proc
raise CannotValidateStaticallyError, "is: proc { } must be evaluated once for each resource" if self == Chef::Mixin::ParamsValidate
instance_exec(value, &tb)
when Property
begin
validate(opts, { key => tb.validation_options })
true
rescue Exceptions::ValidationFailed
# re-raise immediately if there is only one "is" so we get a better stack
raise if to_be.size == 1
errors << $!
false
end
else
tb === value
end
end
if passed
true
else
message = "Property #{key} must be one of: #{to_be.map { |v| v.inspect }.join(", ")}! You passed #{value.inspect}."
unless errors.empty?
message << " Errors:\n#{errors.map { |m| "- #{m}" }.join("\n")}"
end
raise Exceptions::ValidationFailed, message
end
end
#
# Method to mess with a value before it is validated and stored.
#
# Allows you to transform values into a canonical form that is easy to
# work with.
#
# This is passed the value to transform, and is run in the context of the
# instance (so it has access to other resource properties). It must return
# the value that will be stored in the instance.
#
# @example
# ```ruby
# property :x, Integer, coerce: { |v| v.to_i }
# ```
#
def _pv_coerce(opts, key, coercer)
if opts.has_key?(key.to_s)
raise CannotValidateStaticallyError, "coerce must be evaluated for each resource." if self == Chef::Mixin::ParamsValidate
opts[key.to_s] = instance_exec(opts[key], &coercer)
elsif opts.has_key?(key.to_sym)
raise CannotValidateStaticallyError, "coerce must be evaluated for each resource." if self == Chef::Mixin::ParamsValidate
opts[key.to_sym] = instance_exec(opts[key], &coercer)
end
end
# We allow Chef::Mixin::ParamsValidate.validate(), but we will raise an
# error if you try to do anything requiring there to be an actual resource.
# This way, you can statically validate things if you have constant validation
# (which is the norm).
extend self
# Used by #set_or_return to avoid emitting a deprecation warning for
# "value nil" and to keep default stickiness working exactly the same
# @api private
class SetOrReturnProperty < (defined?(::Chef::Mixin::ParamsValidate::SetOrReturnProperty) ? ::Chef::Mixin::ParamsValidate::SetOrReturnProperty : Chef::Property)
def get(resource, nil_set: false)
value = super
# All values are sticky, frozen or not
if !is_set?(resource)
set_value(resource, value)
end
value
end
def call(resource, value = NOT_PASSED)
# setting to nil does a get
if value.nil? && !explicitly_accepts_nil?(resource)
get(resource, nil_set: true)
else
super
end
end
end
end
end
end
end
end
end

View File

@@ -0,0 +1,117 @@
#
# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE
#
# THIS IS A FILE AUTOGENERATED BY 'rake update' DO NOT EDIT!!!!
#
# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE
#
begin
require 'chef/mixin/powershell_out'
rescue LoadError; end
require 'chef_compat/copied_from_chef'
class Chef
module ::ChefCompat
module CopiedFromChef
#--
# Copyright:: Copyright 2015-2016, 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 < (defined?(::Chef) ? ::Chef : Object)
module Mixin
CopiedFromChef.extend_chef_module(::Chef::Mixin, self) if defined?(::Chef::Mixin)
module PowershellOut
CopiedFromChef.extend_chef_module(::Chef::Mixin::PowershellOut, self) if defined?(::Chef::Mixin::PowershellOut)
include Chef::Mixin::ShellOut
include Chef::Mixin::WindowsArchitectureHelper
# Run a command under powershell with the same API as shell_out. The
# options hash is extended to take an "architecture" flag which
# can be set to :i386 or :x86_64 to force the windows architecture.
#
# @param script [String] script to run
# @param options [Hash] options hash
# @return [Mixlib::Shellout] mixlib-shellout object
def powershell_out(*command_args)
script = command_args.first
options = command_args.last.is_a?(Hash) ? command_args.last : nil
run_command_with_os_architecture(script, options)
end
# Run a command under powershell with the same API as shell_out!
# (raises exceptions on errors)
#
# @param script [String] script to run
# @param options [Hash] options hash
# @return [Mixlib::Shellout] mixlib-shellout object
def powershell_out!(*command_args)
cmd = powershell_out(*command_args)
cmd.error!
cmd
end
private
# Helper function to run shell_out and wrap it with the correct
# flags to possibly disable WOW64 redirection (which we often need
# because chef-client runs as a 32-bit app on 64-bit windows).
#
# @param script [String] script to run
# @param options [Hash] options hash
# @return [Mixlib::Shellout] mixlib-shellout object
def run_command_with_os_architecture(script, options)
options ||= {}
options = options.dup
arch = options.delete(:architecture)
with_os_architecture(nil, architecture: arch) do
shell_out(
build_powershell_command(script),
options
)
end
end
# Helper to build a powershell command around the script to run.
#
# @param script [String] script to run
# @retrurn [String] powershell command to execute
def build_powershell_command(script)
flags = [
# Hides the copyright banner at startup.
"-NoLogo",
# Does not present an interactive prompt to the user.
"-NonInteractive",
# Does not load the Windows PowerShell profile.
"-NoProfile",
# always set the ExecutionPolicy flag
# see http://technet.microsoft.com/en-us/library/ee176961.aspx
"-ExecutionPolicy Unrestricted",
# Powershell will hang if STDIN is redirected
# http://connect.microsoft.com/PowerShell/feedback/details/572313/powershell-exe-can-hang-if-stdin-is-redirected
"-InputFormat None",
]
"powershell.exe #{flags.join(' ')} -Command \"#{script.gsub('"', '\"')}\""
end
end
end
end
end
end
end

View File

@@ -0,0 +1,328 @@
#
# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE
#
# THIS IS A FILE AUTOGENERATED BY 'rake update' DO NOT EDIT!!!!
#
# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE
#
begin
require 'chef/mixin/properties'
rescue LoadError; end
require 'chef_compat/copied_from_chef'
class Chef
module ::ChefCompat
module CopiedFromChef
require "chef_compat/copied_from_chef/chef/delayed_evaluator"
require "chef_compat/copied_from_chef/chef/mixin/params_validate"
require "chef_compat/copied_from_chef/chef/property"
class Chef < (defined?(::Chef) ? ::Chef : Object)
module Mixin
CopiedFromChef.extend_chef_module(::Chef::Mixin, self) if defined?(::Chef::Mixin)
module Properties
CopiedFromChef.extend_chef_module(::Chef::Mixin::Properties, self) if defined?(::Chef::Mixin::Properties)
module ClassMethods
CopiedFromChef.extend_chef_module(::Chef::Mixin::Properties::ClassMethods, self) if defined?(::Chef::Mixin::Properties::ClassMethods)
#
# The list of properties defined on this resource.
#
# Everything defined with `property` is in this list.
#
# @param include_superclass [Boolean] `true` to include properties defined
# on superclasses; `false` or `nil` to return the list of properties
# directly on this class.
#
# @return [Hash<Symbol,Property>] The list of property names and types.
#
def properties(include_superclass = true)
if include_superclass
result = {}
ancestors.reverse_each { |c| result.merge!(c.properties(false)) if c.respond_to?(:properties) }
result
else
@properties ||= {}
end
end
#
# Create a property on this resource class.
#
# If a superclass has this property, or if this property has already been
# defined by this resource, this will *override* the previous value.
#
# @param name [Symbol] The name of the property.
# @param type [Object,Array<Object>] The type(s) of this property.
# If present, this is prepended to the `is` validation option.
# @param options [Hash<Symbol,Object>] Validation options.
# @option options [Object,Array] :is An object, or list of
# objects, that must match the value using Ruby's `===` operator
# (`options[:is].any? { |v| v === value }`).
# @option options [Object,Array] :equal_to An object, or list
# of objects, that must be equal to the value using Ruby's `==`
# operator (`options[:is].any? { |v| v == value }`)
# @option options [Regexp,Array<Regexp>] :regex An object, or
# list of objects, that must match the value with `regex.match(value)`.
# @option options [Class,Array<Class>] :kind_of A class, or
# list of classes, that the value must be an instance of.
# @option options [Hash<String,Proc>] :callbacks A hash of
# messages -> procs, all of which match the value. The proc must
# return a truthy or falsey value (true means it matches).
# @option options [Symbol,Array<Symbol>] :respond_to A method
# name, or list of method names, the value must respond to.
# @option options [Symbol,Array<Symbol>] :cannot_be A property,
# or a list of properties, that the value cannot have (such as `:nil` or
# `:empty`). The method with a questionmark at the end is called on the
# value (e.g. `value.empty?`). If the value does not have this method,
# it is considered valid (i.e. if you don't respond to `empty?` we
# assume you are not empty).
# @option options [Proc] :coerce A proc which will be called to
# transform the user input to canonical form. The value is passed in,
# and the transformed value returned as output. Lazy values will *not*
# be passed to this method until after they are evaluated. Called in the
# context of the resource (meaning you can access other properties).
# @option options [Boolean] :required `true` if this property
# must be present; `false` otherwise. This is checked after the resource
# is fully initialized.
# @option options [Boolean] :name_property `true` if this
# property defaults to the same value as `name`. Equivalent to
# `default: lazy { name }`, except that #property_is_set? will
# return `true` if the property is set *or* if `name` is set.
# @option options [Boolean] :name_attribute Same as `name_property`.
# @option options [Object] :default The value this property
# will return if the user does not set one. If this is `lazy`, it will
# be run in the context of the instance (and able to access other
# properties).
# @option options [Boolean] :desired_state `true` if this property is
# part of desired state. Defaults to `true`.
# @option options [Boolean] :identity `true` if this property
# is part of object identity. Defaults to `false`.
# @option options [Boolean] :sensitive `true` if this property could
# contain sensitive information and whose value should be redacted
# in any resource reporting / auditing output. Defaults to `false`.
#
# @example Bare property
# property :x
#
# @example With just a type
# property :x, String
#
# @example With just options
# property :x, default: 'hi'
#
# @example With type and options
# property :x, String, default: 'hi'
#
def property(name, type = NOT_PASSED, **options)
name = name.to_sym
options = options.inject({}) { |memo, (key, value)| memo[key.to_sym] = value; memo }
options[:instance_variable_name] = :"@#{name}" if !options.has_key?(:instance_variable_name)
options[:name] = name
options[:declared_in] = self
if type == NOT_PASSED
# If a type is not passed, the property derives from the
# superclass property (if any)
if properties.has_key?(name)
property = properties[name].derive(**options)
else
property = property_type(**options)
end
# If a Property is specified, derive a new one from that.
elsif type.is_a?(Property) || (type.is_a?(Class) && type <= Property)
property = type.derive(**options)
# If a primitive type was passed, combine it with "is"
else
if options[:is]
options[:is] = ([ type ] + [ options[:is] ]).flatten(1)
else
options[:is] = type
end
property = property_type(**options)
end
local_properties = properties(false)
local_properties[name] = property
property.emit_dsl
end
#
# Create a reusable property type that can be used in multiple properties
# in different resources.
#
# @param options [Hash<Symbol,Object>] Validation options. see #property for
# the list of options.
#
# @example
# property_type(default: 'hi')
#
def property_type(**options)
Property.derive(**options)
end
#
# Create a lazy value for assignment to a default value.
#
# @param block The block to run when the value is retrieved.
#
# @return [Chef::DelayedEvaluator] The lazy value
#
def lazy(&block)
DelayedEvaluator.new(&block)
end
#
# Get or set the list of desired state properties for this resource.
#
# State properties are properties that describe the desired state
# of the system, such as file permissions or ownership.
# In general, state properties are properties that could be populated by
# examining the state of the system (e.g., File.stat can tell you the
# permissions on an existing file). Contrarily, properties that are not
# "state properties" usually modify the way Chef itself behaves, for example
# by providing additional options for a package manager to use when
# installing a package.
#
# This list is used by the Chef client auditing system to extract
# information from resources to describe changes made to the system.
#
# This method is unnecessary when declaring properties with `property`;
# properties are added to state_properties by default, and can be turned off
# with `desired_state: false`.
#
# ```ruby
# property :x # part of desired state
# property :y, desired_state: false # not part of desired state
# ```
#
# @param names [Array<Symbol>] A list of property names to set as desired
# state.
#
# @return [Array<Property>] All properties in desired state.
#
def state_properties(*names)
if !names.empty?
names = names.map { |name| name.to_sym }.uniq
local_properties = properties(false)
# Add new properties to the list.
names.each do |name|
property = properties[name]
if !property
self.property name, instance_variable_name: false, desired_state: true
elsif !property.desired_state?
self.property name, desired_state: true
end
end
# If state_attrs *excludes* something which is currently desired state,
# mark it as desired_state: false.
local_properties.each do |name, property|
if property.desired_state? && !names.include?(name)
self.property name, desired_state: false
end
end
end
properties.values.select { |property| property.desired_state? }
end
#
# Set the identity of this resource to a particular set of properties.
#
# This drives #identity, which returns data that uniquely refers to a given
# resource on the given node (in such a way that it can be correlated
# across Chef runs).
#
# This method is unnecessary when declaring properties with `property`;
# properties can be added to identity during declaration with
# `identity: true`.
#
# ```ruby
# property :x, identity: true # part of identity
# property :y # not part of identity
# ```
#
# If no properties are marked as identity, "name" is considered the identity.
#
# @param names [Array<Symbol>] A list of property names to set as the identity.
#
# @return [Array<Property>] All identity properties.
#
def identity_properties(*names)
if !names.empty?
names = names.map { |name| name.to_sym }
# Add or change properties that are not part of the identity.
names.each do |name|
property = properties[name]
if !property
self.property name, instance_variable_name: false, identity: true
elsif !property.identity?
self.property name, identity: true
end
end
# If identity_properties *excludes* something which is currently part of
# the identity, mark it as identity: false.
properties.each do |name, property|
if property.identity? && !names.include?(name)
self.property name, identity: false
end
end
end
result = properties.values.select { |property| property.identity? }
result = [ properties[:name] ] if result.empty?
result
end
def included(other)
other.extend ClassMethods
end
end
def self.included(other)
other.extend ClassMethods
end
include Chef::Mixin::ParamsValidate
#
# Whether this property has been set (or whether it has a default that has
# been retrieved).
#
# @param name [Symbol] The name of the property.
# @return [Boolean] `true` if the property has been set.
#
def property_is_set?(name)
property = self.class.properties[name.to_sym]
raise ArgumentError, "Property #{name} is not defined in class #{self}" if !property
property.is_set?(self)
end
#
# Clear this property as if it had never been set. It will thereafter return
# the default.
# been retrieved).
#
# @param name [Symbol] The name of the property.
#
def reset_property(name)
property = self.class.properties[name.to_sym]
raise ArgumentError, "Property #{name} is not defined in class #{self}" if !property
property.reset(self)
end
end
end
end
end
end
end

View File

@@ -0,0 +1,713 @@
#
# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE
#
# THIS IS A FILE AUTOGENERATED BY 'rake update' DO NOT EDIT!!!!
#
# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE
#
begin
require 'chef/property'
rescue LoadError; end
require 'chef_compat/copied_from_chef'
class Chef
module ::ChefCompat
module CopiedFromChef
#
# Author:: John Keiser <jkeiser@chef.io>
# Copyright:: Copyright 2015-2016, John Keiser.
# 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 "chef_compat/copied_from_chef/chef/delayed_evaluator"
class Chef < (defined?(::Chef) ? ::Chef : Object)
#
# Type and validation information for a property on a resource.
#
# A property named "x" manipulates the "@x" instance variable on a
# resource. The *presence* of the variable (`instance_variable_defined?(@x)`)
# tells whether the variable is defined; it may have any actual value,
# constrained only by validation.
#
# Properties may have validation, defaults, and coercion, and have full
# support for lazy values.
#
# @see Chef::Resource.property
# @see Chef::DelayedEvaluator
#
class Property < (defined?(::Chef::Property) ? ::Chef::Property : Object)
#
# Create a reusable property type that can be used in multiple properties
# in different resources.
#
# @param options [Hash<Symbol,Object>] Validation options. See Chef::Resource.property for
# the list of options.
#
# @example
# Property.derive(default: 'hi')
#
def self.derive(**options)
new(**options)
end
#
# Create a new property.
#
# @param options [Hash<Symbol,Object>] Property options, including
# control options here, as well as validation options (see
# Chef::Mixin::ParamsValidate#validate for a description of validation
# options).
# @option options [Symbol] :name The name of this property.
# @option options [Class] :declared_in The class this property comes from.
# @option options [Symbol] :instance_variable_name The instance variable
# tied to this property. Must include a leading `@`. Defaults to `@<name>`.
# `nil` means the property is opaque and not tied to a specific instance
# variable.
# @option options [Boolean] :desired_state `true` if this property is part of desired
# state. Defaults to `true`.
# @option options [Boolean] :identity `true` if this property is part of object
# identity. Defaults to `false`.
# @option options [Boolean] :name_property `true` if this
# property defaults to the same value as `name`. Equivalent to
# `default: lazy { name }`, except that #property_is_set? will
# return `true` if the property is set *or* if `name` is set.
# @option options [Boolean] :nillable `true` opt-in to Chef-13 style behavior where
# attempting to set a nil value will really set a nil value instead of issuing
# a warning and operating like a getter
# @option options [Object] :default The value this property
# will return if the user does not set one. If this is `lazy`, it will
# be run in the context of the instance (and able to access other
# properties) and cached. If not, the value will be frozen with Object#freeze
# to prevent users from modifying it in an instance.
# @option options [Proc] :coerce A proc which will be called to
# transform the user input to canonical form. The value is passed in,
# and the transformed value returned as output. Lazy values will *not*
# be passed to this method until after they are evaluated. Called in the
# context of the resource (meaning you can access other properties).
# @option options [Boolean] :required `true` if this property
# must be present; `false` otherwise. This is checked after the resource
# is fully initialized.
#
def initialize(**options)
super if defined?(::Chef::Property)
options = options.inject({}) { |memo, (key, value)| memo[key.to_sym] = value; memo }
@options = options
options[:name] = options[:name].to_sym if options[:name]
options[:instance_variable_name] = options[:instance_variable_name].to_sym if options[:instance_variable_name]
# Replace name_attribute with name_property
if options.has_key?(:name_attribute)
# If we have both name_attribute and name_property and they differ, raise an error
if options.has_key?(:name_property)
raise ArgumentError, "Cannot specify both name_property and name_attribute together on property #{self}."
end
# replace name_property with name_attribute in place
options = Hash[options.map { |k, v| k == :name_attribute ? [ :name_property, v ] : [ k, v ] }]
@options = options
end
# Only pick the first of :default, :name_property and :name_attribute if
# more than one is specified.
if options.has_key?(:default) && options[:name_property]
if options[:default].nil? || options.keys.index(:name_property) < options.keys.index(:default)
options.delete(:default)
preferred_default = :name_property
else
options.delete(:name_property)
preferred_default = :default
end
Chef.log_deprecation("Cannot specify both default and name_property together on property #{self}. Only one (#{preferred_default}) will be obeyed. In Chef 13, this will become an error. Please remove one or the other from the property.")
end
# Validate the default early, so the user gets a good error message, and
# cache it so we don't do it again if so
begin
# If we can validate it all the way to output, do it.
@stored_default = input_to_stored_value(nil, default, is_default: true)
rescue Chef::Exceptions::CannotValidateStaticallyError
# If the validation is not static (i.e. has procs), we will have to
# coerce and validate the default each time we run
end
end
def to_s
"#{name || "<property type>"}#{declared_in ? " of resource #{declared_in.resource_name}" : ""}"
end
#
# The name of this property.
#
# @return [String]
#
def name
options[:name]
end
#
# The class this property was defined in.
#
# @return [Class]
#
def declared_in
options[:declared_in]
end
#
# The instance variable associated with this property.
#
# Defaults to `@<name>`
#
# @return [Symbol]
#
def instance_variable_name
if options.has_key?(:instance_variable_name)
options[:instance_variable_name]
elsif name
:"@#{name}"
end
end
#
# The raw default value for this resource.
#
# Does not coerce or validate the default. Does not evaluate lazy values.
#
# Defaults to `lazy { name }` if name_property is true; otherwise defaults to
# `nil`
#
def default
return options[:default] if options.has_key?(:default)
return Chef::DelayedEvaluator.new { name } if name_property?
nil
end
#
# Whether this is part of the resource's natural identity or not.
#
# @return [Boolean]
#
def identity?
options[:identity]
end
#
# Whether this is part of desired state or not.
#
# Defaults to true.
#
# @return [Boolean]
#
def desired_state?
return true if !options.has_key?(:desired_state)
options[:desired_state]
end
#
# Whether this is name_property or not.
#
# @return [Boolean]
#
def name_property?
options[:name_property]
end
#
# Whether this property has a default value.
#
# @return [Boolean]
#
def has_default?
options.has_key?(:default) || name_property?
end
#
# Whether this property is required or not.
#
# @return [Boolean]
#
def required?
options[:required]
end
#
# Whether this property is sensitive or not.
#
# Defaults to false.
#
# @return [Boolean]
#
def sensitive?
options.fetch(:sensitive, false)
end
#
# Validation options. (See Chef::Mixin::ParamsValidate#validate.)
#
# @return [Hash<Symbol,Object>]
#
def validation_options
@validation_options ||= options.reject do |k, v|
[:declared_in, :name, :instance_variable_name, :desired_state, :identity, :default, :name_property, :coerce, :required, :nillable, :sensitive].include?(k)
end
end
#
# Handle the property being called.
#
# The base implementation does the property get-or-set:
#
# ```ruby
# resource.myprop # get
# resource.myprop value # set
# ```
#
# Subclasses may implement this with any arguments they want, as long as
# the corresponding DSL calls it correctly.
#
# @param resource [Chef::Resource] The resource to get the property from.
# @param value The value to set (or NOT_PASSED if it is a get).
#
# @return The current value of the property. If it is a `set`, lazy values
# will be returned without running, validating or coercing. If it is a
# `get`, the non-lazy, coerced, validated value will always be returned.
#
def call(resource, value = NOT_PASSED)
if value == NOT_PASSED
return get(resource)
end
if value.nil? && !nillable?
# In Chef 12, value(nil) does a *get* instead of a set, so we
# warn if the value would have been changed. In Chef 13, it will be
# equivalent to value = nil.
result = get(resource, nil_set: true)
# Warn about this becoming a set in Chef 13.
begin
input_to_stored_value(resource, value)
# If nil is valid, and it would change the value, warn that this will change to a set.
if !result.nil?
Chef.log_deprecation("An attempt was made to change #{name} from #{result.inspect} to nil by calling #{name}(nil). In Chef 12, this does a get rather than a set. In Chef 13, this will change to set the value to nil.")
end
rescue Chef::Exceptions::DeprecatedFeatureError
raise
rescue
# If nil is invalid, warn that this will become an error.
Chef.log_deprecation("nil is an invalid value for #{self}. In Chef 13, this warning will change to an error. Error: #{$!}")
end
result
else
# Anything else, such as myprop(value) is a set
set(resource, value)
end
end
#
# Get the property value from the resource, handling lazy values,
# defaults, and validation.
#
# - If the property's value is lazy, it is evaluated, coerced and validated.
# - If the property has no value, and is required, raises ValidationFailed.
# - If the property has no value, but has a lazy default, it is evaluated,
# coerced and validated. If the evaluated value is frozen, the resulting
# - If the property has no value, but has a default, the default value
# will be returned and frozen. If the default value is lazy, it will be
# evaluated, coerced and validated, and the result stored in the property.
# - If the property has no value, but is name_property, `resource.name`
# is retrieved, coerced, validated and stored in the property.
# - Otherwise, `nil` is returned.
#
# @param resource [Chef::Resource] The resource to get the property from.
#
# @return The value of the property.
#
# @raise Chef::Exceptions::ValidationFailed If the value is invalid for
# this property, or if the value is required and not set.
#
def get(resource, nil_set: false)
# If it's set, return it (and evaluate any lazy values)
if is_set?(resource)
value = get_value(resource)
value = stored_value_to_output(resource, value)
else
# We are getting the default value.
# If the user does something like this:
#
# ```
# class MyResource < Chef::Resource
# property :content
# action :create do
# file '/x.txt' do
# content content
# end
# end
# end
# ```
#
# It won't do what they expect. This checks whether you try to *read*
# `content` while we are compiling the resource.
if !nil_set &&
resource.respond_to?(:resource_initializing) &&
resource.resource_initializing &&
resource.respond_to?(:enclosing_provider) &&
resource.enclosing_provider &&
resource.enclosing_provider.new_resource &&
resource.enclosing_provider.new_resource.respond_to?(name)
Chef::Log.warn("#{Chef::Log.caller_location}: property #{name} is declared in both #{resource} and #{resource.enclosing_provider}. Use new_resource.#{name} instead. At #{Chef::Log.caller_location}")
end
if has_default?
# If we were able to cache the stored_default, grab it.
if defined?(@stored_default)
value = @stored_default
else
# Otherwise, we have to validate it now.
value = input_to_stored_value(resource, default, is_default: true)
end
value = stored_value_to_output(resource, value, is_default: true)
# If the value is mutable (non-frozen), we set it on the instance
# so that people can mutate it. (All constant default values are
# frozen.)
if !value.frozen? && !value.nil?
set_value(resource, value)
end
value
elsif required?
raise Chef::Exceptions::ValidationFailed, "#{name} is required"
end
end
end
#
# Set the value of this property in the given resource.
#
# Non-lazy values are coerced and validated before being set. Coercion
# and validation of lazy values is delayed until they are first retrieved.
#
# @param resource [Chef::Resource] The resource to set this property in.
# @param value The value to set.
#
# @return The value that was set, after coercion (if lazy, still returns
# the lazy value)
#
# @raise Chef::Exceptions::ValidationFailed If the value is invalid for
# this property.
#
def set(resource, value)
set_value(resource, input_to_stored_value(resource, value))
end
#
# Find out whether this property has been set.
#
# This will be true if:
# - The user explicitly set the value
# - The property has a default, and the value was retrieved.
#
# From this point of view, it is worth looking at this as "what does the
# user think this value should be." In order words, if the user grabbed
# the value, even if it was a default, they probably based calculations on
# it. If they based calculations on it and the value changes, the rest of
# the world gets inconsistent.
#
# @param resource [Chef::Resource] The resource to get the property from.
#
# @return [Boolean]
#
def is_set?(resource)
value_is_set?(resource)
end
#
# Reset the value of this property so that is_set? will return false and the
# default will be returned in the future.
#
# @param resource [Chef::Resource] The resource to get the property from.
#
def reset(resource)
reset_value(resource)
end
#
# Coerce an input value into canonical form for the property.
#
# After coercion, the value is suitable for storage in the resource.
# You must validate values after coercion, however.
#
# Does no special handling for lazy values.
#
# @param resource [Chef::Resource] The resource we're coercing against
# (to provide context for the coerce).
# @param value The value to coerce.
#
# @return The coerced value.
#
# @raise Chef::Exceptions::ValidationFailed If the value is invalid for
# this property.
#
def coerce(resource, value)
if options.has_key?(:coerce)
# If we have no default value, `nil` is never coerced or validated
unless !has_default? && value.nil?
value = exec_in_resource(resource, options[:coerce], value)
end
end
value
end
#
# Validate a value.
#
# Calls Chef::Mixin::ParamsValidate#validate with #validation_options as
# options.
#
# @param resource [Chef::Resource] The resource we're validating against
# (to provide context for the validate).
# @param value The value to validate.
#
# @raise Chef::Exceptions::ValidationFailed If the value is invalid for
# this property.
#
def validate(resource, value)
# If we have no default value, `nil` is never coerced or validated
unless value.nil? && !has_default?
if resource
resource.validate({ name => value }, { name => validation_options })
else
name = self.name || :property_type
Chef::Mixin::ParamsValidate.validate({ name => value }, { name => validation_options })
end
end
end
#
# Derive a new Property that is just like this one, except with some added or
# changed options.
#
# @param options [Hash<Symbol,Object>] List of options that would be passed
# to #initialize.
#
# @return [Property] The new property type.
#
def derive(**modified_options)
# Since name_property, name_attribute and default override each other,
# if you specify one of them in modified_options it overrides anything in
# the original options.
options = self.options
if modified_options.has_key?(:name_property) ||
modified_options.has_key?(:name_attribute) ||
modified_options.has_key?(:default)
options = options.reject { |k, v| k == :name_attribute || k == :name_property || k == :default }
end
self.class.new(options.merge(modified_options))
end
#
# Emit the DSL for this property into the resource class (`declared_in`).
#
# Creates a getter and setter for the property.
#
def emit_dsl
# We don't create the getter/setter if it's a custom property; we will
# be using the existing getter/setter to manipulate it instead.
return if !instance_variable_name
# We prefer this form because the property name won't show up in the
# stack trace if you use `define_method`.
declared_in.class_eval <<-EOM, __FILE__, __LINE__ + 1
def #{name}(value=NOT_PASSED)
raise "Property `#{name}` of `\#{self}` was incorrectly passed a block. Possible property-resource collision. To call a resource named `#{name}` either rename the property or else use `declare_resource(:#{name}, ...)`" if block_given?
self.class.properties[#{name.inspect}].call(self, value)
end
def #{name}=(value)
raise "Property `#{name}` of `\#{self}` was incorrectly passed a block. Possible property-resource collision. To call a resource named `#{name}` either rename the property or else use `declare_resource(:#{name}, ...)`" if block_given?
self.class.properties[#{name.inspect}].set(self, value)
end
EOM
rescue SyntaxError
# If the name is not a valid ruby name, we use define_method.
declared_in.define_method(name) do |value = NOT_PASSED, &block|
raise "Property `#{name}` of `#{self}` was incorrectly passed a block! Possible property-resource collision. To call a resource named `#{name}` either rename the property or else use `declare_resource(:#{name}, ...)`" if block
self.class.properties[name].call(self, value)
end
declared_in.define_method("#{name}=") do |value, &block|
raise "Property `#{name}` of `#{self}` was incorrectly passed a block! Possible property-resource collision. To call a resource named `#{name}` either rename the property or else use `declare_resource(:#{name}, ...)`" if block
self.class.properties[name].set(self, value)
end
end
#
# The options this Property will use for get/set behavior and validation.
#
# @see #initialize for a list of valid options.
#
attr_reader :options
#
# Find out whether this type accepts nil explicitly.
#
# A type accepts nil explicitly if "is" allows nil, it validates as nil, *and* is not simply
# an empty type.
#
# A type is presumed to accept nil if it does coercion (which must handle nil).
#
# These examples accept nil explicitly:
# ```ruby
# property :a, [ String, nil ]
# property :a, [ String, NilClass ]
# property :a, [ String, proc { |v| v.nil? } ]
# ```
#
# This does not (because the "is" doesn't exist or doesn't have nil):
#
# ```ruby
# property :x, String
# ```
#
# These do not, even though nil would validate fine (because they do not
# have "is"):
#
# ```ruby
# property :a
# property :a, equal_to: [ 1, 2, 3, nil ]
# property :a, kind_of: [ String, NilClass ]
# property :a, respond_to: [ ]
# property :a, callbacks: { "a" => proc { |v| v.nil? } }
# ```
#
# @param resource [Chef::Resource] The resource we're coercing against
# (to provide context for the coerce).
#
# @return [Boolean] Whether this value explicitly accepts nil.
#
# @api private
def explicitly_accepts_nil?(resource)
options.has_key?(:coerce) ||
(options.has_key?(:is) && resource.send(:_pv_is, { name => nil }, name, options[:is], raise_error: false))
end
# @api private
def get_value(resource)
if instance_variable_name
resource.instance_variable_get(instance_variable_name)
else
resource.send(name)
end
end
# @api private
def set_value(resource, value)
if instance_variable_name
resource.instance_variable_set(instance_variable_name, value)
else
resource.send(name, value)
end
end
# @api private
def value_is_set?(resource)
if instance_variable_name
resource.instance_variable_defined?(instance_variable_name)
else
true
end
end
# @api private
def reset_value(resource)
if instance_variable_name
if value_is_set?(resource)
resource.remove_instance_variable(instance_variable_name)
end
else
raise ArgumentError, "Property #{name} has no instance variable defined and cannot be reset"
end
end
private
def exec_in_resource(resource, proc, *args)
if resource
if proc.arity > args.size
value = proc.call(resource, *args)
else
value = resource.instance_exec(*args, &proc)
end
else
# If we don't have a resource yet, we can't exec in resource!
raise Chef::Exceptions::CannotValidateStaticallyError, "Cannot validate or coerce without a resource"
end
end
def input_to_stored_value(resource, value, is_default: false)
unless value.is_a?(DelayedEvaluator)
value = coerce_and_validate(resource, value, is_default: is_default)
end
value
end
def stored_value_to_output(resource, value, is_default: false)
# Crack open lazy values before giving the result to the user
if value.is_a?(DelayedEvaluator)
value = exec_in_resource(resource, value)
value = coerce_and_validate(resource, value, is_default: is_default)
end
value
end
# Coerces and validates the value. If the value is a default, it will warn
# the user that invalid defaults are bad mmkay, and return it as if it were
# valid.
def coerce_and_validate(resource, value, is_default: false)
result = coerce(resource, value)
begin
# If the input is from a default, we need to emit an invalid default warning on validate.
validate(resource, result)
rescue Chef::Exceptions::CannotValidateStaticallyError
# This one gets re-raised
raise
rescue
# Anything else is just an invalid default: in those cases, we just
# warn and return the (possibly coerced) value to the user.
if is_default
if value.nil?
Chef.log_deprecation("Default value nil is invalid for property #{self}. Possible fixes: 1. Remove 'default: nil' if nil means 'undefined'. 2. Set a valid default value if there is a reasonable one. 3. Allow nil as a valid value of your property (for example, 'property #{name.inspect}, [ String, nil ], default: nil'). Error: #{$!}")
else
Chef.log_deprecation("Default value #{value.inspect} is invalid for property #{self}. In Chef 13 this will become an error: #{$!}.")
end
else
raise
end
end
result
end
def nillable?
!!options[:nillable]
end
end
end
end
end
end

View File

@@ -0,0 +1,164 @@
#
# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE
#
# THIS IS A FILE AUTOGENERATED BY 'rake update' DO NOT EDIT!!!!
#
# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE
#
begin
require 'chef/provider'
rescue LoadError; end
require 'chef_compat/copied_from_chef'
class Chef
module ::ChefCompat
module CopiedFromChef
require "chef_compat/copied_from_chef/chef/dsl/core"
class Chef < (defined?(::Chef) ? ::Chef : Object)
class Provider < (defined?(::Chef::Provider) ? ::Chef::Provider : Object)
include Chef::DSL::Core
attr_accessor :action
def initialize(new_resource, run_context)
super if defined?(::Chef::Provider)
@new_resource = new_resource
@action = action
@current_resource = nil
@run_context = run_context
@converge_actions = nil
@recipe_name = nil
@cookbook_name = nil
self.class.include_resource_dsl_module(new_resource)
end
def converge_if_changed(*properties, &converge_block)
if !converge_block
raise ArgumentError, "converge_if_changed must be passed a block!"
end
properties = new_resource.class.state_properties.map { |p| p.name } if properties.empty?
properties = properties.map { |p| p.to_sym }
if current_resource
# Collect the list of modified properties
specified_properties = properties.select { |property| new_resource.property_is_set?(property) }
modified = specified_properties.select { |p| new_resource.send(p) != current_resource.send(p) }
if modified.empty?
properties_str = if sensitive
specified_properties.join(", ")
else
specified_properties.map { |p| "#{p}=#{new_resource.send(p).inspect}" }.join(", ")
end
Chef::Log.debug("Skipping update of #{new_resource}: has not changed any of the specified properties #{properties_str}.")
return false
end
# Print the pretty green text and run the block
property_size = modified.map { |p| p.size }.max
modified.map! do |p|
properties_str = if sensitive
"(suppressed sensitive property)"
else
"#{new_resource.send(p).inspect} (was #{current_resource.send(p).inspect})"
end
" set #{p.to_s.ljust(property_size)} to #{properties_str}"
end
converge_by([ "update #{current_resource.identity}" ] + modified, &converge_block)
else
# The resource doesn't exist. Mark that we are *creating* this, and
# write down any properties we are setting.
property_size = properties.map { |p| p.size }.max
created = properties.map do |property|
default = " (default value)" unless new_resource.property_is_set?(property)
properties_str = if sensitive
"(suppressed sensitive property)"
else
new_resource.send(property).inspect
end
" set #{property.to_s.ljust(property_size)} to #{properties_str}#{default}"
end
converge_by([ "create #{new_resource.identity}" ] + created, &converge_block)
end
true
end
def self.include_resource_dsl(include_resource_dsl)
@include_resource_dsl = include_resource_dsl
end
def self.include_resource_dsl_module(resource)
if @include_resource_dsl && !defined?(@included_resource_dsl_module)
provider_class = self
@included_resource_dsl_module = Module.new do
extend Forwardable
define_singleton_method(:to_s) { "forwarder module for #{provider_class}" }
define_singleton_method(:inspect) { to_s }
# Add a delegator for each explicit property that will get the *current* value
# of the property by default instead of the *actual* value.
resource.class.properties.each do |name, property|
class_eval(<<-EOM, __FILE__, __LINE__)
def #{name}(*args, &block)
# If no arguments were passed, we process "get" by defaulting
# the value to current_resource, not new_resource. This helps
# avoid issues where resources accidentally overwrite perfectly
# valid stuff with default values.
if args.empty? && !block
if !new_resource.property_is_set?(__method__) && current_resource
return current_resource.public_send(__method__)
end
end
new_resource.public_send(__method__, *args, &block)
end
EOM
end
dsl_methods =
resource.class.public_instance_methods +
resource.class.protected_instance_methods -
provider_class.instance_methods -
resource.class.properties.keys
def_delegators(:new_resource, *dsl_methods)
end
include @included_resource_dsl_module
end
end
def self.use_inline_resources
extend InlineResources::ClassMethods
include InlineResources
end
module InlineResources
CopiedFromChef.extend_chef_module(::Chef::Provider::InlineResources, self) if defined?(::Chef::Provider::InlineResources)
def compile_and_converge_action(&block)
old_run_context = run_context
@run_context = run_context.create_child
return_value = instance_eval(&block)
Chef::Runner.new(run_context).converge
return_value
ensure
if run_context.resource_collection.any? { |r| r.updated? }
new_resource.updated_by_last_action(true)
end
@run_context = old_run_context
end
module ClassMethods
CopiedFromChef.extend_chef_module(::Chef::Provider::InlineResources::ClassMethods, self) if defined?(::Chef::Provider::InlineResources::ClassMethods)
def action(name, &block)
# We need the block directly in a method so that `super` works
define_method("compile_action_#{name}", &block)
# We try hard to use `def` because define_method doesn't show the method name in the stack.
begin
class_eval <<-EOM
def action_#{name}
compile_and_converge_action { compile_action_#{name} }
end
EOM
rescue SyntaxError
define_method("action_#{name}") { send("compile_action_#{name}") }
end
end
end
end
protected
end
end
end
end
end

View File

@@ -0,0 +1,269 @@
#
# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE
#
# THIS IS A FILE AUTOGENERATED BY 'rake update' DO NOT EDIT!!!!
#
# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE
#
begin
require 'chef/provider/apt_repository'
rescue LoadError; end
require 'chef_compat/copied_from_chef'
class Chef
module ::ChefCompat
module CopiedFromChef
#
# Author:: Thom May (<thom@chef.io>)
# Copyright:: Copyright (c) 2016 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 "chef_compat/copied_from_chef/chef/resource"
require "chef_compat/copied_from_chef/chef/dsl/declare_resource"
require "chef_compat/copied_from_chef/chef/provider/noop"
class Chef < (defined?(::Chef) ? ::Chef : Object)
class Provider < (defined?(::Chef::Provider) ? ::Chef::Provider : Object)
class AptRepository < (defined?(::Chef::Provider::AptRepository) ? ::Chef::Provider::AptRepository : Chef::Provider)
use_inline_resources
include Chef::Mixin::ShellOut
extend Chef::Mixin::Which
provides :apt_repository do
which("apt-get")
end
def whyrun_supported?
true
end
def load_current_resource
end
action :add do
unless new_resource.key.nil?
if is_key_id?(new_resource.key) && !has_cookbook_file?(new_resource.key)
install_key_from_keyserver
else
install_key_from_uri
end
end
declare_resource(:execute, "apt-cache gencaches") do
ignore_failure true
action :nothing
end
declare_resource(:apt_update, new_resource.name) do
ignore_failure true
action :nothing
end
components = if is_ppa_url?(new_resource.uri) && new_resource.components.empty?
"main"
else
new_resource.components
end
repo = build_repo(
new_resource.uri,
new_resource.distribution,
components,
new_resource.trusted,
new_resource.arch,
new_resource.deb_src
)
declare_resource(:file, "/etc/apt/sources.list.d/#{new_resource.name}.list") do
owner "root"
group "root"
mode "0644"
content repo
sensitive new_resource.sensitive
action :create
notifies :run, "execute[apt-cache gencaches]", :immediately
notifies :update, "apt_update[#{new_resource.name}]", :immediately if new_resource.cache_rebuild
end
end
action :remove do
if ::File.exist?("/etc/apt/sources.list.d/#{new_resource.name}.list")
converge_by "Removing #{new_resource.name} repository from /etc/apt/sources.list.d/" do
declare_resource(:file, "/etc/apt/sources.list.d/#{new_resource.name}.list") do
sensitive new_resource.sensitive
action :delete
notifies :update, "apt_update[#{new_resource.name}]", :immediately if new_resource.cache_rebuild
end
declare_resource(:apt_update, new_resource.name) do
ignore_failure true
action :nothing
end
end
end
end
def is_key_id?(id)
id = id[2..-1] if id.start_with?("0x")
id =~ /^\h+$/ && [8, 16, 40].include?(id.length)
end
def extract_fingerprints_from_cmd(cmd)
so = shell_out(cmd)
so.run_command
so.stdout.split(/\n/).map do |t|
if z = t.match(/^ +Key fingerprint = ([0-9A-F ]+)/)
z[1].split.join
end
end.compact
end
def key_is_valid?(cmd, key)
valid = true
so = shell_out(cmd)
so.run_command
so.stdout.split(/\n/).map do |t|
if t =~ %r{^\/#{key}.*\[expired: .*\]$}
Chef::Log.debug "Found expired key: #{t}"
valid = false
break
end
end
Chef::Log.debug "key #{key} #{valid ? "is valid" : "is not valid"}"
valid
end
def cookbook_name
new_resource.cookbook || new_resource.cookbook_name
end
def has_cookbook_file?(fn)
run_context.has_cookbook_file_in_cookbook?(cookbook_name, fn)
end
def no_new_keys?(file)
installed_keys = extract_fingerprints_from_cmd("apt-key finger")
proposed_keys = extract_fingerprints_from_cmd("gpg --with-fingerprint #{file}")
(installed_keys & proposed_keys).sort == proposed_keys.sort
end
def install_key_from_uri
key_name = new_resource.key.gsub(/[^0-9A-Za-z\-]/, "_")
cached_keyfile = ::File.join(Chef::Config[:file_cache_path], key_name)
type = if new_resource.key.start_with?("http")
:remote_file
elsif has_cookbook_file?(new_resource.key)
:cookbook_file
else
raise Chef::Exceptions::FileNotFound, "Cannot locate key file"
end
declare_resource(type, cached_keyfile) do
source new_resource.key
mode "0644"
sensitive new_resource.sensitive
action :create
end
raise "The key #{cached_keyfile} is invalid and cannot be used to verify an apt repository." unless key_is_valid?("gpg #{cached_keyfile}", "")
declare_resource(:execute, "apt-key add #{cached_keyfile}") do
sensitive new_resource.sensitive
action :run
not_if do
no_new_keys?(cached_keyfile)
end
notifies :run, "execute[apt-cache gencaches]", :immediately
end
end
def install_key_from_keyserver(key = new_resource.key, keyserver = new_resource.keyserver)
cmd = "apt-key adv --recv"
cmd << " --keyserver-options http-proxy=#{new_resource.key_proxy}" if new_resource.key_proxy
cmd << " --keyserver "
cmd << if keyserver.start_with?("hkp://")
keyserver
else
"hkp://#{keyserver}:80"
end
cmd << " #{key}"
declare_resource(:execute, "install-key #{key}") do
command cmd
sensitive new_resource.sensitive
not_if do
present = extract_fingerprints_from_cmd("apt-key finger").any? do |fp|
fp.end_with? key.upcase
end
present && key_is_valid?("apt-key list", key.upcase)
end
notifies :run, "execute[apt-cache gencaches]", :immediately
end
raise "The key #{key} is invalid and cannot be used to verify an apt repository." unless key_is_valid?("apt-key list", key.upcase)
end
def install_ppa_key(owner, repo)
url = "https://launchpad.net/api/1.0/~#{owner}/+archive/#{repo}"
key_id = Chef::HTTP::Simple.new(url).get("signing_key_fingerprint").delete('"')
install_key_from_keyserver(key_id, "keyserver.ubuntu.com")
rescue Net::HTTPServerException => e
raise "Could not access Launchpad ppa API: #{e.message}"
end
def is_ppa_url?(url)
url.start_with?("ppa:")
end
def make_ppa_url(ppa)
return unless is_ppa_url?(ppa)
owner, repo = ppa[4..-1].split("/")
repo ||= "ppa"
install_ppa_key(owner, repo)
"http://ppa.launchpad.net/#{owner}/#{repo}/ubuntu"
end
def build_repo(uri, distribution, components, trusted, arch, add_src = false)
uri = make_ppa_url(uri) if is_ppa_url?(uri)
uri = '"' + uri + '"' unless uri.start_with?("'", '"')
components = Array(components).join(" ")
options = []
options << "arch=#{arch}" if arch
options << "trusted=yes" if trusted
optstr = unless options.empty?
"[" + options.join(" ") + "]"
end
info = [ optstr, uri, distribution, components ].compact.join(" ")
repo = "deb #{info}\n"
repo << "deb-src #{info}\n" if add_src
repo
end
end
end
end
Chef::Provider::Noop.provides :apt_repository
end
end
end

View File

@@ -0,0 +1,105 @@
#
# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE
#
# THIS IS A FILE AUTOGENERATED BY 'rake update' DO NOT EDIT!!!!
#
# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE
#
begin
require 'chef/provider/apt_update'
rescue LoadError; end
require 'chef_compat/copied_from_chef'
class Chef
module ::ChefCompat
module CopiedFromChef
#
# Author:: Thom May (<thom@chef.io>)
# Copyright:: Copyright (c) 2016 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 "chef_compat/copied_from_chef/chef/provider"
require "chef_compat/copied_from_chef/chef/provider/noop"
class Chef < (defined?(::Chef) ? ::Chef : Object)
class Provider < (defined?(::Chef::Provider) ? ::Chef::Provider : Object)
class AptUpdate < (defined?(::Chef::Provider::AptUpdate) ? ::Chef::Provider::AptUpdate : Chef::Provider)
use_inline_resources
extend Chef::Mixin::Which
provides :apt_update do
which("apt-get")
end
APT_CONF_DIR = "/etc/apt/apt.conf.d"
STAMP_DIR = "/var/lib/apt/periodic"
def whyrun_supported?
true
end
def load_current_resource
end
action :periodic do
if !apt_up_to_date?
converge_by "update new lists of packages" do
do_update
end
end
end
action :update do
converge_by "force update new lists of packages" do
do_update
end
end
private
# Determines whether we need to run `apt-get update`
#
# @return [Boolean]
def apt_up_to_date?
::File.exist?("#{STAMP_DIR}/update-success-stamp") &&
::File.mtime("#{STAMP_DIR}/update-success-stamp") > Time.now - new_resource.frequency
end
def do_update
[STAMP_DIR, APT_CONF_DIR].each do |d|
declare_resource(:directory, d) do
recursive true
end
end
declare_resource(:file, "#{APT_CONF_DIR}/15update-stamp") do
content "APT::Update::Post-Invoke-Success {\"touch #{STAMP_DIR}/update-success-stamp 2>/dev/null || true\";};\n"
action :create_if_missing
end
declare_resource(:execute, "apt-get -q update")
end
end
end
end
Chef::Provider::Noop.provides :apt_update
end
end
end

View File

@@ -0,0 +1,56 @@
#
# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE
#
# THIS IS A FILE AUTOGENERATED BY 'rake update' DO NOT EDIT!!!!
#
# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE
#
begin
require 'chef/provider/noop'
rescue LoadError; end
require 'chef_compat/copied_from_chef'
class Chef
module ::ChefCompat
module CopiedFromChef
#
# Author:: Thom May (<thom@chef.io>)
# Copyright:: Copyright (c) 2016 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 < (defined?(::Chef) ? ::Chef : Object)
class Provider < (defined?(::Chef::Provider) ? ::Chef::Provider : Object)
class Noop < (defined?(::Chef::Provider::Noop) ? ::Chef::Provider::Noop : Chef::Provider)
def load_current_resource; end
def respond_to_missing?(method_sym, include_private = false)
method_sym.to_s.start_with?("action_") || super
end
def method_missing(method_sym, *arguments, &block)
if method_sym.to_s =~ /^action_/
Chef::Log.debug("NoOp-ing for #{method_sym}")
else
super
end
end
end
end
end
end
end
end

View File

@@ -0,0 +1,132 @@
# This file was generated by Chef
# Do NOT modify this file by hand.
[<%= @config.repositoryid %>]
name=<%= @config.description %>
<% if @config.baseurl %>
baseurl=<%= case @config.baseurl
when Array
@config.baseurl.join("\n")
else
@config.baseurl
end %>
<% end -%>
<% if @config.cost %>
cost=<%= @config.cost %>
<% end %>
<% if @config.enabled %>
enabled=1
<% else %>
enabled=0
<% end %>
<% if @config.enablegroups %>
enablegroups=1
<% end %>
<% if @config.exclude %>
exclude=<%= @config.exclude %>
<% end %>
<% if @config.failovermethod %>
failovermethod=<%= @config.failovermethod %>
<% end %>
<% if @config.fastestmirror_enabled %>
fastestmirror_enabled=1
<% else %>
fastestmirror_enabled=0
<% end %>
<% if @config.gpgcheck %>
gpgcheck=1
<% else %>
gpgcheck=0
<% end %>
<% if @config.gpgkey %>
gpgkey=<%= case @config.gpgkey
when Array
@config.gpgkey.join("\n ")
else
@config.gpgkey
end %>
<% end -%>
<% if @config.http_caching %>
http_caching=<%= @config.http_caching %>
<% end %>
<% if @config.include_config %>
include=<%= @config.include_config %>
<% end %>
<% if @config.includepkgs %>
includepkgs=<%= @config.includepkgs %>
<% end %>
<% if @config.keepalive %>
keepalive=1
<% end %>
<% if @config.metadata_expire %>
metadata_expire=<%= @config.metadata_expire %>
<% end %>
<% if @config.mirrorlist %>
mirrorlist=<%= @config.mirrorlist %>
<% end %>
<% if @config.mirror_expire %>
mirror_expire=<%= @config.mirror_expire %>
<% end %>
<% if @config.mirrorlist_expire %>
mirrorlist_expire=<%= @config.mirrorlist_expire %>
<% end %>
<% if @config.priority %>
priority=<%= @config.priority %>
<% end %>
<% if @config.proxy %>
proxy=<%= @config.proxy %>
<% end %>
<% if @config.proxy_username %>
proxy_username=<%= @config.proxy_username %>
<% end %>
<% if @config.proxy_password %>
proxy_password=<%= @config.proxy_password %>
<% end %>
<% if @config.username %>
username=<%= @config.username %>
<% end %>
<% if @config.password %>
password=<%= @config.password %>
<% end %>
<% if @config.repo_gpgcheck %>
repo_gpgcheck=1
<% end %>
<% if @config.max_retries %>
retries=<%= @config.max_retries %>
<% end %>
<% if @config.report_instanceid %>
report_instanceid=<%= @config.report_instanceid %>
<% end %>
<% if @config.skip_if_unavailable %>
skip_if_unavailable=1
<% end %>
<% if @config.sslcacert %>
sslcacert=<%= @config.sslcacert %>
<% end %>
<% if @config.sslclientcert %>
sslclientcert=<%= @config.sslclientcert %>
<% end %>
<% if @config.sslclientkey %>
sslclientkey=<%= @config.sslclientkey %>
<% end %>
<% unless @config.sslverify.nil? %>
sslverify=<%= ( @config.sslverify ) ? 'true' : 'false' %>
<% end %>
<% if @config.timeout %>
timeout=<%= @config.timeout %>
<% end %>
<% if @config.options -%>
<% @config.options.each do |key, value| -%>
<%= key %>=<%=
case value
when Array
value.join("\n ")
when TrueClass
'1'
when FalseClass
'0'
else
value
end %>
<% end -%>
<% end -%>

View File

@@ -0,0 +1,253 @@
#
# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE
#
# THIS IS A FILE AUTOGENERATED BY 'rake update' DO NOT EDIT!!!!
#
# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE
#
begin
require 'chef/provider/systemd_unit'
rescue LoadError; end
require 'chef_compat/copied_from_chef'
class Chef
module ::ChefCompat
module CopiedFromChef
#
# Author:: Nathan Williams (<nath.e.will@gmail.com>)
# Copyright:: Copyright 2016, Nathan Williams
# 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 "chef_compat/copied_from_chef/chef/provider"
class Chef < (defined?(::Chef) ? ::Chef : Object)
class Provider < (defined?(::Chef::Provider) ? ::Chef::Provider : Object)
class SystemdUnit < (defined?(::Chef::Provider::SystemdUnit) ? ::Chef::Provider::SystemdUnit : Chef::Provider)
include Chef::Mixin::Which
include Chef::Mixin::ShellOut
provides :systemd_unit, os: "linux"
def load_current_resource
@current_resource = Chef::Resource::SystemdUnit.new(new_resource.name)
current_resource.content(::File.read(unit_path)) if ::File.exist?(unit_path)
current_resource.user(new_resource.user)
current_resource.enabled(enabled?)
current_resource.active(active?)
current_resource.masked(masked?)
current_resource.static(static?)
current_resource.triggers_reload(new_resource.triggers_reload)
current_resource
end
def define_resource_requirements
super
requirements.assert(:create) do |a|
a.assertion { IniParse.parse(new_resource.to_ini) }
a.failure_message "Unit content is not valid INI text"
end
end
def action_create
if current_resource.content != new_resource.to_ini
converge_by("creating unit: #{new_resource.name}") do
manage_unit_file(:create)
daemon_reload if new_resource.triggers_reload
end
end
end
def action_delete
if ::File.exist?(unit_path)
converge_by("deleting unit: #{new_resource.name}") do
manage_unit_file(:delete)
daemon_reload if new_resource.triggers_reload
end
end
end
def action_enable
if current_resource.static
Chef::Log.debug("#{new_resource.name} is a static unit, enabling is a NOP.")
end
unless current_resource.enabled || current_resource.static
converge_by("enabling unit: #{new_resource.name}") do
systemctl_execute!(:enable, new_resource.name)
end
end
end
def action_disable
if current_resource.static
Chef::Log.debug("#{new_resource.name} is a static unit, disabling is a NOP.")
end
if current_resource.enabled && !current_resource.static
converge_by("disabling unit: #{new_resource.name}") do
systemctl_execute!(:disable, new_resource.name)
end
end
end
def action_mask
unless current_resource.masked
converge_by("masking unit: #{new_resource.name}") do
systemctl_execute!(:mask, new_resource.name)
end
end
end
def action_unmask
if current_resource.masked
converge_by("unmasking unit: #{new_resource.name}") do
systemctl_execute!(:unmask, new_resource.name)
end
end
end
def action_start
unless current_resource.active
converge_by("starting unit: #{new_resource.name}") do
systemctl_execute!(:start, new_resource.name)
end
end
end
def action_stop
if current_resource.active
converge_by("stopping unit: #{new_resource.name}") do
systemctl_execute!(:stop, new_resource.name)
end
end
end
def action_restart
converge_by("restarting unit: #{new_resource.name}") do
systemctl_execute!(:restart, new_resource.name)
end
end
def action_reload
if current_resource.active
converge_by("reloading unit: #{new_resource.name}") do
systemctl_execute!(:reload, new_resource.name)
end
else
Chef::Log.debug("#{new_resource.name} is not active, skipping reload.")
end
end
def action_try_restart
converge_by("try-restarting unit: #{new_resource.name}") do
systemctl_execute!("try-restart", new_resource.name)
end
end
def action_reload_or_restart
converge_by("reload-or-restarting unit: #{new_resource.name}") do
systemctl_execute!("reload-or-restart", new_resource.name)
end
end
def action_reload_or_try_restart
converge_by("reload-or-try-restarting unit: #{new_resource.name}") do
systemctl_execute!("reload-or-try-restart", new_resource.name)
end
end
def active?
systemctl_execute("is-active", new_resource.name).exitstatus == 0
end
def enabled?
systemctl_execute("is-enabled", new_resource.name).exitstatus == 0
end
def masked?
systemctl_execute(:status, new_resource.name).stdout.include?("masked")
end
def static?
systemctl_execute("is-enabled", new_resource.name).stdout.include?("static")
end
private
def unit_path
if new_resource.user
"/etc/systemd/user/#{new_resource.name}"
else
"/etc/systemd/system/#{new_resource.name}"
end
end
def manage_unit_file(action = :nothing)
Chef::Resource::File.new(unit_path, run_context).tap do |f|
f.owner "root"
f.group "root"
f.mode "0644"
f.content new_resource.to_ini
end.run_action(action)
end
def daemon_reload
shell_out_with_systems_locale!("#{systemctl_path} daemon-reload")
end
def systemctl_execute!(action, unit)
shell_out_with_systems_locale!("#{systemctl_cmd} #{action} #{unit}", systemctl_opts)
end
def systemctl_execute(action, unit)
shell_out("#{systemctl_cmd} #{action} #{unit}", systemctl_opts)
end
def systemctl_cmd
@systemctl_cmd ||= "#{systemctl_path} #{systemctl_args}"
end
def systemctl_path
@systemctl_path ||= which("systemctl")
end
def systemctl_args
@systemctl_args ||= new_resource.user ? "--user" : "--system"
end
def systemctl_opts
@systemctl_opts ||=
if new_resource.user
{
:user => new_resource.user,
:environment => {
"DBUS_SESSION_BUS_ADDRESS" => "unix:path=/run/user/#{node['etc']['passwd'][new_resource.user]['uid']}/bus",
},
}
else
{}
end
end
end
end
end
end
end
end

View File

@@ -0,0 +1,136 @@
#
# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE
#
# THIS IS A FILE AUTOGENERATED BY 'rake update' DO NOT EDIT!!!!
#
# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE
#
begin
require 'chef/provider/yum_repository'
rescue LoadError; end
require 'chef_compat/copied_from_chef'
class Chef
module ::ChefCompat
module CopiedFromChef
#
# Author:: Thom May (<thom@chef.io>)
# Copyright:: Copyright (c) 2016 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 "chef_compat/copied_from_chef/chef/resource"
require "chef_compat/copied_from_chef/chef/dsl/declare_resource"
require "chef_compat/copied_from_chef/chef/provider/noop"
class Chef < (defined?(::Chef) ? ::Chef : Object)
class Provider < (defined?(::Chef::Provider) ? ::Chef::Provider : Object)
class YumRepository < (defined?(::Chef::Provider::YumRepository) ? ::Chef::Provider::YumRepository : Chef::Provider)
use_inline_resources
extend Chef::Mixin::Which
provides :yum_repository do
which "yum"
end
def whyrun_supported?; true; end
def load_current_resource; end
action :create do
declare_resource(:template, "/etc/yum.repos.d/#{new_resource.repositoryid}.repo") do
if template_available?(new_resource.source)
source new_resource.source
else
source ::File.expand_path("../support/yum_repo.erb", __FILE__)
local true
end
sensitive new_resource.sensitive
variables(config: new_resource)
mode new_resource.mode
if new_resource.make_cache
notifies :run, "execute[yum clean metadata #{new_resource.repositoryid}]", :immediately if new_resource.clean_metadata || new_resource.clean_headers
notifies :run, "execute[yum-makecache-#{new_resource.repositoryid}]", :immediately
notifies :create, "ruby_block[yum-cache-reload-#{new_resource.repositoryid}]", :immediately
end
end
declare_resource(:execute, "yum clean metadata #{new_resource.repositoryid}") do
command "yum clean metadata --disablerepo=* --enablerepo=#{new_resource.repositoryid}"
action :nothing
end
# get the metadata for this repo only
declare_resource(:execute, "yum-makecache-#{new_resource.repositoryid}") do
command "yum -q -y makecache --disablerepo=* --enablerepo=#{new_resource.repositoryid}"
action :nothing
only_if { new_resource.enabled }
end
# reload internal Chef yum cache
declare_resource(:ruby_block, "yum-cache-reload-#{new_resource.repositoryid}") do
block { Chef::Provider::Package::Yum::YumCache.instance.reload }
action :nothing
end
end
action :delete do
# clean the repo cache first
declare_resource(:execute, "yum clean all #{new_resource.repositoryid}") do
command "yum clean all --disablerepo=* --enablerepo=#{new_resource.repositoryid}"
only_if "yum repolist all | grep -P '^#{new_resource.repositoryid}([ \t]|$)'"
end
declare_resource(:file, "/etc/yum.repos.d/#{new_resource.repositoryid}.repo") do
action :delete
notifies :create, "ruby_block[yum-cache-reload-#{new_resource.repositoryid}]", :immediately
end
declare_resource(:ruby_block, "yum-cache-reload-#{new_resource.repositoryid}") do
block { Chef::Provider::Package::Yum::YumCache.instance.reload }
action :nothing
end
end
action :makecache do
declare_resource(:execute, "yum-makecache-#{new_resource.repositoryid}") do
command "yum -q -y makecache --disablerepo=* --enablerepo=#{new_resource.repositoryid}"
action :run
only_if { new_resource.enabled }
end
declare_resource(:ruby_block, "yum-cache-reload-#{new_resource.repositoryid}") do
block { Chef::Provider::Package::Yum::YumCache.instance.reload }
action :run
end
end
alias_method :action_add, :action_create
alias_method :action_remove, :action_delete
def template_available?(path)
!path.nil? && run_context.has_template_in_cookbook?(new_resource.cookbook_name, path)
end
end
end
end
Chef::Provider::Noop.provides :yum_repository
end
end
end

View File

@@ -0,0 +1,214 @@
#
# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE
#
# THIS IS A FILE AUTOGENERATED BY 'rake update' DO NOT EDIT!!!!
#
# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE
#
begin
require 'chef/resource'
rescue LoadError; end
require 'chef_compat/copied_from_chef'
class Chef
module ::ChefCompat
module CopiedFromChef
require "chef_compat/copied_from_chef/chef/resource/action_class"
require "chef_compat/copied_from_chef/chef/provider"
require "chef_compat/copied_from_chef/chef/mixin/properties"
require "chef_compat/copied_from_chef/chef/dsl/universal"
class Chef < (defined?(::Chef) ? ::Chef : Object)
class Resource < (defined?(::Chef::Resource) ? ::Chef::Resource : Object)
include Chef::Mixin::Properties
property :name, String, coerce: proc { |v| v.is_a?(Array) ? v.join(", ") : v.to_s }, desired_state: false
def initialize(name, run_context = nil)
super if defined?(::Chef::Resource)
name(name) unless name.nil?
@run_context = run_context
@noop = nil
@before = nil
@params = Hash.new
@provider = nil
@allowed_actions = self.class.allowed_actions.to_a
@action = self.class.default_action
@updated = false
@updated_by_last_action = false
@supports = {}
@ignore_failure = false
@retries = 0
@retry_delay = 2
@not_if = []
@only_if = []
@source_line = nil
# We would like to raise an error when the user gives us a guard
# interpreter and a ruby_block to the guard. In order to achieve this
# we need to understand when the user overrides the default guard
# interpreter. Therefore we store the default separately in a different
# attribute.
@guard_interpreter = nil
@default_guard_interpreter = :default
@elapsed_time = 0
@sensitive = false
end
def action(arg = nil)
if arg
arg = Array(arg).map(&:to_sym)
arg.each do |action|
validate(
{ action: action },
{ action: { kind_of: Symbol, equal_to: allowed_actions } }
)
end
@action = arg
else
@action
end
end
alias_method :action=, :action
class UnresolvedSubscribes < (defined?(::Chef::Resource::UnresolvedSubscribes) ? ::Chef::Resource::UnresolvedSubscribes : self)
alias_method :to_s, :name
alias_method :declared_key, :name
end
def state_for_resource_reporter
state = {}
state_properties = self.class.state_properties
state_properties.each do |property|
if property.identity? || property.is_set?(self)
state[property.name] = property.sensitive? ? "*sensitive value suppressed*" : send(property.name)
end
end
state
end
alias_method :state, :state_for_resource_reporter
def identity
result = {}
identity_properties = self.class.identity_properties
identity_properties.each do |property|
result[property.name] = send(property.name)
end
return result.values.first if identity_properties.size == 1
result
end
attr_reader :resource_initializing
def resource_initializing=(value)
if value
@resource_initializing = true
else
remove_instance_variable(:@resource_initializing)
end
end
def to_hash
# Grab all current state, then any other ivars (backcompat)
result = {}
self.class.state_properties.each do |p|
result[p.name] = p.get(self)
end
safe_ivars = instance_variables.map { |ivar| ivar.to_sym } - FORBIDDEN_IVARS
safe_ivars.each do |iv|
key = iv.to_s.sub(/^@/, "").to_sym
next if result.has_key?(key)
result[key] = instance_variable_get(iv)
end
result
end
def self.identity_property(name = nil)
result = identity_properties(*Array(name))
if result.size > 1
raise Chef::Exceptions::MultipleIdentityError, "identity_property cannot be called on an object with more than one identity property (#{result.map { |r| r.name }.join(", ")})."
end
result.first
end
attr_accessor :allowed_actions
def allowed_actions(value = NOT_PASSED)
if value != NOT_PASSED
self.allowed_actions = value
end
@allowed_actions
end
def resource_name
@resource_name || self.class.resource_name
end
def self.use_automatic_resource_name
automatic_name = convert_to_snake_case(self.name.split("::")[-1])
resource_name automatic_name
end
def self.allowed_actions(*actions)
@allowed_actions ||=
if superclass.respond_to?(:allowed_actions)
superclass.allowed_actions.dup
else
[ :nothing ]
end
@allowed_actions |= actions.flatten
end
def self.allowed_actions=(value)
@allowed_actions = value.uniq
end
def self.default_action(action_name = NOT_PASSED)
unless action_name.equal?(NOT_PASSED)
@default_action = Array(action_name).map(&:to_sym)
self.allowed_actions |= @default_action
end
if @default_action
@default_action
elsif superclass.respond_to?(:default_action)
superclass.default_action
else
[:nothing]
end
end
def self.default_action=(action_name)
default_action action_name
end
def self.action(action, &recipe_block)
action = action.to_sym
declare_action_class
action_class.action(action, &recipe_block)
self.allowed_actions += [ action ]
default_action action if Array(default_action) == [:nothing]
end
def self.load_current_value(&load_block)
define_method(:load_current_value!, &load_block)
end
def current_value_does_not_exist!
raise Chef::Exceptions::CurrentValueDoesNotExist
end
def self.action_class(&block)
return @action_class if @action_class && !block
# If the superclass needed one, then we need one as well.
if block || (superclass.respond_to?(:action_class) && superclass.action_class)
@action_class = declare_action_class(&block)
end
@action_class
end
def self.declare_action_class(&block)
@action_class ||= begin
if superclass.respond_to?(:action_class)
base_provider = superclass.action_class
end
base_provider ||= Chef::Provider
resource_class = self
Class.new(base_provider) do
include ActionClass
self.resource_class = resource_class
end
end
@action_class.class_eval(&block) if block
@action_class
end
FORBIDDEN_IVARS = [:@run_context, :@not_if, :@only_if, :@enclosing_provider]
HIDDEN_IVARS = [:@allowed_actions, :@resource_name, :@source_line, :@run_context, :@name, :@not_if, :@only_if, :@elapsed_time, :@enclosing_provider]
class << self
end
@@sorted_descendants = nil
module DeprecatedLWRPClass
CopiedFromChef.extend_chef_module(::Chef::Resource::DeprecatedLWRPClass, self) if defined?(::Chef::Resource::DeprecatedLWRPClass)
end
end
end
end
end
end

View File

@@ -0,0 +1,114 @@
#
# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE
#
# THIS IS A FILE AUTOGENERATED BY 'rake update' DO NOT EDIT!!!!
#
# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE
#
begin
require 'chef/resource/action_class'
rescue LoadError; end
require 'chef_compat/copied_from_chef'
class Chef
module ::ChefCompat
module CopiedFromChef
#
# Author:: John Keiser (<jkeiser@chef.io)
# Copyright:: Copyright 2015-2016, 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 "chef_compat/copied_from_chef/chef/dsl/recipe"
class Chef < (defined?(::Chef) ? ::Chef : Object)
class Resource < (defined?(::Chef::Resource) ? ::Chef::Resource : Object)
module ActionClass
CopiedFromChef.extend_chef_module(::Chef::Resource::ActionClass, self) if defined?(::Chef::Resource::ActionClass)
include Chef::DSL::Recipe
def to_s
"#{new_resource || "<no resource>"} action #{action ? action.inspect : "<no action>"}"
end
def whyrun_supported?
true
end
#
# If load_current_value! is defined on the resource, use that.
#
def load_current_resource
if new_resource.respond_to?(:load_current_value!)
# dup the resource and then reset desired-state properties.
current_resource = new_resource.dup
# We clear desired state in the copy, because it is supposed to be actual state.
# We keep identity properties and non-desired-state, which are assumed to be
# "control" values like `recurse: true`
current_resource.class.properties.each do |name, property|
if property.desired_state? && !property.identity? && !property.name_property?
property.reset(current_resource)
end
end
# Call the actual load_current_value! method. If it raises
# CurrentValueDoesNotExist, set current_resource to `nil`.
begin
# If the user specifies load_current_value do |desired_resource|, we
# pass in the desired resource as well as the current one.
if current_resource.method(:load_current_value!).arity > 0
current_resource.load_current_value!(new_resource)
else
current_resource.load_current_value!
end
rescue Chef::Exceptions::CurrentValueDoesNotExist
current_resource = nil
end
end
@current_resource = current_resource
end
def self.included(other)
other.extend(ClassMethods)
other.use_inline_resources
other.include_resource_dsl true
end
module ClassMethods
CopiedFromChef.extend_chef_module(::Chef::Resource::ActionClass::ClassMethods, self) if defined?(::Chef::Resource::ActionClass::ClassMethods)
#
# The Chef::Resource class this ActionClass was declared against.
#
# @return [Class] The Chef::Resource class this ActionClass was declared against.
#
attr_accessor :resource_class
def to_s
"#{resource_class} action provider"
end
def inspect
to_s
end
end
end
end
end
end
end
end

View File

@@ -0,0 +1,65 @@
#
# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE
#
# THIS IS A FILE AUTOGENERATED BY 'rake update' DO NOT EDIT!!!!
#
# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE
#
begin
require 'chef/resource/apt_repository'
rescue LoadError; end
require 'chef_compat/copied_from_chef'
class Chef
module ::ChefCompat
module CopiedFromChef
#
# Author:: Thom May (<thom@chef.io>)
# Copyright:: Copyright (c) 2016 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 "chef_compat/copied_from_chef/chef/resource"
class Chef < (defined?(::Chef) ? ::Chef : Object)
class Resource < (defined?(::Chef::Resource) ? ::Chef::Resource : Object)
class AptRepository < (defined?(::Chef::Resource::AptRepository) ? ::Chef::Resource::AptRepository : Chef::Resource)
resource_name :apt_repository
provides :apt_repository
property :repo_name, String, name_property: true
property :uri, String
property :distribution, [ String, nil, false ], default: lazy { node["lsb"]["codename"] }, nillable: true, coerce: proc { |x| x ? x : nil }
property :components, Array, default: []
property :arch, [String, nil, false], default: nil, nillable: true, coerce: proc { |x| x ? x : nil }
property :trusted, [TrueClass, FalseClass], default: false
# whether or not to add the repository as a source repo, too
property :deb_src, [TrueClass, FalseClass], default: false
property :keyserver, [String, nil, false], default: "keyserver.ubuntu.com", nillable: true, coerce: proc { |x| x ? x : nil }
property :key, [String, nil, false], default: nil, nillable: true, coerce: proc { |x| x ? x : nil }
property :key_proxy, [String, nil, false], default: nil, nillable: true, coerce: proc { |x| x ? x : nil }
property :cookbook, [String, nil, false], default: nil, desired_state: false, nillable: true, coerce: proc { |x| x ? x : nil }
property :cache_rebuild, [TrueClass, FalseClass], default: true, desired_state: false
default_action :add
allowed_actions :add, :remove
end
end
end
end
end
end

View File

@@ -0,0 +1,52 @@
#
# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE
#
# THIS IS A FILE AUTOGENERATED BY 'rake update' DO NOT EDIT!!!!
#
# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE
#
begin
require 'chef/resource/apt_update'
rescue LoadError; end
require 'chef_compat/copied_from_chef'
class Chef
module ::ChefCompat
module CopiedFromChef
#
# Author:: Thom May (<thom@chef.io>)
# Copyright:: Copyright (c) 2016 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 "chef_compat/copied_from_chef/chef/resource"
class Chef < (defined?(::Chef) ? ::Chef : Object)
class Resource < (defined?(::Chef::Resource) ? ::Chef::Resource : Object)
class AptUpdate < (defined?(::Chef::Resource::AptUpdate) ? ::Chef::Resource::AptUpdate : Chef::Resource)
resource_name :apt_update
provides :apt_update
property :frequency, Integer, default: 86_400
default_action :periodic
allowed_actions :update, :periodic
end
end
end
end
end
end

View File

@@ -0,0 +1,81 @@
#
# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE
#
# THIS IS A FILE AUTOGENERATED BY 'rake update' DO NOT EDIT!!!!
#
# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE
#
begin
require 'chef/resource/systemd_unit'
rescue LoadError; end
require 'chef_compat/copied_from_chef'
class Chef
module ::ChefCompat
module CopiedFromChef
#
# Author:: Nathan Williams (<nath.e.will@gmail.com>)
# Copyright:: Copyright 2016, Nathan Williams
# 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 "chef_compat/copied_from_chef/chef/resource"
class Chef < (defined?(::Chef) ? ::Chef : Object)
class Resource < (defined?(::Chef::Resource) ? ::Chef::Resource : Object)
class SystemdUnit < (defined?(::Chef::Resource::SystemdUnit) ? ::Chef::Resource::SystemdUnit : Chef::Resource)
resource_name :systemd_unit
default_action :nothing
allowed_actions :create, :delete,
:enable, :disable,
:mask, :unmask,
:start, :stop,
:restart, :reload,
:try_restart, :reload_or_restart,
:reload_or_try_restart
property :enabled, [TrueClass, FalseClass]
property :active, [TrueClass, FalseClass]
property :masked, [TrueClass, FalseClass]
property :static, [TrueClass, FalseClass]
property :user, String, desired_state: false
property :content, [String, Hash]
property :triggers_reload, [TrueClass, FalseClass],
default: true, desired_state: false
def to_ini
case content
when Hash
IniParse.gen do |doc|
content.each_pair do |sect, opts|
doc.section(sect) do |section|
opts.each_pair do |opt, val|
section.option(opt, val)
end
end
end
end.to_s
else
content.to_s
end
end
end
end
end
end
end
end

View File

@@ -0,0 +1,97 @@
#
# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE
#
# THIS IS A FILE AUTOGENERATED BY 'rake update' DO NOT EDIT!!!!
#
# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE
#
begin
require 'chef/resource/yum_repository'
rescue LoadError; end
require 'chef_compat/copied_from_chef'
class Chef
module ::ChefCompat
module CopiedFromChef
#
# Author:: Thom May (<thom@chef.io>)
# Copyright:: Copyright (c) 2016 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 "chef_compat/copied_from_chef/chef/resource"
class Chef < (defined?(::Chef) ? ::Chef : Object)
class Resource < (defined?(::Chef::Resource) ? ::Chef::Resource : Object)
class YumRepository < (defined?(::Chef::Resource::YumRepository) ? ::Chef::Resource::YumRepository : Chef::Resource)
resource_name :yum_repository
provides :yum_repository
# http://linux.die.net/man/5/yum.conf
property :baseurl, [String, Array], regex: /.*/
property :cost, String, regex: /^\d+$/
property :clean_headers, [TrueClass, FalseClass], default: false # deprecated
property :clean_metadata, [TrueClass, FalseClass], default: true
property :description, String, regex: /.*/, default: "Yum Repository"
property :enabled, [TrueClass, FalseClass], default: true
property :enablegroups, [TrueClass, FalseClass]
property :exclude, String, regex: /.*/
property :failovermethod, String, equal_to: %w{priority roundrobin}
property :fastestmirror_enabled, [TrueClass, FalseClass]
property :gpgcheck, [TrueClass, FalseClass], default: true
property :gpgkey, [String, Array], regex: /.*/
property :http_caching, String, equal_to: %w{packages all none}
property :include_config, String, regex: /.*/
property :includepkgs, String, regex: /.*/
property :keepalive, [TrueClass, FalseClass]
property :make_cache, [TrueClass, FalseClass], default: true
property :max_retries, [String, Integer]
property :metadata_expire, String, regex: [/^\d+$/, /^\d+[mhd]$/, /never/]
property :mirrorexpire, String, regex: /.*/
property :mirrorlist, String, regex: /.*/
property :mirror_expire, String, regex: [/^\d+$/, /^\d+[mhd]$/]
property :mirrorlist_expire, String, regex: [/^\d+$/, /^\d+[mhd]$/]
property :mode, default: "0644"
property :priority, String, regex: /^(\d?[0-9]|[0-9][0-9])$/
property :proxy, String, regex: /.*/
property :proxy_username, String, regex: /.*/
property :proxy_password, String, regex: /.*/
property :username, String, regex: /.*/
property :password, String, regex: /.*/
property :repo_gpgcheck, [TrueClass, FalseClass]
property :report_instanceid, [TrueClass, FalseClass]
property :repositoryid, String, regex: /.*/, name_property: true
property :skip_if_unavailable, [TrueClass, FalseClass]
property :source, String, regex: /.*/
property :sslcacert, String, regex: /.*/
property :sslclientcert, String, regex: /.*/
property :sslclientkey, String, regex: /.*/
property :sslverify, [TrueClass, FalseClass]
property :timeout, String, regex: /^\d+$/
property :options, Hash
default_action :create
allowed_actions :create, :remove, :makecache, :add, :delete
# provide compatibility with the yum cookbook < 3.0 properties
alias_method :url, :baseurl
alias_method :keyurl, :gpgkey
end
end
end
end
end
end

View File

@@ -0,0 +1,174 @@
#
# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE
#
# THIS IS A FILE AUTOGENERATED BY 'rake update' DO NOT EDIT!!!!
#
# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE
#
begin
require 'chef/resource_builder'
rescue LoadError; end
require 'chef_compat/copied_from_chef'
class Chef
module ::ChefCompat
module CopiedFromChef
#
# Author:: Lamont Granquist (<lamont@chef.io>)
# Copyright:: Copyright 2015-2016, 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.
#
# NOTE: this was extracted from the Recipe DSL mixin, relevant specs are in spec/unit/recipe_spec.rb
class Chef < (defined?(::Chef) ? ::Chef : Object)
class ResourceBuilder < (defined?(::Chef::ResourceBuilder) ? ::Chef::ResourceBuilder : Object)
attr_reader :type
attr_reader :name
attr_reader :created_at
attr_reader :params
attr_reader :run_context
attr_reader :cookbook_name
attr_reader :recipe_name
attr_reader :enclosing_provider
attr_reader :resource
# FIXME (ruby-2.1 syntax): most of these are mandatory
def initialize(type: nil, name: nil, created_at: nil, params: nil, run_context: nil, cookbook_name: nil, recipe_name: nil, enclosing_provider: nil)
super if defined?(::Chef::ResourceBuilder)
@type = type
@name = name
@created_at = created_at
@params = params
@run_context = run_context
@cookbook_name = cookbook_name
@recipe_name = recipe_name
@enclosing_provider = enclosing_provider
end
def build(&block)
raise ArgumentError, "You must supply a name when declaring a #{type} resource" if name.nil?
@resource = resource_class.new(name, run_context)
if resource.resource_name.nil?
raise Chef::Exceptions::InvalidResourceSpecification, "#{resource}.resource_name is `nil`! Did you forget to put `provides :blah` or `resource_name :blah` in your resource class?"
end
resource.source_line = created_at
resource.declared_type = type
# If we have a resource like this one, we want to steal its state
# This behavior is very counter-intuitive and should be removed.
# See CHEF-3694, https://tickets.opscode.com/browse/CHEF-3694
# Moved to this location to resolve CHEF-5052, https://tickets.opscode.com/browse/CHEF-5052
if prior_resource
resource.load_from(prior_resource)
end
resource.cookbook_name = cookbook_name
resource.recipe_name = recipe_name
# Determine whether this resource is being created in the context of an enclosing Provider
resource.enclosing_provider = enclosing_provider
# XXX: this is required for definition params inside of the scope of a
# subresource to work correctly.
resource.params = params
# Evaluate resource attribute DSL
if block_given?
resource.resource_initializing = true
begin
resource.instance_eval(&block)
ensure
resource.resource_initializing = false
end
end
# emit a cloned resource warning if it is warranted
if prior_resource
if is_trivial_resource?(prior_resource) && identicalish_resources?(prior_resource, resource)
emit_harmless_cloning_debug
else
emit_cloned_resource_warning
end
end
# Run optional resource hook
resource.after_created
resource
end
private
def resource_class
# Checks the new platform => short_name => resource mapping initially
# then fall back to the older approach (Chef::Resource.const_get) for
# backward compatibility
@resource_class ||= Chef::Resource.resource_for_node(type, run_context.node)
end
def is_trivial_resource?(resource)
trivial_resource = resource_class.new(name, run_context)
# force un-lazy the name property on the created trivial resource
name_property = resource_class.properties.find { |sym, p| p.name_property? }
trivial_resource.send(name_property[0]) unless name_property.nil?
identicalish_resources?(trivial_resource, resource)
end
# this is an equality test specific to checking for 3694 cloning warnings
def identicalish_resources?(first, second)
skipped_ivars = [ :@source_line, :@cookbook_name, :@recipe_name, :@params, :@elapsed_time, :@declared_type ]
checked_ivars = ( first.instance_variables | second.instance_variables ) - skipped_ivars
non_matching_ivars = checked_ivars.reject do |iv|
if iv == :@action && ( [first.instance_variable_get(iv)].flatten == [:nothing] || [second.instance_variable_get(iv)].flatten == [:nothing] )
# :nothing action on either side of the comparison always matches
true
else
first.instance_variable_get(iv) == second.instance_variable_get(iv)
end
end
Chef::Log.debug("ivars which did not match with the prior resource: #{non_matching_ivars}")
non_matching_ivars.empty?
end
def emit_cloned_resource_warning
message = "Cloning resource attributes for #{resource} from prior resource (CHEF-3694)"
message << "\nPrevious #{prior_resource}: #{prior_resource.source_line}" if prior_resource.source_line
message << "\nCurrent #{resource}: #{resource.source_line}" if resource.source_line
Chef.log_deprecation(message)
end
def emit_harmless_cloning_debug
Chef::Log.debug("Harmless resource cloning from #{prior_resource}:#{prior_resource.source_line} to #{resource}:#{resource.source_line}")
end
def prior_resource
@prior_resource ||=
begin
key = "#{type}[#{name}]"
run_context.resource_collection.lookup_local(key)
rescue Chef::Exceptions::ResourceNotFound
nil
end
end
end
end
require "chef_compat/copied_from_chef/chef/resource"
end
end
end

View File

@@ -0,0 +1,8 @@
require 'chef_compat/monkeypatches'
require 'chef_compat/copied_from_chef/chef/mixin/properties'
module ChefCompat
module Mixin
Properties = ChefCompat::CopiedFromChef::Chef::Mixin::Properties
end
end

View File

@@ -0,0 +1,41 @@
class Chef
class RunContext
class ChildRunContext < RunContext
# magic that lets us re-parse the ChildRunContext without erroring due to
# cheffish and chef-provisioning hooks having been loaded (on old versions of
# chef-client without the lazy hooks for those gems)
@__skip_method_checking = true
end
end
end
# fix to quiet constant redefined warnings
if defined?(Chef::RunContext::ChildRunContext::CHILD_STATE)
Chef::RunContext::ChildRunContext.send(:remove_const, :CHILD_STATE)
end
require 'chef_compat/monkeypatches/chef'
require 'chef_compat/monkeypatches/chef/exceptions'
require 'chef_compat/monkeypatches/chef/log'
require 'chef_compat/monkeypatches/chef/node'
require 'chef_compat/monkeypatches/chef/mixin/params_validate'
require 'chef_compat/monkeypatches/chef/property'
require 'chef_compat/monkeypatches/chef/provider'
require 'chef_compat/monkeypatches/chef/recipe' # copied from chef
require 'chef_compat/monkeypatches/chef/recipe_hook'
require 'chef_compat/monkeypatches/chef/resource'
require 'chef_compat/monkeypatches/chef/resource_builder'
require 'chef_compat/monkeypatches/chef/resource/lwrp_base'
require 'chef_compat/monkeypatches/chef/resource_collection'
require 'chef_compat/monkeypatches/chef/resource_collection/resource_list'
require 'chef_compat/monkeypatches/chef/resource_collection/resource_set'
require 'chef_compat/monkeypatches/chef/run_context' # copied from chef
require 'chef_compat/monkeypatches/chef/runner' # copied from chef
# fix for Chef::RunContext instance that has already been created
ObjectSpace.each_object(Chef::RunContext) do |run_context|
run_context.node.run_context = run_context
run_context.instance_variable_set(:@loaded_recipes_hash, {})
run_context.instance_variable_set(:@loaded_attributes_hash, {})
run_context.initialize_child_state
end

View File

@@ -0,0 +1,33 @@
class Chef
NOT_PASSED = Object.new if !defined?(NOT_PASSED)
# Earlier versions of Chef didn't have this message
module ChefCompatDeprecation
def log_deprecation(message, location=nil)
if !location
# Pick the first caller that is *not* part of the Chef or ChefCompat gem,
# that's the thing the user wrote.
chef_compat_gem_path = File.expand_path("../../..", __FILE__)
chef_gem_path = File.expand_path("../..",::Chef::Resource.instance_method(:initialize).source_location[0])
caller(0..10).each do |c|
if !c.start_with?(chef_gem_path) && !c.start_with?(chef_compat_gem_path)
location = c
break
end
end
end
begin
super
# Bleagh. `super_method` doesn't exist on older rubies and I haven't
# figured out a way to check for its existence otherwise.
rescue NoMethodError
Chef::Log.warn(message)
end
end
end
class<<self
prepend ChefCompatDeprecation
end
end

View File

@@ -0,0 +1,10 @@
require 'chef/exceptions'
class Chef
class Exceptions
# Used in Resource::ActionClass#load_current_resource to denote that
# the resource doesn't actually exist (for example, the file does not exist)
class CurrentValueDoesNotExist < RuntimeError; end unless defined?(CurrentValueDoesNotExist)
class CannotValidateStaticallyError < RuntimeError; end unless defined?(CannotValidateStaticallyError)
end
end

View File

@@ -0,0 +1,30 @@
require 'chef/log'
# for now we have to patch this in everything
class Chef
class Log
def self.caller_location
# Pick the first caller that is *not* part of the Chef gem, that's the
# thing the user wrote.
compat_resource_path = File.expand_path("../../../../..", __FILE__)
chef_gem_path = Gem.loaded_specs['chef'].full_gem_path
caller(0..20).find { |c| !c.start_with?(compat_resource_path) && !c.start_with?(chef_gem_path) }
end
end
end
if Gem::Requirement.new('< 12.13.37').satisfied_by?(Gem::Version.new(Chef::VERSION))
# FIXME: why does this not match the implementation in Chef itself?
class Chef
class Log
module ChefCompatDeprecation
def deprecation(message, location=nil)
Chef.log_deprecation(message, location)
end
end
extend ChefCompatDeprecation
end
end
end

View File

@@ -0,0 +1,17 @@
if Chef::VERSION.to_f >= 12.5 && Chef::VERSION.to_f <= 12.8
require 'chef/mixin/params_validate'
class Chef
module Mixin
module ParamsValidate
class SetOrReturnProperty < Chef::Property
# 12.9 introduced a new optional parameter to `get()` to avoid a nil-set warning.
# When their method gets called with 2 args, we need to ignore and call with 1.
alias_method :_original_get2, :get
def get(resource, *args)
_original_get2(resource)
end
end
end
end
end
end

View File

@@ -0,0 +1,9 @@
class Chef
class Node
unless method_defined?(:set_cookbook_attribute)
def set_cookbook_attribute
# this implementation deliberately left blank - we don't need to do anything we just need to not fail
end
end
end
end

View File

@@ -0,0 +1,15 @@
# 12.9 introduced a new optional parameter to `get()` to avoid a nil-set warning.
# We need to mimick it here.
if Chef::VERSION.to_f >= 12.5 && Chef::VERSION.to_f <= 12.8
require 'chef/property'
class Chef
class Property
# 12.9 introduced a new optional parameter to `get()` to avoid a nil-set warning.
# When their method gets called with 2 args, we need to ignore and call with 1.
alias_method :_original_get, :get
def get(resource, *args)
_original_get(resource)
end
end
end
end

View File

@@ -0,0 +1,65 @@
require 'chef/provider'
require 'chef/provider/lwrp_base'
class Chef::Provider
if !defined?(InlineResources)
InlineResources = Chef::Provider::LWRPBase::InlineResources
end
module InlineResources
require 'chef/dsl/recipe'
require 'chef/dsl/platform_introspection'
require 'chef/dsl/data_query'
require 'chef/dsl/include_recipe'
include Chef::DSL::Recipe
include Chef::DSL::PlatformIntrospection
include Chef::DSL::DataQuery
include Chef::DSL::IncludeRecipe
unless Chef::Provider::InlineResources::ClassMethods.instance_method(:action).source_location[0] =~ /chefspec/
# Don't override action if chefspec is doing its thing
module ::ChefCompat
module Monkeypatches
module InlineResources
module ClassMethods
def action(name, &block)
super(name) { send("compile_action_#{name}") }
# We put the action in its own method so that super() works.
define_method("compile_action_#{name}", &block)
end
end
end
end
end
module ClassMethods
prepend ChefCompat::Monkeypatches::InlineResources::ClassMethods
end
end
end
end
class Chef
class Provider
class LWRPBase < Provider
if defined?(InlineResources)
module InlineResources
# since we upgrade the Chef::Runner and Chef::RunContext globally to >= 12.14 style classes, we need to also
# fix the use_inline_resources LWRPBase wrapper that creates a sub-resource collection with the ugpraded code
# from the Chef::Provider subclasses that do similar things in post-12.5 chef.
def recipe_eval_with_update_check(&block)
old_run_context = run_context
@run_context = run_context.create_child
return_value = instance_eval(&block)
Chef::Runner.new(run_context).converge
return_value
ensure
if run_context.resource_collection.any? { |r| r.updated? }
new_resource.updated_by_last_action(true)
end
@run_context = old_run_context
end
end
end
end
end
end

View File

@@ -0,0 +1,118 @@
#
# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE
#
# THIS IS A FILE AUTOGENERATED BY 'rake update' DO NOT EDIT!!!!
#
# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE
#
if Gem::Requirement.new('< 12.16.42').satisfied_by?(Gem::Version.new(Chef::VERSION))
#--
# Author:: Adam Jacob (<adam@chef.io>)
# Author:: Christopher Walters (<cw@chef.io>)
# Copyright:: Copyright 2008-2016, 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 "chef/dsl/recipe"
require "chef/mixin/from_file"
require "chef/mixin/deprecation"
class Chef
# == Chef::Recipe
# A Recipe object is the context in which Chef recipes are evaluated.
class Recipe
attr_accessor :cookbook_name, :recipe_name, :recipe, :params, :run_context
include Chef::DSL::Recipe
include Chef::Mixin::FromFile
include Chef::Mixin::Deprecation
# Parses a potentially fully-qualified recipe name into its
# cookbook name and recipe short name.
#
# For example:
# "aws::elastic_ip" returns [:aws, "elastic_ip"]
# "aws" returns [:aws, "default"]
# "::elastic_ip" returns [ current_cookbook, "elastic_ip" ]
#--
# TODO: Duplicates functionality of RunListItem
def self.parse_recipe_name(recipe_name, current_cookbook: nil)
case recipe_name
when /(.+?)::(.+)/
[ $1.to_sym, $2 ]
when /^::(.+)/
raise "current_cookbook is nil, cannot resolve #{recipe_name}" if current_cookbook.nil?
[ current_cookbook.to_sym, $1 ]
else
[ recipe_name.to_sym, "default" ]
end
end
def initialize(cookbook_name, recipe_name, run_context)
@cookbook_name = cookbook_name
@recipe_name = recipe_name
@run_context = run_context
# TODO: 5/19/2010 cw/tim: determine whether this can be removed
@params = Hash.new
end
# Used in DSL mixins
def node
run_context.node
end
# Used by the DSL to look up resources when executing in the context of a
# recipe.
def resources(*args)
run_context.resource_collection.find(*args)
end
# This was moved to Chef::Node#tag, redirecting here for compatibility
def tag(*tags)
run_context.node.tag(*tags)
end
# Returns true if the node is tagged with *all* of the supplied +tags+.
#
# === Parameters
# tags<Array>:: A list of tags
#
# === Returns
# true<TrueClass>:: If all the parameters are present
# false<FalseClass>:: If any of the parameters are missing
def tagged?(*tags)
tags.each do |tag|
return false unless run_context.node.tags.include?(tag)
end
true
end
# Removes the list of tags from the node.
#
# === Parameters
# tags<Array>:: A list of tags
#
# === Returns
# tags<Array>:: The current list of run_context.node.tags
def untag(*tags)
tags.each do |tag|
run_context.node.tags.delete(tag)
end
end
end
end
end

View File

@@ -0,0 +1,20 @@
require 'chef/recipe'
require 'chef_compat/recipe'
class Chef::Recipe
# If the cookbook depends on compat_resource, create a ChefCompat::Recipe object
# instead of Chef::Recipe, for the extra goodies.
def self.new(cookbook_name, recipe_name, run_context)
if run_context &&
cookbook_name &&
recipe_name &&
run_context.cookbook_collection &&
run_context.cookbook_collection[cookbook_name] &&
run_context.cookbook_collection[cookbook_name].metadata.dependencies.has_key?('compat_resource') &&
self != ::ChefCompat::Recipe
::ChefCompat::Recipe.new(cookbook_name, recipe_name, run_context)
else
super
end
end
end

View File

@@ -0,0 +1,156 @@
# this is NOT an AUTOGENERATED file
require 'chef/resource'
class Chef
class Resource
class UnresolvedSubscribes < self
# The full key ise given as the name in {Resource#subscribes}
alias_method :to_s, :name
alias_method :declared_key, :name
end
#
# Force a delayed notification into this resource's run_context.
#
# This should most likely be paired with action :nothing
#
# @param arg [Array[Symbol], Symbol] A list of actions (e.g. `:create`)
#
def delayed_action(arg)
arg = Array(arg).map(&:to_sym)
arg.map do |action|
validate(
{ action: action },
{ action: { kind_of: Symbol, equal_to: allowed_actions } }
)
# the resource effectively sends a delayed notification to itself
run_context.add_delayed_action(Notification.new(self, action, self))
end
end
def subscribes(action, resources, timing = :delayed)
resources = [resources].flatten
resources.each do |resource|
if resource.is_a?(String)
resource = UnresolvedSubscribes.new(resource, run_context)
end
if resource.run_context.nil?
resource.run_context = run_context
end
resource.notifies(action, self, timing)
end
true
end
def notifies(action, resource_spec, timing = :delayed)
# when using old-style resources(:template => "/foo.txt") style, you
# could end up with multiple resources.
validate_resource_spec!(resource_spec)
resources = [ resource_spec ].flatten
resources.each do |resource|
case timing.to_s
when "delayed"
notifies_delayed(action, resource)
when "immediate", "immediately"
notifies_immediately(action, resource)
when "before"
notifies_before(action, resource)
else
raise ArgumentError, "invalid timing: #{timing} for notifies(#{action}, #{resources.inspect}, #{timing}) resource #{self} "\
"Valid timings are: :delayed, :immediate, :immediately, :before"
end
end
true
end
#
# Iterates over all immediate and delayed notifications, calling
# resolve_resource_reference on each in turn, causing them to
# resolve lazy/forward references.
def resolve_notification_references
run_context.before_notifications(self).each { |n|
n.resolve_resource_reference(run_context.resource_collection)
}
run_context.immediate_notifications(self).each { |n|
n.resolve_resource_reference(run_context.resource_collection)
}
run_context.delayed_notifications(self).each {|n|
n.resolve_resource_reference(run_context.resource_collection)
}
end
# Helper for #notifies
def notifies_before(action, resource_spec)
run_context.notifies_before(Notification.new(resource_spec, action, self))
end
# Helper for #notifies
def notifies_immediately(action, resource_spec)
run_context.notifies_immediately(Notification.new(resource_spec, action, self))
end
# Helper for #notifies
def notifies_delayed(action, resource_spec)
run_context.notifies_delayed(Notification.new(resource_spec, action, self))
end
#
# Get the current actual value of this resource.
#
# This does not cache--a new value will be returned each time.
#
# @return A new copy of the resource, with values filled in from the actual
# current value.
#
def current_value
provider = provider_for_action(Array(action).first)
if provider.whyrun_mode? && !provider.whyrun_supported?
raise "Cannot retrieve #{self.class.current_resource} in why-run mode: #{provider} does not support why-run"
end
provider.load_current_resource
provider.current_resource
end
# These methods are necessary for new resources to initialize old ones properly
attr_reader :resource_initializing
def resource_initializing=(value)
if value
@resource_initializing = value
else
remove_instance_variable(:@resource_initializing)
end
end
if !respond_to?(:resource_name)
def self.resource_name(name=Chef::NOT_PASSED)
# Setter
if name != Chef::NOT_PASSED
# remove_canonical_dsl
# Set the resource_name and call provides
if name
name = name.to_sym
# If our class is not already providing this name, provide it.
# Commented out: use of resource_name and provides will need to be
# mutually exclusive in this world, generally.
# if !Chef::ResourceResolver.includes_handler?(name, self)
provides name#, canonical: true
# end
@resource_name = name
else
@resource_name = nil
end
end
@resource_name
end
def self.resource_name=(name)
resource_name(name)
end
end
end
end

View File

@@ -0,0 +1,60 @@
require 'chef_compat/resource/lwrp_base'
require 'chef/resource/lwrp_base'
module ChefCompat
module Monkeypatches
#
# NOTE: LOTS OF METAPROGRAMMING HERE. NOT FOR FAINT OF HEART.
#
# Add an empty module to Class so we can temporarily override it in build_from_file
module Class
end
class<<::Class
prepend(ChefCompat::Monkeypatches::Class)
end
module Chef
module Resource
module LWRPBase
def build_from_file(cookbook_name, filename, run_context)
# If the cookbook this LWRP is from depends on compat_resource, fix its LWRPs up real good
if run_context.cookbook_collection[cookbook_name].metadata.dependencies.has_key?('compat_resource')
# All cookbooks do Class.new(Chef::Resource::LWRPBase). Change Class.new
# temporarily to translate Chef::Resource::LWRPBase to ChefCompat::Resource
ChefCompat::Monkeypatches::Class.module_eval do
def new(*args, &block)
# Trick it! Use ChefCompat::Resource instead of Chef::Resource::LWRPBase
if args == [ ::Chef::Resource::LWRPBase ]
ChefCompat::Monkeypatches::Class.module_eval do
remove_method(:new) if method_defined?(:new)
end
args = [ ChefCompat::Resource::LWRPBase ]
end
super(*args, &block)
end
end
begin
# Call the actual build_from_file
super
ensure
class<<ChefCompat::Monkeypatches::Class
remove_method(:new) if method_defined?(:new)
end
end
else
# Call the actual build_from_file
super
end
end
end
class <<::Chef::Resource::LWRPBase
prepend(LWRPBase)
end
end
end
end
end

View File

@@ -0,0 +1,167 @@
#
# Author:: Lamont Granquist (<lamont@chef.io>)
# Copyright:: Copyright 2015-2016, 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.
#
# XXX: we now have two copies of this file in the compat_resource cookbook. I'm uncertain if this is a
# bug or a feature, and I suspect it is actually a feature. The point of this file is that for all
# resources and cookbooks the global Chef::ResourceBuilder class must be upgraded to at least the
# 12.10.24 version. The point of the other copy is that for compat_resource cookbooks all their
# resources should be using the lastest version that has been sync'd. So these two files should
# diverge as times goes on. I believe that is the correct behavior and that we want to have both
# files in this cookbook.
# NOTE: this was extracted from the Recipe DSL mixin, relevant specs are in spec/unit/recipe_spec.rb
if Gem::Requirement.new("< 12.10.24").satisfied_by?(Gem::Version.new(Chef::VERSION))
begin
require 'chef/resource_builder'
# we use the LoadError this creates on early 12.x to not monkeypatch chef client versions that don't have Chef::ResourceBuilder
# (it is lazily included and doesn't appear until compile time so we can't resolve the symbol during library loading)
class Chef
class ResourceBuilder
attr_reader :type
attr_reader :name
attr_reader :created_at
attr_reader :params
attr_reader :run_context
attr_reader :cookbook_name
attr_reader :recipe_name
attr_reader :enclosing_provider
attr_reader :resource
# FIXME (ruby-2.1 syntax): most of these are mandatory
def initialize(type:nil, name:nil, created_at: nil, params: nil, run_context: nil, cookbook_name: nil, recipe_name: nil, enclosing_provider: nil)
@type = type
@name = name
@created_at = created_at
@params = params
@run_context = run_context
@cookbook_name = cookbook_name
@recipe_name = recipe_name
@enclosing_provider = enclosing_provider
end
def build(&block)
raise ArgumentError, "You must supply a name when declaring a #{type} resource" if name.nil?
@resource = resource_class.new(name, run_context)
if resource.resource_name.nil?
raise Chef::Exceptions::InvalidResourceSpecification, "#{resource}.resource_name is `nil`! Did you forget to put `provides :blah` or `resource_name :blah` in your resource class?"
end
resource.source_line = created_at
resource.declared_type = type
# If we have a resource like this one, we want to steal its state
# This behavior is very counter-intuitive and should be removed.
# See CHEF-3694, https://tickets.opscode.com/browse/CHEF-3694
# Moved to this location to resolve CHEF-5052, https://tickets.opscode.com/browse/CHEF-5052
if prior_resource
resource.load_from(prior_resource)
end
resource.cookbook_name = cookbook_name
resource.recipe_name = recipe_name
# Determine whether this resource is being created in the context of an enclosing Provider
resource.enclosing_provider = enclosing_provider
# XXX: this is required for definition params inside of the scope of a
# subresource to work correctly.
resource.params = params
# Evaluate resource attribute DSL
if block_given?
resource.resource_initializing = true
begin
resource.instance_eval(&block)
ensure
resource.resource_initializing = false
end
end
# emit a cloned resource warning if it is warranted
if prior_resource
if is_trivial_resource?(prior_resource) && identicalish_resources?(prior_resource, resource)
emit_harmless_cloning_debug
else
emit_cloned_resource_warning
end
end
# Run optional resource hook
resource.after_created
resource
end
private
def resource_class
# Checks the new platform => short_name => resource mapping initially
# then fall back to the older approach (Chef::Resource.const_get) for
# backward compatibility
@resource_class ||= Chef::Resource.resource_for_node(type, run_context.node)
end
def is_trivial_resource?(resource)
identicalish_resources?(resource_class.new(name, run_context), resource)
end
# this is an equality test specific to checking for 3694 cloning warnings
def identicalish_resources?(first, second)
skipped_ivars = [ :@source_line, :@cookbook_name, :@recipe_name, :@params, :@elapsed_time, :@declared_type ]
checked_ivars = ( first.instance_variables | second.instance_variables ) - skipped_ivars
non_matching_ivars = checked_ivars.reject do |iv|
if iv == :@action && ( [first.instance_variable_get(iv)].flatten == [:nothing] || [second.instance_variable_get(iv)].flatten == [:nothing] )
# :nothing action on either side of the comparison always matches
true
else
first.instance_variable_get(iv) == second.instance_variable_get(iv)
end
end
Chef::Log.debug("ivars which did not match with the prior resource: #{non_matching_ivars}")
non_matching_ivars.empty?
end
def emit_cloned_resource_warning
Chef::Log.warn("Cloning resource attributes for #{resource} from prior resource (CHEF-3694)")
Chef::Log.warn("Previous #{prior_resource}: #{prior_resource.source_line}") if prior_resource.source_line
Chef::Log.warn("Current #{resource}: #{resource.source_line}") if resource.source_line
end
def emit_harmless_cloning_debug
Chef::Log.debug("Harmless resource cloning from #{prior_resource}:#{prior_resource.source_line} to #{resource}:#{resource.source_line}")
end
def prior_resource
@prior_resource ||=
begin
key = "#{type}[#{name}]"
run_context.resource_collection.lookup_local(key)
rescue Chef::Exceptions::ResourceNotFound
nil
end
end
end
end
rescue LoadError
# cool we're just on early chef 12.x, nothing to do -- we don't have to worry because there's also not parent_run_context pointer, so we don't have to
# use lookup_local to avoid resource cloning shit out of the parent run_context. the resource collection's lookup() method will always use lookup_local
# over lookup_recursive.
end
end

View File

@@ -0,0 +1,103 @@
#
# Author:: Adam Jacob (<adam@chef.io>)
# Author:: Christopher Walters (<cw@chef.io>)
# Copyright:: Copyright 2008-2016, 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 "chef/resource_collection/resource_set"
require "chef/resource_collection/resource_list"
require "chef/resource_collection"
require "chef/exceptions"
module ChefCompat
module Monkeypatches
module Chef
module ResourceCollection
module RecursiveNotificationLookup
#
# Copied verbatim from Chef 12.10.24
#
attr_accessor :run_context
def initialize(run_context = nil)
super()
@run_context = run_context
end
def lookup_local(key)
resource_set.lookup(key)
end
def find_local(*args)
resource_set.find(*args)
end
def lookup(key)
if run_context.nil?
lookup_local(key)
else
lookup_recursive(run_context, key)
end
end
def find(*args)
if run_context.nil?
find_local(*args)
else
find_recursive(run_context, *args)
end
end
private
def lookup_recursive(rc, key)
rc.resource_collection.send(:resource_set).lookup(key)
rescue ::Chef::Exceptions::ResourceNotFound
raise if !rc.respond_to?(:parent_run_context) || rc.parent_run_context.nil?
lookup_recursive(rc.parent_run_context, key)
end
def find_recursive(rc, *args)
rc.resource_collection.send(:resource_set).find(*args)
rescue ::Chef::Exceptions::ResourceNotFound
raise if !rc.respond_to?(:parent_run_context) || rc.parent_run_context.nil?
find_recursive(rc.parent_run_context, *args)
end
end
module DeleteResources
#
# Copied verbatim from Chef 12.10.24
#
def delete(key)
resource_list.delete(key)
resource_set.delete(key)
end
end
end
end
end
end
class Chef::ResourceCollection
unless method_defined?(:lookup_local)
prepend ChefCompat::Monkeypatches::Chef::ResourceCollection::RecursiveNotificationLookup
end
unless method_defined?(:delete)
prepend ChefCompat::Monkeypatches::Chef::ResourceCollection::DeleteResources
end
end

View File

@@ -0,0 +1,49 @@
#
# Author:: Tyler Ball (<tball@chef.io>)
# Copyright:: Copyright 2014-2016, 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 "chef/resource_collection/resource_list"
require "chef/exceptions"
module ChefCompat
module Monkeypatches
module Chef
module ResourceCollection
module ResourceList
module DeleteResource
# Copied verbatim from Chef 12.10.4
def delete(key)
raise ArgumentError, "Must pass a Chef::Resource or String to delete" unless key.is_a?(String) || key.is_a?(Chef::Resource)
key = key.to_s
ret = @resources.reject! { |r| r.to_s == key }
if ret.nil?
raise ::Chef::Exceptions::ResourceNotFound, "Cannot find a resource matching #{key} (did you define it first?)"
end
ret
end
end
end
end
end
end
end
class Chef::ResourceCollection::ResourceList
unless method_defined?(:delete)
prepend ChefCompat::Monkeypatches::Chef::ResourceCollection::ResourceList::DeleteResource
end
end

View File

@@ -0,0 +1,49 @@
#
# Author:: Tyler Ball (<tball@chef.io>)
# Copyright:: Copyright 2014-2016, 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 "chef/resource_collection/resource_list"
require "chef/exceptions"
module ChefCompat
module Monkeypatches
module Chef
module ResourceCollection
module ResourceSet
module DeleteResource
def delete(key)
raise ArgumentError, "Must pass a Chef::Resource or String to delete" unless key.is_a?(String) || key.is_a?(Chef::Resource)
key = key.to_s
res = @resources_by_key.delete(key)
if res == @resources_by_key.default
raise Chef::Exceptions::ResourceNotFound, "Cannot find a resource matching #{key} (did you define it first?)"
end
res
end
end
end
end
end
end
end
class Chef::ResourceCollection::ResourceSet
unless method_defined?(:delete)
prepend ChefCompat::Monkeypatches::Chef::ResourceCollection::ResourceSet::DeleteResource
end
end

View File

@@ -0,0 +1,691 @@
#
# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE
#
# THIS IS A FILE AUTOGENERATED BY 'rake update' DO NOT EDIT!!!!
#
# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE
#
if Gem::Requirement.new('< 12.16.42').satisfied_by?(Gem::Version.new(Chef::VERSION))
#
# Author:: Adam Jacob (<adam@chef.io>)
# Author:: Christopher Walters (<cw@chef.io>)
# Author:: Tim Hinderliter (<tim@chef.io>)
# Copyright:: Copyright 2008-2016, 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 "chef/resource_collection"
require "chef/cookbook_version"
require "chef/node"
require "chef/role"
require "chef/log"
require "chef/recipe"
require "chef/run_context/cookbook_compiler"
require "chef/event_dispatch/events_output_stream"
require "forwardable"
class Chef
# == Chef::RunContext
# Value object that loads and tracks the context of a Chef run
class RunContext
#
# Global state
#
#
# The node for this run
#
# @return [Chef::Node]
#
attr_reader :node
#
# The set of cookbooks involved in this run
#
# @return [Chef::CookbookCollection]
#
attr_reader :cookbook_collection
#
# Resource Definitions for this run. Populated when the files in
# +definitions/+ are evaluated (this is triggered by #load).
#
# @return [Array[Chef::ResourceDefinition]]
#
attr_reader :definitions
#
# Event dispatcher for this run.
#
# @return [Chef::EventDispatch::Dispatcher]
#
attr_reader :events
#
# Hash of factoids for a reboot request.
#
# @return [Hash]
#
attr_accessor :reboot_info
#
# Scoped state
#
#
# The parent run context.
#
# @return [Chef::RunContext] The parent run context, or `nil` if this is the
# root context.
#
attr_reader :parent_run_context
#
# The root run context.
#
# @return [Chef::RunContext] The root run context.
#
def root_run_context
rc = self
rc = rc.parent_run_context until rc.parent_run_context.nil?
rc
end
#
# The collection of resources intended to be converged (and able to be
# notified).
#
# @return [Chef::ResourceCollection]
#
# @see CookbookCompiler
#
attr_reader :resource_collection
#
# The list of control groups to execute during the audit phase
#
attr_reader :audits
#
# Notification handling
#
#
# A Hash containing the before notifications triggered by resources
# during the converge phase of the chef run.
#
# @return [Hash[String, Array[Chef::Resource::Notification]]] A hash from
# <notifying resource name> => <list of notifications it sent>
#
attr_reader :before_notification_collection
#
# A Hash containing the immediate notifications triggered by resources
# during the converge phase of the chef run.
#
# @return [Hash[String, Array[Chef::Resource::Notification]]] A hash from
# <notifying resource name> => <list of notifications it sent>
#
attr_reader :immediate_notification_collection
#
# A Hash containing the delayed (end of run) notifications triggered by
# resources during the converge phase of the chef run.
#
# @return [Hash[String, Array[Chef::Resource::Notification]]] A hash from
# <notifying resource name> => <list of notifications it sent>
#
attr_reader :delayed_notification_collection
#
# An Array containing the delayed (end of run) notifications triggered by
# resources during the converge phase of the chef run.
#
# @return [Array[Chef::Resource::Notification]] An array of notification objects
#
attr_reader :delayed_actions
# Creates a new Chef::RunContext object and populates its fields. This object gets
# used by the Chef Server to generate a fully compiled recipe list for a node.
#
# @param node [Chef::Node] The node to run against.
# @param cookbook_collection [Chef::CookbookCollection] The cookbooks
# involved in this run.
# @param events [EventDispatch::Dispatcher] The event dispatcher for this
# run.
#
def initialize(node, cookbook_collection, events)
@node = node
@cookbook_collection = cookbook_collection
@events = events
node.run_context = self
node.set_cookbook_attribute
@definitions = Hash.new
@loaded_recipes_hash = {}
@loaded_attributes_hash = {}
@reboot_info = {}
@cookbook_compiler = nil
@delayed_actions = []
initialize_child_state
end
#
# Triggers the compile phase of the chef run.
#
# @param run_list_expansion [Chef::RunList::RunListExpansion] The run list.
# @see Chef::RunContext::CookbookCompiler
#
def load(run_list_expansion)
@cookbook_compiler = CookbookCompiler.new(self, run_list_expansion, events)
cookbook_compiler.compile
end
#
# Initialize state that applies to both Chef::RunContext and Chef::ChildRunContext
#
def initialize_child_state
@audits = {}
@resource_collection = Chef::ResourceCollection.new(self)
@before_notification_collection = Hash.new { |h, k| h[k] = [] }
@immediate_notification_collection = Hash.new { |h, k| h[k] = [] }
@delayed_notification_collection = Hash.new { |h, k| h[k] = [] }
@delayed_actions = []
end
#
# Adds an before notification to the +before_notification_collection+.
#
# @param [Chef::Resource::Notification] The notification to add.
#
def notifies_before(notification)
# Note for the future, notification.notifying_resource may be an instance
# of Chef::Resource::UnresolvedSubscribes when calling {Resource#subscribes}
# with a string value.
before_notification_collection[notification.notifying_resource.declared_key] << notification
end
#
# Adds an immediate notification to the +immediate_notification_collection+.
#
# @param [Chef::Resource::Notification] The notification to add.
#
def notifies_immediately(notification)
# Note for the future, notification.notifying_resource may be an instance
# of Chef::Resource::UnresolvedSubscribes when calling {Resource#subscribes}
# with a string value.
immediate_notification_collection[notification.notifying_resource.declared_key] << notification
end
#
# Adds a delayed notification to the +delayed_notification_collection+.
#
# @param [Chef::Resource::Notification] The notification to add.
#
def notifies_delayed(notification)
# Note for the future, notification.notifying_resource may be an instance
# of Chef::Resource::UnresolvedSubscribes when calling {Resource#subscribes}
# with a string value.
delayed_notification_collection[notification.notifying_resource.declared_key] << notification
end
#
# Adds a delayed action to the +delayed_actions+.
#
def add_delayed_action(notification)
if delayed_actions.any? { |existing_notification| existing_notification.duplicates?(notification) }
Chef::Log.info( "#{notification.notifying_resource} not queuing delayed action #{notification.action} on #{notification.resource}"\
" (delayed), as it's already been queued")
else
delayed_actions << notification
end
end
#
# Get the list of before notifications sent by the given resource.
#
# @return [Array[Notification]]
#
def before_notifications(resource)
return before_notification_collection[resource.declared_key]
end
#
# Get the list of immediate notifications sent by the given resource.
#
# @return [Array[Notification]]
#
def immediate_notifications(resource)
return immediate_notification_collection[resource.declared_key]
end
#
# Get the list of delayed (end of run) notifications sent by the given
# resource.
#
# @return [Array[Notification]]
#
def delayed_notifications(resource)
return delayed_notification_collection[resource.declared_key]
end
#
# Cookbook and recipe loading
#
#
# Evaluates the recipes +recipe_names+. Used by DSL::IncludeRecipe
#
# @param recipe_names [Array[String]] The list of recipe names (e.g.
# 'my_cookbook' or 'my_cookbook::my_resource').
# @param current_cookbook The cookbook we are currently running in.
#
# @see DSL::IncludeRecipe#include_recipe
#
def include_recipe(*recipe_names, current_cookbook: nil)
result_recipes = Array.new
recipe_names.flatten.each do |recipe_name|
if result = load_recipe(recipe_name, current_cookbook: current_cookbook)
result_recipes << result
end
end
result_recipes
end
#
# Evaluates the recipe +recipe_name+. Used by DSL::IncludeRecipe
#
# TODO I am sort of confused why we have both this and include_recipe ...
# I don't see anything different beyond accepting and returning an
# array of recipes.
#
# @param recipe_names [Array[String]] The recipe name (e.g 'my_cookbook' or
# 'my_cookbook::my_resource').
# @param current_cookbook The cookbook we are currently running in.
#
# @return A truthy value if the load occurred; `false` if already loaded.
#
# @see DSL::IncludeRecipe#load_recipe
#
def load_recipe(recipe_name, current_cookbook: nil)
Chef::Log.debug("Loading recipe #{recipe_name} via include_recipe")
cookbook_name, recipe_short_name = Chef::Recipe.parse_recipe_name(recipe_name, current_cookbook: current_cookbook)
if unreachable_cookbook?(cookbook_name) # CHEF-4367
Chef::Log.warn(<<-ERROR_MESSAGE)
MissingCookbookDependency:
Recipe `#{recipe_name}` is not in the run_list, and cookbook '#{cookbook_name}'
is not a dependency of any cookbook in the run_list. To load this recipe,
first add a dependency on cookbook '#{cookbook_name}' in the cookbook you're
including it from in that cookbook's metadata.
ERROR_MESSAGE
end
if loaded_fully_qualified_recipe?(cookbook_name, recipe_short_name)
Chef::Log.debug("I am not loading #{recipe_name}, because I have already seen it.")
false
else
loaded_recipe(cookbook_name, recipe_short_name)
node.loaded_recipe(cookbook_name, recipe_short_name)
cookbook = cookbook_collection[cookbook_name]
cookbook.load_recipe(recipe_short_name, self)
end
end
#
# Load the given recipe from a filename.
#
# @param recipe_file [String] The recipe filename.
#
# @return [Chef::Recipe] The loaded recipe.
#
# @raise [Chef::Exceptions::RecipeNotFound] If the file does not exist.
#
def load_recipe_file(recipe_file)
if !File.exist?(recipe_file)
raise Chef::Exceptions::RecipeNotFound, "could not find recipe file #{recipe_file}"
end
Chef::Log.debug("Loading recipe file #{recipe_file}")
recipe = Chef::Recipe.new("@recipe_files", recipe_file, self)
recipe.from_file(recipe_file)
recipe
end
#
# Look up an attribute filename.
#
# @param cookbook_name [String] The cookbook name of the attribute file.
# @param attr_file_name [String] The attribute file's name (not path).
#
# @return [String] The filename.
#
# @see DSL::IncludeAttribute#include_attribute
#
# @raise [Chef::Exceptions::CookbookNotFound] If the cookbook could not be found.
# @raise [Chef::Exceptions::AttributeNotFound] If the attribute file could not be found.
#
def resolve_attribute(cookbook_name, attr_file_name)
cookbook = cookbook_collection[cookbook_name]
raise Chef::Exceptions::CookbookNotFound, "could not find cookbook #{cookbook_name} while loading attribute #{name}" unless cookbook
attribute_filename = cookbook.attribute_filenames_by_short_filename[attr_file_name]
raise Chef::Exceptions::AttributeNotFound, "could not find filename for attribute #{attr_file_name} in cookbook #{cookbook_name}" unless attribute_filename
attribute_filename
end
#
# A list of all recipes that have been loaded.
#
# This is stored internally as a Hash, so ordering is predictable.
#
# TODO is the above statement true in a 1.9+ ruby world? Is it relevant?
#
# @return [Array[String]] A list of recipes in fully qualified form, e.g.
# the recipe "nginx" will be given as "nginx::default".
#
# @see #loaded_recipe? To determine if a particular recipe has been loaded.
#
def loaded_recipes
loaded_recipes_hash.keys
end
#
# A list of all attributes files that have been loaded.
#
# Stored internally using a Hash, so order is predictable.
#
# TODO is the above statement true in a 1.9+ ruby world? Is it relevant?
#
# @return [Array[String]] A list of attribute file names in fully qualified
# form, e.g. the "nginx" will be given as "nginx::default".
#
def loaded_attributes
loaded_attributes_hash.keys
end
#
# Find out if a given recipe has been loaded.
#
# @param cookbook [String] Cookbook name.
# @param recipe [String] Recipe name.
#
# @return [Boolean] `true` if the recipe has been loaded, `false` otherwise.
#
def loaded_fully_qualified_recipe?(cookbook, recipe)
loaded_recipes_hash.has_key?("#{cookbook}::#{recipe}")
end
#
# Find out if a given recipe has been loaded.
#
# @param recipe [String] Recipe name. "nginx" and "nginx::default" yield
# the same results.
#
# @return [Boolean] `true` if the recipe has been loaded, `false` otherwise.
#
def loaded_recipe?(recipe)
cookbook, recipe_name = Chef::Recipe.parse_recipe_name(recipe)
loaded_fully_qualified_recipe?(cookbook, recipe_name)
end
#
# Mark a given recipe as having been loaded.
#
# @param cookbook [String] Cookbook name.
# @param recipe [String] Recipe name.
#
def loaded_recipe(cookbook, recipe)
loaded_recipes_hash["#{cookbook}::#{recipe}"] = true
end
#
# Find out if a given attribute file has been loaded.
#
# @param cookbook [String] Cookbook name.
# @param attribute_file [String] Attribute file name.
#
# @return [Boolean] `true` if the recipe has been loaded, `false` otherwise.
#
def loaded_fully_qualified_attribute?(cookbook, attribute_file)
loaded_attributes_hash.has_key?("#{cookbook}::#{attribute_file}")
end
#
# Mark a given attribute file as having been loaded.
#
# @param cookbook [String] Cookbook name.
# @param attribute_file [String] Attribute file name.
#
def loaded_attribute(cookbook, attribute_file)
loaded_attributes_hash["#{cookbook}::#{attribute_file}"] = true
end
##
# Cookbook File Introspection
#
# Find out if the cookbook has the given template.
#
# @param cookbook [String] Cookbook name.
# @param template_name [String] Template name.
#
# @return [Boolean] `true` if the template is in the cookbook, `false`
# otherwise.
# @see Chef::CookbookVersion#has_template_for_node?
#
def has_template_in_cookbook?(cookbook, template_name)
cookbook = cookbook_collection[cookbook]
cookbook.has_template_for_node?(node, template_name)
end
#
# Find out if the cookbook has the given file.
#
# @param cookbook [String] Cookbook name.
# @param cb_file_name [String] File name.
#
# @return [Boolean] `true` if the file is in the cookbook, `false`
# otherwise.
# @see Chef::CookbookVersion#has_cookbook_file_for_node?
#
def has_cookbook_file_in_cookbook?(cookbook, cb_file_name)
cookbook = cookbook_collection[cookbook]
cookbook.has_cookbook_file_for_node?(node, cb_file_name)
end
#
# Find out whether the given cookbook is in the cookbook dependency graph.
#
# @param cookbook_name [String] Cookbook name.
#
# @return [Boolean] `true` if the cookbook is reachable, `false` otherwise.
#
# @see Chef::CookbookCompiler#unreachable_cookbook?
def unreachable_cookbook?(cookbook_name)
cookbook_compiler.unreachable_cookbook?(cookbook_name)
end
#
# Open a stream object that can be printed into and will dispatch to events
#
# @param name [String] The name of the stream.
# @param options [Hash] Other options for the stream.
#
# @return [EventDispatch::EventsOutputStream] The created stream.
#
# @yield If a block is passed, it will be run and the stream will be closed
# afterwards.
# @yieldparam stream [EventDispatch::EventsOutputStream] The created stream.
#
def open_stream(name: nil, **options)
stream = EventDispatch::EventsOutputStream.new(events, name: name, **options)
if block_given?
begin
yield stream
ensure
stream.close
end
else
stream
end
end
# there are options for how to handle multiple calls to these functions:
# 1. first call always wins (never change reboot_info once set).
# 2. last call always wins (happily change reboot_info whenever).
# 3. raise an exception on the first conflict.
# 4. disable reboot after this run if anyone ever calls :cancel.
# 5. raise an exception on any second call.
# 6. ?
def request_reboot(reboot_info)
Chef::Log.info "Changing reboot status from #{self.reboot_info.inspect} to #{reboot_info.inspect}"
@reboot_info = reboot_info
end
def cancel_reboot
Chef::Log.info "Changing reboot status from #{reboot_info.inspect} to {}"
@reboot_info = {}
end
def reboot_requested?
reboot_info.size > 0
end
#
# Create a child RunContext.
#
def create_child
ChildRunContext.new(self)
end
# @api private
attr_writer :resource_collection
protected
attr_reader :cookbook_compiler
attr_reader :loaded_attributes_hash
attr_reader :loaded_recipes_hash
module Deprecated
###
# These need to be settable so deploy can run a resource_collection
# independent of any cookbooks via +recipe_eval+
def audits=(value)
Chef.log_deprecation("Setting run_context.audits will be removed in a future Chef. Use run_context.create_child to create a new RunContext instead.")
@audits = value
end
def immediate_notification_collection=(value)
Chef.log_deprecation("Setting run_context.immediate_notification_collection will be removed in a future Chef. Use run_context.create_child to create a new RunContext instead.")
@immediate_notification_collection = value
end
def delayed_notification_collection=(value)
Chef.log_deprecation("Setting run_context.delayed_notification_collection will be removed in a future Chef. Use run_context.create_child to create a new RunContext instead.")
@delayed_notification_collection = value
end
end
prepend Deprecated
#
# A child run context. Delegates all root context calls to its parent.
#
# @api private
#
class ChildRunContext < RunContext
extend Forwardable
def_delegators :parent_run_context, *%w{
cancel_reboot
config
cookbook_collection
cookbook_compiler
definitions
events
has_cookbook_file_in_cookbook?
has_template_in_cookbook?
load
loaded_attribute
loaded_attributes
loaded_attributes_hash
loaded_fully_qualified_attribute?
loaded_fully_qualified_recipe?
loaded_recipe
loaded_recipe?
loaded_recipes
loaded_recipes_hash
node
open_stream
reboot_info
reboot_info=
reboot_requested?
request_reboot
resolve_attribute
unreachable_cookbook?
}
def initialize(parent_run_context)
@parent_run_context = parent_run_context
# We don't call super, because we don't bother initializing stuff we're
# going to delegate to the parent anyway. Just initialize things that
# every instance needs.
initialize_child_state
end
CHILD_STATE = %w{
audits
audits=
create_child
add_delayed_action
delayed_actions
delayed_notification_collection
delayed_notification_collection=
delayed_notifications
immediate_notification_collection
immediate_notification_collection=
immediate_notifications
before_notification_collection
before_notifications
include_recipe
initialize_child_state
load_recipe
load_recipe_file
notifies_before
notifies_immediately
notifies_delayed
parent_run_context
root_run_context
resource_collection
resource_collection=
}.map { |x| x.to_sym }
# Verify that we didn't miss any methods
unless @__skip_method_checking # hook specifically for compat_resource
missing_methods = superclass.instance_methods(false) - instance_methods(false) - CHILD_STATE
if !missing_methods.empty?
raise "ERROR: not all methods of RunContext accounted for in ChildRunContext! All methods must be marked as child methods with CHILD_STATE or delegated to the parent_run_context. Missing #{missing_methods.join(", ")}."
end
end
end
end
end
end

View File

@@ -0,0 +1,153 @@
#
# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE
#
# THIS IS A FILE AUTOGENERATED BY 'rake update' DO NOT EDIT!!!!
#
# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE
#
if Gem::Requirement.new('< 12.16.42').satisfied_by?(Gem::Version.new(Chef::VERSION))
#--
# Author:: Adam Jacob (<adam@chef.io>)
# Author:: Christopher Walters (<cw@chef.io>)
# Author:: Tim Hinderliter (<tim@chef.io>)
# Copyright:: Copyright 2008-2016, 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 "chef/exceptions"
require "chef/mixin/params_validate"
require "chef/node"
require "chef/resource_collection"
class Chef
# == Chef::Runner
# This class is responsible for executing the steps in a Chef run.
class Runner
attr_reader :run_context
include Chef::Mixin::ParamsValidate
def initialize(run_context)
@run_context = run_context
end
def delayed_actions
@run_context.delayed_actions
end
def events
@run_context.events
end
# Determine the appropriate provider for the given resource, then
# execute it.
def run_action(resource, action, notification_type = nil, notifying_resource = nil)
# If there are any before notifications, why-run the resource
# and notify anyone who needs notifying
before_notifications = run_context.before_notifications(resource) || []
unless before_notifications.empty?
forced_why_run do
Chef::Log.info("#{resource} running why-run #{action} action to support before action")
resource.run_action(action, notification_type, notifying_resource)
end
if resource.updated_by_last_action?
before_notifications.each do |notification|
Chef::Log.info("#{resource} sending #{notification.action} action to #{notification.resource} (before)")
run_action(notification.resource, notification.action, :before, resource)
end
resource.updated_by_last_action(false)
end
end
# Actually run the action for realsies
resource.run_action(action, notification_type, notifying_resource)
# Execute any immediate and queue up any delayed notifications
# associated with the resource, but only if it was updated *this time*
# we ran an action on it.
if resource.updated_by_last_action?
run_context.immediate_notifications(resource).each do |notification|
Chef::Log.info("#{resource} sending #{notification.action} action to #{notification.resource} (immediate)")
run_action(notification.resource, notification.action, :immediate, resource)
end
run_context.delayed_notifications(resource).each do |notification|
# send the notification to the run_context of the receiving resource
notification.resource.run_context.add_delayed_action(notification)
end
end
end
# Iterates over the +resource_collection+ in the +run_context+ calling
# +run_action+ for each resource in turn.
def converge
# Resolve all lazy/forward references in notifications
run_context.resource_collection.each do |resource|
resource.resolve_notification_references
end
# Execute each resource.
run_context.resource_collection.execute_each_resource do |resource|
Array(resource.action).each { |action| run_action(resource, action) }
end
rescue Exception => e
Chef::Log.info "Running queued delayed notifications before re-raising exception"
run_delayed_notifications(e)
else
run_delayed_notifications(nil)
true
end
private
# Run all our :delayed actions
def run_delayed_notifications(error = nil)
collected_failures = Exceptions::MultipleFailures.new
collected_failures.client_run_failure(error) unless error.nil?
delayed_actions.each do |notification|
result = run_delayed_notification(notification)
if result.kind_of?(Exception)
collected_failures.notification_failure(result)
end
end
collected_failures.raise!
end
def run_delayed_notification(notification)
Chef::Log.info( "#{notification.notifying_resource} sending #{notification.action}"\
" action to #{notification.resource} (delayed)")
# Struct of resource/action to call
run_action(notification.resource, notification.action, :delayed)
true
rescue Exception => e
e
end
# helper to run a block of code with why_run forced to true and then restore it correctly
def forced_why_run
saved = Chef::Config[:why_run]
Chef::Config[:why_run] = true
yield
ensure
Chef::Config[:why_run] = saved
end
end
end
end

View File

@@ -0,0 +1,6 @@
require 'chef_compat/copied_from_chef/chef/property'
module ChefCompat
class Property < ChefCompat::CopiedFromChef::Chef::Property
end
end

View File

@@ -0,0 +1,8 @@
require 'chef/recipe'
require 'chef_compat/copied_from_chef/chef/dsl/recipe'
module ChefCompat
class Recipe < Chef::Recipe
include ChefCompat::CopiedFromChef::Chef::DSL::Recipe::FullDSL
end
end

View File

@@ -0,0 +1,56 @@
require 'chef_compat/monkeypatches'
require 'chef_compat/copied_from_chef/chef/resource'
# We do NOT want action defined if chefspec is engaged
if Chef::Provider::InlineResources::ClassMethods.instance_method(:action).source_location[0] =~ /chefspec/
ChefCompat::CopiedFromChef::Chef::Provider::InlineResources::ClassMethods.instance_eval do
remove_method(:action)
end
end
module ChefCompat
class Resource < ChefCompat::CopiedFromChef::Chef::Resource
def initialize(*args, &block)
super
# @resource_name is used in earlier Chef versions
@resource_name = self.class.resource_name
end
# Things we'll need to define ourselves:
# 1. provider
# 2. resource_name
def provider(*args, &block)
super || self.class.action_class
end
def provider=(arg)
provider(arg)
end
if !respond_to?(:resource_name)
def self.resource_name(name=Chef::NOT_PASSED)
# Setter
if name != Chef::NOT_PASSED
# remove_canonical_dsl
# Set the resource_name and call provides
if name
name = name.to_sym
# If our class is not already providing this name, provide it.
# Commented out: use of resource_name and provides will need to be
# mutually exclusive in this world, generally.
# if !Chef::ResourceResolver.includes_handler?(name, self)
provides name#, canonical: true
# end
@resource_name = name
else
@resource_name = nil
end
end
@resource_name
end
def self.resource_name=(name)
resource_name(name)
end
end
end
end

View File

@@ -0,0 +1,44 @@
require 'chef_compat/resource'
require 'chef_compat/copied_from_chef/chef/resource'
require 'chef/mixin/convert_to_class_name'
require 'chef/mixin/from_file'
module ChefCompat
class Resource < ChefCompat::CopiedFromChef::Chef::Resource
class LWRPBase < ChefCompat::Resource
class<<self
include Chef::Mixin::ConvertToClassName
include Chef::Mixin::FromFile
alias :attribute :property
# Adds +action_names+ to the list of valid actions for this resource.
# Does not include superclass's action list when appending.
def actions(*action_names)
action_names = action_names.flatten
if !action_names.empty? && !@allowed_actions
self.allowed_actions = ([ :nothing ] + action_names).uniq
else
allowed_actions(*action_names)
end
end
alias :actions= :allowed_actions=
# @deprecated
def valid_actions(*args)
Chef::Log.warn("`valid_actions' is deprecated, please use allowed_actions `instead'!")
allowed_actions(*args)
end
# Set the run context on the class. Used to provide access to the node
# during class definition.
attr_accessor :run_context
def node
run_context ? run_context.node : nil
end
end
end
end
end

View File

@@ -0,0 +1,3 @@
module ChefCompat
CHEF_UPSTREAM_VERSION="12.16.42" unless defined? CHEF_UPSTREAM_VERSION
end

View File

@@ -0,0 +1,35 @@
require "chef/version"
if Gem::Requirement.new(">= 12.0").satisfied_by?(Gem::Version.new(Chef::VERSION))
require 'chef_compat/resource'
require 'chef_compat/property'
require 'chef_compat/mixin/properties'
resources_dir = File.expand_path("chef_compat/copied_from_chef/chef/resource", File.dirname(__FILE__))
providers_dir = File.expand_path("chef_compat/copied_from_chef/chef/provider", File.dirname(__FILE__))
Dir["#{resources_dir}/*.rb"].each {|file| require file }
Dir["#{providers_dir}/*.rb"].each {|file| require file }
else
class Chef
class Resource
def self.property(args, &block)
raise_chef_11_error
end
def self.resource_name(args, &block)
raise_chef_11_error
end
def self.action(args, &block)
raise_chef_11_error
end
def self.raise_chef_11_error
raise "This resource is written with Chef 12.5 custom resources, and requires at least Chef 12.0 used with the compat_resource cookbook, it will not work with Chef 11.x clients, and those users must pin their cookbooks to older versions or upgrade."
end
end
end
end