Update chef-sugar to fix a conflict in Chef 16+

This commit is contained in:
Greg Karékinian
2023-06-28 16:08:32 +02:00
parent b9cf396d42
commit ddeebc739d
63 changed files with 4700 additions and 101 deletions

View File

@@ -0,0 +1,51 @@
#
# Copyright 2013-2015, Seth Vargo <sethvargo@gmail.com>
#
# 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/recipe'
require 'chef/resource'
require 'chef/provider'
class Chef
module Sugar
require_relative 'sugar/architecture'
require_relative 'sugar/cloud'
require_relative 'sugar/constraints'
require_relative 'sugar/constraints_dsl'
require_relative 'sugar/data_bag'
require_relative 'sugar/docker'
require_relative 'sugar/filters'
require_relative 'sugar/init'
require_relative 'sugar/ip'
require_relative 'sugar/kernel'
require_relative 'sugar/kitchen'
require_relative 'sugar/node'
require_relative 'sugar/platform'
require_relative 'sugar/platform_family'
require_relative 'sugar/ruby'
require_relative 'sugar/run_context'
require_relative 'sugar/shell'
require_relative 'sugar/vagrant'
require_relative 'sugar/version'
require_relative 'sugar/virtualization'
end
end
Chef::Recipe.send(:include, Chef::Sugar::DSL)
Chef::Recipe.send(:include, Chef::Sugar::RecipeDSL) # TODO: this is a hack
Chef::Resource.send(:include, Chef::Sugar::DSL)
Chef::Provider.send(:include, Chef::Sugar::DSL)
Object.send(:include, Chef::Sugar::Kernel)

View File

@@ -0,0 +1,176 @@
#
# Copyright 2013-2015, Seth Vargo <sethvargo@gmail.com>
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
class Chef
module Sugar
module Architecture
extend self
# these helpers have been moved to core-chef
if !defined?(Chef::VERSION) || Gem::Requirement.new("< 15.4.70").satisfied_by?(Gem::Version.new(Chef::VERSION))
#
# Determine if the current architecture is 64-bit
#
# @return [Boolean]
#
def _64_bit?(node)
%w(amd64 x86_64 ppc64 ppc64le s390x ia64 sparc64 aarch64 arch64 arm64 sun4v sun4u s390x)
.include?(node['kernel']['machine']) || ( node['kernel']['bits'] == '64' )
end
#
# Determine if the current architecture is 32-bit
#
# @todo Make this more than "not 64-bit"
#
# @return [Boolean]
#
def _32_bit?(node)
!_64_bit?(node)
end
#
# Determine if the current architecture is i386
#
# @return [Boolean]
#
def i386?(node)
_32_bit?(node) && intel?(node)
end
#
# Determine if the current architecture is Intel.
#
# @return [Boolean]
#
def intel?(node)
%w(i86pc i386 x86_64 amd64 i686)
.include?(node['kernel']['machine'])
end
#
# Determine if the current architecture is SPARC.
#
# @return [Boolean]
#
def sparc?(node)
%w(sun4u sun4v)
.include?(node['kernel']['machine'])
end
#
# Determine if the current architecture is Powerpc64 Big Endian
#
# @return [Boolean]
#
def ppc64?(node)
%w(ppc64)
.include?(node['kernel']['machine'])
end
#
# Determine if the current architecture is Powerpc64 Little Endian
#
# @return [Boolean]
#
def ppc64le?(node)
%w(ppc64le)
.include?(node['kernel']['machine'])
end
#
# Determine if the current architecture is PowerPC
#
# @return [Boolean]
#
def powerpc?(node)
%w(powerpc)
.include?(node['kernel']['machine'])
end
#
# Determine if the current architecture is ARM with Hard Float
#
# @return [Boolean]
#
def armhf?(node)
# Add more arm variants as needed here
%w(armv6l armv7l)
.include?(node['kernel']['machine'])
end
#
# Determine if the current architecture is AArch64
#
# @return [Boolean]
#
def aarch64?(node)
# Add more arm variants as needed here
%w(aarch64)
.include?(node['kernel']['machine'])
end
#
# Determine if the current architecture is s390x
#
# @return [Boolean]
#
def s390x?(node)
%w(s390x)
.include?(node['kernel']['machine'])
end
end
end
module DSL
if !defined?(Chef::VERSION) || Gem::Requirement.new("< 15.4.70").satisfied_by?(Gem::Version.new(Chef::VERSION))
# @see Chef::Sugar::Architecture#_64_bit?
def _64_bit?; Chef::Sugar::Architecture._64_bit?(node); end
# @see Chef::Sugar::Architecture#_32_bit?
def _32_bit?; Chef::Sugar::Architecture._32_bit?(node); end
# @see Chef::Sugar::Architecture#intel?
def i386?; Chef::Sugar::Architecture.i386?(node); end
# @see Chef::Sugar::Architecture#intel?
def intel?; Chef::Sugar::Architecture.intel?(node); end
# @see Chef::Sugar::Architecture#sparc?
def sparc?; Chef::Sugar::Architecture.sparc?(node); end
# @see Chef::Sugar::Architecture#ppc64?
def ppc64?; Chef::Sugar::Architecture.ppc64?(node); end
# @see Chef::Sugar::Architecture#ppc64le?
def ppc64le?; Chef::Sugar::Architecture.ppc64le?(node); end
# @see Chef::Sugar::Architecture#powerpc?
def powerpc?; Chef::Sugar::Architecture.powerpc?(node); end
# @see Chef::Sugar::Architecture#arm?
def armhf?; Chef::Sugar::Architecture.armhf?(node); end
# @see Chef::Sugar::Architecture#aarch64?
def aarch64?; Chef::Sugar::Architecture.aarch64?(node); end
# @see Chef::Sugar::Architecture#s390x?
def s390x?; Chef::Sugar::Architecture.s390x?(node); end
end
end
end
end

View File

@@ -0,0 +1,192 @@
#
# Copyright 2013-2015, Seth Vargo <sethvargo@gmail.com>
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
class Chef
module Sugar
module Cloud
extend self
#
# Return true if the current current node is in "the cloud".
#
# @param [Chef::Node] node
# the node to check
#
# @return [Boolean]
#
def cloud?(node)
node.key?('cloud')
end
#
# Return true if the current current node is in EC2
#
# @param [Chef::Node] node
# the node to check
#
# @return [Boolean]
#
def ec2?(node)
node.key?('ec2')
end
#
# Return true if the current current node is in GCE
#
# @param [Chef::Node] node
# the node to check
#
# @return [Boolean]
#
def gce?(node)
node.key?('gce')
end
#
# Return true if the current current node is in Rackspace
#
# @param [Chef::Node] node
# the node to check
#
# @return [Boolean]
#
def rackspace?(node)
node.key?('rackspace')
end
#
# Return true if the current current node is in Eucalyptus
#
# @param [Chef::Node] node
# the node to check
#
# @return [Boolean]
#
def eucalyptus?(node)
node.key?('eucalyptus')
end
alias_method :euca?, :eucalyptus?
#
# Return true if the current current node is in Linode
#
# @param [Chef::Node] node
# the node to check
#
# @return [Boolean]
#
def linode?(node)
node.key?('linode')
end
#
# Return true if the current current node is in Openstack
#
# @param [Chef::Node] node
# the node to check
#
# @return [Boolean]
#
def openstack?(node)
node.key?('openstack')
end
#
# Return true if the current current node is in Cloudstack
#
# @param [Chef::Node] node
# the node to check
#
# @return [Boolean]
#
def cloudstack?(node)
node.key?('cloudstack')
end
#
# Return true if the current current node is in Azure
#
# @param [Chef::Node] node
# the node to check
#
# @return [Boolean]
#
def azure?(node)
node.key?('azure')
end
#
# Return true if the current current node is in DigitalOcean
#
# @param [Chef::Node] node
# the node to check
#
# @return [Boolean]
#
def digitalocean?(node)
node.key?('digital_ocean')
end
#
# Return true if the current current node is in SoftLayer
#
# @param [Chef::Node] node
# the node to check
#
# @return [Boolean]
#
def softlayer?(node)
node.key?('softlayer')
end
end
module DSL
# @see Chef::Sugar::Cloud#cloud?
def cloud?; Chef::Sugar::Cloud.cloud?(node); end
# @see Chef::Sugar::Cloud#ec2?
def ec2?; Chef::Sugar::Cloud.ec2?(node); end
# @see Chef::Sugar::Cloud#gce?
def gce?; Chef::Sugar::Cloud.gce?(node); end
# @see Chef::Sugar::Cloud#rackspace?
def rackspace?; Chef::Sugar::Cloud.rackspace?(node); end
# @see Chef::Sugar::Cloud#eucalyptus?
def eucalyptus?; Chef::Sugar::Cloud.eucalyptus?(node); end
alias_method :euca?, :eucalyptus?
# @see Chef::Sugar::Cloud#linode?
def linode?; Chef::Sugar::Cloud.linode?(node); end
# @see Chef::Sugar::Cloud#openstack?
def openstack?; Chef::Sugar::Cloud.openstack?(node); end
# @see Chef::Sugar::Cloud#cloudstack?
def cloudstack?; Chef::Sugar::Cloud.cloudstack?(node); end
# @see Chef::Sugar::Cloud#azure?
def azure?; Chef::Sugar::Cloud.azure?(node); end
# @see Chef::Sugar::Cloud#digitalocean?
def digitalocean?; Chef::Sugar::Cloud.digitalocean?(node); end
# @see Chef::Sugar::Cloud#softlayer?
def softlayer?; Chef::Sugar::Cloud.softlayer?(node); end
end
end
end

View File

@@ -0,0 +1,108 @@
#
# Copyright 2013-2015, Seth Vargo <sethvargo@gmail.com>
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
class Chef
module Sugar
module Constraints
#
# This class is a wrapper around a version requirement that adds a nice
# DSL for comparing constraints:
#
# @example Comparing a single constraint
# Constraint.new('~> 1.2.3').satisfied_by?('1.2.7')
#
# @example Comparing multiple constraints
# Constraint.new('> 1.2.3', '< 2.0.0').satisfied_by?('1.2.7')
#
class Constraint
#
# Create a new constraint object.
#
# @param [String, Array<String>] constraints
# the list of constraints
#
def initialize(*constraints)
@requirement = Gem::Requirement.new(*constraints)
end
#
# Determine if the given version string is satisfied by this constraint
# or group of constraints.
#
# @example Given a satisified constraint
# Constraint.new('~> 1.2.0').satisfied_by?('1.2.5') #=> true
#
# @example Given an unsatisfied constraint
# Constraint.new('~> 1.2.0').satisfied_by?('2.0.0') #=> false
#
#
# @param [String] version
# the version to compare
#
# @return [Boolean]
# true if the constraint is satisfied, false otherwise
#
def satisfied_by?(version)
@requirement.satisfied_by?(Gem::Version.new(version))
end
end
#
# This class exposes a single version constraint object that wraps the
# string representation of a version string and proved helpful comparator
# methods.
#
# @example Create a new version
# Chef::Sugar::Version('1.2.3')
#
# @example Compare a version with constraints
# Chef::Sugar::Version('1.2.3').satisfies?('~> 1.3.4', '< 2.0.5')
#
class Version < String
#
# Create a new version object.
#
# @param [String] version
# the version to create
#
def initialize(version)
super
@version = Gem::Version.new(version)
end
#
# Determine if the given constraint is satisfied by this version.
#
# @example Given a satisified version
# Version.new('1.2.5').satisfies?('~> 1.2.0') #=> true
#
# @example Given an unsatisfied version
# Version.new('2.0.0').satisfies?('~> 1.2.0') #=> false
#
#
# @param [String, Array<String>] constraints
# the constraints to satisfy
#
# @return [Boolean]
# true if the version satisfies the constraints, false otherwise
#
def satisfies?(*constraints)
Gem::Requirement.new(*constraints).satisfied_by?(@version)
end
end
end
end
end

View File

@@ -0,0 +1,83 @@
#
# Copyright 2013-2015, Seth Vargo <sethvargo@gmail.com>
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
require_relative 'constraints'
class Chef
module Sugar
#
# The Constraints DSL methods were broken out into this separate
# file to allow projects (such as Omnibus) to consume the
# Chef::Sugar::Constraints classes without the DSL methods
# stepping on existing methods of the same name.
#
module Constraints
extend self
#
# Shortcut method for creating a new {Version} object.
#
# @param [String] version
# the version (as a string) to create
#
# @return [Chef::Sugar::Constraints::Version]
# the new version object
#
def version(version)
Chef::Sugar::Constraints::Version.new(version)
end
#
# Shortcut method for creating a new {Constraint} object.
#
# @param [String, Array<String>] constraints
# the list of constraints to use
#
# @return [Chef::Sugar::Constraints::Constraint]
# the new constraint object
#
def constraint(*constraints)
Chef::Sugar::Constraints::Constraint.new(*constraints)
end
end
module DSL
# @see Chef::Sugar::Constraints#version
def version(version)
Chef::Sugar::Constraints::Version.new(version)
end
# @see Chef::Sugar::Constraints#constraint
def constraint(*constraints)
Chef::Sugar::Constraints.constraint(*constraints)
end
#
# This wrapper/convenience method is only available in the recipe DSL. It
# creates a new version object from the {Chef::VERSION}.
#
# @example Check if Chef 11+
# chef_version.satisfies?('>= 11.0.0')
#
# @return [Chef::Sugar::Constraints::Version]
# a version object, wrapping the current {Chef::VERSION}
#
def chef_version
version(Chef::VERSION)
end
end
end
end

View File

@@ -0,0 +1,19 @@
#
# Copyright 2013-2015, Seth Vargo <sethvargo@gmail.com>
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
require_relative 'core_extensions/array'
require_relative 'core_extensions/string'
require_relative 'core_extensions/object'

View File

@@ -0,0 +1,34 @@
#
# Copyright 2013-2015, Seth Vargo <sethvargo@gmail.com>
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
require_relative '../constraints'
class Array
#
# Treat an array of objects as version constraints.
#
# @see Chef::Sugar::Constraints::Constraint
#
# @example Using pure Array<String> objects like constraints
# ['> 2.0.0', '< 3.0.0'].satisfied_by?('2.1.0')
#
# @param [String] version
# the version to check if it is satisfied
#
def satisfied_by?(version)
Chef::Sugar::Constraints::Constraint.new(*dup).satisfied_by?(version)
end unless method_defined?(:satisfied_by?)
end

View File

@@ -0,0 +1,27 @@
#
# Copyright 2013-2015, Seth Vargo <sethvargo@gmail.com>
#
# 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 Object
# An object is blank if it's false, empty, or a whitespace string.
# This is implemented in rails.
#
# @example foo.nil? || foo.empty? can be replaced by foo.blank?
#
# @return [true, false]
def blank?
respond_to?(:empty?) ? empty? : !self
end unless method_defined?(:blank?)
end

View File

@@ -0,0 +1,66 @@
#
# Copyright 2013-2015, Seth Vargo <sethvargo@gmail.com>
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# require_relative '../constraints'
class String
#
# Treat strings as version objects.
#
# @see Chef::Sugar::Constraints::Version
#
# @example Using pure string objects like versions
# '1.2.3'.satisfies?('~> 1.2.0')
#
# @param [String, Array<String>] constraints
# the list of constraints to satisfy
#
def satisfies?(*constraints)
Chef::Sugar::Constraints::Version.new(dup).satisfies?(*constraints)
end unless method_defined?(:satisfies?)
#
# Treat strings as version constraints.
#
# @see Chef::Sugar::Constraints::Constraint
#
# @example Using pure string objects like constraints
# '~> 1.2.0'.satisfied_by?('1.2.3')
#
# @param [String] version
# the version to check if it is satisfied
#
def satisfied_by?(version)
Chef::Sugar::Constraints::Constraint.new(dup).satisfied_by?(version)
end unless method_defined?(:satisfied_by?)
#
# Left-flush a string based off of the number of whitespace characters on the
# first line. This is especially useful for heredocs when whitespace matters.
#
# @example Remove leading whitespace and flush
# <<-EOH.flush
# def method
# 'This is a string!'
# end
# EOH #=>"def method\n 'This is a string!'\nend"
#
# @return [String]
#
def flush
gsub(/^#{self[/\A\s*/]}/, '').chomp
end unless method_defined?(:flush)
end

View File

@@ -0,0 +1,146 @@
#
# Copyright 2013-2015, Seth Vargo <sethvargo@gmail.com>
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
class Chef
module Sugar
module DataBag
class EncryptedDataBagSecretNotGiven < StandardError
def initialize
super <<-EOH
You did not set your `encrypted_data_bag_secret'! In order to use the
`encrypted_data_bag_item' helper, you must load your encrypted data bag secret
into the `Chef::Config'.
Alternatively, you can pass the secret key as the last parameter to the method
call. For more information, please see
http://docs.opscode.com/chef/essentials_data_bags.html#access-from-recipe.
EOH
end
end
extend self
#
# Helper method for loading an encrypted data bag item in a similar
# syntax/recipe DSL method.
#
# @param [String] bag
# the name of the encrypted data bag
# @param [String] id
# the id of the encrypted data bag
# @param [String] secret
# the encrypted data bag secret raw value
#
# @return [Hash]
#
def encrypted_data_bag_item(bag, id, secret = nil)
Chef::Log.debug "Loading encrypted data bag item #{bag}/#{id}"
if secret.nil? && Chef::Config[:encrypted_data_bag_secret].nil?
raise EncryptedDataBagSecretNotGiven.new
end
secret ||= File.read(Chef::Config[:encrypted_data_bag_secret]).strip
Chef::EncryptedDataBagItem.load(bag, id, secret)
end
#
# This algorithm attempts to find the data bag entry for the current
# node's Chef environment. If there are no environment-specific
# values, the "default" bucket is used. The data bag must follow the
# schema:
#
# {
# "default": {...},
# "environment_name": {...},
# "other_environment": {...},
# }
#
# @param [Node] node
# the current Chef node
# @param [String] bag
# the name of the encrypted data bag
# @param [String] id
# the id of the encrypted data bag
# @param [String] secret
# the encrypted data bag secret (default's to the +Chef::Config+ value)
#
# @return [Hash]
#
def encrypted_data_bag_item_for_environment(node, bag, id, secret = nil)
data = encrypted_data_bag_item(bag, id, secret)
if data[node.chef_environment]
Chef::Log.debug "Using #{node.chef_environment} as the key"
data[node.chef_environment]
else
Chef::Log.debug "#{node.chef_environment} key does not exist, using `default`"
data['default']
end
end
#
# This algorithm attempts to find the data bag entry for the current
# node's Chef environment. If there are no environment-specific
# values, the "default" bucket is used. The data bag must follow the
# schema:
#
# {
# "default": {...},
# "environment_name": {...},
# "other_environment": {...},
# }
#
# @param [Node] node
# the current Chef node
# @param [String] bag
# the name of the data bag
# @param [String] id
# the id of the data bag
#
# @return [Hash]
#
def data_bag_item_for_environment(node, bag, id)
data = Chef::DataBagItem.load(bag, id)
if data[node.chef_environment]
Chef::Log.debug "Using #{node.chef_environment} as the key"
data[node.chef_environment]
else
Chef::Log.debug "#{node.chef_environment} key does not exist, using `default`"
data['default']
end
end
end
module DSL
# @see Chef::Sugar::DataBag#encrypted_data_bag_item
def encrypted_data_bag_item(bag, id, secret = nil)
Chef::Sugar::DataBag.encrypted_data_bag_item(bag, id, secret)
end
# @see Chef::Sugar::DataBag#encrypted_data_bag_item_for_environment
def encrypted_data_bag_item_for_environment(bag, id, secret = nil)
Chef::Sugar::DataBag.encrypted_data_bag_item_for_environment(node, bag, id, secret)
end
# @see Chef::Sugar::DataBag#data_bag_item_for_environment
def data_bag_item_for_environment(bag, id)
Chef::Sugar::DataBag.data_bag_item_for_environment(node, bag, id)
end
end
end
end

View File

@@ -0,0 +1,45 @@
#
# 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.
#
if defined?(Chef::Deprecated::Base)
class Chef
class Deprecated
class ChefSugar < Base
def id
28
end
def target
"chef_sugar.html"
end
end
end
end
end
class Chef
module Sugar
module Deprecation
if defined?(Chef::Deprecated::Base)
def deprecated(message)
Chef.deprecated(:chef_sugar, message)
end
else
def deprecated(message)
Chef::Log.warn(message)
end
end
extend self
end
end
end

View File

@@ -0,0 +1,45 @@
#
# Copyright 2013-2015, Seth Vargo <sethvargo@gmail.com>
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
class Chef
module Sugar
module Docker
extend self
# these helpers have been moved to core chef
if !defined?(Chef::VERSION) || Gem::Requirement.new("< 15.4.70").satisfied_by?(Gem::Version.new(Chef::VERSION))
#
# Returns true if the current node is a docker container.
#
# @param [Chef::Node] node
# the node to check
#
# @return [Boolean]
#
def docker?(node)
File.exist?('/.dockerinit') || File.exist?('/.dockerenv')
end
end
end
module DSL
if !defined?(Chef::VERSION) || Gem::Requirement.new("< 15.4.70").satisfied_by?(Gem::Version.new(Chef::VERSION))
# @see Chef::Sugar::Docker#docker?
def docker?; Chef::Sugar::Docker.docker?(node); end
end
end
end
end

View File

@@ -0,0 +1,227 @@
class Chef
module Sugar
module Filters
#
# Evaluate resources at compile time instead of converge time.
#
class AtCompileTime
def initialize(recipe)
@recipe = recipe
end
def evaluate(&block)
instance_eval(&block)
end
def method_missing(m, *args, &block)
resource = @recipe.send(m, *args, &block)
if resource.is_a?(Chef::Resource)
actions = Array(resource.action)
resource.action(:nothing)
actions.each do |action|
resource.run_action(action)
end
end
resource
end
end
#
# A top-level class for manipulation the resource collection.
#
class Injector
def initialize(recipe, identifier, placement)
@recipe = recipe
@resource_collection = @recipe.run_context.resource_collection
@resource = @resource_collection.lookup(identifier)
@placement = placement
end
def evaluate(&block)
instance_eval(&block)
end
def insert_before(resource, new_resource)
@resource_collection.instance_eval do
# Remove the resource because it's automatically created
@resources.delete_at(@resources_by_name[new_resource.to_s])
@resources_by_name.delete(new_resource.to_s)
index = @resources_by_name[resource.to_s]
@resources.insert(index, new_resource)
@resources_by_name[new_resource.to_s] = index
end
end
def insert_after(resource, new_resource)
@resource_collection.instance_eval do
# Remove the resource because it's automatically created
@resources.delete_at(@resources_by_name[new_resource.to_s])
@resources_by_name.delete(new_resource.to_s)
index = @resources_by_name[resource.to_s] + 2
@resources.insert(index, new_resource)
@resources_by_name[new_resource.to_s] = index
end
end
def method_missing(m, *args, &block)
new_resource = @recipe.send(m, *args, &block)
case @placement
when :before
insert_before(@resource, new_resource)
when :after
insert_after(@resource, new_resource)
else
super
end
end
end
end
module DSL
#
# Dynamically run resources specified in the block during the compilation
# phase, instead of the convergence phase.
#
# @example The old way
# package('apache2') do
# action :nothing
# end.run_action(:install)
#
# @example The new way
# at_compile_time do
# package('apache2')
# end
#
# @example Resource actions are run in order
# at_compile_time do
# service 'apache2' do
# action [:enable, :start] # run_action(:enable), run_action(:start)
# end
# end
#
def at_compile_time(&block)
Chef::Sugar::Filters::AtCompileTime.new(self).evaluate(&block)
end
#
# Dynamically insert resources before an existing resource in the
# resource_collection.
#
# @example Write a custom template before the apache2 service actions
# are run
# before 'service[apache2]' do
# template '/etc/apache2/thing.conf' do
# source '...'
# end
# end
#
#
# @param [String] identifier
# the +resource[name]+ identifier string
#
def before(identifier, &block)
Chef::Sugar::Filters::Injector.new(self, identifier, :before).evaluate(&block)
end
#
# Dynamically insert resources after an existing resource in the
# resource_collection.
#
# @example Write a custom template after the apache2 service actions
# are run
# after 'service[apache2]' do
# template '/etc/apache2/thing.conf' do
# source '...'
# end
# end
#
#
# @param [String] identifier
# the +resource[name]+ identifier string
#
def after(identifier, &block)
Chef::Sugar::Filters::Injector.new(self, identifier, :after).evaluate(&block)
end
end
module RecipeDSL
#
# @deprecated The description is in the method body pretty accurately...
#
def compile_time(&block)
message = <<-EOH
The Chef Sugar recipe DSL method `compile_time' has been renamed to
`at_compile_time'! This is a breaking change that was released in a patch
version, so please continue reading to understand the necessary semantic
versioning violation.
Chef Software implemented a version of `compile_time' in Chef 12.1, breaking any
cookbook that uses or depends on Chef Sugar on Chef 12.1:
https://www.chef.io/blog/2015/03/03/chef-12-1-0-released
In order to progress Chef Sugar forward, the DSL method has been renamed to
avoid the namespace collision.
In short, you should change this:
compile_time do
# ...
end
to this:
at_compile_time do
# ...
end
EOH
if Chef::Resource::ChefGem.instance_methods(false).include?(:compile_time)
message << <<-EOH
You are running a version of Chef Client that includes the `compile_time'
attribute on core Chef resources (most likely Chef 12.1+). Instead of continuing
and having Chef provide you with an obscure error message, I am going to error
here. There is no way for the Chef Recipe to successfully continue unless you
change the Chef Sugar `compile_time' method to `at_compile_time' in your Chef
recipes.
You should NOT change resource-level `compile_time' attributes:
package "foo" do
compile_time true # Do NOT change these
end
I truly apologize for the inconvienence and hope the reason for introducing this
breaking change is clear. I am sorry if it causes extra work, but I promise this
error message is much more informative than "wrong number of arguments".
If you have any questions, please feel free to open an issue on GitHub at:
https://github.com/sethvargo/chef-sugar
Thank you, and have a great day!
EOH
raise RuntimeError, message
else
message << <<-EOH
You are running a version of Chef Client that does not include the
`compile_time' attribute on core Chef resources (most likely less than
Chef 12.1), so this is just a warning. Please consider changing the Chef Sugar
`compile_time' method to `at_compile_time' in your Chef recipes. If you upgrade
Chef, your recipes WILL break.
EOH
Chef::Log.warn(message)
at_compile_time(&block)
end
end
end
end
end

View File

@@ -0,0 +1,61 @@
#
# Copyright 2015, Nathan Williams <nath.e.will@gmail.com>
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
class Chef
module Sugar
module Init
extend self
#
# Determine if the current init system is systemd.
#
# @return [Boolean]
#
def systemd?(node)
File.exist?('/bin/systemctl')
end
#
# Determine if the current init system is upstart.
#
# @return [Boolean]
#
def upstart?(node)
File.executable?('/sbin/initctl')
end
#
# Determine if the current init system is runit.
#
# @return [Boolean]
#
def runit?(node)
File.executable?('/sbin/runit-init')
end
end
module DSL
# @see Chef::Sugar::Init#systemd?
def systemd?; Chef::Sugar::Init.systemd?(node); end
# @see Chef::Sugar::Init#upstart?
def upstart?; Chef::Sugar::Init.upstart?(node); end
# @see Chef::Sugar::Init#runit?
def runit?; Chef::Sugar::Init.runit?(node); end
end
end
end

View File

@@ -0,0 +1,48 @@
#
# Copyright 2013-2015, Seth Vargo <sethvargo@gmail.com>
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
class Chef
module Sugar
module IP
extend self
#
# The best IP address for the given node, in the context of
# the current node. Useful for choosing a local IP address
# over a public one to limit bandwidth on cloud providers.
#
# @param [Chef::Node] other
# the node to calculate the best IP address for
#
def best_ip_for(node, other)
if other['cloud']
if node['cloud'] && other['cloud']['provider'] == node['cloud']['provider']
other['cloud']['local_ipv4']
else
other['cloud']['public_ipv4']
end
else
other['ipaddress']
end
end
end
module DSL
# @see Chef::Sugar::IP#best_ip_for
def best_ip_for(other); Chef::Sugar::IP.best_ip_for(node, other); end
end
end
end

View File

@@ -0,0 +1,49 @@
#
# Copyright 2013-2015, Seth Vargo <sethvargo@gmail.com>
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
class Chef
module Sugar
module Kernel
class ChefGemLoadError < StandardError
def initialize(name)
super <<-EOH
Chef could not load the gem `#{name}'! You may need to install the gem manually
with `gem install #{name}', or include a recipe before you can use this
resource. Please consult the documentation for this cookbook for proper usage.
EOH
end
end
#
# Require a gem that should have been installed by Chef, such as in a
# recipes as a +chef_gem+. This method will gracefully degrade if the
# gem cannot be loaded.
#
# @param [String] name
# the name of the gem to install
#
# @return [Boolean]
# true if the require is successful and false if the gem is already
# loaded
#
def require_chef_gem(name)
require(name)
rescue LoadError
raise ChefGemLoadError.new(name)
end
end
end
end

View File

@@ -0,0 +1,45 @@
#
# Copyright 2013-2015, Seth Vargo <sethvargo@gmail.com>
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
class Chef
module Sugar
module Kitchen
extend self
# these helpers have been moved to core-chef
if !defined?(Chef::VERSION) || Gem::Requirement.new("< 15.4.70").satisfied_by?(Gem::Version.new(Chef::VERSION))
#
# Returns true if the current node is provisioned by Test Kitchen.
#
# @param [Chef::Node] node
# the node to check
#
# @return [Boolean]
#
def kitchen?(node)
!ENV['TEST_KITCHEN'].nil?
end
end
end
module DSL
if !defined?(Chef::VERSION) || Gem::Requirement.new("< 15.4.70").satisfied_by?(Gem::Version.new(Chef::VERSION))
# @see Chef::Sugar::Kitchen#kitchen?
def kitchen?; Chef::Sugar::Kitchen.kitchen?(node); end
end
end
end
end

View File

@@ -0,0 +1,219 @@
#
# Copyright 2013-2015, Seth Vargo <sethvargo@gmail.com>
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
require_relative "deprecation"
class Chef
class Node
class AttributeDoesNotExistError < StandardError
def initialize(keys, key)
hash = keys.map { |key| "['#{key}']" }
super <<-EOH
No attribute `node#{hash.join}' exists on
the current node. Specifically the `#{key}' attribute is not
defined. Please make sure you have spelled everything correctly.
EOH
end
end
#
# Determine if the current node is in the given Chef environment
# (or matches the given regular expression).
#
# @param [String, Regex] environment
#
# @return [Boolean]
#
def in?(environment)
Chef::Sugar::Deprecation.deprecated "the chef-sugar node.in? method is deprecated"
environment === chef_environment
end
#
# Safely fetch a deeply nested attribute by specifying a list of keys,
# bypassing Ruby's Hash notation. This method swallows +NoMethodError+
# exceptions, avoiding the most common error in Chef-land.
#
# This method will return +nil+ if any deeply nested key does not exist.
#
# @see [Node#deep_fetch!]
#
def deep_fetch(*keys)
Chef::Sugar::Deprecation.deprecated "the chef-sugar deep_fetch method is deprecated and should be replaced by node.read"
deep_fetch!(*keys)
rescue NoMethodError, AttributeDoesNotExistError
nil
end
#
# Deeply fetch a node attribute by specifying a list of keys, bypassing
# Ruby's Hash notation.
#
# This method will raise any exceptions, such as
# +undefined method `[]' for nil:NilClass+, just as if you used the native
# attribute notation. If you want a safely vivified hash, see {deep_fetch}.
#
# @example Fetch a deeply nested key
# node.deep_fetch(:foo, :bar, :zip) #=> node['foo']['bar']['zip']
#
# @param [Array<String, Symbol>] keys
# the list of keys to kdeep fetch
#
# @return [Object]
#
def deep_fetch!(*keys)
Chef::Sugar::Deprecation.deprecated "the chef-sugar deep_fetch method is deprecated and should be replaced by node.read!"
keys.map!(&:to_s)
keys.inject(attributes.to_hash) do |hash, key|
if hash.key?(key)
hash[key]
else
raise AttributeDoesNotExistError.new(keys, key)
end
end
end
#
# Dynamically define the current namespace. Multiple namespaces may be
# nested.
#
# @example Define a simple namespace
#
# namespace 'apache2' do
# # ...
# end
#
# @example Define a nested namespace
#
# namespace 'apache2', 'config' do
# # ...
# end
#
# @example Define a complex nested namespace
#
# namespace 'apache2' do
# namespace 'config' do
# # ...
# end
# end
#
# @example Define a namespace with a custom precedence level
#
# namespace 'apache2', precedence: normal do
# # Attributes here will use the "normal" level
# end
#
# @example Define different nested precedence levels
#
# namespace 'apache2', precedence: normal do
# # Attributes defined here will use the "normal" level
#
# namespace 'config', precedence: override do
# # Attributes defined here will use the "override" level
# end
# end
#
#
# @param [Array] args
# the list of arguments (such as the namespace and precedence levels)
# the user gave
# @param [Proc] block
# the nested evaluation context
#
# @return [nil]
# to prevent accidential method chaining if the block isn't closed
#
def namespace(*args, &block)
Chef::Sugar::Deprecation.deprecated "the chef-sugar attribute namespace setting is deprecated, please use traditional chef attribute notation"
@namespace_options = namespace_options.merge(args.last.is_a?(Hash) ? args.pop : {})
keys = args.map(&:to_s)
@current_namespace = current_namespace + keys
instance_eval(&block)
@current_namespace = current_namespace - keys
if @current_namespace.empty?
@namespace_options = nil
end
nil
end
alias_method :old_method_missing, :method_missing
#
# Provide a nice DSL for defining attributes. +method_missing+ is called
# on all the attribute names. For more information on how to use the DSL,
# see the class-level documentation.
#
# @return [nil]
# to prevent accidential method chaining if the block isn't closed
# @return [Object]
# If no argument is passed in, method becomes an attribute accessor
#
def method_missing(m, *args, &block)
old_method_missing(m, *args, &block)
rescue NoMethodError
# The Node Attribute's key is the method name
key = m.to_s
# If arguments are passed in, set node attribute with args as the value
if args.size > 0
vivified[key] = args.size == 1 ? args.first : args
return nil
# If no arguments are passed in, attempt to access corresponding attribute
else
deep_key = current_namespace.dup << key
return deep_fetch!(*deep_key)
end
end
private
#
# The namespace options.
#
# @return [Hash]
#
def namespace_options
@namespace_options ||= {
precedence: default
}
end
#
# The current namespace. This is actually a reverse-ordered array that
# vivifies the correct hash.#
#
# @return [Array<String>]
#
def current_namespace
@current_namespace ||= []
end
#
# The vivified (fake-filled) hash. It is assumed that the default value
# for non-existent keys in the hash is a new, empty hash.
#
# @return [Hash<String, Hash>]
#
def vivified
current_namespace.inject(namespace_options[:precedence]) do |hash, item|
hash[item] ||= {}
hash[item]
end
end
end
end

View File

@@ -0,0 +1,331 @@
#
# Copyright 2013-2015, Seth Vargo <sethvargo@gmail.com>
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
require_relative 'constraints'
class Chef
module Sugar
module Platform
extend self
PLATFORM_VERSIONS = {
'debian' => {
'squeeze' => '6',
'wheezy' => '7',
'jessie' => '8',
'stretch' => '9',
'buster' => '10',
},
'linuxmint' => {
'tara' => '19',
'sarah' => '18',
'qiana' => '17',
'petra' => '16',
'olivia' => '15',
'nadia' => '14',
'maya' => '13',
'lisa' => '12',
},
'mac_os_x' => {
'lion' => '10.7',
'mountain_lion' => '10.8',
'mavericks' => '10.9',
'yosemite' => '10.10',
'el_capitan' => '10.11',
'sierra' => '10.12',
'high_sierra' => '10.13',
'mojave' => '10.14',
},
'redhat' => {
'santiago' => '6',
'6' => '6',
'maipo' => '7',
'7' => '7',
'oompa' => '8',
'8' => '8'
},
'centos' => {
'final' => '6',
'6' => '6',
'core' => '7',
'7' => '7'
},
'solaris' => {
'7' => '5.7',
'8' => '5.8',
'9' => '5.9',
'10' => '5.10',
'11' => '5.11',
},
'ubuntu' => {
'lucid' => '10.04',
'maverick' => '10.10',
'natty' => '11.04',
'oneiric' => '11.10',
'precise' => '12.04',
'quantal' => '12.10',
'raring' => '13.04',
'saucy' => '13.10',
'trusty' => '14.04',
'utopic' => '14.10',
'vivid' => '15.04',
'wily' => '15.10',
'xenial' => '16.04',
'zesty' => '17.04',
'artful' => '17.10',
'bionic' => '18.04',
'cosmic' => '18.10',
},
}
COMPARISON_OPERATORS = {
'after' => ->(a, b) { a > b },
'after_or_at' => ->(a, b) { a >= b },
'' => ->(a, b) { a == b },
'before' => ->(a, b) { a < b },
'before_or_at' => ->(a, b) { a <= b },
}
# Dynamically define custom matchers at runtime in a matrix. For each
# Platform, we create a map of named versions to their numerical
# equivalents (e.g. debian_before_squeeze?).
PLATFORM_VERSIONS.each do |platform, versions|
versions.each do |name, version|
COMPARISON_OPERATORS.each do |operator, block|
method_name = "#{platform}_#{operator}_#{name}?".squeeze('_').to_sym
define_method(method_name) do |node|
# Find the highest precedence that we actually care about based
# off of what was given to us in the list.
length = version.split('.').size
check = node['platform_version'].split('.')[0...length].join('.')
# Calling #to_f will ensure we only check major versions since
# '10.04.4'.to_f #=> 10.04. We also use a regex to match on
# platform so things like `solaris2` match on `solaris`.
node['platform'] =~ %r(^#{platform}) && block.call(check.to_f, version.to_f)
end
end
end
end
# these helpers have been moved to core chef
if !defined?(Chef::VERSION) || Gem::Requirement.new("< 15.4.70").satisfied_by?(Gem::Version.new(Chef::VERSION))
#
# Determine if the current node is linux mint.
#
# @param [Chef::Node] node
#
# @return [Boolean]
#
def linux_mint?(node)
node['platform'] == 'linuxmint'
end
alias_method :mint?, :linux_mint?
#
# Determine if the current node is ubuntu.
#
# @param [Chef::Node] node
#
# @return [Boolean]
#
def ubuntu?(node)
node['platform'] == 'ubuntu'
end
#
# Determine if the current node is debian (platform, not platform_family).
#
# @param [Chef::Node] node
#
# @return [Boolean]
#
def debian_platform?(node)
node['platform'] == 'debian'
end
#
# Determine if the current node is amazon linux.
#
# @param [Chef::Node] node
#
# @return [Boolean]
#
def amazon_linux?(node)
node['platform'] == 'amazon'
end
alias_method :amazon?, :amazon_linux?
#
# Determine if the current node is centos.
#
# @param [Chef::Node] node
#
# @return [Boolean]
#
def centos?(node)
node['platform'] == 'centos'
end
#
# Determine if the current node is oracle linux.
#
# @param [Chef::Node] node
#
# @return [Boolean]
#
def oracle_linux?(node)
node['platform'] == 'oracle'
end
alias_method :oracle?, :oracle_linux?
#
# Determine if the current node is scientific linux.
#
# @param [Chef::Node] node
#
# @return [Boolean]
#
def scientific_linux?(node)
node['platform'] == 'scientific'
end
alias_method :scientific?, :scientific_linux?
#
# Determine if the current node is redhat enterprise.
#
# @param [Chef::Node] node
#
# @return [Boolean]
#
def redhat_enterprise_linux?(node)
node['platform'] == 'redhat'
end
alias_method :redhat_enterprise?, :redhat_enterprise_linux?
#
# Determine if the current node is fedora (platform, not platform_family).
#
# @param [Chef::Node] node
#
# @return [Boolean]
#
def fedora_platform?(node)
node['platform'] == 'fedora'
end
#
# Determine if the current node is solaris2
#
# @param [Chef::Node] node
#
# @return [Boolean]
#
def solaris2?(node)
node['platform'] == 'solaris2'
end
alias_method :solaris?, :solaris2?
#
# Determine if the current node is aix
#
# @param [Chef::Node] node
#
# @return [Boolean]
#
def aix?(node)
node['platform'] == 'aix'
end
#
# Determine if the current node is smartos
#
# @param [Chef::Node] node
#
# @return [Boolean]
#
def smartos?(node)
node['platform'] == 'smartos'
end
#
# Determine if the current node is omnios
#
# @param [Chef::Node] node
#
# @return [Boolean]
#
def omnios?(node)
node['platform'] == 'omnios'
end
#
# Determine if the current node is raspbian
#
# @param [Chef::Node] node
#
# @return [Boolean]
#
def raspbian?(node)
node['platform'] == 'raspbian'
end
#
# Determine if the current node is a Cisco nexus device
#
# @param [Chef::Node] node
#
# @return [Boolean]
#
def nexus?(node)
node['platform'] == 'nexus'
end
#
# Determine if the current node is a Cisco IOS-XR device
#
# @param [Chef::Node] node
#
# @return [Boolean]
#
def ios_xr?(node)
node['platform'] == 'ios_xr'
end
end
#
# Return the platform_version for the node. Acts like a String
# but also provides a mechanism for checking version constraints.
#
# @param [Chef::Node] node
#
# @return [Chef::Sugar::Constraints::Version]
#
def platform_version(node)
Chef::Sugar::Constraints::Version.new(node['platform_version'])
end
end
module DSL
Chef::Sugar::Platform.instance_methods.each do |name|
define_method(name) do
Chef::Sugar::Platform.send(name, node)
end
end
end
end
end

View File

@@ -0,0 +1,184 @@
#
# Copyright 2013-2015, Seth Vargo <sethvargo@gmail.com>
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
class Chef
module Sugar
module PlatformFamily
extend self
# these helpers have been moved to core chef
if !defined?(Chef::VERSION) || Gem::Requirement.new("< 15.4.70").satisfied_by?(Gem::Version.new(Chef::VERSION))
#
# Determine if the current node is a member of the arch family.
#
# @param [Chef::Node] node
#
# @return [Boolean]
#
def arch_linux?(node)
node['platform_family'] == 'arch'
end
alias_method :arch?, :arch_linux?
#
# Determine if the current node is a member of the debian family.
#
# @param [Chef::Node] node
#
# @return [Boolean]
#
def debian?(node)
node['platform_family'] == 'debian'
end
#
# Determine if the current node is a member of the fedora family.
#
# @param [Chef::Node] node
#
# @return [Boolean]
#
def fedora?(node)
node['platform_family'] == 'fedora'
end
#
# Determine if the current node is a member of the freebsd family.
#
# @param [Chef::Node] node
#
# @return [Boolean]
#
def freebsd?(node)
node['platform_family'] == 'freebsd'
end
#
# Determine if the current node is a member of the arch family.
#
# @param [Chef::Node] node
#
# @return [Boolean]
#
def gentoo?(node)
node['platform_family'] == 'gentoo'
end
#
# Determine if the current node is a member of the OSX family.
#
# @param [Chef::Node] node
#
# @return [Boolean]
#
def mac_os_x?(node)
node['platform_family'] == 'mac_os_x'
end
alias_method :osx?, :mac_os_x?
alias_method :mac?, :mac_os_x?
#
# Determine if the current node is a member of the openbsd family.
#
# @param [Chef::Node] node
#
# @return [Boolean]
#
def openbsd?(node)
node['platform_family'] == 'openbsd'
end
#
# Determine if the current node is a member of the redhat family.
#
# @param [Chef::Node] node
#
# @return [Boolean]
#
def rhel?(node)
node['platform_family'] == 'rhel'
end
alias_method :redhat?, :rhel?
alias_method :el?, :rhel?
#
# Determine if the current node is a member of the slackware family.
#
# @param [Chef::Node] node
#
# @return [Boolean]
#
def slackware?(node)
node['platform_family'] == 'slackware'
end
#
# Determine if the current node is a member of the suse family.
#
# @param [Chef::Node] node
#
# @return [Boolean]
#
def suse?(node)
node['platform_family'] == 'suse'
end
#
# Determine if the current node is a member of the windows family.
#
# @param [Chef::Node] node
#
# @return [Boolean]
#
def windows?(node)
node['platform_family'] == 'windows'
end
#
# Determine if the current node is a member of the wrlinux family.
#
# @param [Chef::Node] node
#
# @return [Boolean]
#
def wrlinux?(node)
node['platform_family'] == 'wrlinux'
end
#
# Determine if the current system is a linux derivative
#
# @param [Chef::Node] node
#
# @return [Boolean]
#
def linux?(node)
node['os'] == 'linux'
end
end
end
module DSL
Chef::Sugar::PlatformFamily.instance_methods.each do |name|
define_method(name) do
Chef::Sugar::PlatformFamily.send(name, node)
end
end
end
end
end

View File

@@ -0,0 +1,51 @@
#
# Copyright 2013-2015, Seth Vargo <sethvargo@gmail.com>
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
class Chef
module Sugar
module Ruby
extend self
#
# Determine if the current Ruby version is 2.0.
#
# @return [Boolean]
#
def ruby_20?(node)
version = Gem::Version.new(node['languages']['ruby']['version'])
Gem::Requirement.new('~> 2.0.0').satisfied_by?(version)
end
#
# Determine if the current Ruby version is 1.9.
#
# @return [Boolean]
#
def ruby_19?(node)
version = Gem::Version.new(node['languages']['ruby']['version'])
Gem::Requirement.new('~> 1.9.0').satisfied_by?(version)
end
end
module DSL
# @see Chef::Sugar::Ruby#ruby_20?
def ruby_20?; Chef::Sugar::Ruby.ruby_20?(node); end
# @see Chef::Sugar::Ruby#ruby_19?
def ruby_19?; Chef::Sugar::Ruby.ruby_19?(node); end
end
end
end

View File

@@ -0,0 +1,41 @@
#
# Copyright 2013-2015, Seth Vargo <sethvargo@gmail.com>
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
class Chef
module Sugar
module RunContext
extend self
#
# Determine if the current node includes the given recipe name.
#
# @param [String] recipe_name
#
def includes_recipe?(node, recipe_name)
node.recipe?(recipe_name)
end
alias_method :include_recipe?, :includes_recipe?
end
module DSL
# @see Chef::Sugar::IP#best_ip_for
def includes_recipe?(recipe_name)
Chef::Sugar::RunContext.includes_recipe?(node, recipe_name)
end
alias_method :include_recipe?, :includes_recipe?
end
end
end

View File

@@ -0,0 +1,157 @@
#
# Copyright 2013-2015, Seth Vargo <sethvargo@gmail.com>
#
# 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 'mixlib/shellout' unless defined?(Mixlib::ShellOut)
require 'pathname' unless defined?(Pathname)
class Chef
module Sugar
module Shell
extend self
# this helper has been moved to core chef
if !defined?(Chef::VERSION) || Gem::Requirement.new("< 16.0.257").satisfied_by?(Gem::Version.new(Chef::VERSION))
#
# Finds a command in $PATH
#
# @param [String] cmd
# the command to find
#
# @return [String, nil]
#
def which(cmd)
if Pathname.new(cmd).absolute?
File.executable?(cmd) ? cmd : nil
else
paths = ENV['PATH'].split(::File::PATH_SEPARATOR) + %w(/bin /usr/bin /sbin /usr/sbin)
paths.each do |path|
possible = File.join(path, cmd)
return possible if File.executable?(possible)
end
nil
end
end
end
#
# The platform-specific output path to +/dev/null+.
#
# @return [String]
#
def dev_null(node)
if defined?(ChefUtils)
ChefUtils.windows?(node) ? 'NUL' : '/dev/null'
else
Chef::Sugar::PlatformFamily.windows?(node) ? 'NUL' : '/dev/null'
end
end
#
# Boolean method to check if a command line utility is installed.
#
# @param [String] cmd
# the command to find
#
# @return [Boolean]
# true if the command is found in the path, false otherwise
#
def installed?(cmd)
!which(cmd).nil?
end
#
# Checks if the given binary is installed and exists at the given
# version. Also see {version_for}.
#
# @param [String] cmd
# the command to check
# @param [String] expected_version
# the version to check
# @param [String] flag
# the flag to use to check the version of the binary
#
# @return [Boolean]
# true if the command exists and is at the given version, false
# otherwise
#
def installed_at_version?(cmd, expected_version, flag = '--version')
return false if !installed?(cmd)
version = version_for(cmd, flag)
return false if version.nil?
if expected_version.is_a?(Regexp)
!version.match(expected_version).nil?
else
version.include?(expected_version)
end
end
#
# The version for a given command. This method does NOT check if the
# command exists! It is assumed the command existence has been
# checked with +which+ or similar. To simply check if an installed
# version is acceptable, please see {installed_at_version}.
#
# Assumptions:
# 1. The command exists.
# 2. The command outputs version information to +$stdout+ or +$stderr+.
# Did you know that java outputs its version to $stderr?
#
#
# @param [String] cmd
# the command to find the version for
# @param [String] flag
# the flag to use to get the version
#
# @return [String]
# the entire output of the version command (stderr and stdout)
#
def version_for(cmd, flag = '--version')
cmd = Mixlib::ShellOut.new("#{cmd} #{flag}")
cmd.run_command
cmd.error!
[cmd.stdout.strip, cmd.stderr.strip].join("\n")
end
end
module DSL
# this helper has been moved to core chef
if !defined?(Chef::VERSION) || Gem::Requirement.new("< 16.0.257").satisfied_by?(Gem::Version.new(Chef::VERSION))
# @see Chef::Sugar::Shell#which
def which(cmd); Chef::Sugar::Shell.which(cmd); end
end
# @see Chef::Sugar::Shell#dev_null
def dev_null; Chef::Sugar::Shell.dev_null(node); end
# @see Chef::Sugar::Shell#installed?
def installed?(cmd); Chef::Sugar::Shell.installed?(cmd); end
# @see Chef::Sugar::Shell#installed_at_version?
def installed_at_version?(cmd, version, flag = '--version')
Chef::Sugar::Shell.installed_at_version?(cmd, version, flag)
end
# @see Chef::Sugar::Shell#version_for
def version_for(cmd, flag = '--version')
Chef::Sugar::Shell.version_for(cmd, flag)
end
end
end
end

View File

@@ -0,0 +1,77 @@
#
# Copyright 2013-2015, Seth Vargo <sethvargo@gmail.com>
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
class Chef
module Sugar
module Vagrant
extend self
#
# Determine if the current node is running in vagrant mode.
#
# @param [Chef::Node] node
#
# @return [Boolean]
# true if the machine is currently running vagrant, false
# otherwise
#
def vagrant?(node)
vagrant_key?(node) || vagrant_domain?(node) || vagrant_user?(node)
end
private
#
# Check if the +vagrant+ key exists on the +node+ object. This key is no
# longer populated by vagrant, but it is kept around for legacy purposes.
#
# @param (see vagrant?)
# @return (see vagrant?)
#
def vagrant_key?(node)
node.key?('vagrant')
end
#
# Check if "vagrantup.com" is included in the node's domain. Technically,
# this would make Chef Sugar falsely detect +vagrant?+ on any of
# Hashicorp's servers. But if that edge case becomes a serious problem,
# @mitchellh has my phone number.
#
# @param (see vagrant?)
# @return (see vagrant?)
#
def vagrant_domain?(node)
node.key?('domain') && !node['domain'].nil? && node['domain'].include?('vagrantup.com')
end
#
# Check if the system contains a +vagrant+ user.
#
# @param (see vagrant?)
# @return (see vagrant?)
#
def vagrant_user?(node)
node.key?('etc') && node['etc'].key?('passwd') && node['etc']['passwd'].key?('vagrant')
end
end
module DSL
# @see Chef::Sugar::Vagrant#vagrant?
def vagrant?; Chef::Sugar::Vagrant.vagrant?(node); end
end
end
end

View File

@@ -0,0 +1,21 @@
#
# Copyright 2013-2015, Seth Vargo <sethvargo@gmail.com>
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
class Chef
module Sugar
VERSION = "5.1.12"
end
end

View File

@@ -0,0 +1,151 @@
#
# Copyright 2014, Joseph J. Nuspl Jr. <nuspl@nvwls.com>
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
class Chef
module Sugar
module Virtualization
extend self
#
# Determine if the current node is running under KVM.
#
# @param [Chef::Node] node
#
# @return [Boolean]
# true if the machine is currently running under KVM, false
# otherwise
#
def kvm?(node)
node.key?('virtualization') && node['virtualization']['system'] == 'kvm'
end
#
# Determine if the current node is running in a linux container.
#
# @param [Chef::Node] node
#
# @return [Boolean]
# true if the machine is currently running in a container, false
# otherwise
#
def lxc?(node)
node.key?('virtualization') && node['virtualization']['system'] == 'lxc'
end
#
# Determine if the current node is running under Parallels Desktop.
#
# @param [Chef::Node] node
#
# @return [Boolean]
# true if the machine is currently running under Parallels Desktop, false
# otherwise
#
def parallels?(node)
node.key?('virtualization') && node['virtualization']['system'] == 'parallels'
end
#
# Determine if the current node is running under VirtualBox.
#
# @param [Chef::Node] node
#
# @return [Boolean]
# true if the machine is currently running under VirtualBox, false
# otherwise
#
def virtualbox?(node)
node.key?('virtualization') && node['virtualization']['system'] == 'vbox'
end
#
# Determine if the current node is running under VMware.
#
# @param [Chef::Node] node
#
# @return [Boolean]
# true if the machine is currently running under VMware, false
# otherwise
#
def vmware?(node)
node.key?('virtualization') && node['virtualization']['system'] == 'vmware'
end
#
# Determine if the current node is running under openvz.
#
# @param [Chef::Node] node
#
# @return [Boolean]
# true if the machine is currently running under openvz, false
# otherwise
#
def openvz?(node)
node.key?('virtualization') && node['virtualization']['system'] == 'openvz'
end
def virtual?(node)
openvz?(node) || vmware?(node) || virtualbox?(node) || parallels?(node) || lxc?(node) || kvm?(node)
end
def physical?(node)
!virtual?(node)
end
end
module DSL
# @see Chef::Sugar::Virtualization#kvm?
def kvm?
Chef::Sugar::Virtualization.kvm?(node)
end
# @see Chef::Sugar::Virtualization#lxc?
def lxc?
Chef::Sugar::Virtualization.lxc?(node)
end
# @see Chef::Sugar::Virtualization#parallels?
def parallels?
Chef::Sugar::Virtualization.parallels?(node)
end
# @see Chef::Sugar::Virtualization#virtualbox?
def virtualbox?
Chef::Sugar::Virtualization.virtualbox?(node)
end
# @see Chef::Sugar::Virtualization#vmware?
def vmware?
Chef::Sugar::Virtualization.vmware?(node)
end
# @see Chef::Sugar::Virtualization#openvz?
def openvz?
Chef::Sugar::Virtualization.openvz?(node)
end
# @see Chef::Sugar::Virtualization#virtual?
def virtual?
Chef::Sugar::Virtualization.virtual?(node)
end
# @see Chef::Sugar::Virtualization#physical?
def physical?
Chef::Sugar::Virtualization.physical?(node)
end
end
end
end