# -*- encoding: utf-8 -*- # # Author:: Fletcher Nichol () # # Copyright (C) 2013, Fletcher Nichol # # 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 "kitchen/provisioner/chef_base" module Kitchen module Provisioner # Chef Zero provisioner. # # @author Fletcher Nichol class ChefZero < ChefBase kitchen_provisioner_api_version 2 plugin_version Kitchen::VERSION default_config :client_rb, {} default_config :named_run_list, {} default_config :json_attributes, true default_config :chef_zero_host, nil default_config :chef_zero_port, 8889 default_config :chef_client_path do |provisioner| provisioner .remote_path_join(%W{#{provisioner[:chef_omnibus_root]} bin chef-client}) .tap { |path| path.concat(".bat") if provisioner.windows_os? } end default_config :ruby_bindir do |provisioner| provisioner .remote_path_join(%W{#{provisioner[:chef_omnibus_root]} embedded bin}) end # (see Base#create_sandbox) def create_sandbox super prepare_validation_pem prepare_config_rb end def run_command cmd = "#{sudo(config[:chef_client_path])} --local-mode".tap { |str| str.insert(0, "& ") if powershell_shell? } chef_cmd(cmd) end private # Adds optional flags to a chef-client command, depending on # configuration data. Note that this method mutates the incoming Array. # # @param args [Array] array of flags # @api private # rubocop:disable Metrics/CyclomaticComplexity def add_optional_chef_client_args!(args) if config[:json_attributes] json = remote_path_join(config[:root_path], "dna.json") args << "--json-attributes #{json}" end args << "--logfile #{config[:log_file]}" if config[:log_file] # these flags are chef-client local mode only and will not work # on older versions of chef-client if config[:chef_zero_host] args << "--chef-zero-host #{config[:chef_zero_host]}" end if config[:chef_zero_port] args << "--chef-zero-port #{config[:chef_zero_port]}" end args << "--profile-ruby" if config[:profile_ruby] end # rubocop:enable Metrics/CyclomaticComplexity # Returns an Array of command line arguments for the chef client. # # @return [Array] an array of command line arguments # @api private def chef_args(client_rb_filename) level = config[:log_level] args = [ "--config #{remote_path_join(config[:root_path], client_rb_filename)}", "--log_level #{level}", "--force-formatter", "--no-color", ] add_optional_chef_client_args!(args) args end # Generates a string of shell environment variables needed for the # chef-client-zero.rb shim script to properly function. # # @return [String] a shell script string # @api private def chef_client_zero_env root = config[:root_path] gem_home = gem_path = remote_path_join(root, "chef-client-zero-gems") gem_cache = remote_path_join(gem_home, "cache") [ shell_env_var("CHEF_REPO_PATH", root), shell_env_var("GEM_HOME", gem_home), shell_env_var("GEM_PATH", gem_path), shell_env_var("GEM_CACHE", gem_cache), ].join("\n").concat("\n") end # Writes a fake (but valid) validation.pem into the sandbox directory. # # @api private def prepare_validation_pem info("Preparing validation.pem") debug("Using a dummy validation.pem") source = File.join(File.dirname(__FILE__), %w{.. .. .. support dummy-validation.pem}) FileUtils.cp(source, File.join(sandbox_path, "validation.pem")) end # Returns the command that will run a backwards compatible shim script # that approximates local mode in a modern chef-client run. # # @return [String] the command string # @api private def shim_command ruby = remote_path_join(config[:ruby_bindir], "ruby") .tap { |path| path.concat(".exe") if windows_os? } shim = remote_path_join(config[:root_path], "chef-client-zero.rb") "#{chef_client_zero_env}\n#{sudo(ruby)} #{shim}" end # This provisioner supports policyfiles, so override the default (which # is false) # @return [true] always returns true # @api private def supports_policyfile? true end end end end