Skip to content
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
26 changes: 11 additions & 15 deletions lib/mixlib/install.rb
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
require_relative "install/generator/bourne"
require_relative "install/generator/powershell"
require_relative "install/dist"
require_relative "install/product_matrix"

module Mixlib
class Install
Expand Down Expand Up @@ -177,16 +178,15 @@ def download_artifact(directory = Dir.pwd)
# Returns the base installation directory for the given options
#
# @return [String] the installation directory for the project
# habitat products use Habitat install directories
#
def root
# This only works for chef and chefdk but they are the only projects
# we are supporting as of now.
# chef-ice uses Habitat install directories
if options.product_name.casecmp("chef-ice") == 0
product = PRODUCT_MATRIX.lookup(options.product_name) if options.product_name
if product&.habitat?
if options.for_ps1?
"$env:systemdrive\\#{Mixlib::Install::Dist::HABITAT_WINDOWS_INSTALL_DIR}\\chef\\chef-infra-client\\*\\*"
"$env:systemdrive\\#{Mixlib::Install::Dist::HABITAT_WINDOWS_INSTALL_DIR}\\#{product.hab_origin}\\#{product.hab_package_name}\\*\\*"
else
"#{Mixlib::Install::Dist::HABITAT_LINUX_INSTALL_DIR}/chef/chef-infra-client/*/*"
"#{Mixlib::Install::Dist::HABITAT_LINUX_INSTALL_DIR}/#{product.hab_origin}/#{product.hab_package_name}/*/*"
end
else
if options.for_ps1?
Expand All @@ -200,19 +200,15 @@ def root
#
# Returns the current version of the installed product.
# Returns nil if the product is not installed.
# habitat products use Habitat install directories
#
def current_version
# Note that this logic does not work for products other than
# chef & chefdk since version-manifest is created under the
# install directory which can be different than the product name (e.g.
# chef-server -> /opt/opscode). But this is OK for now since
# chef & chefdk are the only supported products.
# chef-ice uses Habitat install directories
version_manifest_file = if options.product_name.casecmp("chef-ice") == 0
product = PRODUCT_MATRIX.lookup(options.product_name) if options.product_name
version_manifest_file = if product&.habitat?
if options.for_ps1?
"$env:systemdrive\\#{Mixlib::Install::Dist::HABITAT_WINDOWS_INSTALL_DIR}\\chef\\chef-infra-client\\*\\*\\version-manifest.json"
"$env:systemdrive\\#{Mixlib::Install::Dist::HABITAT_WINDOWS_INSTALL_DIR}\\#{product.hab_origin}\\#{product.hab_package_name}\\*\\*\\version-manifest.json"
else
"#{Mixlib::Install::Dist::HABITAT_LINUX_INSTALL_DIR}/chef/chef-infra-client/*/*/version-manifest.json"
"#{Mixlib::Install::Dist::HABITAT_LINUX_INSTALL_DIR}/#{product.hab_origin}/#{product.hab_package_name}/*/*/version-manifest.json"
end
else
if options.for_ps1?
Expand Down
12 changes: 11 additions & 1 deletion lib/mixlib/install/generator/base.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
require "ostruct" unless defined?(OpenStruct)
require_relative "../util"
require_relative "../dist"
require_relative "../product_matrix"

module Mixlib
class Install
Expand Down Expand Up @@ -54,7 +55,16 @@ def self.get_script(name, context = {})
context[:support_url] ||= Mixlib::Install::Dist::SUPPORT_URL.freeze
context[:resources_url] ||= Mixlib::Install::Dist::RESOURCES_URL.freeze
context[:macos_dir] ||= Mixlib::Install::Dist::MACOS_VOLUME.freeze
context[:windows_dir] ||= context[:default_product].casecmp("chef-ice") == 0 ? Mixlib::Install::Dist::HABITAT_WINDOWS_INSTALL_DIR.freeze : Mixlib::Install::Dist::OMNIBUS_WINDOWS_INSTALL_DIR.freeze
context[:habitat_products] ||= begin
PRODUCT_MATRIX.products.each_with_object({}) do |pname, h|
p = PRODUCT_MATRIX.lookup(pname)
h[pname] = { origin: p.hab_origin, package_name: p.hab_package_name } if p.habitat?
end
end
context[:habitat_windows_dir] ||=
Mixlib::Install::Dist::HABITAT_WINDOWS_INSTALL_DIR.freeze
context[:omnibus_windows_dir] ||=
Mixlib::Install::Dist::OMNIBUS_WINDOWS_INSTALL_DIR.freeze
context[:user_agent_string] = Util.user_agent_string(context[:user_agent_headers])

context_object = OpenStruct.new(context).instance_eval { binding }
Expand Down
2 changes: 1 addition & 1 deletion lib/mixlib/install/generator/powershell.rb
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ def install_command
install_project_module = []
install_project_module << get_script("helpers.ps1", user_agent_headers: options.user_agent_headers)
install_project_module << get_script("get_project_metadata.ps1", license_id: options.license_id, base_url: options.base_url)
install_project_module << get_script("install_project.ps1", license_id: options.license_id)
install_project_module << get_script("install_project.ps1", license_id: options.license_id, default_product: options.product_name)
install_command = []
install_command << ps1_modularize(install_project_module.join("\n"), "Installer-Module")
install_command << render_command
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,18 +73,23 @@ function Install-Project {
$license_id = $env:CHEF_LICENSE_KEY
}

# Habitat products mapped to their Habitat Builder origin/package names
$habitat_products = @{
<% habitat_products.each do |pname, meta| %>
'<%= pname %>' = @{ origin = '<%= meta[:origin] %>'; package_name = '<%= meta[:package_name] %>' }
<% end %>
}

# Check for product installation in various locations
if ($project -eq 'chef' -or $project -eq 'chef-ice') {
# For chef or chef-ice, look for chef-infra-client paths
if ($habitat_products.ContainsKey($project)) {
$hab_meta = $habitat_products[$project]
$install_locations = @(
"$env:systemdrive\hab\pkgs\chef\chef-infra-client\*\*\bin",
"$env:systemdrive\<%= windows_dir %>\chef\bin"
"$env:systemdrive\hab\pkgs\$($hab_meta.origin)\$($hab_meta.package_name)\*\*\bin",
"$env:systemdrive\<%= habitat_windows_dir %>\$($hab_meta.origin)\bin"
)
} else {
# For other products, look for product-specific paths
$install_locations = @(
"$env:systemdrive\hab\pkgs\chef\$project\*\*\bin",
"$env:systemdrive\<%= windows_dir %>\$project\bin"
"$env:systemdrive\<%= omnibus_windows_dir %>\$project\bin"
)
}
foreach ($path in $install_locations) {
Expand Down Expand Up @@ -253,7 +258,8 @@ Function Install-ChefMsi($msi, $addlocal) {
Function Install-ChefAppx($appx, $project) {
Add-AppxPackage -Path $appx -ErrorAction Stop
$package = (Get-AppxPackage -Name $project).InstallLocation
$installRoot = "$env:SystemDrive/<%= windows_dir %>"
# AppX packages are always omnibus-style installs, never habitat
$installRoot = "$env:SystemDrive/<%= omnibus_windows_dir %>"
$omnibusRoot = Join-Path $installRoot $project

if(!(Test-Path $installRoot)) {
Expand Down
34 changes: 30 additions & 4 deletions lib/mixlib/install/product.rb
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@ def initialize(key, &block)
:github_repo,
:downloads_product_page_url,
:api_url,
:distribution_type,
:hab_origin,
:hab_builder_url,
:hab_package_name
]

#
Expand Down Expand Up @@ -80,20 +84,42 @@ def initialize(key, &block)
def default_value_for(prop)
case prop
when :install_path
"/opt/#{package_name}"
if distribution_type == "habitat"
"/hab/pkgs/#{hab_origin}/#{hab_package_name}"
else
"/opt/#{package_name}"
end
when :omnibus_project
package_name
when :downloads_product_page_url
"#{Mixlib::Install::Dist::DOWNLOADS_PAGE}/#{product_key}"
"#{Mixlib::Install::Dist::DOWNLOADS_PAGE}"
when :github_repo
"#{Mixlib::Install::Dist::GITHUB_ORG}/#{product_key}"
when :api_url
ENV.fetch("PACKAGE_ROUTER_ENDPOINT", Mixlib::Install::Dist::PRODUCT_ENDPOINT)
else
nil
when :distribution_type
"omnibus"
when :hab_origin
"chef"
when :hab_builder_url
"https://bldr.habitat.sh"
when :hab_package_name
package_name
end
end

def habitat?
distribution_type == "habitat"
end

def omnibus?
distribution_type == "omnibus"
end

def hab_package_url
"#{hab_builder_url}/#/pkgs/#{hab_origin}/#{hab_package_name}/latest"
end

#
# Return all known omnibus project names for a product
#
Expand Down
7 changes: 6 additions & 1 deletion lib/mixlib/install/product_matrix.rb
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@
product "chef-ice" do
product_name "Chef Infra Client Enterprise"
package_name "chef-ice"
distribution_type "habitat"
hab_package_name "chef-infra-client"
end

product "chef-foundation" do
Expand Down Expand Up @@ -111,7 +113,8 @@
product "chef-workstation-enterprise" do
product_name "Chef Workstation Enterprise"
package_name "chef-workstation-enterprise"
github_repo "chef/chef-workstation-enterprise"
distribution_type "habitat"
hab_package_name "chef-workstation"
end

product "chefdk" do
Expand Down Expand Up @@ -164,6 +167,8 @@
product "inspec-enterprise" do
product_name "Chef InSpec Enterprise"
package_name "inspec-enterprise"
distribution_type "habitat"
hab_package_name "inspec"
end

product "mac-bootstrapper" do
Expand Down
18 changes: 10 additions & 8 deletions lib/mixlib/install/script_generator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
require_relative "util"
require_relative "generator/powershell"
require_relative "dist"
require_relative "product_matrix"
require "cgi"

module Mixlib
Expand Down Expand Up @@ -99,14 +100,15 @@ def initialize(version, powershell = false, opts = {})

parse_opts(opts)

# Update root for chef-ice to use Habitat install directories
if @project&.casecmp("chef-ice") == 0
@root = if powershell
"$env:systemdrive\\#{Mixlib::Install::Dist::HABITAT_WINDOWS_INSTALL_DIR}\\chef\\chef-infra-client\\*\\*"
else
"#{Mixlib::Install::Dist::HABITAT_LINUX_INSTALL_DIR}/chef/chef-infra-client/*/*"
end
end
# Update root based on product distribution type (habitat vs omnibus)
product = PRODUCT_MATRIX.lookup(@project) if @project
return unless product&.habitat?

@root = if powershell
"$env:systemdrive\\#{Mixlib::Install::Dist::HABITAT_WINDOWS_INSTALL_DIR}\\#{product.hab_origin}\\#{product.hab_package_name}\\*\\*"
else
"#{Mixlib::Install::Dist::HABITAT_LINUX_INSTALL_DIR}/#{product.hab_origin}/#{product.hab_package_name}/*/*"
end
end

def install_command
Expand Down
2 changes: 1 addition & 1 deletion spec/functional/mixlib/install/cli_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@
end
end

context "with output option", :focus do
context "with output option" do
let(:args) { "-o #{File.join(test_temp_dir, 'script.sh')}" }

it "writes to a file" do
Expand Down
20 changes: 11 additions & 9 deletions spec/unit/mixlib/install/generator/base_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ def self.script_base_path
before do
@temp_dir = Dir.mktmpdir
@script_path = File.join(@temp_dir, "windows_dir.sh.erb")
File.write(@script_path, "dir=<%= windows_dir %>")
File.write(@script_path, "hab=<%= habitat_windows_dir %>\nomnibus=<%= omnibus_windows_dir %>")

allow(test_generator_class).to receive(:script_base_path).and_return(@temp_dir)
end
Expand All @@ -169,18 +169,22 @@ def self.script_base_path
FileUtils.rm_rf(@temp_dir) if @temp_dir
end

it "uses habitat directory for chef-ice" do
it "sets habitat_products, habitat_windows_dir, omnibus_windows_dir" do
context = { default_product: "chef-ice" }
script = test_generator_class.get_script("windows_dir.sh", context)
test_generator_class.get_script("windows_dir.sh", context)

expect(script).to include("dir=hab\\pkgs")
expect(context[:habitat_products]).to be_a(Hash)
expect(context[:habitat_products]["chef-ice"]).to eq({ origin: "chef", package_name: "chef-infra-client" })
expect(context[:habitat_windows_dir]).to be_a(String)
expect(context[:omnibus_windows_dir]).to be_a(String)
end

it "uses omnibus directory for chef" do
context = { default_product: "chef" }
it "renders habitat_windows_dir and omnibus_windows_dir in scripts" do
context = { default_product: "chef-ice" }
script = test_generator_class.get_script("windows_dir.sh", context)

expect(script).to include("dir=opscode")
expect(script).to include("hab=hab\\pkgs")
expect(script).to include("omnibus=opscode")
end
end
end
Expand Down Expand Up @@ -236,7 +240,6 @@ def self.script_base_path
support=<%= support_url %>
resources=<%= resources_url %>
macos=<%= macos_dir %>
windows=<%= windows_dir %>
SCRIPT

allow(test_generator_class).to receive(:script_base_path).and_return(@temp_dir)
Expand All @@ -257,7 +260,6 @@ def self.script_base_path
expect(script).to include("support=https://www.chef.io/support/tickets")
expect(script).to include("resources=https://www.chef.io/support")
expect(script).to include("macos=chef_software")
expect(script).to include("windows=opscode")
end
end
end
71 changes: 71 additions & 0 deletions spec/unit/mixlib/install/generator_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -681,6 +681,77 @@
end
end

context "habitat install-location hashtable for chef-ice" do
let(:add_options) do
{
product_name: "chef-ice",
shell_type: :ps1,
license_id: "test-license-key-123",
}
end

it_behaves_like "the correct ps1 script"

it "contains the habitat_products hashtable with chef-ice entry" do
expect(install_script).to include("'chef-ice' = @{ origin = 'chef'; package_name = 'chef-infra-client' }")
end

it "uses runtime ContainsKey check not compile-time ERB branching" do
expect(install_script).to include("$habitat_products.ContainsKey($project)")
expect(install_script).not_to include("is_habitat")
end

it "includes hab\\pkgs path in the habitat install location logic" do
expect(install_script).to include("hab\\pkgs\\$($hab_meta.origin)\\$($hab_meta.package_name)")
end
end

context "habitat install-location hashtable for chef-workstation-enterprise" do
let(:add_options) do
{
product_name: "chef-workstation-enterprise",
shell_type: :ps1,
license_id: "test-license-key-123",
}
end

it_behaves_like "the correct ps1 script"

it "contains the habitat_products hashtable with chef-workstation-enterprise entry" do
expect(install_script).to include("'chef-workstation-enterprise' = @{ origin = 'chef'; package_name = 'chef-workstation' }")
end

it "uses runtime ContainsKey check" do
expect(install_script).to include("$habitat_products.ContainsKey($project)")
end
end

context "omnibus product (chef) does not use habitat paths" do
let(:add_options) do
{
product_name: "chef",
shell_type: :ps1,
license_id: "test-license-key-123",
}
end

it_behaves_like "the correct ps1 script"

it "still includes the habitat_products hashtable (runtime check)" do
expect(install_script).to include("$habitat_products = @{")
expect(install_script).to include("$habitat_products.ContainsKey($project)")
end

it "does not hardcode habitat paths" do
expect(install_script).not_to include("\\hab\\pkgs\\chef\\chef-infra-client")
end

it "includes omnibus install path via elseif branch" do
expect(install_script).to include("elseif ($project -eq 'chef')")
expect(install_script).to include("opscode\\chef\\bin")
end
end

context "optional package_manager parameter for PowerShell" do
let(:add_options) do
{
Expand Down
Loading
Loading