Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Chef-infra provisioner to use the new omnitruck apis #9

Merged
merged 9 commits into from
Nov 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .expeditor/habitat-test.pipeline.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,4 @@ steps:
- FORCE_FFI_YAJL=ext
- EXPIRE_CACHE=true
- CHEF_LICENSE=accept-no-persist
- CHEF_LICENSE_SERVER=http://hosted-license-service-lb-8000-606952349.us-west-2.elb.amazonaws.com:8000/
8 changes: 8 additions & 0 deletions .expeditor/verify.pipeline.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ steps:
executor:
docker:
image: ruby:3.1
environment:
- CHEF_LICENSE=accept-no-persist
- CHEF_LICENSE_SERVER=http://hosted-license-service-lb-8000-606952349.us-west-2.elb.amazonaws.com:8000/

- label: run-specs-ruby-3.3
command:
Expand All @@ -25,6 +28,9 @@ steps:
executor:
docker:
image: ruby:3.3
environment:
- CHEF_LICENSE=accept-no-persist
- CHEF_LICENSE_SERVER=http://hosted-license-service-lb-8000-606952349.us-west-2.elb.amazonaws.com:8000/

- label: run-specs-windows-ruby-3.1
command:
Expand All @@ -40,6 +46,7 @@ steps:
- FORCE_FFI_YAJL=ext
- EXPIRE_CACHE=true
- CHEF_LICENSE=accept-no-persist
- CHEF_LICENSE_SERVER=http://hosted-license-service-lb-8000-606952349.us-west-2.elb.amazonaws.com:8000/

- label: run-specs-windows-ruby-3.3
command:
Expand All @@ -55,3 +62,4 @@ steps:
- FORCE_FFI_YAJL=ext
- EXPIRE_CACHE=true
- CHEF_LICENSE=accept-no-persist
- CHEF_LICENSE_SERVER=http://hosted-license-service-lb-8000-606952349.us-west-2.elb.amazonaws.com:8000/
2 changes: 2 additions & 0 deletions kitchen.dokken.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ driver:
provisioner:
name: dokken
chef_license: accept-no-persist
chef_license_server:
- http://hosted-license-service-lb-8000-606952349.us-west-2.elb.amazonaws.com:8000/

transport:
name: dokken
Expand Down
5 changes: 5 additions & 0 deletions lib/kitchen/cli.rb
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,11 @@ def console
perform("console", "console")
end

desc "license", "Manage the chef licenses"
def license(*args)
perform("license", "license", args)
end

register Kitchen::Generator::Init, "init",
"init", "Adds some configuration to your cookbook so Kitchen can rock"
long_desc <<-D, for: "init"
Expand Down
22 changes: 22 additions & 0 deletions lib/kitchen/command/license.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
require_relative "../command"
require "kitchen/licensing/base"

module Kitchen
module Command
# Command to manage the licenses
class License < Kitchen::Command::Base
def call
case args[0]
when "list"
ChefLicensing.list_license_keys_info
when "add"
ChefLicensing.add_license
else
ChefLicensing.fetch_and_persist.each do |key|
puts "License_key: #{key}"
end
end
end
end
end
end
53 changes: 53 additions & 0 deletions lib/kitchen/licensing/base.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# frozen_string_literal: true

# Copyright:: 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 "config"
require "chef-licensing"
require "faraday_middleware"

module Kitchen
module Licensing
class Base

OMNITRUCK_URLS = {
"free" => "https://chefdownload-trial.chef.io",
"trial" => "https://chefdownload-trial.chef.io",
"commercial" => "https://chefdownload-commerical.chef.io",
}.freeze

class << self
def get_license_keys
keys = ChefLicensing.license_keys
raise ChefLicensing::InvalidLicense, "A valid license is required to perform this action." if keys.blank?

client = get_license_client(keys)

[keys.last, client.license_type, install_sh_url(client.license_type, keys)]
end

def get_license_client(keys)
ChefLicensing::Api::Client.info(license_keys: keys)
end

def install_sh_url(type, keys, ext = "sh")
OMNITRUCK_URLS[type] + "/install.#{ext}?license_id=#{keys.join(",")}"
end
end
end
end
end
27 changes: 27 additions & 0 deletions lib/kitchen/licensing/config.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# frozen_string_literal: true

# Copyright:: Chef Software Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

require "chef-licensing"

ChefLicensing.configure do |config|
config.chef_product_name = "Test Kitchen"
config.chef_entitlement_id = "x6f3bc76-a94f-4b6c-bc97-4b7ed2b045c0"
config.chef_executable_name = "kitchen"
config.license_server_url = "https://services.chef.io/licensing"
# config.license_server_url = "https://licensing-acceptance.chef.co/License"
end
2 changes: 1 addition & 1 deletion lib/kitchen/provisioner/base.rb
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@ def sandbox_dirs
# will persist after the process terminates. In other words, cleanup is
# explicit. This method is safe to call multiple times.
def cleanup_sandbox
return if sandbox_path.nil?
return if @sandbox_path.nil?

debug("Cleaning up local sandbox in #{sandbox_path}")
FileUtils.rmtree(sandbox_path)
Expand Down
15 changes: 13 additions & 2 deletions lib/kitchen/provisioner/chef_base.rb
Original file line number Diff line number Diff line change
Expand Up @@ -345,7 +345,7 @@ def install_options
add_omnibus_directory_option if instance.driver.cache_directory
project = /\s*-P (\w+)\s*/.match(config[:chef_omnibus_install_options])
{
omnibus_url: config[:chef_omnibus_url],
omnibus_url: config[:install_sh_url] || config[:chef_omnibus_url],
project: project.nil? ? nil : project[1],
install_flags: config[:chef_omnibus_install_options],
sudo_command:,
Expand Down Expand Up @@ -544,6 +544,15 @@ def script_for_product
prox.delete_if { |p| %i{https_proxy ftp_proxy no_proxy}.include?(p) } if powershell_shell?
end
opts[:install_command_options].merge!(proxies)

if config[:install_sh_url] || config[:install_ps1_url]
opts[:new_omnibus_download_url] = if powershell_shell?
config[:install_ps1_url]
else
config[:install_sh_url]
end

end
end)
config[:chef_omnibus_root] = installer.root
if powershell_shell?
Expand Down Expand Up @@ -580,8 +589,10 @@ def install_from_file(command)
# @api private
def script_for_omnibus_version
require "mixlib/install/script_generator"
opts = install_options
opts[:omnibus_url] = config[:install_sh_url] if config[:install_sh_url]
installer = Mixlib::Install::ScriptGenerator.new(
config[:require_chef_omnibus], powershell_shell?, install_options
config[:require_chef_omnibus], powershell_shell?, opts
)
config[:chef_omnibus_root] = installer.root
sudo(installer.install_command)
Expand Down
54 changes: 53 additions & 1 deletion lib/kitchen/provisioner/chef_infra.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# frozen_string_literal: true
#
# Author:: Fletcher Nichol (<[email protected]>)
#
Expand All @@ -16,13 +17,15 @@
# limitations under the License.

require_relative "chef_base"
require "kitchen/licensing/base"

module Kitchen
module Provisioner
# Chef Zero provisioner.
#
# @author Fletcher Nichol <[email protected]>
class ChefInfra < ChefBase

kitchen_provisioner_api_version 2

plugin_version Kitchen::VERSION
Expand All @@ -32,6 +35,8 @@ class ChefInfra < ChefBase
default_config :json_attributes, true
default_config :chef_zero_host, nil
default_config :chef_zero_port, 8889
default_config :chef_license_key, nil
default_config :chef_license_server, []

default_config :chef_client_path do |provisioner|
provisioner
Expand All @@ -51,12 +56,47 @@ def create_sandbox
prepare_config_rb
end

def prepare_command
nonce = Base64.encode64(SecureRandom.random_bytes(16)).strip
timestamp = Time.now.utc.to_i.to_s

message = "#{nonce}:#{timestamp}"
signature = OpenSSL::HMAC.hexdigest("SHA256", context_key, message)

file_content = "nonce:#{nonce}\ntimestamp:#{timestamp}\nsignature:#{signature}"
file_location = config[:root_path] + "/#{context_key}"

sudo("echo '#{file_content}' > #{file_location}")
end

def run_command
cmd = "#{sudo(config[:chef_client_path])} --local-mode".tap { |str| str.insert(0, "& ") if powershell_shell? }
cmd = "#{context_env_command} #{sudo(config[:chef_client_path])} --local-mode --chef-license-key=#{config[:chef_license_key]} "

chef_cmd(cmd)
end

def check_license
super

info("Fetching the Chef license key")
unless config[:chef_license_server].nil? || config[:chef_license_server].empty?
ENV["CHEF_LICENSE_SERVER"] = config[:chef_license_server].join(",")
end

key, type, install_sh_url = if config[:chef_license_key].nil?
Licensing::Base.get_license_keys
else
key = config[:chef_license_key]
client = Licensing::Base.get_license_client([key])

[key, client.license_type, Licensing::Base.install_sh_url(client.license_type, [key])]
end

config[:chef_license_key] = key
config[:install_sh_url] = install_sh_url
config[:chef_license_type] = type
end

private

# Adds optional flags to a chef-client command, depending on
Expand Down Expand Up @@ -162,6 +202,18 @@ def shim_command
def supports_policyfile?
true
end

def context_key
@context_key ||= SecureRandom.hex(16)
end

def context_env_command
if powershell_shell?
"$env:TEST_KITCHEN_CONTEXT = '#{context_key}'; &"
else
"export TEST_KITCHEN_CONTEXT=#{context_key};"
end
end
end
end
end
1 change: 1 addition & 0 deletions test-kitchen.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,5 @@ Gem::Specification.new do |gem|
# Required to run the Chef provisioner local license check for remote systems
# TK is not under Chef EULA
gem.add_dependency "license-acceptance", ">= 1.0.11", "< 3.0" # pinning until we can confirm 3+ works
gem.add_dependency "chef-licensing", "~> 1.0"
end
Loading