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:
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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 -%>
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -0,0 +1,6 @@
|
||||
require 'chef_compat/copied_from_chef/chef/property'
|
||||
|
||||
module ChefCompat
|
||||
class Property < ChefCompat::CopiedFromChef::Chef::Property
|
||||
end
|
||||
end
|
||||
@@ -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
|
||||
56
cookbooks/compat_resource/files/lib/chef_compat/resource.rb
Normal file
56
cookbooks/compat_resource/files/lib/chef_compat/resource.rb
Normal 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
|
||||
@@ -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
|
||||
@@ -0,0 +1,3 @@
|
||||
module ChefCompat
|
||||
CHEF_UPSTREAM_VERSION="12.16.42" unless defined? CHEF_UPSTREAM_VERSION
|
||||
end
|
||||
35
cookbooks/compat_resource/files/lib/compat_resource.rb
Normal file
35
cookbooks/compat_resource/files/lib/compat_resource.rb
Normal 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
|
||||
Reference in New Issue
Block a user