chef-utils-16.12.3/0000755000175100017510000000000014034013321012744 5ustar pravipravichef-utils-16.12.3/Rakefile0000644000175100017510000000057314034013321014416 0ustar pravipravi# frozen_string_literal: true require "bundler/gem_tasks" task default: :spec begin require "rspec/core/rake_task" desc "Run standard specs" RSpec::Core::RakeTask.new(:spec) do |t| t.verbose = false t.pattern = FileList["spec/**/*_spec.rb"] end rescue LoadError STDERR.puts "\n*** RSpec not available. (sudo) gem install rspec to run unit tests. ***\n\n" end chef-utils-16.12.3/chef-utils.gemspec0000644000175100017510000000402514034013321016355 0ustar pravipravi# frozen_string_literal: true lib = File.expand_path("lib", __dir__) $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) require "chef-utils/version" Gem::Specification.new do |spec| spec.name = "chef-utils" spec.version = ChefUtils::VERSION spec.authors = ["Chef Software, Inc"] spec.email = ["oss@chef.io"] spec.summary = %q{Basic utility functions for Core Chef Infra development} spec.homepage = "https://github.com/chef/chef/tree/master/chef-utils" spec.license = "Apache-2.0" spec.required_ruby_version = ">= 2.6.0" spec.metadata = { "bug_tracker_uri" => "https://github.com/chef/chef/issues", "changelog_uri" => "https://github.com/chef/chef/blob/master/CHANGELOG.md", "documentation_uri" => "https://github.com/chef/chef/tree/master/chef-utils/README.md", "homepage_uri" => "https://github.com/chef/chef/tree/master/chef-utils", "source_code_uri" => "https://github.com/chef/chef/tree/master/chef-utils", } spec.require_paths = ["lib"] # # NOTE: DO NOT ADD RUNTIME DEPS TO OTHER CHEF ECOSYSTEM GEMS # (e.g. chef, ohai, mixlib-anything, ffi-yajl, and IN PARTICULAR NOT chef-config) # # This is so that this set of common code can be reused in any other library without # creating circular dependencies. If you find yourself wanting to do that you probably # have a helper that should go into the library you want to declare a dependency on, # or you need to create another gem that is not this one. You may also want to rub some # dependency injection on your API to invert things so that you don't have to take # a dependency on the thing you need (i.e. allow injecting a hash-like thing instead of taking # a dep on mixlib-config and then require the consumer to wire up chef-config to your # API). Same for mixlib-log and Chef::Log in general. # # ABSOLUTELY NO EXCEPTIONS # spec.files = %w{Rakefile LICENSE} + Dir.glob("*.gemspec") + Dir.glob("{lib,spec}/**/*", File::FNM_DOTMATCH).reject { |f| File.directory?(f) } end chef-utils-16.12.3/spec/0000755000175100017510000000000014034013321013676 5ustar pravipravichef-utils-16.12.3/spec/unit/0000755000175100017510000000000014034013321014655 5ustar pravipravichef-utils-16.12.3/spec/unit/mash_spec.rb0000644000175100017510000000327614034013321017154 0ustar pravipravi# frozen_string_literal: true # # Author:: Matthew Kent () # Copyright:: Copyright (c) Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # require "spec_helper" RSpec.describe ChefUtils::Mash do it "should duplicate a simple key/value mash to a new mash" do data = { x: "one", y: "two", z: "three" } @orig = ChefUtils::Mash.new(data) @copy = @orig.dup expect(@copy.to_hash).to eq(ChefUtils::Mash.new(data).to_hash) @copy[:x] = "four" expect(@orig[:x]).to eq("one") end it "should duplicate a mash with an array to a new mash" do data = { x: "one", y: "two", z: [1, 2, 3] } @orig = ChefUtils::Mash.new(data) @copy = @orig.dup expect(@copy.to_hash).to eq(ChefUtils::Mash.new(data).to_hash) @copy[:z] << 4 expect(@orig[:z]).to eq([1, 2, 3]) end it "should duplicate a nested mash to a new mash" do data = { x: "one", y: "two", z: ChefUtils::Mash.new({ a: [1, 2, 3] }) } @orig = ChefUtils::Mash.new(data) @copy = @orig.dup expect(@copy.to_hash).to eq(ChefUtils::Mash.new(data).to_hash) @copy[:z][:a] << 4 expect(@orig[:z][:a]).to eq([1, 2, 3]) end # add more! end chef-utils-16.12.3/spec/unit/dsl/0000755000175100017510000000000014034013321015437 5ustar pravipravichef-utils-16.12.3/spec/unit/dsl/architecture_spec.rb0000644000175100017510000000702714034013321021466 0ustar pravipravi# frozen_string_literal: true # # Copyright:: Copyright (c) Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # require "spec_helper" def arch_reports_true_for(*args) args.each do |method| it "reports true for #{method}" do expect(described_class.send(method, node)).to be true end end (ARCH_HELPERS - args).each do |method| it "reports false for #{method}" do expect(described_class.send(method, node)).to be false end end end RSpec.describe ChefUtils::DSL::Architecture do let(:node) { { "kernel" => { "machine" => arch } } } ( HELPER_MODULES - [ described_class ] ).each do |klass| it "does not have methods that collide with #{klass}" do expect((klass.methods - Module.methods) & ARCH_HELPERS).to be_empty end end ARCH_HELPERS.each do |helper| it "has the #{helper} in the ChefUtils module" do expect(ChefUtils).to respond_to(helper) end end context "on x86_64" do let(:arch) { "x86_64" } arch_reports_true_for(:intel?, :_64_bit?) end context "on amd64" do let(:arch) { "amd64" } arch_reports_true_for(:intel?, :_64_bit?) end context "on ppc64" do let(:arch) { "ppc64" } arch_reports_true_for(:ppc64?, :_64_bit?) end context "on ppc64le" do let(:arch) { "ppc64le" } arch_reports_true_for(:ppc64le?, :_64_bit?) end context "on s390x" do let(:arch) { "s390x" } arch_reports_true_for(:s390x?, :_64_bit?) end context "on ia64" do let(:arch) { "ia64" } arch_reports_true_for(:_64_bit?) end context "on sparc64" do let(:arch) { "sparc64" } arch_reports_true_for(:_64_bit?) end context "on aarch64" do let(:arch) { "aarch64" } arch_reports_true_for(:_64_bit?, :arm?) end context "on arch64" do let(:arch) { "arch64" } arch_reports_true_for(:_64_bit?, :arm?) end context "on arm64" do let(:arch) { "arm64" } arch_reports_true_for(:_64_bit?, :arm?) end context "on sun4v" do let(:arch) { "sun4v" } arch_reports_true_for(:sparc?, :_64_bit?) end context "on sun4u" do let(:arch) { "sun4u" } arch_reports_true_for(:sparc?, :_64_bit?) end context "on i86pc" do let(:arch) { "i86pc" } arch_reports_true_for(:i386?, :intel?, :_32_bit?) end context "on i386" do let(:arch) { "i386" } arch_reports_true_for(:i386?, :intel?, :_32_bit?) end context "on i686" do let(:arch) { "i686" } arch_reports_true_for(:i386?, :intel?, :_32_bit?) end context "on powerpc" do let(:arch) { "powerpc" } arch_reports_true_for(:powerpc?, :_32_bit?) end context "on armhf" do let(:arch) { "armhf" } arch_reports_true_for(:armhf?, :_32_bit?, :arm?) end context "on armv6l" do let(:arch) { "armv6l" } arch_reports_true_for(:armhf?, :_32_bit?, :arm?) end context "on armv7l" do let(:arch) { "armv7l" } arch_reports_true_for(:armhf?, :_32_bit?, :arm?) end context "on s390" do let(:arch) { "s390" } arch_reports_true_for(:s390?, :_32_bit?) end end chef-utils-16.12.3/spec/unit/dsl/os_spec.rb0000644000175100017510000000730714034013321017426 0ustar pravipravi# frozen_string_literal: true # # Copyright:: Copyright (c) Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # require "spec_helper" require "fauxhai" def os_reports_true_for(*args) args.each do |method| it "reports true for #{method}" do expect(described_class.send(method, node)).to be true end end (OS_HELPERS - args).each do |method| it "reports false for #{method}" do expect(described_class.send(method, node)).to be false end end end RSpec.describe ChefUtils::DSL::OS do let(:node) { Fauxhai.mock(options).data } ( HELPER_MODULES - [ described_class ] ).each do |klass| it "does not have methods that collide with #{klass}" do expect((klass.methods - Module.methods) & OS_HELPERS).to be_empty end end OS_HELPERS.each do |helper| it "has the #{helper} in the ChefUtils module" do expect(ChefUtils).to respond_to(helper) end end context "on ubuntu" do let(:options) { { platform: "ubuntu" } } os_reports_true_for(:linux?) end context "on raspbian" do let(:options) { { platform: "raspbian" } } os_reports_true_for(:linux?) end context "on linuxmint" do let(:options) { { platform: "linuxmint" } } os_reports_true_for(:linux?) end context "on debian" do let(:options) { { platform: "debian" } } os_reports_true_for(:linux?) end context "on amazon" do let(:options) { { platform: "amazon" } } os_reports_true_for(:linux?) end context "on arch" do let(:options) { { platform: "arch" } } os_reports_true_for(:linux?) end context "on centos" do let(:options) { { platform: "centos" } } os_reports_true_for(:linux?) end context "on clearos" do let(:options) { { platform: "clearos" } } os_reports_true_for(:linux?) end context "on dragonfly4" do let(:options) { { platform: "dragonfly4" } } os_reports_true_for end context "on fedora" do let(:options) { { platform: "fedora" } } os_reports_true_for(:linux?) end context "on freebsd" do let(:options) { { platform: "freebsd" } } os_reports_true_for end context "on gentoo" do let(:options) { { platform: "gentoo" } } os_reports_true_for(:linux?) end context "on mac_os_x" do let(:options) { { platform: "mac_os_x" } } os_reports_true_for(:darwin?) end context "on openbsd" do let(:options) { { platform: "openbsd" } } os_reports_true_for end context "on opensuse" do let(:options) { { platform: "opensuse" } } os_reports_true_for(:linux?) end context "on oracle" do let(:options) { { platform: "oracle" } } os_reports_true_for(:linux?) end context "on redhat" do let(:options) { { platform: "redhat" } } os_reports_true_for(:linux?) end context "on smartos" do let(:options) { { platform: "smartos" } } os_reports_true_for end context "on solaris2" do let(:options) { { platform: "solaris2" } } os_reports_true_for end context "on suse" do let(:options) { { platform: "suse" } } os_reports_true_for(:linux?) end context "on windows" do let(:options) { { platform: "windows" } } os_reports_true_for end end chef-utils-16.12.3/spec/unit/dsl/cloud_spec.rb0000644000175100017510000000531114034013321020104 0ustar pravipravi# frozen_string_literal: true # # Copyright:: Copyright (c) Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # require "spec_helper" require "fauxhai" def cloud_reports_true_for(*args, node:) args.each do |method| it "reports true for #{method}" do expect(described_class.send(method, node)).to be true end end (CLOUD_HELPERS - args).each do |method| it "reports false for #{method}" do expect(described_class.send(method, node)).to be false end end end RSpec.describe ChefUtils::DSL::Cloud do ( HELPER_MODULES - [ described_class ] ).each do |klass| it "does not have methods that collide with #{klass}" do expect((klass.methods - Module.methods) & CLOUD_HELPERS).to be_empty end end CLOUD_HELPERS.each do |helper| it "has the #{helper} in the ChefUtils module" do expect(ChefUtils).to respond_to(helper) end end context "on ec2" do cloud_reports_true_for(:cloud?, :ec2?, node: { "ec2" => {}, "cloud" => {} }) end context "on gce" do cloud_reports_true_for(:cloud?, :gce?, node: { "gce" => {}, "cloud" => {} }) end context "on rackspace" do cloud_reports_true_for(:cloud?, :rackspace?, node: { "rackspace" => {}, "cloud" => {} }) end context "on eucalyptus" do cloud_reports_true_for(:cloud?, :eucalyptus?, :euca?, node: { "eucalyptus" => {}, "cloud" => {} }) end context "on linode" do cloud_reports_true_for(:cloud?, :linode?, node: { "linode" => {}, "cloud" => {} }) end context "on openstack" do cloud_reports_true_for(:cloud?, :openstack?, node: { "openstack" => {}, "cloud" => {} }) end context "on azure" do cloud_reports_true_for(:cloud?, :azure?, node: { "azure" => {}, "cloud" => {} }) end context "on digital_ocean" do cloud_reports_true_for(:cloud?, :digital_ocean?, :digitalocean?, node: { "digital_ocean" => {}, "cloud" => {} }) end context "on softlayer" do cloud_reports_true_for(:cloud?, :softlayer?, node: { "softlayer" => {}, "cloud" => {} }) end context "on virtualbox" do it "does not return true for cloud?" do expect(described_class.cloud?({ "virtualbox" => {}, "cloud" => nil })).to be false end end end chef-utils-16.12.3/spec/unit/dsl/virtualization_spec.rb0000644000175100017510000000673014034013321022070 0ustar pravipravi# frozen_string_literal: true # # Copyright:: Copyright (c) Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # require "spec_helper" require "fauxhai" def virtualization_reports_true_for(*args, node:) args.each do |method| it "reports true for #{method}" do expect(described_class.send(method, node)).to be true end end (VIRTUALIZATION_HELPERS - args).each do |method| it "reports false for #{method}" do expect(described_class.send(method, node)).to be false end end end RSpec.describe ChefUtils::DSL::Virtualization do ( HELPER_MODULES - [ described_class ] ).each do |klass| it "does not have methods that collide with #{klass}" do expect((klass.methods - Module.methods) & VIRTUALIZATION_HELPERS).to be_empty end end VIRTUALIZATION_HELPERS.each do |helper| it "has the #{helper} in the ChefUtils module" do expect(ChefUtils).to respond_to(helper) end end context "on kvm" do virtualization_reports_true_for(:guest?, :virtual?, :kvm?, node: { "virtualization" => { "system" => "kvm", "role" => "guest" } }) virtualization_reports_true_for(:hypervisor?, :physical?, :kvm_host?, node: { "virtualization" => { "system" => "kvm", "role" => "host" } }) end context "on lxc" do virtualization_reports_true_for(:guest?, :virtual?, :lxc?, node: { "virtualization" => { "system" => "lxc", "role" => "guest" } }) virtualization_reports_true_for(:hypervisor?, :physical?, :lxc_host?, node: { "virtualization" => { "system" => "lxc", "role" => "host" } }) end context "on parallels" do virtualization_reports_true_for(:guest?, :virtual?, :parallels?, node: { "virtualization" => { "system" => "parallels", "role" => "guest" } }) virtualization_reports_true_for(:hypervisor?, :physical?, :parallels_host?, node: { "virtualization" => { "system" => "parallels", "role" => "host" } }) end context "on virtualbox" do virtualization_reports_true_for(:guest?, :virtual?, :virtualbox?, :vbox?, node: { "virtualization" => { "system" => "vbox", "role" => "guest" } }) virtualization_reports_true_for(:hypervisor?, :physical?, :vbox_host?, node: { "virtualization" => { "system" => "vbox", "role" => "host" } }) end context "on vmware" do virtualization_reports_true_for(:guest?, :virtual?, :vmware?, node: { "virtualization" => { "system" => "vmware", "role" => "guest" } }) virtualization_reports_true_for(:hypervisor?, :physical?, :vmware_host?, node: { "virtualization" => { "system" => "vmware", "role" => "host" } }) end context "on openvz" do virtualization_reports_true_for(:guest?, :virtual?, :openvz?, node: { "virtualization" => { "system" => "openvz", "role" => "guest" } }) virtualization_reports_true_for(:hypervisor?, :physical?, :openvz_host?, node: { "virtualization" => { "system" => "openvz", "role" => "host" } }) end context "on metal which is not a virt host" do virtualization_reports_true_for(:physical?, node: {} ) end end chef-utils-16.12.3/spec/unit/dsl/path_sanity_spec.rb0000644000175100017510000000631414034013321021325 0ustar pravipravi# frozen_string_literal: true # # Copyright:: Copyright (c) Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # require "spec_helper" RSpec.describe ChefUtils::DSL::DefaultPaths do class DefaultPathsTestClass include ChefUtils::DSL::DefaultPaths end before do allow(Gem).to receive(:bindir).and_return("/opt/ruby/bin/bundle") allow(RbConfig::CONFIG).to receive(:[]).with("bindir").and_return("/opt/ruby/bin") end context "on unix" do before do allow(ChefUtils).to receive(:windows?).and_return(false) end let(:test_instance) { DefaultPathsTestClass.new } it "works with no path" do env = {} expect(test_instance.default_paths(env)).to eql("#{Gem.bindir}:#{RbConfig::CONFIG["bindir"]}:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin") end it "works with nil path" do env = { "PATH" => nil } expect(test_instance.default_paths(env)).to eql("#{Gem.bindir}:#{RbConfig::CONFIG["bindir"]}:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin") end it "works with empty path" do env = { "PATH" => "" } expect(test_instance.default_paths(env)).to eql("#{Gem.bindir}:#{RbConfig::CONFIG["bindir"]}:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin") end it "appends the default_paths to the end of the path, preserving any that already exist, in the same order" do env = { "PATH" => "/bin:/opt/app/bin:/sbin" } expect(test_instance.default_paths(env)).to eql("#{Gem.bindir}:#{RbConfig::CONFIG["bindir"]}:/bin:/opt/app/bin:/sbin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin") end end context "on windows" do before do allow(ChefUtils).to receive(:windows?).and_return(true) end let(:test_instance) { DefaultPathsTestClass.new } it "works with no path" do env = {} expect(test_instance.default_paths(env)).to eql("#{Gem.bindir};#{RbConfig::CONFIG["bindir"]}") end it "works with nil path" do env = { "PATH" => nil } expect(test_instance.default_paths(env)).to eql("#{Gem.bindir};#{RbConfig::CONFIG["bindir"]}") end it "works with empty path" do env = { "PATH" => "" } expect(test_instance.default_paths(env)).to eql("#{Gem.bindir};#{RbConfig::CONFIG["bindir"]}") end it "prepends to an existing path" do env = { "PATH" => '%SystemRoot%\system32;%SystemRoot%;%SystemRoot%\System32\Wbem;%SYSTEMROOT%\System32\WindowsPowerShell\v1.0\\' } expect(test_instance.default_paths(env)).to eql("#{Gem.bindir};#{RbConfig::CONFIG["bindir"]};%SystemRoot%\\system32;%SystemRoot%;%SystemRoot%\\System32\\Wbem;%SYSTEMROOT%\\System32\\WindowsPowerShell\\v1.0\\") end end end chef-utils-16.12.3/spec/unit/dsl/platform_spec.rb0000644000175100017510000001462314034013321020630 0ustar pravipravi# frozen_string_literal: true # # Copyright:: Copyright (c) Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # require "spec_helper" require "fauxhai" def platform_reports_true_for(*args) args.each do |method| it "reports true for #{method} on the module given a node" do expect(described_class.send(method, node)).to be true end it "reports true for #{method} when mixed into a class with a node" do expect(thing_with_a_node.send(method, node)).to be true end it "reports true for #{method} when mixed into a class with a run_context" do expect(thing_with_a_run_context.send(method, node)).to be true end it "reports true for #{method} when mixed into a class with the dsl" do expect(thing_with_the_dsl.send(method, node)).to be true end it "reports true for #{method} on the main class give a node" do expect(ChefUtils.send(method, node)).to be true end end (PLATFORM_HELPERS - args).each do |method| it "reports false for #{method} on the module given a node" do expect(described_class.send(method, node)).to be false end it "reports false for #{method} when mixed into a class with a node" do expect(thing_with_a_node.send(method, node)).to be false end it "reports false for #{method} when mixed into a class with the dsl" do expect(thing_with_the_dsl.send(method, node)).to be false end it "reports false for #{method} on the main class give a node" do expect(ChefUtils.send(method, node)).to be false end end end RSpec.describe ChefUtils::DSL::Platform do let(:node) { Fauxhai.mock(options).data } class ThingWithANode include ChefUtils::DSL::Platform attr_accessor :node def initialize(node) @node = node end end class ThingWithARunContext include ChefUtils::DSL::Platform class RunContext attr_accessor :node end attr_accessor :run_context def initialize(node) @run_context = RunContext.new run_context.node = node end end class ThingWithTheDSL include ChefUtils attr_accessor :node def initialize(node) @node = node end end let(:thing_with_a_node) { ThingWithANode.new(node) } let(:thing_with_a_run_context) { ThingWithARunContext.new(node) } let(:thing_with_the_dsl) { ThingWithTheDSL.new(node) } ( HELPER_MODULES - [ described_class ] ).each do |klass| it "does not have methods that collide with #{klass}" do expect((klass.methods - Module.methods) & PLATFORM_HELPERS).to be_empty end end context "on ubuntu" do let(:options) { { platform: "ubuntu" } } platform_reports_true_for(:ubuntu?, :ubuntu_platform?) end context "on raspbian" do let(:options) { { platform: "raspbian" } } platform_reports_true_for(:raspbian?, :raspbian_platform?) end context "on linuxmint" do let(:options) { { platform: "linuxmint" } } platform_reports_true_for(:mint?, :linux_mint?, :linuxmint?, :linuxmint_platform?) end context "on debian" do let(:options) { { platform: "debian" } } platform_reports_true_for(:debian_platform?) end context "on aix" do let(:options) { { platform: "aix" } } platform_reports_true_for(:aix_platform?) end context "on amazon" do let(:options) { { platform: "amazon" } } platform_reports_true_for(:amazon_platform?) end context "on arch" do let(:options) { { platform: "arch" } } platform_reports_true_for(:arch_platform?) end context "on centos" do let(:options) { { platform: "centos" } } platform_reports_true_for(:centos?, :centos_platform?) end context "on clearos" do let(:options) { { platform: "clearos" } } platform_reports_true_for(:clearos?, :clearos_platform?) end context "on dragonfly4" do let(:options) { { platform: "dragonfly4" } } platform_reports_true_for(:dragonfly_platform?) end context "on fedora" do let(:options) { { platform: "fedora" } } platform_reports_true_for(:fedora_platform?) end context "on freebsd" do let(:options) { { platform: "freebsd" } } platform_reports_true_for(:freebsd_platform?) end context "on gentoo" do let(:options) { { platform: "gentoo" } } platform_reports_true_for(:gentoo_platform?) end context "on mac_os_x" do let(:options) { { platform: "mac_os_x" } } platform_reports_true_for(:mac_os_x_platform?, :macos_platform?) end context "on openbsd" do let(:options) { { platform: "openbsd" } } platform_reports_true_for(:openbsd_platform?) end context "on oracle" do let(:options) { { platform: "oracle" } } platform_reports_true_for(:oracle?, :oracle_linux?, :oracle_platform?) end context "on redhat" do let(:options) { { platform: "redhat" } } platform_reports_true_for(:redhat?, :redhat_enterprise_linux?, :redhat_enterprise?, :redhat_platform?) end context "on smartos" do let(:options) { { platform: "smartos" } } platform_reports_true_for(:smartos_platform?) end context "on solaris2" do let(:options) { { platform: "solaris2" } } platform_reports_true_for(:solaris2_platform?) end context "on suse" do let(:options) { { platform: "suse" } } platform_reports_true_for(:suse_platform?) end context "on windows" do let(:options) { { platform: "windows" } } platform_reports_true_for(:windows_platform?) end context "on opensuseleap" do let(:node) { { "platform" => "opensuseleap", "platform_version" => "15.1", "platform_family" => "suse", "os" => "linux" } } platform_reports_true_for(:opensuse_platform?, :opensuseleap_platform?, :opensuse?, :leap_platform?) end context "on opensuse" do let(:node) { { "platform" => "opensuse", "platform_version" => "11.0", "platform_family" => "suse", "os" => "linux" } } platform_reports_true_for(:opensuse_platform?, :opensuseleap_platform?, :opensuse?, :leap_platform?) end end chef-utils-16.12.3/spec/unit/dsl/service_spec.rb0000644000175100017510000001155614034013321020446 0ustar pravipravi# frozen_string_literal: true # # Copyright:: Copyright (c) Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # require "spec_helper" RSpec.describe ChefUtils::DSL::Service do class ServiceTestClass include ChefUtils::DSL::Service end let(:test_instance) { ServiceTestClass.new } context "#debianrcd?" do it "is true if the binary is installed" do expect(File).to receive(:exist?).with("/usr/sbin/update-rc.d").and_return(true) expect(test_instance.debianrcd?).to be true end it "is false if the binary is not installed" do expect(File).to receive(:exist?).with("/usr/sbin/update-rc.d").and_return(false) expect(test_instance.debianrcd?).to be false end end context "#invokercd?" do it "is true if the binary is installed" do expect(File).to receive(:exist?).with("/usr/sbin/invoke-rc.d").and_return(true) expect(test_instance.invokercd?).to be true end it "is false if the binary is not installed" do expect(File).to receive(:exist?).with("/usr/sbin/invoke-rc.d").and_return(false) expect(test_instance.invokercd?).to be false end end context "#upstart?" do it "is true if the binary is installed" do expect(File).to receive(:exist?).with("/sbin/initctl").and_return(true) expect(test_instance.upstart?).to be true end it "is false if the binary is not installed" do expect(File).to receive(:exist?).with("/sbin/initctl").and_return(false) expect(test_instance.upstart?).to be false end end context "#insserv?" do it "is true if the binary is installed" do expect(File).to receive(:exist?).with("/sbin/insserv").and_return(true) expect(test_instance.insserv?).to be true end it "is false if the binary is not installed" do expect(File).to receive(:exist?).with("/sbin/insserv").and_return(false) expect(test_instance.insserv?).to be false end end context "#redhatrcd?" do it "is true if the binary is installed" do expect(File).to receive(:exist?).with("/sbin/chkconfig").and_return(true) expect(test_instance.redhatrcd?).to be true end it "is false if the binary is not installed" do expect(File).to receive(:exist?).with("/sbin/chkconfig").and_return(false) expect(test_instance.redhatrcd?).to be false end end context "#service_script_exist?" do it "is true if the type is :initd and /etc/init.d script exists" do expect(File).to receive(:exist?).with("/etc/init.d/example").and_return(true) expect(test_instance.service_script_exist?(:initd, "example")).to be true end it "is false if the type is :initd and /etc/init.d script does not exist" do expect(File).to receive(:exist?).with("/etc/init.d/example").and_return(false) expect(test_instance.service_script_exist?(:initd, "example")).to be false end it "is true if the type is :upstart and /etc/init script exists" do expect(File).to receive(:exist?).with("/etc/init/example.conf").and_return(true) expect(test_instance.service_script_exist?(:upstart, "example")).to be true end it "is false if the type is :upstart and /etc/init script does not exist" do expect(File).to receive(:exist?).with("/etc/init/example.conf").and_return(false) expect(test_instance.service_script_exist?(:upstart, "example")).to be false end it "is true if the type is :xinetd and /etc/xinetd.d script exists" do expect(File).to receive(:exist?).with("/etc/xinetd.d/example").and_return(true) expect(test_instance.service_script_exist?(:xinetd, "example")).to be true end it "is false if the type is :xinetd and /etc/xinetd.d script does not exist" do expect(File).to receive(:exist?).with("/etc/xinetd.d/example").and_return(false) expect(test_instance.service_script_exist?(:xinetd, "example")).to be false end it "is true if the type is :etc_rcd and /etc/rc.d script exists" do expect(File).to receive(:exist?).with("/etc/rc.d/example").and_return(true) expect(test_instance.service_script_exist?(:etc_rcd, "example")).to be true end it "is false if the type is :etc_rcd and /etc/rc.d script does not exist" do expect(File).to receive(:exist?).with("/etc/rc.d/example").and_return(false) expect(test_instance.service_script_exist?(:etc_rcd, "example")).to be false end end end chef-utils-16.12.3/spec/unit/dsl/platform_family_spec.rb0000644000175100017510000001341314034013321022165 0ustar pravipravi# frozen_string_literal: true # # Copyright:: Copyright (c) Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # require "spec_helper" require "fauxhai" def pf_reports_true_for(*args) args.each do |method| it "reports true for #{method}" do expect(described_class.send(method, node)).to be true end end (PLATFORM_FAMILY_HELPERS - [ :windows_ruby? ] - args).each do |method| it "reports false for #{method}" do expect(described_class.send(method, node)).to be false end end end RSpec.describe ChefUtils::DSL::PlatformFamily do let(:node) { Fauxhai.mock(options).data } ( HELPER_MODULES - [ described_class ] ).each do |klass| it "does not have methods that collide with #{klass}" do expect((klass.methods - Module.methods) & PLATFORM_FAMILY_HELPERS).to be_empty end end ( PLATFORM_FAMILY_HELPERS - [ :windows_ruby? ]).each do |helper| it "has the #{helper} in the ChefUtils module" do expect(ChefUtils).to respond_to(helper) end end context "on ubuntu" do let(:options) { { platform: "ubuntu" } } pf_reports_true_for(:debian?) end context "on raspbian" do let(:options) { { platform: "raspbian" } } pf_reports_true_for(:debian?) end context "on linuxmint" do let(:options) { { platform: "linuxmint" } } pf_reports_true_for(:debian?) end context "on debian" do let(:options) { { platform: "debian" } } pf_reports_true_for(:debian?) end context "on aix" do let(:options) { { platform: "aix" } } pf_reports_true_for(:aix?) end context "on amazon" do let(:options) { { platform: "amazon" } } pf_reports_true_for(:amazon?, :amazon_linux?, :rpm_based?, :fedora_derived?) end context "on arch" do let(:options) { { platform: "arch" } } pf_reports_true_for(:arch?, :arch_linux?) end context "on centos6" do let(:options) { { platform: "centos", version: "6.10" } } pf_reports_true_for(:rhel?, :rpm_based?, :fedora_derived?, :redhat_based?, :el?, :rhel6?) end context "on centos7" do let(:options) { { platform: "centos", version: "7.7.1908" } } pf_reports_true_for(:rhel?, :rpm_based?, :fedora_derived?, :redhat_based?, :el?, :rhel7?) end context "on centos8" do let(:options) { { platform: "centos", version: "8" } } pf_reports_true_for(:rhel?, :rpm_based?, :fedora_derived?, :redhat_based?, :el?, :rhel8?) end context "on clearos7" do let(:options) { { platform: "clearos", version: "7.4" } } pf_reports_true_for(:rhel?, :rpm_based?, :fedora_derived?, :redhat_based?, :el?, :rhel7?) end context "on dragonfly4" do let(:options) { { platform: "dragonfly4" } } pf_reports_true_for(:dragonflybsd?) end context "on fedora" do let(:options) { { platform: "fedora" } } pf_reports_true_for(:fedora?, :rpm_based?, :fedora_derived?, :redhat_based?) end context "on freebsd" do let(:options) { { platform: "freebsd" } } pf_reports_true_for(:freebsd?, :bsd_based?) end context "on gentoo" do let(:options) { { platform: "gentoo" } } pf_reports_true_for(:gentoo?) end context "on mac_os_x" do let(:options) { { platform: "mac_os_x" } } pf_reports_true_for(:mac_os_x?, :mac?, :osx?, :macos?) end context "on openbsd" do let(:options) { { platform: "openbsd" } } pf_reports_true_for(:openbsd?, :bsd_based?) end context "on opensuse" do let(:options) { { platform: "opensuse" } } pf_reports_true_for(:suse?, :rpm_based?) end context "on oracle6" do let(:options) { { platform: "oracle", version: "6.10" } } pf_reports_true_for(:rhel?, :rpm_based?, :fedora_derived?, :redhat_based?, :el?, :rhel6?) end context "on oracle7" do let(:options) { { platform: "oracle", version: "7.6" } } pf_reports_true_for(:rhel?, :rpm_based?, :fedora_derived?, :redhat_based?, :el?, :rhel7?) end context "on redhat6" do let(:options) { { platform: "redhat", version: "6.10" } } pf_reports_true_for(:rhel?, :rpm_based?, :fedora_derived?, :redhat_based?, :el?, :rhel6?) end context "on redhat7" do let(:options) { { platform: "redhat", version: "7.6" } } pf_reports_true_for(:rhel?, :rpm_based?, :fedora_derived?, :redhat_based?, :el?, :rhel7?) end context "on redhat8" do let(:options) { { platform: "redhat", version: "8" } } pf_reports_true_for(:rhel?, :rpm_based?, :fedora_derived?, :redhat_based?, :el?, :rhel8?) end context "on smartos" do let(:options) { { platform: "smartos" } } pf_reports_true_for(:smartos?, :solaris_based?) end context "on solaris2" do let(:options) { { platform: "solaris2" } } pf_reports_true_for(:solaris?, :solaris2?, :solaris_based?) end context "on suse" do let(:options) { { platform: "suse" } } pf_reports_true_for(:suse?, :rpm_based?) end context "on windows" do let(:options) { { platform: "windows" } } pf_reports_true_for(:windows?) end context "node-independent windows APIs" do if RUBY_PLATFORM.match?(/mswin|mingw32|windows/) it "reports true for :windows_ruby?" do expect(described_class.windows_ruby?).to be true end else it "reports false for :windows_ruby?" do expect(described_class.windows_ruby?).to be false end end end end chef-utils-16.12.3/spec/unit/dsl/dsl_spec.rb0000644000175100017510000000214614034013321017563 0ustar pravipravi# frozen_string_literal: true # # Copyright:: Copyright (c) Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # require "spec_helper" RSpec.describe ChefUtils do class ThingWithDSL extend ChefUtils end (OS_HELPERS + ARCH_HELPERS + PLATFORM_HELPERS + PLATFORM_FAMILY_HELPERS + INTROSPECTION_HELPERS).each do |helper| it "has the #{helper} in the ChefUtils module" do expect(ThingWithDSL).to respond_to(helper) end it "has the #{helper} class method in the ChefUtils module" do expect(ChefUtils).to respond_to(helper) end end end chef-utils-16.12.3/spec/unit/dsl/windows_spec.rb0000644000175100017510000000545714034013321020503 0ustar pravipravi# frozen_string_literal: true # # Copyright:: Copyright (c) Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # require "spec_helper" WINDOWS_BOOL_HELPERS = %i{windows_server_core? windows_server? windows_workstation?}.freeze def windows_reports_true_for(*args) args.each do |method| it "reports true for #{method}" do expect(described_class.send(method, node)).to be true end end (WINDOWS_BOOL_HELPERS - args).each do |method| it "reports false for #{method}" do expect(described_class.send(method, node)).to be false end end end RSpec.describe ChefUtils::DSL::Windows do ( HELPER_MODULES - [ described_class ] ).each do |klass| it "does not have methods that collide with #{klass}" do expect((klass.methods - Module.methods) & WINDOWS_HELPERS).to be_empty end end WINDOWS_HELPERS.each do |helper| it "has the #{helper} in the ChefUtils module" do expect(ChefUtils).to respond_to(helper) end end context "windows boolean helpers" do context "on Windows Server Core" do let(:node) { { "kernel" => { "server_core" => true } } } windows_reports_true_for(:windows_server_core?) end context "on Windows Workstation" do let(:node) { { "kernel" => { "product_type" => "Workstation" } } } windows_reports_true_for(:windows_workstation?) end context "on Windows Server" do let(:node) { { "kernel" => { "product_type" => "Server" } } } windows_reports_true_for(:windows_server?) end end context "#windows_nt_version on Windows Server 2012 R2" do let(:node) { { "os_version" => "6.3.9600" } } it "it returns a ChefUtils::VersionString object with 6.3.9600" do expect(described_class.send(:windows_nt_version, node)).to eq "6.3.9600" expect(described_class.send(:windows_nt_version, node)).to be_a_kind_of ChefUtils::VersionString end end context "#powershell_version on Windows Server 2012 R2" do let(:node) { { "languages" => { "powershell" => { "version" => "4.0" } } } } it "it returns a ChefUtils::VersionString object with 4.0" do expect(described_class.send(:powershell_version, node)).to eq "4.0" expect(described_class.send(:powershell_version, node)).to be_a_kind_of ChefUtils::VersionString end end end chef-utils-16.12.3/spec/unit/dsl/which_spec.rb0000644000175100017510000001402714034013321020104 0ustar pravipravi# frozen_string_literal: true # # Copyright:: Copyright (c) Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # require "spec_helper" RSpec.describe ChefUtils::DSL::Which do class WhichTestClass include ChefUtils::DSL::Which end let(:test) { WhichTestClass.new } describe "#which" do def self.test_which(description, *args, path: ["/dir1", "/dir2" ].join(File::PATH_SEPARATOR), finds: nil, others: [], directory: false, &block) it description do # stub the ENV['PATH'] expect(ENV).to receive(:[]).with("PATH").and_return(path) expect(ENV).to receive(:[]).with("PATHEXT").and_return(nil) # most files should not be found allow(File).to receive(:executable?).and_return(false) allow(File).to receive(:directory?).and_return(false) # stub the expectation expect(File).to receive(:executable?).with(finds).and_return(true) if finds # if the file we find is a directory expect(File).to receive(:directory?).with(finds).and_return(true) if finds && directory # allow for stubbing other paths to exist that we should not find others.each do |other| allow(File).to receive(:executable?).with(other).and_return(true) end # setup the actual expectation on the return value if finds && !directory expect(test.which(*args, &block)).to eql(finds) else expect(test.which(*args, &block)).to eql(false) end end end context "simple usage" do test_which("returns false when it does not find anything", "foo1") ["/dir1", "/dir2" ].each do |dir| test_which("finds `foo1` in #{dir} when it is stubbed", "foo1", finds: "#{dir}/foo1") end test_which("does not find an executable directory", "foo1", finds: "/dir1/foo1", directory: true) end context "with an array of args" do test_which("finds the first arg", "foo1", "foo2", finds: "/dir2/foo1") test_which("finds the second arg", "foo1", "foo2", finds: "/dir2/foo2") test_which("finds the first arg when there's both", "foo1", "foo2", finds: "/dir2/foo1", others: [ "/dir1/foo2" ]) test_which("and the directory order can be reversed", "foo1", "foo2", finds: "/dir1/foo1", others: [ "/dir2/foo2" ]) test_which("or be the same", "foo1", "foo2", finds: "/dir1/foo1", others: [ "/dir1/foo2" ]) end context "with a block" do test_which("doesn't find it if its false", "foo1", others: [ "/dir1/foo1" ]) do |f| false end test_which("finds it if its true", "foo1", finds: "/dir1/foo1") do |f| true end test_which("passes in the filename as the arg", "foo1", finds: "/dir1/foo1") do |f| raise "bad arg to block" unless f == "/dir1/foo1" true end test_which("arrays with blocks", "foo1", "foo2", finds: "/dir2/foo1", others: [ "/dir1/foo2" ]) do |f| raise "bad arg to block" unless ["/dir2/foo1", "/dir1/foo2"].include?(f) true end end context "nil path" do test_which("returns false when it does not find anything", "foo1", path: nil) end end describe "#where" do def self.test_where(description, *args, path: ["/dir1", "/dir2" ].join(File::PATH_SEPARATOR), finds: [], others: [], &block) it description do # stub the ENV['PATH'] expect(ENV).to receive(:[]).with("PATH").and_return(path) expect(ENV).to receive(:[]).with("PATHEXT").and_return(nil) # most files should not be found allow(File).to receive(:executable?).and_return(false) allow(File).to receive(:directory?).and_return(false) # allow for stubbing other paths to exist that we should not return others.each do |other| allow(File).to receive(:executable?).with(other).and_return(true) end # stub the expectation finds.each do |path| expect(File).to receive(:executable?).with(path).and_return(true) end # setup the actual expectation on the return value expect(test.where(*args, &block)).to eql(finds) end end context "simple usage" do test_where("returns empty array when it doesn't find anything", "foo1") ["/dir1", "/dir2" ].each do |dir| test_where("finds `foo1` in #{dir} when it is stubbed", "foo1", finds: [ "#{dir}/foo1" ]) end test_where("finds `foo1` in all directories", "foo1", finds: [ "/dir1/foo1", "/dir2/foo1" ]) end context "with an array of args" do test_where("finds the first arg", "foo1", "foo2", finds: [ "/dir2/foo1" ]) test_where("finds the second arg", "foo1", "foo2", finds: [ "/dir2/foo2" ]) test_where("finds foo1 before foo2 if the dirs are reversed", "foo1", "foo2", finds: [ "/dir1/foo1", "/dir2/foo2" ]) test_where("finds them both in the same directory", "foo1", "foo2", finds: [ "/dir1/foo1", "/dir1/foo2" ]) test_where("finds foo2 first if they're reversed", "foo2", "foo1", finds: [ "/dir1/foo2", "/dir1/foo1" ]) end context "with a block do" do test_where("finds foo1 and foo2 if they exist and the block is true", "foo1", "foo2", finds: [ "/dir1/foo2", "/dir2/foo2" ]) do true end test_where("does not finds foo1 and foo2 if they exist and the block is false", "foo1", "foo2", others: [ "/dir1/foo2", "/dir2/foo2" ]) do false end end context "with a nil path" do test_where("returns empty array when it doesn't find anything", "foo1", path: nil) end end end chef-utils-16.12.3/spec/unit/dsl/introspection_spec.rb0000644000175100017510000001441114034013321021677 0ustar pravipravi# frozen_string_literal: true # # Copyright:: Copyright (c) Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # require "spec_helper" RSpec.describe ChefUtils::DSL::Introspection do class IntrospectionTestClass include ChefUtils::DSL::Introspection attr_accessor :node def initialize(node) @node = node end end let(:node) { double("node") } let(:test_instance) { IntrospectionTestClass.new(node) } context "#docker?" do # FIXME: use a real VividMash for these tests instead of stubbing it "is false by default" do expect(node).to receive(:read).with("virtualization", "systems", "docker").and_return(nil) expect(ChefUtils.docker?(node)).to be false end it "is true when ohai reports a docker guest" do expect(node).to receive(:read).with("virtualization", "systems", "docker").and_return("guest") expect(ChefUtils.docker?(node)).to be true end it "is false for any other value other than guest" do expect(node).to receive(:read).with("virtualization", "systems", "docker").and_return("some nonsense") expect(ChefUtils.docker?(node)).to be false end end context "#systemd?" do # FIXME: somehow test the train helpers it "returns false if /proc/1/comm does not exist" do expect(File).to receive(:exist?).with("/proc/1/comm").and_return(false) expect(ChefUtils.systemd?(node)).to be false end it "returns false if /proc/1/comm is not systemd" do expect(File).to receive(:exist?).with("/proc/1/comm").and_return(true) expect(File).to receive(:open).with("/proc/1/comm").and_return(StringIO.new("upstart\n")) expect(ChefUtils.systemd?(node)).to be false end it "returns true if /proc/1/comm is systemd" do expect(File).to receive(:exist?).with("/proc/1/comm").and_return(true) expect(File).to receive(:open).with("/proc/1/comm").and_return(StringIO.new("systemd\n")) expect(ChefUtils.systemd?(node)).to be true end end context "#kitchen?" do before do @saved = ENV["TEST_KITCHEN"] end after do ENV["TEST_KITCHEN"] = @saved end it "return true if ENV['TEST_KITCHEN'] is not set" do ENV.delete("TEST_KITCHEN") expect(ChefUtils.kitchen?(node)).to be false end it "return true if ENV['TEST_KITCHEN'] is nil" do ENV["TEST_KITCHEN"] = nil expect(ChefUtils.kitchen?(node)).to be false end it "return true if ENV['TEST_KITCHEN'] is set" do ENV["TEST_KITCHEN"] = "1" expect(ChefUtils.kitchen?(node)).to be true end end context "#ci?" do before do @saved = ENV["CI"] end after do ENV["CI"] = @saved end it "return true if ENV['CI'] is not set" do ENV.delete("CI") expect(ChefUtils.ci?(node)).to be false end it "return true if ENV['CI'] is nil" do ENV["CI"] = nil expect(ChefUtils.ci?(node)).to be false end it "return true if ENV['CI'] is set" do ENV["CI"] = "1" expect(ChefUtils.ci?(node)).to be true end end context "#has_systemd_service_unit?" do # FIXME: test through train helpers before do %w{ /etc /usr/lib /lib /run }.each do |base| allow(File).to receive(:exist?).with("#{base}/systemd/system/example.service").and_return(false) allow(File).to receive(:exist?).with("#{base}/systemd/system/example@.service").and_return(false) end end it "is false if no unit is present" do expect(ChefUtils.has_systemd_service_unit?("example")).to be false end it "is false if no template is present" do expect(ChefUtils.has_systemd_service_unit?("example@instance1")).to be false end %w{ /etc /usr/lib /lib /run }.each do |base| it "finds a unit in #{base}" do expect(File).to receive(:exist?).with("#{base}/systemd/system/example.service").and_return(true) expect(ChefUtils.has_systemd_service_unit?("example")).to be true end it "finds a template in #{base}" do expect(File).to receive(:exist?).with("#{base}/systemd/system/example@.service").and_return(true) expect(ChefUtils.has_systemd_service_unit?("example@instance1")).to be true end end end context "#has_systemd_unit?" do # FIXME: test through train helpers before do %w{ /etc /usr/lib /lib /run }.each do |base| allow(File).to receive(:exist?).with("#{base}/systemd/system/example.mount").and_return(false) end end it "is false if no unit is present" do expect(ChefUtils.has_systemd_unit?("example.mount")).to be false end %w{ /etc /usr/lib /lib /run }.each do |base| it "finds a unit in #{base}" do expect(File).to receive(:exist?).with("#{base}/systemd/system/example.mount").and_return(true) expect(ChefUtils.has_systemd_unit?("example.mount")).to be true end end end context "#include_recipe?" do it "is true when the recipe has been seen by the node" do expect(node).to receive(:recipe?).with("myrecipe").and_return(true) expect(ChefUtils.include_recipe?("myrecipe", node)).to be true end it "is false when the recipe has not been seen by the node" do expect(node).to receive(:recipe?).with("myrecipe").and_return(false) expect(ChefUtils.include_recipe?("myrecipe", node)).to be false end it "the alias is true when the recipe has been seen by the node" do expect(node).to receive(:recipe?).with("myrecipe").and_return(true) expect(ChefUtils.includes_recipe?("myrecipe", node)).to be true end it "the alias is false when the recipe has not been seen by the node" do expect(node).to receive(:recipe?).with("myrecipe").and_return(false) expect(ChefUtils.includes_recipe?("myrecipe", node)).to be false end end end chef-utils-16.12.3/spec/spec_helper.rb0000644000175100017510000001050114034013321016511 0ustar pravipravi# frozen_string_literal: true require "chef-utils" # FIXME: dynamically generate this for accuracy HELPER_MODULES = [ ChefUtils::DSL::Architecture, ChefUtils::DSL::Cloud, ChefUtils::DSL::Introspection, ChefUtils::DSL::OS, ChefUtils::DSL::DefaultPaths, ChefUtils::DSL::Platform, ChefUtils::DSL::PlatformFamily, ChefUtils::DSL::Service, ChefUtils::DSL::Virtualization, ChefUtils::DSL::Which, ChefUtils::DSL::Windows, ].freeze ARCH_HELPERS = (ChefUtils::DSL::Architecture.methods - Module.methods).freeze CLOUD_HELPERS = (ChefUtils::DSL::Cloud.methods - Module.methods).freeze INTROSPECTION_HELPERS = (ChefUtils::DSL::Introspection.methods - Module.methods).freeze OS_HELPERS = (ChefUtils::DSL::OS.methods - Module.methods).freeze PLATFORM_FAMILY_HELPERS = (ChefUtils::DSL::PlatformFamily.methods - Module.methods).freeze PLATFORM_HELPERS = (ChefUtils::DSL::Platform.methods - Module.methods).freeze VIRTUALIZATION_HELPERS = (ChefUtils::DSL::Virtualization.methods - Module.methods).freeze WINDOWS_HELPERS = (ChefUtils::DSL::Windows.methods - Module.methods).freeze # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration RSpec.configure do |config| # rspec-expectations config goes here. You can use an alternate # assertion/expectation library such as wrong or the stdlib/minitest # assertions if you prefer. config.expect_with :rspec do |expectations| # This option will default to `true` in RSpec 4. It makes the `description` # and `failure_message` of custom matchers include text for helper methods # defined using `chain`, e.g.: # be_bigger_than(2).and_smaller_than(4).description # # => "be bigger than 2 and smaller than 4" # ...rather than: # # => "be bigger than 2" expectations.include_chain_clauses_in_custom_matcher_descriptions = true end # rspec-mocks config goes here. You can use an alternate test double # library (such as bogus or mocha) by changing the `mock_with` option here. config.mock_with :rspec do |mocks| # Prevents you from mocking or stubbing a method that does not exist on # a real object. This is generally recommended, and will default to # `true` in RSpec 4. mocks.verify_partial_doubles = true end # These two settings work together to allow you to limit a spec run # to individual examples or groups you care about by tagging them with # `:focus` metadata. When nothing is tagged with `:focus`, all examples # get run. config.filter_run :focus config.run_all_when_everything_filtered = true config.filter_run_excluding windows_only: true unless ChefUtils.windows? config.filter_run_excluding unix_only: true if ChefUtils.windows? # Limits the available syntax to the non-monkey patched syntax that is # recommended. For more details, see: # - http://myronmars.to/n/dev-blog/2012/06/rspecs-new-expectation-syntax # - http://teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/ # - http://myronmars.to/n/dev-blog/2014/05/notable-changes-in-rspec-3#new__config_option_to_disable_rspeccore_monkey_patching config.disable_monkey_patching! # This setting enables warnings. It's recommended, but in some cases may # be too noisy due to issues in dependencies. config.warnings = true # Many RSpec users commonly either run the entire suite or an individual # file, and it's useful to allow more verbose output when running an # individual spec file. if config.files_to_run.one? # Use the documentation formatter for detailed output, # unless a formatter has already been configured # (e.g. via a command-line flag). config.default_formatter = "doc" end # Print the 10 slowest examples and example groups at the # end of the spec run, to help surface which specs are running # particularly slow. # config.profile_examples = 10 # Run specs in random order to surface order dependencies. If you find an # order dependency and want to debug it, you can fix the order by providing # the seed, which is printed after each run. # --seed 1234 config.order = :random # Seed global randomization in this process using the `--seed` CLI option. # Setting this allows you to use `--seed` to deterministically reproduce # test failures related to randomization by passing the same `--seed` value # as the one that triggered the failure. Kernel.srand config.seed end chef-utils-16.12.3/lib/0000755000175100017510000000000014034013321013512 5ustar pravipravichef-utils-16.12.3/lib/chef-utils/0000755000175100017510000000000014034013321015555 5ustar pravipravichef-utils-16.12.3/lib/chef-utils/mash.rb0000644000175100017510000001655414034013321017045 0ustar pravipravi# frozen_string_literal: true # Copyright 2009-2016, Dan Kubb # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the # "Software"), to deal in the Software without restriction, including # without limitation the rights to use, copy, modify, merge, publish, # distribute, sublicense, and/or sell copies of the Software, and to # permit persons to whom the Software is furnished to do so, subject to # the following conditions: # The above copyright notice and this permission notice shall be # included in all copies or substantial portions of the Software. # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # --- # --- # Some portions of blank.rb and mash.rb are verbatim copies of software # licensed under the MIT license. That license is included below: # Copyright 2005-2016, David Heinemeier Hansson # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the # "Software"), to deal in the Software without restriction, including # without limitation the rights to use, copy, modify, merge, publish, # distribute, sublicense, and/or sell copies of the Software, and to # permit persons to whom the Software is furnished to do so, subject to # the following conditions: # The above copyright notice and this permission notice shall be # included in all copies or substantial portions of the Software. # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # This class has dubious semantics and we only have it so that people can write # params[:key] instead of params['key']. module ChefUtils class Mash < Hash # @param constructor # The default value for the mash. Defaults to an empty hash. # # @details [Alternatives] # If constructor is a Hash, a new mash will be created based on the keys of # the hash and no default value will be set. def initialize(constructor = {}) if constructor.is_a?(Hash) super() update(constructor) else super(constructor) end end # @param orig Mash being copied # # @return [Object] A new copied Mash def initialize_copy(orig) super # Handle nested values each do |k, v| if v.is_a?(Mash) || v.is_a?(Array) self[k] = v.dup end end self end # @param key The default value for the mash. Defaults to nil. # # @details [Alternatives] # If key is a Symbol and it is a key in the mash, then the default value will # be set to the value matching the key. def default(key = nil) if key.is_a?(Symbol) && include?(key = key.to_s) self[key] else super end end unless method_defined?(:regular_writer) alias_method :regular_writer, :[]= end unless method_defined?(:regular_update) alias_method :regular_update, :update end # @param key The key to set. # @param value # The value to set the key to. # # @see Mash#convert_key # @see Mash#convert_value def []=(key, value) regular_writer(convert_key(key), convert_value(value)) end # internal API for use by Chef's deep merge cache # @api private def internal_set(key, value) regular_writer(key, convert_value(value)) end # @param other_hash # A hash to update values in the mash with. The keys and the values will be # converted to Mash format. # # @return [Mash] The updated mash. def update(other_hash) other_hash.each_pair { |key, value| regular_writer(convert_key(key), convert_value(value)) } self end alias_method :merge!, :update # @param key The key to check for. This will be run through convert_key. # # @return [Boolean] True if the key exists in the mash. def key?(key) super(convert_key(key)) end # def include? def has_key? def member? alias_method :include?, :key? alias_method :has_key?, :key? alias_method :member?, :key? # @param key The key to fetch. This will be run through convert_key. # @param *extras Default value. # # @return [Object] The value at key or the default value. def fetch(key, *extras) super(convert_key(key), *extras) end # @param *indices # The keys to retrieve values for. These will be run through +convert_key+. # # @return [Array] The values at each of the provided keys def values_at(*indices) indices.collect { |key| self[convert_key(key)] } end # @param hash The hash to merge with the mash. # # @return [Mash] A new mash with the hash values merged in. def merge(hash) dup.update(hash) end # @param key # The key to delete from the mash.\ def delete(key) super(convert_key(key)) end # @param *rejected 1, :two => 2, :three => 3 }.except(:one) # #=> { "two" => 2, "three" => 3 } def except(*keys) super(*keys.map { |k| convert_key(k) }) end # Used to provide the same interface as Hash. # # @return [Mash] This mash unchanged. def stringify_keys!; self end # @return [Hash] The mash as a Hash with symbolized keys. def symbolize_keys h = Hash.new(default) each { |key, val| h[key.to_sym] = val } h end # @return [Hash] The mash as a Hash with string keys. def to_hash Hash.new(default).merge(self) end # @return [Mash] Convert a Hash into a Mash # The input Hash's default value is maintained def self.from_hash(hash) mash = Mash.new(hash) mash.default = hash.default mash end protected # @param key The key to convert. # # @param [Object] # The converted key. If the key was a symbol, it will be converted to a # string. # # @api private def convert_key(key) key.is_a?(Symbol) ? key.to_s : key end # @param value The value to convert. # # @return [Object] # The converted value. A Hash or an Array of hashes, will be converted to # their Mash equivalents. # # @api private def convert_value(value) if value.class == Hash Mash.from_hash(value) elsif value.is_a?(Array) value.collect { |e| convert_value(e) } else value end end end end chef-utils-16.12.3/lib/chef-utils/dist.rb0000644000175100017510000000464514034013321017056 0ustar pravipravi# frozen_string_literal: true module ChefUtils # This class is not fully implemented, depending on it is not recommended! module Dist class Apply # The chef-apply product name PRODUCT = "Chef Infra Apply" # The chef-apply binary EXEC = "chef-apply" end class Automate # name of the automate product PRODUCT = "Chef Automate" end class Infra # When referencing a product directly, like Chef (Now Chef Infra) PRODUCT = "Chef Infra Client" # A short designation for the product, used in Windows event logs # and some nomenclature. SHORT = "chef" # The client's alias (chef-client) CLIENT = "chef-client" # The chef executable, as in `chef gem install` or `chef generate cookbook` EXEC = "chef" # The chef-shell executable SHELL = "chef-shell" # Configuration related constants # The chef-shell configuration file SHELL_CONF = "chef_shell.rb" # The user's configuration directory USER_CONF_DIR = ".chef" # The suffix for Chef's /etc/chef, /var/chef and C:\\Chef directories # "chef" => /etc/cinc, /var/cinc, C:\\cinc DIR_SUFFIX = "chef" end class Org # product Website address WEBSITE = "https://chef.io" # The downloads site DOWNLOADS_URL = "downloads.chef.io" # The legacy conf folder: C:/opscode/chef. Specifically the "opscode" part # DIR_SUFFIX is appended to it in code where relevant LEGACY_CONF_DIR = "opscode" # Enable forcing Chef EULA ENFORCE_LICENSE = true # product patents page PATENTS = "https://www.chef.io/patents" # knife documentation page KNIFE_DOCS = "https://docs.chef.io/workstation/knife/" end class Server # The name of the server product PRODUCT = "Chef Infra Server" # The server's configuration directory CONF_DIR = "/etc/chef-server" # The servers's alias (chef-server) SERVER = "chef-server" # The server's configuration utility SERVER_CTL = "chef-server-ctl" end class Solo # Chef-Solo's product name PRODUCT = "Chef Infra Solo" # The chef-solo executable (legacy local mode) EXEC = "chef-solo" end class Zero # chef-zero executable PRODUCT = "Chef Infra Zero" # The chef-zero executable (local mode) EXEC = "chef-zero" end end end chef-utils-16.12.3/lib/chef-utils/version.rb0000644000175100017510000000136614034013321017575 0ustar pravipravi# frozen_string_literal: true # Copyright:: Copyright (c) Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. module ChefUtils CHEFUTILS_ROOT = File.expand_path("..", __dir__) VERSION = "16.12.3" end chef-utils-16.12.3/lib/chef-utils/dsl/0000755000175100017510000000000014034013321016337 5ustar pravipravichef-utils-16.12.3/lib/chef-utils/dsl/path_sanity.rb0000644000175100017510000000172514034013321021214 0ustar pravipravi# frozen_string_literal: true # # Copyright:: Copyright (c) Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # require_relative "default_paths" module ChefUtils module DSL module PathSanity include ChefUtils::DSL::DefaultPaths def sanitized_path(env = nil) default_paths(env) end private def __sane_paths __default_paths end extend self end end end chef-utils-16.12.3/lib/chef-utils/dsl/cloud.rb0000644000175100017510000000707514034013321020003 0ustar pravipravi# frozen_string_literal: true # # Copyright:: Copyright (c) Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # require_relative "../internal" module ChefUtils module DSL module Cloud include Internal # Determine if the current node is "in the cloud". # # @param [Chef::Node] node the node to check # @since 15.8 # # @return [Boolean] # def cloud?(node = __getnode) # cloud is always present, but nil if not on a cloud !node["cloud"].nil? end # Return true if the current current node is in EC2. # # @param [Chef::Node] node the node to check # @since 15.8 # # @return [Boolean] # def ec2?(node = __getnode) node.key?("ec2") end # Return true if the current current node is in GCE. # # @param [Chef::Node] node the node to check # @since 15.8 # # @return [Boolean] # def gce?(node = __getnode) node.key?("gce") end # Return true if the current current node is in Rackspace. # # @param [Chef::Node] node the node to check # @since 15.8 # # @return [Boolean] # def rackspace?(node = __getnode) node.key?("rackspace") end # Return true if the current current node is in Eucalyptus. # # @param [Chef::Node] node the node to check # @since 15.8 # # @return [Boolean] # def eucalyptus?(node = __getnode) node.key?("eucalyptus") end # chef-sugar backcompat method alias_method :euca?, :eucalyptus? # Return true if the current current node is in Linode. # # @param [Chef::Node] node the node to check # @since 15.8 # # @return [Boolean] # def linode?(node = __getnode) node.key?("linode") end # Return true if the current current node is in OpenStack. # # @param [Chef::Node] node the node to check # @since 15.8 # # @return [Boolean] # def openstack?(node = __getnode) node.key?("openstack") end # Return true if the current current node is in Azure. # # @param [Chef::Node] node the node to check # @since 15.8 # # @return [Boolean] # def azure?(node = __getnode) node.key?("azure") end # Return true if the current current node is in DigitalOcean. # # @param [Chef::Node] node the node to check # @since 15.8 # # @return [Boolean] # def digital_ocean?(node = __getnode) node.key?("digital_ocean") end # chef-sugar backcompat method alias_method :digitalocean?, :digital_ocean? # Return true if the current current node is in SoftLayer. # # @param [Chef::Node] node the node to check # @since 15.8 # # @return [Boolean] # def softlayer?(node = __getnode) node.key?("softlayer") end extend self end end end chef-utils-16.12.3/lib/chef-utils/dsl/train_helpers.rb0000644000175100017510000000554114034013321021530 0ustar pravipravi# frozen_string_literal: true # # Copyright:: Copyright (c) Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. require "stringio" unless defined?(StringIO) require_relative "../internal" module ChefUtils module DSL module TrainHelpers include Internal # # FIXME: generally these helpers all use the pattern of checking for target_mode? # and then if it is we use train. That approach should likely be flipped so that # even when we're running without target mode we still use train in its local # mode. A prerequisite for that will be better CI testing of train against # chef-client though, and ensuring that the APIs are entirely compatible. This # will be particularly problematic for shell_out APIs and eventual file-creating # APIs which are unlikely to be as sophisticated as the exiting code in chef-client # for locally shelling out and creating files, and just dropping inspec local mode # into chef-client would break the world. # # Train wrapper around File.exist? to make it local mode aware. # # @param filename filename to check # @return [Boolean] if it exists # def file_exist?(filename) if __transport_connection __transport_connection.file(filename).exist? else File.exist?(filename) end end # XXX: modifications to the StringIO won't get written back # FIXME: this is very experimental and may be a bad idea and may break at any time # @api private # def file_open(*args, &block) if __transport_connection content = __transport_connection.file(args[0]).content string_io = StringIO.new content yield string_io if block_given? string_io else File.open(*args, &block) end end # Alias to easily convert IO.read / File.read to file_read def file_read(path) file_open(path).read end def file_directory?(path) if __transport_connection __transport_connection.file(filename).directory? else File.directory?(path) end end # Alias to easily convert Dir.exist to dir_exist def dir_exist?(path) file_directory?(path) end extend self end end end chef-utils-16.12.3/lib/chef-utils/dsl/platform_family.rb0000644000175100017510000002561114034013321022056 0ustar pravipravi# frozen_string_literal: true # # Copyright:: Copyright (c) Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # require_relative "../internal" module ChefUtils module DSL module PlatformFamily include Internal # Determine if the current node is a member of the 'arch' family. # # @param [Chef::Node] node the node to check # @since 15.5 # # @return [Boolean] # def arch?(node = __getnode) node["platform_family"] == "arch" end # chef-sugar backcompat method alias_method :arch_linux?, :arch? # Determine if the current node is a member of the 'aix' platform family. # # @param [Chef::Node] node the node to check # @since 15.5 # # @return [Boolean] # def aix?(node = __getnode) node["platform_family"] == "aix" end # Determine if the current node is a member of the 'debian' platform family (Debian, Ubuntu and derivatives). # # @param [Chef::Node] node the node to check # @since 15.5 # # @return [Boolean] # def debian?(node = __getnode) node["platform_family"] == "debian" end # Determine if the current node is a member of the 'fedora' platform family (Fedora and Arista). # # @param [Chef::Node] node the node to check # @since 15.5 # # @return [Boolean] # def fedora?(node = __getnode) node["platform_family"] == "fedora" end # Determine if the current node is a member of the 'mac_os_x' platform family. # # @param [Chef::Node] node the node to check # @since 15.5 # # @return [Boolean] # def macos?(node = __getnode) node["platform_family"] == "mac_os_x" end # chef-sugar backcompat method alias_method :osx?, :macos? # chef-sugar backcompat method alias_method :mac?, :macos? # chef-sugar backcompat method alias_method :mac_os_x?, :macos? # Determine if the current node is a member of the 'rhel' platform family (Red Hat, CentOS, Oracle or Scientific Linux, but NOT Amazon Linux or Fedora). # # @param [Chef::Node] node the node to check # @since 15.5 # # @return [Boolean] # def rhel?(node = __getnode) node["platform_family"] == "rhel" end # chef-sugar backcompat method alias_method :el?, :rhel? # Determine if the current node is a rhel6 compatible build (Red Hat, CentOS, Oracle or Scientific Linux). # # @param [Chef::Node] node the node to check # @since 15.5 # # @return [Boolean] # def rhel6?(node = __getnode) node["platform_family"] == "rhel" && node["platform_version"].to_f >= 6.0 && node["platform_version"].to_f < 7.0 end # Determine if the current node is a rhel7 compatible build (Red Hat, CentOS, Oracle or Scientific Linux). # # @param [Chef::Node] node the node to check # @since 15.5 # # @return [Boolean] # def rhel7?(node = __getnode) node["platform_family"] == "rhel" && node["platform_version"].to_f >= 7.0 && node["platform_version"].to_f < 8.0 end # Determine if the current node is a rhel8 compatible build (Red Hat, CentOS, Oracle or Scientific Linux). # # @param [Chef::Node] node the node to check # @since 15.5 # # @return [Boolean] # def rhel8?(node = __getnode) node["platform_family"] == "rhel" && node["platform_version"].to_f >= 8.0 && node["platform_version"].to_f < 9.0 end # Determine if the current node is a member of the 'amazon' platform family. # # @param [Chef::Node] node the node to check # @since 15.5 # # @return [Boolean] # def amazon?(node = __getnode) node["platform_family"] == "amazon" end # chef-sugar backcompat method alias_method :amazon_linux?, :amazon? # Determine if the current node is a member of the 'solaris2' platform family. # # @param [Chef::Node] node the node to check # @since 15.5 # # @return [Boolean] # def solaris2?(node = __getnode) node["platform_family"] == "solaris2" end # chef-sugar backcompat method alias_method :solaris?, :solaris2? # Determine if the current node is a member of the 'smartos' platform family. # # @param [Chef::Node] node the node to check # @since 15.5 # # @return [Boolean] # def smartos?(node = __getnode) node["platform_family"] == "smartos" end # Determine if the current node is a member of the 'suse' platform family (openSUSE, SLES, and SLED). # # @param [Chef::Node] node the node to check # @since 15.5 # # @return [Boolean] # def suse?(node = __getnode) node["platform_family"] == "suse" end # Determine if the current node is a member of the 'gentoo' platform family. # # @param [Chef::Node] node the node to check # @since 15.5 # # @return [Boolean] # def gentoo?(node = __getnode) node["platform_family"] == "gentoo" end # Determine if the current node is a member of the 'freebsd' platform family. # # @param [Chef::Node] node the node to check # @since 15.5 # # @return [Boolean] # def freebsd?(node = __getnode) node["platform_family"] == "freebsd" end # Determine if the current node is a member of the 'openbsd' platform family. # # @param [Chef::Node] node the node to check # @since 15.5 # # @return [Boolean] # def openbsd?(node = __getnode) node["platform_family"] == "openbsd" end # Determine if the current node is a member of the 'netbsd' platform family. # # @param [Chef::Node] node the node to check # @since 15.5 # # @return [Boolean] # def netbsd?(node = __getnode) node["platform_family"] == "netbsd" end # Determine if the current node is a member of the 'dragonflybsd' platform family. # # @param [Chef::Node] node the node to check # @since 15.5 # # @return [Boolean] # def dragonflybsd?(node = __getnode) node["platform_family"] == "dragonflybsd" end # Determine if the current node is a member of the 'windows' platform family. # # @param [Chef::Node] node the node to check # @since 15.5 # # @return [Boolean] # def windows?(node = __getnode(true)) # This is all somewhat complicated. We prefer to get the node object so that chefspec can # stub the node object. But we also have to deal with class-parsing time where there is # no node object, so we have to fall back to RUBY_PLATFORM based detection. We cannot pull # the node object out of the Chef.run_context.node global object here (which is what the # false flag to __getnode is about) because some run-time code also cannot run under chefspec # on non-windows where the node is stubbed to windows. # # As a result of this the `windows?` helper and the `ChefUtils.windows?` helper do not behave # the same way in that the latter is not stubbable by chefspec. # node ? node["platform_family"] == "windows" : windows_ruby? end # Determine if the Ruby VM is currently running on a Windows node (ChefSpec can never stub # this behavior, so this is useful for code which can never be parsed on a non-Windows box). # # @since 15.5 # # @return [Boolean] # def windows_ruby? !!(RUBY_PLATFORM =~ /mswin|mingw32|windows/) end # # Platform-Family-like Helpers # # These are meta-helpers which address the issue that platform_family is single valued and cannot # be an array while a tree-like Taxonomy is what is called for in some cases. # # If it uses RPM, it goes in here (rhel, fedora, amazon, suse platform_families). Deliberately does not # include AIX because bff is AIX's primary package manager and adding it here would make this substantially # less useful since in no way can AIX trace its lineage back to old redhat distros. This is most useful for # "smells like redhat, including SuSE". # # @param [Chef::Node] node the node to check # @since 15.5 # # @return [Boolean] # def rpm_based?(node = __getnode) fedora_derived?(node) || node["platform_family"] == "suse" end # RPM-based distros which are not SuSE and are very loosely similar to fedora, using yum or dnf. The historical # lineage of the distro should have forked off from old redhat fedora distros at some point. Currently rhel, # fedora and amazon. This is most useful for "smells like redhat, but isn't SuSE". # # @param [Chef::Node] node the node to check # @since 15.5 # # @return [Boolean] # def fedora_derived?(node = __getnode) redhat_based?(node) || node["platform_family"] == "amazon" end # RedHat distros -- fedora and rhel platform_families, nothing else. This is most likely not as useful as the # "fedora_derived?" helper. # # @param [Chef::Node] node the node to check # @since 15.5 # # @return [Boolean] # def redhat_based?(node = __getnode) %w{rhel fedora}.include?(node["platform_family"]) end # All of the Solaris-lineage. # # @param [Chef::Node] node the node to check # @since 15.5 # # @return [Boolean] # def solaris_based?(node = __getnode) %w{solaris2 smartos omnios openindiana}.include?(node["platform"]) end # All of the BSD-lineage. # # Note that macOS is not included since macOS deviates so significantly from BSD that including it would not be useful. # # @param [Chef::Node] node the node to check # @since 15.5 # # @return [Boolean] # def bsd_based?(node = __getnode) # we could use os, platform_family or platform here equally %w{netbsd freebsd openbsd dragonflybsd}.include?(node["platform"]) end extend self end end end chef-utils-16.12.3/lib/chef-utils/dsl/virtualization.rb0000644000175100017510000001617014034013321021755 0ustar pravipravi# frozen_string_literal: true # # Copyright:: Copyright (c) Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # require_relative "../internal" module ChefUtils module DSL module Virtualization include Internal # Determine if the current node is a KVM guest. # # @param [Chef::Node] node # @since 15.8 # # @return [Boolean] # def kvm?(node = __getnode) node.dig("virtualization", "system") == "kvm" && node.dig("virtualization", "role") == "guest" end # Determine if the current node is a KVM host. # # @param [Chef::Node] node # @since 15.8 # # @return [Boolean] # def kvm_host?(node = __getnode) node.dig("virtualization", "system") == "kvm" && node.dig("virtualization", "role") == "host" end # Determine if the current node is running in a linux container. # # @param [Chef::Node] node # @since 15.8 # # @return [Boolean] # def lxc?(node = __getnode) node.dig("virtualization", "system") == "lxc" && node.dig("virtualization", "role") == "guest" end # Determine if the current node is a linux container host. # # @param [Chef::Node] node # @since 15.8 # # @return [Boolean] # def lxc_host?(node = __getnode) node.dig("virtualization", "system") == "lxc" && node.dig("virtualization", "role") == "host" end # Determine if the current node is running under Parallels Desktop. # # @param [Chef::Node] node # @since 15.8 # # @return [Boolean] # true if the machine is currently running under Parallels Desktop, false # otherwise # def parallels?(node = __getnode) node.dig("virtualization", "system") == "parallels" && node.dig("virtualization", "role") == "guest" end # Determine if the current node is a Parallels Desktop host. # # @param [Chef::Node] node # @since 15.8 # # @return [Boolean] # true if the machine is currently running under Parallels Desktop, false # otherwise # def parallels_host?(node = __getnode) node.dig("virtualization", "system") == "parallels" && node.dig("virtualization", "role") == "host" end # Determine if the current node is a VirtualBox guest. # # @param [Chef::Node] node # @since 15.8 # # @return [Boolean] # def vbox?(node = __getnode) node.dig("virtualization", "system") == "vbox" && node.dig("virtualization", "role") == "guest" end # Determine if the current node is a VirtualBox host. # # @param [Chef::Node] node # @since 15.8 # # @return [Boolean] # def vbox_host?(node = __getnode) node.dig("virtualization", "system") == "vbox" && node.dig("virtualization", "role") == "host" end # chef-sugar backcompat method alias_method :virtualbox?, :vbox? # Determine if the current node is a VMWare guest. # # @param [Chef::Node] node # @since 15.8 # # @return [Boolean] # def vmware?(node = __getnode) node.dig("virtualization", "system") == "vmware" && node.dig("virtualization", "role") == "guest" end # Determine if the current node is VMware host. # # @param [Chef::Node] node # @since 15.8 # # @return [Boolean] # def vmware_host?(node = __getnode) node.dig("virtualization", "system") == "vmware" && node.dig("virtualization", "role") == "host" end # Determine if the current node is an openvz guest. # # @param [Chef::Node] node # @since 15.8 # # @return [Boolean] # def openvz?(node = __getnode) node.dig("virtualization", "system") == "openvz" && node.dig("virtualization", "role") == "guest" end # Determine if the current node is an openvz host. # # @param [Chef::Node] node # @since 15.8 # # @return [Boolean] # def openvz_host?(node = __getnode) node.dig("virtualization", "system") == "openvz" && node.dig("virtualization", "role") == "host" end # Determine if the current node is running under any virtualization environment # # @param [Chef::Node] node # @since 15.8 # # @return [Boolean] # def guest?(node = __getnode) node.dig("virtualization", "role") == "guest" end # chef-sugar backcompat method alias_method :virtual?, :guest? # Determine if the current node supports running guests under any virtualization environment # # @param [Chef::Node] node # @since 15.8 # # @return [Boolean] # def hypervisor?(node = __getnode) node.dig("virtualization", "role") == "host" end # Determine if the current node is NOT running under any virtualization environment (bare-metal or hypervisor on metal) # # @param [Chef::Node] node # @since 15.8 # # @return [Boolean] # def physical?(node = __getnode) !virtual?(node) end # Determine if the current node is running as a vagrant guest. # # Note that this API is equivalent to just looking for the vagrant user or the # vagrantup.com domain in the hostname, which is the best API we have. # # @param [Chef::Node] node # @since 15.8 # # @return [Boolean] # true if the machine is currently running vagrant, false # otherwise # def vagrant?(node = __getnode) 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 = __getnode) node.key?("vagrant") end # Check if "vagrantup.com" is included in the node's domain. # # @param (see vagrant?) # @return (see vagrant?) # def vagrant_domain?(node = __getnode) 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 = __getnode) !!(Etc.getpwnam("vagrant") rescue nil) end extend self end end end chef-utils-16.12.3/lib/chef-utils/dsl/which.rb0000644000175100017510000001207314034013321017771 0ustar pravipravi# frozen_string_literal: true # # Copyright:: Copyright (c) Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # require_relative "../internal" module ChefUtils module DSL module Which include Internal # Lookup an executable through the systems search PATH. Allows specifying an array # of executables to look for. The first executable that is found, along any path entry, # will be the preferred one and returned first. The extra_path will override any default # extra_paths which are added (allowing the user to pass an empty array to remove them). # # When passed a block the block will be called with the full pathname of any executables # which are found, and the block should return truthy or falsey values to further filter # the executable based on arbitrary criteria. # # This is syntactic sugar for `where(...).first` # # This helper can be used in target mode in chef or with train using the appropriate # wiring externally. # # @example Find the most appropriate python executable, searching through the system PATH # plus additionally the "/usr/libexec" directory, which has the dnf libraries # installed and available. # # cmd = which("platform-python", "python", "python3", "python2", "python2.7", extra_path: "/usr/libexec") do |f| # shell_out("#{f} -c 'import dnf'").exitstatus == 0 # end # # @param [Array] list of commands to search for # @param [String,Array] array of extra paths to search through # @return [String] the first match # def which(*cmds, extra_path: nil, &block) where(*cmds, extra_path: extra_path, &block).first || false end # Lookup all the instances of an an executable that can be found through the systems search PATH. # Allows specifying an array of executables to look for. All the instances of the first executable # that is found will be returned first. The extra_path will override any default extra_paths # which are added (allowing the user to pass an empty array to remove them). # # When passed a block the block will be called with the full pathname of any executables # which are found, and the block should return truthy or falsey values to further filter # the executable based on arbitrary criteria. # # This helper can be used in target mode in chef or with train using the appropriate # wiring externally. # # @example Find all the python executables, searching through the system PATH plus additionally # the "/usr/libexec" directory, which have the dnf libraries installed and available. # # cmds = where("platform-python", "python", "python3", "python2", "python2.7", extra_path: "/usr/libexec") do |f| # shell_out("#{f} -c 'import dnf'").exitstatus == 0 # end # # @param [Array] list of commands to search for # @param [String,Array] array of extra paths to search through # @return [String] the first match # def where(*cmds, extra_path: nil, &block) extra_path ||= __extra_path paths = __env_path.split(File::PATH_SEPARATOR) + Array(extra_path) paths.uniq! exts = ENV["PATHEXT"] ? ENV["PATHEXT"].split(";") : [] exts.unshift("") cmds.map do |cmd| paths.map do |path| exts.map do |ext| filename = File.join(path, "#{cmd}#{ext}") filename if __valid_executable?(filename, &block) end.compact end end.flatten end private # This is for injecting common extra_paths into the search PATH. The chef-client codebase overrides this into its # own custom mixin to ensure that /usr/sbin, /sbin, etc are in the search PATH for chef-client. # # @api private def __extra_path nil end # Windows compatible and train/target-mode-enhanced helper to determine if an executable is valid. # # @api private def __valid_executable?(filename, &block) is_executable = if __transport_connection __transport_connection.file(filename).stat[:mode] & 1 && !__transport_connection.file(filename).directory? else File.executable?(filename) && !File.directory?(filename) end return false unless is_executable block ? yield(filename) : true end extend self end end end chef-utils-16.12.3/lib/chef-utils/dsl/windows.rb0000644000175100017510000000477714034013321020375 0ustar pravipravi# frozen_string_literal: true # # Copyright:: Copyright (c) Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # require_relative "../internal" module ChefUtils module DSL module Windows require_relative "../version_string" include Internal # Determine if the current node is Windows Server Core. # # @param [Chef::Node] node the node to check # @since 15.7 # # @return [Boolean] # def windows_server_core?(node = __getnode) node["kernel"]["server_core"] == true end # Determine if the current node is Windows Workstation. # # @param [Chef::Node] node the node to check # @since 15.7 # # @return [Boolean] # def windows_workstation?(node = __getnode) node["kernel"]["product_type"] == "Workstation" end # Determine if the current node is Windows Server. # # @param [Chef::Node] node the node to check # @since 15.7 # # @return [Boolean] # def windows_server?(node = __getnode) node["kernel"]["product_type"] == "Server" end # Determine the current Windows NT version. The NT version often differs from the marketing version, but offers a good way to find desktop and server releases that are based on the same codebase. IE: NT 6.3 is Windows 8.1 and Windows 2012 R2. # # @param [Chef::Node] node the node to check # @since 15.8 # # @return [ChefUtils::VersionString] # def windows_nt_version(node = __getnode) ChefUtils::VersionString.new(node["os_version"]) end # Determine the installed version of PowerShell. # # @param [Chef::Node] node the node to check # @since 15.8 # # @return [ChefUtils::VersionString] # def powershell_version(node = __getnode) ChefUtils::VersionString.new(node["languages"]["powershell"]["version"]) end extend self end end end chef-utils-16.12.3/lib/chef-utils/dsl/service.rb0000644000175100017510000000635114034013321020331 0ustar pravipravi# frozen_string_literal: true # # Copyright:: Copyright (c) Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # require_relative "../internal" require_relative "train_helpers" module ChefUtils module DSL # NOTE: these are mixed into the service resource+providers specifically and deliberately not # injected into the global namespace module Service include Internal include TrainHelpers include Introspection # Returns if debian's old rc.d manager is installed (not necessarily the primary init system). # # @since 15.5 # # @return [Boolean] # def debianrcd? file_exist?("/usr/sbin/update-rc.d") end # Returns if debian's old invoke rc.d manager is installed (not necessarily the primary init system). # # @since 15.5 # # @return [Boolean] # def invokercd? file_exist?("/usr/sbin/invoke-rc.d") end # Returns if upstart is installed (not necessarily the primary init system). # # @since 15.5 # # @return [Boolean] # def upstart? file_exist?("/sbin/initctl") end # Returns if insserv is installed (not necessarily the primary init system). # # @since 15.5 # # @return [Boolean] # def insserv? file_exist?("/sbin/insserv") end # Returns if redhat's init system is installed (not necessarily the primary init system). # # @since 15.5 # # @return [Boolean] # def redhatrcd? file_exist?("/sbin/chkconfig") end # # Returns if a particular service exists for a particular service init system. Init systems may be :initd, :upstart, :etc_rcd, :xinetd, and :systemd. Example: service_script_exist?(:systemd, 'ntpd') # # @param [Symbol] type The type of init system. :initd, :upstart, :xinetd, :etc_rcd, or :systemd # @param [String] script The name of the service # @since 15.5 # # @return [Boolean] # def service_script_exist?(type, script) case type when :initd file_exist?("/etc/init.d/#{script}") when :upstart file_exist?("/etc/init/#{script}.conf") when :xinetd file_exist?("/etc/xinetd.d/#{script}") when :etc_rcd file_exist?("/etc/rc.d/#{script}") when :systemd file_exist?("/etc/init.d/#{script}") || has_systemd_service_unit?(script) || has_systemd_unit?(script) else raise ArgumentError, "type of service must be one of :initd, :upstart, :xinetd, :etc_rcd, or :systemd" end end extend self end end end chef-utils-16.12.3/lib/chef-utils/dsl/os.rb0000644000175100017510000000301114034013321017300 0ustar pravipravi# frozen_string_literal: true # # Copyright:: Copyright (c) Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # require_relative "../internal" module ChefUtils module DSL module OS include Internal # # NOTE CAREFULLY: Most node['os'] values should not appear in this file at all. # # For cases where node['os'] == node['platform_family'] == node['platform'] then # only the platform helper should be added. # # Determine if the current node is Linux. # # @param [Chef::Node] node the node to check # @since 15.5 # # @return [Boolean] # def linux?(node = __getnode) node["os"] == "linux" end # Determine if the current node is Darwin. # # @param [Chef::Node] node the node to check # @since 15.5 # # @return [Boolean] # def darwin?(node = __getnode) node["os"] == "darwin" end extend self end end end chef-utils-16.12.3/lib/chef-utils/dsl/introspection.rb0000644000175100017510000000725114034013321021571 0ustar pravipravi# frozen_string_literal: true # # Copyright:: Copyright (c) Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # require_relative "train_helpers" module ChefUtils module DSL # This is for "introspection" helpers in the sense that we are inspecting the # actual server or image under management to determine running state (duck-typing the system). # The helpers here may use the node object state from ohai, but typically not the big 5: platform, # platform_family, platform_version, arch, os. The helpers here should infer somewhat # higher level facts about the system. # module Introspection include TrainHelpers # Determine if the node is a docker container. # # @param [Chef::Node] node the node to check # @since 12.11 # # @return [Boolean] # def docker?(node = __getnode) # Using "File.exist?('/.dockerinit') || File.exist?('/.dockerenv')" makes Travis sad, # and that makes us sad too. !!(node && node.read("virtualization", "systems", "docker") == "guest") end # Determine if the node uses the systemd init system. # # @param [Chef::Node] node the node to check # @since 15.5 # # @return [Boolean] # def systemd?(node = __getnode) file_exist?("/proc/1/comm") && file_open("/proc/1/comm").gets.chomp == "systemd" end # Determine if the node is running in Test Kitchen. # # @param [Chef::Node] node the node to check # @since 15.5 # # @return [Boolean] # def kitchen?(node = __getnode) ENV.key?("TEST_KITCHEN") end # Determine if the node is running in a CI system that sets the CI env var. # # @param [Chef::Node] node the node to check # @since 15.5 # # @return [Boolean] # def ci?(node = __getnode) ENV.key?("CI") end # Determine if the a systemd service unit is present on the system. # # @param [String] svc_name # @since 15.5 # # @return [Boolean] # def has_systemd_service_unit?(svc_name) %w{ /etc /usr/lib /lib /run }.any? do |load_path| file_exist?( "#{load_path}/systemd/system/#{svc_name.gsub(/@.*$/, "@")}.service" ) end end # Determine if the a systemd unit of any type is present on the system. # # @param [String] svc_name # @since 15.5 # # @return [Boolean] # def has_systemd_unit?(svc_name) # TODO: stop supporting non-service units with service resource %w{ /etc /usr/lib /lib /run }.any? do |load_path| file_exist?("#{load_path}/systemd/system/#{svc_name}") end end # Determine if the current node includes the given recipe name. # # @param [String] recipe_name # @since 15.8 # # @return [Boolean] # def includes_recipe?(recipe_name, node = __getnode) node.recipe?(recipe_name) end # chef-sugar backcompat method alias_method :include_recipe?, :includes_recipe? extend self end end end chef-utils-16.12.3/lib/chef-utils/dsl/default_paths.rb0000644000175100017510000000343414034013321021513 0ustar pravipravi# frozen_string_literal: true # # Copyright:: Copyright (c) Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # require_relative "../internal" require_relative "platform_family" module ChefUtils module DSL module DefaultPaths include Internal # @since 15.5 def default_paths(env = nil) env_path = env ? env["PATH"] : __env_path env_path = "" if env_path.nil? path_separator = ChefUtils.windows? ? ";" : ":" # ensure the Ruby and Gem bindirs are included for omnibus chef installs new_paths = env_path.split(path_separator) [ __ruby_bindir, __gem_bindir ].compact.each do |path| new_paths = [ path ] + new_paths unless new_paths.include?(path) end __default_paths.each do |path| new_paths << path unless new_paths.include?(path) end new_paths.join(path_separator).encode("utf-8", invalid: :replace, undef: :replace) end private def __default_paths ChefUtils.windows? ? %w{} : %w{/usr/local/sbin /usr/local/bin /usr/sbin /usr/bin /sbin /bin} end def __ruby_bindir RbConfig::CONFIG["bindir"] end def __gem_bindir Gem.bindir end extend self end end end chef-utils-16.12.3/lib/chef-utils/dsl/platform.rb0000644000175100017510000002425214034013321020515 0ustar pravipravi# frozen_string_literal: true # # Copyright:: Copyright (c) Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # require_relative "../internal" module ChefUtils module DSL module Platform include Internal # NOTE: if you are adding new platform helpers they should all have the `_platform?` suffix. # DO NOT add new short aliases without the suffix (they will be deprecated in the future) # aliases here are mostly for backwards compatibility with chef-sugar and new ones are DISCOURAGED. # generally there should be one obviously correct way to do things. # Determine if the current node is linux mint. # # @param [Chef::Node] node the node to check # @since 15.5 # # @return [Boolean] # def linuxmint_platform?(node = __getnode) node["platform"] == "linuxmint" end # chef-sugar backcompat method alias_method :mint?, :linuxmint_platform? # chef-sugar backcompat method alias_method :linux_mint?, :linuxmint_platform? # chef-sugar backcompat method alias_method :linuxmint?, :linuxmint_platform? # Determine if the current node is Ubuntu. # # @param [Chef::Node] node the node to check # @since 15.5 # # @return [Boolean] # def ubuntu_platform?(node = __getnode) node["platform"] == "ubuntu" end # chef-sugar backcompat method alias_method :ubuntu?, :ubuntu_platform? # Determine if the current node is Raspbian. # # @param [Chef::Node] node the node to check # @since 15.5 # # @return [Boolean] # def raspbian_platform?(node = __getnode) node["platform"] == "raspbian" end # chef-sugar backcompat method alias_method :raspbian?, :raspbian_platform? # Determine if the current node is Debian. # # @param [Chef::Node] node the node to check # @since 15.5 # # @return [Boolean] # def debian_platform?(node = __getnode) node["platform"] == "debian" end # Determine if the current node is Amazon Linux. # # @param [Chef::Node] node the node to check # @since 15.5 # # @return [Boolean] # def amazon_platform?(node = __getnode) node["platform"] == "amazon" end # Determine if the current node is Red Hat Enterprise Linux. # # @param [Chef::Node] node the node to check # @since 15.5 # # @return [Boolean] # def redhat_platform?(node = __getnode) node["platform"] == "redhat" end # chef-sugar backcompat method alias_method :redhat_enterprise?, :redhat_platform? # chef-sugar backcompat method alias_method :redhat_enterprise_linux?, :redhat_platform? # chef-sugar backcompat method alias_method :redhat?, :redhat_platform? # Determine if the current node is CentOS. # # @param [Chef::Node] node the node to check # @since 15.5 # # @return [Boolean] # def centos_platform?(node = __getnode) node["platform"] == "centos" end # chef-sugar backcompat method alias_method :centos?, :centos_platform? # Determine if the current node is Oracle Linux. # # @param [Chef::Node] node the node to check # @since 15.5 # # @return [Boolean] # def oracle_platform?(node = __getnode) node["platform"] == "oracle" end # chef-sugar backcompat method alias_method :oracle_linux?, :oracle_platform? # chef-sugar backcompat method alias_method :oracle?, :oracle_platform? # Determine if the current node is Scientific Linux. # # @param [Chef::Node] node the node to check # @since 15.5 # # @return [Boolean] # def scientific_platform?(node = __getnode) node["platform"] == "scientific" end # chef-sugar backcompat method alias_method :scientific_linux?, :scientific_platform? # chef-sugar backcompat method alias_method :scientific?, :scientific_platform? # Determine if the current node is ClearOS. # # @param [Chef::Node] node the node to check # @since 15.5 # # @return [Boolean] # def clearos_platform?(node = __getnode) node["platform"] == "clearos" end # chef-sugar backcompat method alias_method :clearos?, :clearos_platform? # Determine if the current node is Fedora. # # @param [Chef::Node] node the node to check # @since 15.5 # # @return [Boolean] # def fedora_platform?(node = __getnode) node["platform"] == "fedora" end # Determine if the current node is Arch Linux # # @param [Chef::Node] node the node to check # @since 15.5 # # @return [Boolean] # def arch_platform?(node = __getnode) node["platform"] == "arch" end # Determine if the current node is Solaris2. # # @param [Chef::Node] node the node to check # @since 15.5 # # @return [Boolean] # def solaris2_platform?(node = __getnode) node["platform"] == "solaris2" end # Determine if the current node is SmartOS. # # @param [Chef::Node] node the node to check # @since 15.5 # # @return [Boolean] # def smartos_platform?(node = __getnode) node["platform"] == "smartos" end # Determine if the current node is OmniOS. # # @param [Chef::Node] node the node to check # @since 15.5 # # @return [Boolean] # def omnios_platform?(node = __getnode) node["platform"] == "omnios" end # chef-sugar backcompat method alias_method :omnios?, :omnios_platform? # Determine if the current node is OpenIndiana. # # @param [Chef::Node] node the node to check # @since 15.5 # # @return [Boolean] # def openindiana_platform?(node = __getnode) node["platform"] == "openindiana" end # chef-sugar backcompat method alias_method :openindiana?, :openindiana_platform? # Determine if the current node is AIX. # # @param [Chef::Node] node the node to check # @since 15.5 # # @return [Boolean] # def aix_platform?(node = __getnode) node["platform"] == "aix" end # Determine if the current node is FreeBSD. # # @param [Chef::Node] node the node to check # @since 15.5 # # @return [Boolean] # def freebsd_platform?(node = __getnode) node["platform"] == "freebsd" end # Determine if the current node is OpenBSD. # # @param [Chef::Node] node the node to check # @since 15.5 # # @return [Boolean] # def openbsd_platform?(node = __getnode) node["platform"] == "openbsd" end # Determine if the current node is NetBSD. # # @param [Chef::Node] node the node to check # @since 15.5 # # @return [Boolean] # def netbsd_platform?(node = __getnode) node["platform"] == "netbsd" end # Determine if the current node is DragonFly BSD. # # @param [Chef::Node] node the node to check # @since 15.5 # # @return [Boolean] # def dragonfly_platform?(node = __getnode) node["platform"] == "dragonfly" end # Determine if the current node is macOS. # # @param [Chef::Node] node the node to check # @since 15.5 # # @return [Boolean] # def macos_platform?(node = __getnode) node["platform"] == "mac_os_x" end # chef-sugar backcompat method alias_method :mac_os_x_platform?, :macos_platform? # Determine if the current node is Gentoo. # # @param [Chef::Node] node the node to check # @since 15.5 # # @return [Boolean] # def gentoo_platform?(node = __getnode) node["platform"] == "gentoo" end # Determine if the current node is Slackware. # # @param [Chef::Node] node the node to check # @since 15.5 # # @return [Boolean] # def slackware_platform?(node = __getnode) node["platform"] == "slackware" end # Determine if the current node is SuSE. # # @param [Chef::Node] node the node to check # @since 15.5 # # @return [Boolean] # def suse_platform?(node = __getnode) node["platform"] == "suse" end # Determine if the current node is openSUSE. # # @param [Chef::Node] node the node to check # @since 15.5 # # @return [Boolean] # def opensuse_platform?(node = __getnode) node["platform"] == "opensuse" || node["platform"] == "opensuseleap" end # chef-sugar backcompat method alias_method :opensuse?, :opensuse_platform? # chef-sugar backcompat method alias_method :opensuseleap_platform?, :opensuse_platform? # chef-sugar backcompat method alias_method :leap_platform?, :opensuse_platform? # NOTE: to anyone adding :tumbleweed_platform? - :[opensuse]leap_platform? should be false on tumbleweed, :opensuse[_platform]? should be true # Determine if the current node is Windows. # # @param [Chef::Node] node the node to check # @since 15.5 # # @return [Boolean] # def windows_platform?(node = __getnode) node["platform"] == "windows" end extend self end end end chef-utils-16.12.3/lib/chef-utils/dsl/architecture.rb0000644000175100017510000000717314034013321021356 0ustar pravipravi# frozen_string_literal: true # # Copyright:: Copyright (c) Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # require_relative "../internal" module ChefUtils module DSL module Architecture include Internal # Determine if the current architecture is 64-bit. # # @since 15.5 # # @return [Boolean] # def _64_bit?(node = __getnode) %w{amd64 x86_64 ppc64 ppc64le s390x ia64 sparc64 aarch64 arch64 arm64 sun4v sun4u} .include?(node["kernel"]["machine"]) end # Determine if the current architecture is 32-bit. # # @since 15.5 # # @return [Boolean] # def _32_bit?(node = __getnode) !_64_bit?(node) end # Determine if the current architecture is i386. # # @since 15.5 # # @return [Boolean] # def i386?(node = __getnode) _32_bit?(node) && intel?(node) end # Determine if the current architecture is Intel. # # @since 15.5 # # @return [Boolean] # def intel?(node = __getnode) %w{i86pc i386 x86_64 amd64 i686}.include?(node["kernel"]["machine"]) end # Determine if the current architecture is SPARC. # # @since 15.5 # # @return [Boolean] # def sparc?(node = __getnode) %w{sun4u sun4v}.include?(node["kernel"]["machine"]) end # Determine if the current architecture is PowerPC 64bit Big Endian. # # @since 15.5 # # @return [Boolean] # def ppc64?(node = __getnode) %w{ppc64}.include?(node["kernel"]["machine"]) end # Determine if the current architecture is PowerPC 64bit Little Endian. # # @since 15.5 # # @return [Boolean] # def ppc64le?(node = __getnode) %w{ppc64le}.include?(node["kernel"]["machine"]) end # Determine if the current architecture is PowerPC. # # @since 15.5 # # @return [Boolean] # def powerpc?(node = __getnode) %w{powerpc}.include?(node["kernel"]["machine"]) end # Determine if the current architecture is arm # # @since 15.10 # # @return [Boolean] # def arm?(node = __getnode) %w{armv6l armv7l armhf aarch64 arm64 arch64}.include?(node["kernel"]["machine"]) end # Determine if the current architecture is 32-bit ARM hard float. # # @since 15.5 # # @return [Boolean] # def armhf?(node = __getnode) %w{armv6l armv7l armhf}.include?(node["kernel"]["machine"]) end # Determine if the current architecture is s390x. # # @since 15.5 # # @return [Boolean] # def s390x?(node = __getnode) %w{s390x}.include?(node["kernel"]["machine"]) end # Determine if the current architecture is s390. # # @since 15.5 # # @return [Boolean] # def s390?(node = __getnode) %w{s390}.include?(node["kernel"]["machine"]) end extend self end end end chef-utils-16.12.3/lib/chef-utils/dsl/platform_version.rb0000644000175100017510000000227714034013321022265 0ustar pravipravi# frozen_string_literal: true # # Copyright:: Copyright (c) Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # require_relative "../internal" module ChefUtils module DSL module PlatformVersion include Internal # Return the platform_version for the node. Acts like a String # but also provides a mechanism for checking version constraints. # # @param [Chef::Node] node the node to check # @since 15.8 # # @return [ChefUtils::VersionString] # def platform_version(node = __getnode) ChefUtils::VersionString.new(node["platform_version"]) end extend self end end end chef-utils-16.12.3/lib/chef-utils/version_string.rb0000644000175100017510000001005714034013321021160 0ustar pravipravi# frozen_string_literal: true # Copyright:: Copyright 2017, Noah Kantrowitz # 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. module ChefUtils # String-like object for version strings. # # @since 13.2 # @api internal class VersionString < String # Parsed version object for the string. # @return [Gem::Version] attr_reader :parsed_version # Create a new VersionString from an input String. # # @param val [String] Version string to parse. def initialize(val) val ||= "" super(val) begin @parsed_version = ::Gem::Version.create(self) rescue ArgumentError @parsed_version = nil end end # @!group Compat wrappers for String # Compat wrapper for + to behave like a normal String. # # @param other [String] # @return [String] def +(other) to_s + other end # Compat wrapper for * to behave like a normal String. # # @param other [Integer] # @return [String] def *(other) to_s * other end # @!group Comparison operators # Compare a VersionString to an object. If compared to another VersionString # then sort like `Gem::Version`, otherwise try to treat the other object as # a version but fall back to normal string comparison. # # @param other [Object] # @return [Integer] def <=>(other) other_ver = case other when VersionString other.parsed_version else begin Gem::Version.create(other.to_s) rescue ArgumentError # Comparing to a string that isn't a version. return super end end parsed_version <=> other_ver end # Compat wrapper for == based on <=>. # # @param other [Object] # @return [Boolean] def ==(other) (self <=> other) == 0 end # Compat wrapper for != based on <=>. # # @param other [Object] # @return [Boolean] def !=(other) (self <=> other) != 0 end # Compat wrapper for < based on <=>. # # @param other [Object] # @return [Boolean] def <(other) (self <=> other) < 0 end # Compat wrapper for <= based on <=>. # # @param other [Object] # @return [Boolean] def <=(other) (self <=> other) < 1 end # Compat wrapper for > based on <=>. # # @param other [Object] # @return [Boolean] def >(other) (self <=> other) > 0 end # Compat wrapper for >= based on <=>. # # @param other [Object] # @return [Boolean] def >=(other) (self <=> other) > -1 end # @!group Matching operators # Matching operator to support checking against a requirement string. # # @param other [Regexp, String] # @return [Boolean] # @example Match against a Regexp # ChefUtils::VersionString.new('1.0.0') =~ /^1/ # @example Match against a requirement # ChefUtils::VersionString.new('1.0.0') =~ '~> 1.0' def =~(other) case other when Regexp super else begin Gem::Requirement.create(other) =~ parsed_version rescue ArgumentError # one side of the comparison wasn't parsable super end end end # Back-compat API for chef-sugar. The other APIs are preferable. # # @api private def satisfies?(*constraints) Gem::Requirement.new(*constraints).satisfied_by?(@parsed_version) end end end chef-utils-16.12.3/lib/chef-utils/internal.rb0000644000175100017510000001102714034013321017717 0ustar pravipravi# frozen_string_literal: true # # Copyright:: Copyright (c) Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # module ChefUtils # # This is glue code to make the helpers work when called as ChefUtils.helper? from inside of chef-client. # # This also is glue code to make the helpers work when mixed into classes that have node/run_context methods that # provide those objects. # # It should not be assumed that any of this code runs from within chef-client and that the # Chef class or run_context, etc exists. # # This gem may be used by gems like mixlib-shellout which can be consumed by external non-Chef utilities, # so including brittle code here which depends on the existence of the chef-client will cause broken # behavior downstream. You must practice defensive coding, and not make assumptions about running within chef-client. # # Other consumers may mix in the helper classes and then override the methods here and provide their own custom # wiring and override what is provided here. They are marked as private because no downstream user should ever touch # them -- they are intended to be subclassable and overridable by Chef developers in other projects. Chef Software # reserves the right to change the implementation details of this class in minor revs which is what "api private" means, # so external persons should subclass and override only when necessary (submit PRs and issues upstream if this is a problem). # module Internal extend self private # This should be set to a Chef::Node instance or to some Hash/Mash-like configuration object with the same keys. It needs to # expose keys like `:os`, `:platform`, `:platform_version` and `:platform_family` at least to be useful. It will automatically # pick up a `node` method when mixed into an object that has that as a method (which is the encouraged "public" API to use # for dependency injection rather than overriding the method in this case. # # @return [Hash] hash-like config object # # @api private def __getnode(skip_global = false) # Software developers should feel free to rely on the default wiring here to the node method by implementing the node method in their # own class. For anything more complicated they should completely override the method (overriding the whole method is never wrong and # is safer). return node if respond_to?(:node) && node return run_context&.node if respond_to?(:run_context) && run_context&.node unless skip_global return Chef.run_context&.node if defined?(Chef) && Chef.respond_to?(:run_context) && Chef.run_context&.node end nil end # Just a helper to pull the ENV["PATH"] in a train-independent way # # @api private # def __env_path if __transport_connection __transport_connection.run_command("echo $PATH").stdout || "" else ENV["PATH"] || "" end end # This should be set to a Train::Plugins::Transport instance. You should wire this up to nil for not using a train transport connection. # # @return [Train::Plugins::Transport] # # @api private # def __transport_connection # Software consumers MUST override this method with their own implementation. The default behavior here is subject to change. return Chef.run_context.transport_connection if defined?(Chef) && Chef.respond_to?(:run_context) && Chef&.run_context&.transport_connection nil end # This should be set to Chef::Config or to some Hash/Mash-like configuration object with the same keys. It must not be nil. # # @return [Hash] hash-like config object # # @api private # def __config raise NotImplementedError end # This should be set to Chef::Log or something that duck-types like it. It must not be nil. # # @return [Chef::Log] logger-like logging object # # @api private # def __log raise NotImplementedError end extend self end end chef-utils-16.12.3/lib/chef-utils.rb0000644000175100017510000000367714034013321016117 0ustar pravipravi# frozen_string_literal: true # # Copyright:: Copyright (c) Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # require_relative "chef-utils/dsl/architecture" require_relative "chef-utils/dsl/cloud" require_relative "chef-utils/dsl/introspection" require_relative "chef-utils/dsl/os" require_relative "chef-utils/dsl/default_paths" require_relative "chef-utils/dsl/path_sanity" require_relative "chef-utils/dsl/platform" require_relative "chef-utils/dsl/platform_family" require_relative "chef-utils/dsl/platform_version" require_relative "chef-utils/dsl/service" require_relative "chef-utils/dsl/train_helpers" require_relative "chef-utils/dsl/virtualization" require_relative "chef-utils/dsl/which" require_relative "chef-utils/dsl/windows" require_relative "chef-utils/mash" # This is the Chef Infra Client DSL, not everything needs to go in here module ChefUtils include ChefUtils::DSL::Architecture include ChefUtils::DSL::Cloud include ChefUtils::DSL::DefaultPaths include ChefUtils::DSL::Introspection include ChefUtils::DSL::OS include ChefUtils::DSL::Platform include ChefUtils::DSL::PlatformFamily include ChefUtils::DSL::PlatformVersion include ChefUtils::DSL::TrainHelpers include ChefUtils::DSL::Virtualization include ChefUtils::DSL::Which include ChefUtils::DSL::Windows # ChefUtils::DSL::Service is deliberately excluded CANARY = 1 # used as a guard for requires extend self end chef-utils-16.12.3/LICENSE0000644000175100017510000002514214034013321013755 0ustar pravipravi Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] 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.