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

Add support for chef-client 19 license requirement and habitat install location to chef provisioner #29

Draft
wants to merge 6 commits into
base: main
Choose a base branch
from
Draft
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
8 changes: 4 additions & 4 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,15 @@ concurrency:
cancel-in-progress: true

jobs:
chefstyle:
cookstyle:
env:
BUNDLE_WITH: ${{ inputs.bundle_with }}
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
ruby: ["3.3"]
name: Chefstyle on Ruby
name: Cookstyle/Chefstyle on Ruby
steps:
- name: Checkout code
uses: actions/checkout@v4
Expand All @@ -40,9 +40,9 @@ jobs:
bundler-cache: true
- uses: r7kamura/rubocop-problem-matchers-action@v1
if: steps.check.outputs.gemfile == 'true'
- name: Chef Style
- name: Cookstyle
if: steps.check.outputs.gemfile == 'true'
run: bundle exec chefstyle
run: bundle exec cookstyle --chefstyle

yamllint:
runs-on: ubuntu-latest
Expand Down
28 changes: 28 additions & 0 deletions .github/workflows/unit.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
---
name: unit

"on":
pull_request:
push:
branches:
- main

concurrency:
group: unit-${{ github.ref }}
cancel-in-progress: true

jobs:
unit-linux:
name: Linux unit Tests
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
ruby: ["3.1", "3.3"]
steps:
- uses: actions/checkout@v4
- uses: ruby/setup-ruby@v1
with:
ruby-version: ${{ matrix.ruby }}
bundler-cache: true
- run: bundle exec rspec
10 changes: 10 additions & 0 deletions .markdownlint-cli2.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
config:
heading-increment: false # MD001
line-length: false # MD013
blanks-around-headings: false # MD022
no-duplicate-heading: false # MD024
blanks-around-lists: false # MD032
no-inline-html: false # MD033
ignores:
- .github/copilot-instructions.md
7 changes: 0 additions & 7 deletions .markdownlint.yaml

This file was deleted.

3 changes: 0 additions & 3 deletions .rubocop.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
---
require:
- chefstyle

AllCops:
TargetRubyVersion: 3.1
Include:
Expand Down
3 changes: 1 addition & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -462,7 +462,6 @@
- Include the Chef-cli as gem with the test-kitchen hab package [#14](https://github.com/chef/chef-test-kitchen-enterprise/pull/14) ([ashiqueps](https://github.com/ashiqueps)) <!-- 1.0.2 -->
- Kitchen init change [#13](https://github.com/chef/chef-test-kitchen-enterprise/pull/13) ([sanghinitin](https://github.com/sanghinitin)) <!-- 1.0.1 -->


### Merged Pull Requests

#### Merged Pull Requests
Expand Down Expand Up @@ -697,4 +696,4 @@
<!-- release_rollup -->

<!-- latest_stable_release -->
<!-- latest_stable_release -->
<!-- latest_stable_release -->
6 changes: 3 additions & 3 deletions Rakefile
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,13 @@ task :stats do
end

begin
require "chefstyle"
require "cookstyle"
require "rubocop/rake_task"
RuboCop::RakeTask.new(:style) do |task|
task.options += ["--display-cop-names", "--no-color"]
task.options += ["--chefstyle", "--display-cop-names", "--no-color"]
end
rescue LoadError
puts "chefstyle is not available. (sudo) gem install chefstyle to do style checking."
puts "cookstyle is not available. (sudo) gem install chefstyle to do style checking."
end

desc "Run all quality tasks"
Expand Down
1 change: 0 additions & 1 deletion docs/content/docs/drivers/vra.md
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,6 @@ Defaults to `nil`. Set to your domain suffix, for example 'mydomain.com'. This

a hash of other data to set on a catalog request, most notably custom properties. Allows updates to existing properties on the blueprint as well as the addition of new properties. Each key in the hash is the property name, and the value is a another hash containing the value data type and the value itself. It is possible to use a `~` to add nested parameters.


Example **kitchen.yml**:

```yaml
Expand Down
9 changes: 6 additions & 3 deletions docs/content/docs/provisioners/chef.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ provisioner:
- recipes/install.rb:22 # specific line in a file
product_name: chef # which package to install chef || chef-workstation
chef_license: nil # to accept the Chef Infra license automatically in Test Kitchen. Valid values: `accept`, `accept-no-persist`, or `accept-silent`
chef_license_key: nil # License key for chef-client 19+
chef_license_server: [] # Array of license servers for chef-client 19+ to verify license key with
hab_binary: /hab/bin/hab # Path to the Habitat binary for habitat package installed chef-clients
product_version: latest # 'latest', partial, or full version number
root_path: /tmp # Directory to create and execute the chef installer from
channel: stable # stable, current or unstable
Expand Down Expand Up @@ -74,6 +77,6 @@ Where `$KEY` corresponds to a folder named `data, data_bags, environments, nodes

Additional Components for `chef_target`:

* locally installed `chef-client` of version >= 19.0
* [kitchen-transport-train >= 0.2](https://github.com/tecracer-chef/kitchen-transport-train)
* [train >= 3.9](https://github.com/inspec/train)
- locally installed `chef-client` of version >= 19.0
- [kitchen-transport-train >= 0.2](https://github.com/tecracer-chef/kitchen-transport-train)
- [train >= 3.9](https://github.com/inspec/train)
2 changes: 1 addition & 1 deletion lib/kitchen/licensing/base.rb
Original file line number Diff line number Diff line change
Expand Up @@ -50,4 +50,4 @@ def install_sh_url(type, keys, ext = "sh")
end
end
end
end
end
7 changes: 4 additions & 3 deletions lib/kitchen/provisioner/chef_apply.rb
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,7 @@ class ChefApply < ChefBase
plugin_version Kitchen::VERSION

default_config :chef_apply_path do |provisioner|
provisioner
.remote_path_join(%W{#{provisioner[:chef_omnibus_root]} bin chef-apply})
.tap { |path| path.concat(".bat") if provisioner.windows_os? }
provisioner.remote_path_join(%W{#{chef_bin_path} chef-apply}).tap { |path| path.concat(".bat") if provisioner.windows_os? }
end

default_config :apply_path do |provisioner|
Expand Down Expand Up @@ -107,6 +105,9 @@ def run_command
]
args << "--logfile #{config[:log_file]}" if config[:log_file]
args << "--chef-license #{config[:chef_license]}" if config[:chef_license]
# Added for Chef-Client 19+
args << "--chef-license-key=#{config[:chef_license_key]}" if config[:chef_license_key]
args << "--chef-license-server=#{config[:chef_license_server]}" unless config[:chef_license_server].empty?

lines << wrap_shell_code(
[cmd, *args].join(" ")
Expand Down
28 changes: 28 additions & 0 deletions lib/kitchen/provisioner/chef_base.rb
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,11 @@ class ChefBase < Base
default_config :chef_omnibus_url, "https://omnitruck.chef.io/install.sh"
default_config :chef_omnibus_install_options, nil
default_config :chef_license, nil
default_config :chef_license_key, nil
default_config :chef_license_server, []
default_config :hab_binary do
windows_os? ? "C:\\hab\\bin\\hab" : "/hab/bin/hab"
end
default_config :run_list, []
default_config :policy_group, nil
default_config :attributes, {}
Expand Down Expand Up @@ -729,6 +734,29 @@ def wrapped_chef_cmd(base_cmd, configfile, append: "")

prefix_command(wrap_shell_code(shell_cmd))
end

# Determine chef binaries location
def chef_bin_path
require_relative "../which"
require_relative "../shell_out"
include ShellOut
include Which

# Check for binlinked chef-client binary and use that first
# If no binlinked chef-client binary is found then check for habiatat installed chef-client
# If no habitat installed chef-client is found then check for omnibus installed chef-client
# all fails raise an error
hab_pkg_cmd = "HAB_LICENSE='accept-no-persist' #{config[:hab_binary]} pkg"
if which("chef-client")
windows_os? ? File.dirname(which("chef-client")) : File.dirname(File.readlink(which("chef-client")))
elsif File.exist?(config[:hab_binary]) && ShellOut.run_command("#{hab_pkg_cmd} list chef/chef-infra-client").include?("chef/chef-infra-client")
remote_path_join(%W{#{ShellOut.run_command("#{hab_pkg_cmd} path chef/chef-infra-client").split("\n").first} bin})
elsif Dir.exist?(config[:chef_omnibus_root])
remote_path_join(%W{#{config[:chef_omnibus_root]} bin})
else
raise "Unable to determine chef binaries path"
end
end
end
end
end
12 changes: 5 additions & 7 deletions lib/kitchen/provisioner/chef_infra.rb
Original file line number Diff line number Diff line change
Expand Up @@ -35,18 +35,13 @@ 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
.remote_path_join(%W{#{provisioner[:chef_omnibus_root]} bin chef-client})
.tap { |path| path.concat(".bat") if provisioner.windows_os? }
provisioner.remote_path_join(%W{#{chef_bin_path} 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})
provisioner.remote_path_join(%W{#{provisioner[:chef_omnibus_root]} embedded bin})
end

# (see Base#create_sandbox)
Expand Down Expand Up @@ -108,6 +103,9 @@ def add_optional_chef_client_args!(args)
end

args << "--logfile #{config[:log_file]}" if config[:log_file]
# Added for Chef-Client 19+
args << "--chef-license-key=#{config[:chef_license_key]}" if config[:chef_license_key]
Comment on lines +106 to +107

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

During the RC1 release, we updated only the kitchen-Dokken driver to download the chef-infra-19, which has its own provisioner. We haven't updated the chef_infra provisioner to download and install the hab version of chef-infra-19.

So, if we pass the license key here, it will be used along with the chef-infra-18 and will cause it to fail because it is an unrecognized argument for infra-18.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

converting to draft, but the if statement only adds the flag if they add the chef_license_key option to the kitchen.yml file. So without it the flag wont be added and thus would work with older versions of chef-client. Still a work in progress as more commands need it.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

by updating the default provisioner here many other kitchen-* plugins will work out of the box, like kitchen-vagrant, without us needing to fork them like kitchen-dokken and can simply be added to chef-test-kitchen-enterprise as additional bundled gems.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is also needed to get additional testing of VM's in chef/chef repo's github actions for community testing of code.

args << "--chef-license-server=#{config[:chef_license_server]}" unless config[:chef_license_server].empty?

# these flags are chef-client local mode only and will not work
# on older versions of chef-client
Expand Down
7 changes: 4 additions & 3 deletions lib/kitchen/provisioner/chef_solo.rb
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,7 @@ class ChefSolo < ChefBase
default_config :solo_rb, {}

default_config :chef_solo_path do |provisioner|
provisioner
.remote_path_join(%W{#{provisioner[:chef_omnibus_root]} bin chef-solo})
.tap { |path| path.concat(".bat") if provisioner.windows_os? }
provisioner.remote_path_join(%W{#{chef_bin_path} chef-solo}).tap { |path| path.concat(".bat") if provisioner.windows_os? }
end

# (see Base#config_filename)
Expand Down Expand Up @@ -75,6 +73,9 @@ def chef_args(solo_rb_filename)
args << "--logfile #{config[:log_file]}" if config[:log_file]
args << "--profile-ruby" if config[:profile_ruby]
args << "--legacy-mode" if config[:legacy_mode]
# Added for Chef-Client 19+
args << "--chef-license-key=#{config[:chef_license_key]}" if config[:chef_license_key]
args << "--chef-license-server=#{config[:chef_license_server]}" unless config[:chef_license_server].empty?
args
end
end
Expand Down
45 changes: 45 additions & 0 deletions spec/kitchen/provisioner/chef_base_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -1827,6 +1827,51 @@ def debug_line(msg)
end
end

describe "#chef_bin_path" do
let(:provisioner) do
Class.new(Kitchen::Provisioner::ChefBase) do
def config
{ chef_omnibus_root: "/opt/chef" }
end
end.new(config).finalize_config!(instance)
end

context "when chef-client is a symlink" do
before do
provisioner.stubs(:which).with("chef-client").returns("/usr/bin/chef-client")
File.stubs(:readlink).with("/usr/bin/chef-client").returns("/opt/chef/bin/chef-client")
end

it "returns the directory of the actual chef-client binary" do
expect(provisioner.chef_bin_path).to eq("/opt/chef/bin")
end
end
context "when chef-client is installed as a habitat package" do
before do
config[:hab_binary] = "/hab/bin/hab"
provisioner.stubs(:run_command).with("#{config[:hab_binary]} pkg list chef/chef-infra-client").returns("chef/chef-infra-client")
provisioner.stubs(:run_command).with("#{config[:hab_binary]} pkg path chef/chef-infra-client").returns("/hab/pkg/chef/chef-infra-client/19.0.54/20241121145703")
end

it "returns the correct path to the chef-client binary" do
expected_path = "/hab/pkg/chef/chef-infra-client/19.0.54/20241121145703/bin"
_(provisioner.chef_bin_path).must_equal expected_path
end
end

context "when it can't find the bin path" do
before do
provisioner.stubs(:which).with("chef-client").returns(nil)
File.stubs(:exist?).with("/hab/bin/hab").returns(false)
Dir.stubs(:exist?).with("/opt/chef").returns(false)
end

it "raises an error" do
expect { provisioner.chef_bin_path }.to raise_error(RuntimeError, "Unable to determine chef binaries path")
end
end
end

def regexify(str, line = :whole_line)
r = Regexp.escape(str)
r = "^\s*#{r}$" if line == :whole_line
Expand Down
Loading