mixlib-install 3.14.0 → 3.16.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (30) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +0 -14
  3. data/lib/mixlib/install/backend/base.rb +15 -1
  4. data/lib/mixlib/install/backend/package_router.rb +60 -17
  5. data/lib/mixlib/install/cli.rb +2 -1
  6. data/lib/mixlib/install/dist.rb +24 -4
  7. data/lib/mixlib/install/generator/base.rb +1 -14
  8. data/lib/mixlib/install/generator/bourne/scripts/check_product.sh +11 -3
  9. data/lib/mixlib/install/generator/bourne/scripts/fetch_metadata.sh.erb +89 -19
  10. data/lib/mixlib/install/generator/bourne/scripts/fetch_package.sh +47 -23
  11. data/lib/mixlib/install/generator/bourne/scripts/helpers.sh.erb +30 -32
  12. data/lib/mixlib/install/generator/bourne/scripts/install_package.sh +2 -2
  13. data/lib/mixlib/install/generator/bourne/scripts/platform_detection.sh +22 -22
  14. data/lib/mixlib/install/generator/bourne/scripts/proxy_env.sh +4 -4
  15. data/lib/mixlib/install/generator/bourne/scripts/script_cli_parameters.sh.erb +9 -2
  16. data/lib/mixlib/install/generator/bourne.rb +11 -6
  17. data/lib/mixlib/install/generator/powershell/scripts/get_project_metadata.ps1.erb +52 -36
  18. data/lib/mixlib/install/generator/powershell/scripts/helpers.ps1.erb +8 -4
  19. data/lib/mixlib/install/generator/powershell/scripts/install_project.ps1.erb +57 -26
  20. data/lib/mixlib/install/generator/powershell/scripts/platform_detection.ps1 +1 -0
  21. data/lib/mixlib/install/generator/powershell.rb +5 -4
  22. data/lib/mixlib/install/generator.rb +5 -4
  23. data/lib/mixlib/install/options.rb +41 -0
  24. data/lib/mixlib/install/product_matrix.rb +1 -1
  25. data/lib/mixlib/install/script_generator.rb +80 -23
  26. data/lib/mixlib/install/util.rb +47 -0
  27. data/lib/mixlib/install/version.rb +1 -1
  28. data/lib/mixlib/install.rb +82 -11
  29. data/support/install_command.ps1 +3 -0
  30. metadata +2 -2
@@ -1,3 +1,4 @@
1
+ ################ install_project.ps1
1
2
  function Install-Project {
2
3
  <#
3
4
  .SYNOPSIS
@@ -5,12 +6,11 @@ function Install-Project {
5
6
  .DESCRIPTION
6
7
  Install a Chef Software, Inc. product
7
8
  .EXAMPLE
8
- iex (new-object net.webclient).downloadstring('https://omnitruck.chef.io/install.ps1'); Install-Project -project chef -channel stable
9
+ iex (new-object net.webclient).downloadstring('<%= base_url || "https://chefdownload-commercial.chef.io" %>/install.ps1<%= base_url && base_url.include?("chefdownload") ? "?license_id=$env:CHEF_LICENSE_KEY" : "" %>'); Install-Project -project chef -channel stable
9
10
 
10
11
  Installs the latest stable version of Chef.
11
12
  .EXAMPLE
12
- iex (irm 'https://omnitruck.chef.io/install.ps1'); Install-Project -project chefdk -channel current
13
-
13
+ iex (irm '<<%= base_url || "https://chefdownload-commercial.chef.io" %>/install.ps1<%= base_url && base_url.include?("chefdownload") ? "?license_id=$env:CHEF_LICENSE_KEY" : "" %>'); Install-Project -project chef -channel current
14
14
  Installs the latest integration build of the Chef Development Kit
15
15
  #>
16
16
  [cmdletbinding(SupportsShouldProcess=$true)]
@@ -57,19 +57,36 @@ function Install-Project {
57
57
  # Set to 'once' to skip install if project is detected
58
58
  [string]
59
59
  $install_strategy,
60
+ # Base server URI for metadata endpoint
61
+ [uri]
62
+ $base_server_uri,
60
63
  # License ID for commercial API access
61
64
  [string]
62
- $license_id
65
+ $license_id <%= "= '#{license_id}'" if license_id && !license_id.to_s.empty? %>
63
66
  )
64
67
 
65
- # Check for chef-client command in various locations
66
- $chef_locations = @(
67
- "$env:systemdrive\hab\pkgs\chef\chef-infra-client\*\*\bin\chef-client.bat",
68
- "$env:systemdrive\<%= windows_dir %>\$project\bin\$project-client.bat"
69
- )
70
- foreach ($path in $chef_locations) {
68
+ # Use CHEF_LICENSE_KEY environment variable if license_id not provided
69
+ if ([string]::IsNullOrEmpty($license_id) -and -not [string]::IsNullOrEmpty($env:CHEF_LICENSE_KEY)) {
70
+ $license_id = $env:CHEF_LICENSE_KEY
71
+ }
72
+
73
+ # Check for product installation in various locations
74
+ if ($project -eq 'chef' -or $project -eq 'chef-ice') {
75
+ # For chef or chef-ice, look for chef-infra-client paths
76
+ $install_locations = @(
77
+ "$env:systemdrive\hab\pkgs\chef\chef-infra-client\*\*\bin",
78
+ "$env:systemdrive\<%= windows_dir %>\chef\bin"
79
+ )
80
+ } else {
81
+ # For other products, look for product-specific paths
82
+ $install_locations = @(
83
+ "$env:systemdrive\hab\pkgs\chef\$project\*\*\bin",
84
+ "$env:systemdrive\<%= windows_dir %>\$project\bin"
85
+ )
86
+ }
87
+ foreach ($path in $install_locations) {
71
88
  $resolved = Get-Item $path -ErrorAction SilentlyContinue | Select-Object -First 1
72
- if ($resolved -and (Test-Path $resolved.FullName) -and ($install_strategy -eq 'once')) {
89
+ if ($resolved -and (Test-Path $resolved.FullName -PathType Container) -and ($install_strategy -eq 'once')) {
73
90
  Write-Host "$project installation detected at $($resolved.FullName)"
74
91
  Write-Host "install_strategy set to 'once'"
75
92
  Write-Host "Nothing to install"
@@ -89,7 +106,7 @@ function Install-Project {
89
106
  $download_url = $download_url_override
90
107
  $sha256 = $checksum
91
108
  } else {
92
- $package_metadata = Get-ProjectMetadata -project $project -channel $channel -version $version -prerelease:$prerelease -nightlies:$nightlies -architecture $architecture -license_id $license_id
109
+ $package_metadata = Get-ProjectMetadata -project $project -channel $channel -version $version -prerelease:$prerelease -nightlies:$nightlies -architecture $architecture -base_server_uri $base_server_uri -license_id $license_id
93
110
  $download_url = $package_metadata.url
94
111
  $sha256 = $package_metadata.sha256
95
112
  }
@@ -102,12 +119,18 @@ function Install-Project {
102
119
  }
103
120
  }
104
121
  else {
105
- # For licensed downloads, we won't know the filename until after download
106
- if ([string]::IsNullOrEmpty($license_id)) {
107
- $filename = (([System.Uri]$download_url).AbsolutePath -split '/')[-1]
108
- } else {
122
+ # Extract filename from URL path (without query params)
123
+ $urlPath = (([System.Uri]$download_url).AbsolutePath -split '/')[-1]
124
+
125
+ # Check if URL path has a package file extension
126
+ $hasPackageExtension = $urlPath -match '\.(msi|appx|pkg|dmg|rpm|deb)$'
127
+
128
+ # For licensed downloads or URLs without package extensions, we won't know the filename until after download
129
+ if (-not [string]::IsNullOrEmpty($license_id) -or -not $hasPackageExtension) {
109
130
  $filename = "chef-download-temp-$PID"
110
- Write-Host "Using temporary filename for licensed download: $filename"
131
+ Write-Host "Using temporary filename for content-disposition download: $filename"
132
+ } else {
133
+ $filename = $urlPath
111
134
  }
112
135
  }
113
136
  Write-Host "Download directory: $download_directory"
@@ -147,14 +170,14 @@ function Install-Project {
147
170
  if ($pscmdlet.ShouldProcess("$($download_url)", "Download $project")) {
148
171
  Write-Host "Downloading $project from $($download_url) to $download_destination."
149
172
  $download_result = Get-WebContent $download_url -filepath $download_destination
150
-
151
- # For licensed downloads, extract actual filename from Content-Disposition
152
- if (-not [string]::IsNullOrEmpty($license_id) -and $download_result -and $download_result.Filename) {
173
+
174
+ # Extract actual filename from Content-Disposition if it was a temp filename
175
+ if ($filename -like "chef-download-temp-*" -and $download_result -and $download_result.Filename) {
153
176
  $actual_filename = $download_result.Filename
154
177
  Write-Host "Extracted filename from Content-Disposition: $actual_filename"
155
-
178
+
156
179
  $final_destination = join-path $download_directory $actual_filename
157
-
180
+
158
181
  # Move temp file to final location with correct name
159
182
  if ($download_destination -ne $final_destination) {
160
183
  Write-Host "Moving to final location: $final_destination"
@@ -164,8 +187,8 @@ function Install-Project {
164
187
  move-item $download_destination $final_destination -force
165
188
  $download_destination = $final_destination
166
189
  }
167
- } elseif (-not [string]::IsNullOrEmpty($license_id)) {
168
- Write-Host "Warning: Could not extract filename from Content-Disposition header for licensed download."
190
+ } elseif ($filename -like "chef-download-temp-*") {
191
+ Write-Host "Warning: Could not extract filename from Content-Disposition header."
169
192
  Write-Host "Using temporary filename. Package installation may fail."
170
193
  }
171
194
  }
@@ -179,17 +202,25 @@ function Install-Project {
179
202
  Write-Host "Installing $project from $download_destination"
180
203
  $installingProject = $True
181
204
  $installAttempts = 0
205
+ $maxAttempts = 5
182
206
  while ($installingProject) {
183
207
  $installAttempts++
184
208
  $result = $false
185
- if($download_destination.EndsWith(".appx")) {
209
+ if ($download_destination.EndsWith(".appx")) {
186
210
  $result = Install-ChefAppx $download_destination $project
187
211
  }
188
212
  else {
189
213
  $result = Install-ChefMsi $download_destination $daemon
190
214
  }
191
- if(!$result) { continue }
215
+ if (!$result) {
216
+ if ($installAttempts -ge $maxAttempts) {
217
+ Write-Host "Failed to install $project after $installAttempts attempts."
218
+ throw "Installation failed after $installAttempts attempts."
219
+ }
220
+ continue
221
+ }
192
222
  $installingProject = $False
223
+ Write-Host "$project installation completed successfully."
193
224
  }
194
225
  }
195
226
  }
@@ -1,3 +1,4 @@
1
+ ################ platform_detection.ps1
1
2
  $platform_version = Get-PlatformVersion
2
3
  $architecture = Get-PlatformArchitecture
3
4
 
@@ -25,7 +25,7 @@ module Mixlib
25
25
  install_project_module = []
26
26
  install_project_module << get_script("helpers.ps1", context)
27
27
  install_project_module << get_script("get_project_metadata.ps1", context)
28
- install_project_module << get_script("install_project.ps1")
28
+ install_project_module << get_script("install_project.ps1", context)
29
29
 
30
30
  install_command = []
31
31
  install_command << ps1_modularize(install_project_module.join("\n"), "Installer-Module")
@@ -46,8 +46,8 @@ module Mixlib
46
46
  def install_command
47
47
  install_project_module = []
48
48
  install_project_module << get_script("helpers.ps1", user_agent_headers: options.user_agent_headers)
49
- install_project_module << get_script("get_project_metadata.ps1")
50
- install_project_module << get_script("install_project.ps1")
49
+ install_project_module << get_script("get_project_metadata.ps1", license_id: options.license_id, base_url: options.base_url)
50
+ install_project_module << get_script("install_project.ps1", license_id: options.license_id)
51
51
  install_command = []
52
52
  install_command << ps1_modularize(install_project_module.join("\n"), "Installer-Module")
53
53
  install_command << render_command
@@ -67,10 +67,11 @@ module Mixlib
67
67
  end
68
68
 
69
69
  def render_command
70
- cmd = "install -project #{options.product_name}"
70
+ cmd = "Install-Project -project #{options.product_name}"
71
71
  cmd << " -version #{options.product_version}"
72
72
  cmd << " -channel #{options.channel}"
73
73
  cmd << " -architecture #{options.architecture}" if options.architecture
74
+ cmd << " -base_server_uri '#{options.base_url}'" if options.base_url && !options.base_url.to_s.empty?
74
75
  cmd << " -license_id #{options.license_id}" if options.license_id && !options.license_id.to_s.empty?
75
76
  cmd << install_command_params if options.install_command_options
76
77
  cmd << "\n"
@@ -22,10 +22,11 @@ module Mixlib
22
22
  class Install
23
23
  class Generator
24
24
  def self.install_command(options)
25
- klass = options.for_ps1? ? PowerShell : Bourne
26
- meth = options.options[:new_omnibus_download_url] ? :install_sh_from_upstream : :install_command
27
-
28
- klass.new(options).send(meth)
25
+ if options.for_ps1?
26
+ PowerShell.new(options).install_command
27
+ else
28
+ Bourne.new(options).install_command
29
+ end
29
30
  end
30
31
  end
31
32
  end
@@ -64,6 +64,7 @@ module Mixlib
64
64
  :user_agent_headers,
65
65
  :install_command_options,
66
66
  :license_id,
67
+ :base_url,
67
68
  ]
68
69
 
69
70
  SUPPORTED_WINDOWS_DESKTOP_VERSIONS = %w{10}
@@ -90,6 +91,8 @@ module Mixlib
90
91
 
91
92
  map_windows_versions!
92
93
 
94
+ enforce_trial_api_defaults!
95
+
93
96
  validate!
94
97
  end
95
98
 
@@ -185,6 +188,7 @@ module Mixlib
185
188
  platform_version_compatibility_mode: false,
186
189
  product_version: :latest,
187
190
  include_metadata: false,
191
+ license_id: ENV["CHEF_LICENSE_KEY"],
188
192
  }
189
193
  end
190
194
 
@@ -256,6 +260,43 @@ Must provide platform (-p), platform version (-l) and architecture (-a) when spe
256
260
  def all_or_none?(items)
257
261
  items.all? || items.compact.empty?
258
262
  end
263
+
264
+ # Trial API only supports stable channel and latest version
265
+ # If using trial API with other settings, default them and warn the user
266
+ def enforce_trial_api_defaults!
267
+ return unless use_trial_api?
268
+
269
+ original_channel = channel
270
+ original_version = product_version
271
+
272
+ # Force stable channel for trial API
273
+ if channel != :stable
274
+ options[:channel] = :stable
275
+ warn "WARNING: Trial API only supports 'stable' channel. Changing from '#{original_channel}' to 'stable'."
276
+ end
277
+
278
+ # Force latest version for trial API
279
+ if product_version != :latest && product_version.to_sym != :latest
280
+ options[:product_version] = :latest
281
+ warn "WARNING: Trial API only supports 'latest' version. Changing from '#{original_version}' to 'latest'."
282
+ end
283
+ end
284
+
285
+ def use_trial_api?
286
+ license_id = options[:license_id] || options["license_id"] || default_options[:license_id]
287
+ Mixlib::Install::Dist.trial_license?(license_id)
288
+ end
289
+
290
+ # Validate that licensed API usage conforms to API restrictions
291
+ # This is informational only - enforce_trial_api_defaults! already handles corrections
292
+ def validate_licensed_api_restrictions
293
+ return unless license_id && !license_id.to_s.empty?
294
+
295
+ if use_trial_api?
296
+ # These are enforced by enforce_trial_api_defaults! but we can add extra validation here if needed
297
+ # Currently no additional validation needed since defaults are auto-applied
298
+ end
299
+ end
259
300
  end
260
301
  end
261
302
  end
@@ -132,7 +132,7 @@ PRODUCT_MATRIX = Mixlib::Install::ProductMatrix.new do
132
132
  end
133
133
  config_file "/etc/delivery/delivery.rb"
134
134
  github_repo "chef/automate"
135
- downloads_product_page_url "https://downloads.chef.io/automate"
135
+ downloads_product_page_url "#{Mixlib::Install::Dist::DOWNLOADS_PAGE}/automate"
136
136
  end
137
137
 
138
138
  product "ha" do
@@ -21,7 +21,6 @@ require_relative "util"
21
21
  require_relative "generator/powershell"
22
22
  require_relative "dist"
23
23
  require "cgi"
24
- require "net/http" unless defined?(Net::HTTP)
25
24
 
26
25
  module Mixlib
27
26
  class Install
@@ -58,18 +57,23 @@ module Mixlib
58
57
  attr_accessor :omnibus_url
59
58
  attr_accessor :install_msi_url
60
59
 
60
+ attr_accessor :license_id
61
+ attr_accessor :base_url
62
+
61
63
  VALID_INSTALL_OPTS = %w{omnibus_url
62
64
  endpoint
63
65
  http_proxy
64
66
  https_proxy
65
67
  install_flags
66
68
  install_msi_url
69
+ license_id
67
70
  nightlies
68
71
  prerelease
69
72
  project
70
73
  root
71
74
  use_sudo
72
- sudo_command}
75
+ sudo_command
76
+ base_url}
73
77
 
74
78
  def initialize(version, powershell = false, opts = {})
75
79
  @version = (version || "latest").to_s.downcase
@@ -80,17 +84,29 @@ module Mixlib
80
84
  @prerelease = false
81
85
  @nightlies = false
82
86
  @endpoint = "metadata"
83
- @omnibus_url = "https://www.chef.io/chef/install.sh"
87
+ @omnibus_url = "#{Mixlib::Install::Dist::OMNITRUCK_ENDPOINT}/install.sh"
84
88
  @use_sudo = true
85
89
  @sudo_command = "sudo -E"
90
+ @license_id = nil
91
+ @project = Mixlib::Install::Dist::DEFAULT_PRODUCT.freeze
92
+ @channel = "stable"
86
93
 
87
94
  @root = if powershell
88
- "$env:systemdrive\\#{Mixlib::Install::Dist::WINDOWS_INSTALL_DIR}\\#{Mixlib::Install::Dist::DEFAULT_PRODUCT}"
95
+ "$env:systemdrive\\#{Mixlib::Install::Dist::OMNIBUS_WINDOWS_INSTALL_DIR}\\#{Mixlib::Install::Dist::DEFAULT_PRODUCT}"
89
96
  else
90
- "#{Mixlib::Install::Dist::LINUX_INSTALL_DIR}/#{Mixlib::Install::Dist::DEFAULT_PRODUCT}"
97
+ "#{Mixlib::Install::Dist::OMNIBUS_LINUX_INSTALL_DIR}/#{Mixlib::Install::Dist::DEFAULT_PRODUCT}"
91
98
  end
92
99
 
93
100
  parse_opts(opts)
101
+
102
+ # Update root for chef-ice to use Habitat install directories
103
+ if @project&.casecmp("chef-ice") == 0
104
+ @root = if powershell
105
+ "$env:systemdrive\\#{Mixlib::Install::Dist::HABITAT_WINDOWS_INSTALL_DIR}\\chef\\chef-infra-client\\*\\*"
106
+ else
107
+ "#{Mixlib::Install::Dist::HABITAT_LINUX_INSTALL_DIR}/chef/chef-infra-client/*/*"
108
+ end
109
+ end
94
110
  end
95
111
 
96
112
  def install_command
@@ -102,17 +118,6 @@ module Mixlib
102
118
  shell_code_from_file(vars)
103
119
  end
104
120
 
105
- def install_command_from_omnitruck(url)
106
- uri = URI.parse(url)
107
- response = Net::HTTP.get_response(uri)
108
-
109
- if response.code == "200"
110
- response.body
111
- else
112
- raise StandardError, "unable to fetch the install.sh"
113
- end
114
- end
115
-
116
121
  private
117
122
 
118
123
  # Generates the install command variables for Bourne shell-based
@@ -124,11 +129,12 @@ module Mixlib
124
129
  flags = %w{latest true nightlies}.include?(version) ? "" : "-v #{CGI.escape(version)}"
125
130
  flags << " " << "-n" if nightlies
126
131
  flags << " " << "-p" if prerelease
132
+ flags << " " << "-l #{license_id}" if license_id && !license_id.to_s.empty?
127
133
  flags << " " << install_flags if install_flags
128
134
 
129
135
  [
130
136
  shell_var("chef_omnibus_root", root),
131
- shell_var("chef_omnibus_url", omnibus_url),
137
+ shell_var("chef_omnibus_url", omnibus_url_for_license),
132
138
  shell_var("install_flags", flags.strip),
133
139
  shell_var("pretty_version", Util.pretty_version(version)),
134
140
  shell_var("sudo_sh", sudo("sh")),
@@ -151,6 +157,7 @@ module Mixlib
151
157
  shell_var("msi", "#{download_directory}\\chef-#{version}.msi"),
152
158
  shell_var("download_directory", download_directory),
153
159
  ].tap do |vars|
160
+ vars << shell_var("license_id", license_id) if license_id && !license_id.to_s.empty?
154
161
  if install_msi_url
155
162
  vars << shell_var("chef_msi_url", install_msi_url)
156
163
  else
@@ -172,6 +179,7 @@ module Mixlib
172
179
  validate_opts!(opt)
173
180
  case opt.to_s
174
181
  when "project", "endpoint"
182
+ @project = setting if opt.to_s == "project"
175
183
  self.endpoint = metadata_endpoint_from_project(setting)
176
184
  else
177
185
  send("#{opt.to_sym}=", setting)
@@ -216,23 +224,72 @@ module Mixlib
216
224
 
217
225
  # @return the correct Chef Omnitruck API metadata endpoint, based on project
218
226
  def metadata_endpoint_from_project(project = nil)
219
- if project.nil? || project.casecmp("chef") == 0
227
+ if project.nil? || project.casecmp(Mixlib::Install::Dist::DEFAULT_PRODUCT) == 0
220
228
  "metadata"
221
229
  else
222
230
  "metadata-#{project.downcase}"
223
231
  end
224
232
  end
225
233
 
234
+ # Returns the appropriate omnibus URL based on whether license_id is provided
235
+ # @return [String] the omnibus URL (commercial/trial or standard omnitruck)
236
+ # @api private
237
+ def omnibus_url_for_license
238
+ return omnibus_url if license_id.nil? || license_id.to_s.empty? || omnibus_url != "#{Mixlib::Install::Dist::OMNITRUCK_ENDPOINT}/install.sh"
239
+
240
+ # Use custom base_url if provided, otherwise determine from license type
241
+ endpoint_base = if @base_url
242
+ @base_url
243
+ elsif license_id.start_with?("free-", "trial-")
244
+ Mixlib::Install::Dist::TRIAL_API_ENDPOINT
245
+ else
246
+ Mixlib::Install::Dist::COMMERCIAL_API_ENDPOINT
247
+ end
248
+
249
+ # Add license_id as query param when using licensed endpoints
250
+ "#{endpoint_base}/install.sh?license_id=#{CGI.escape(license_id)}"
251
+ end
252
+
226
253
  def windows_metadata_url
227
- base = if omnibus_url.match?(%r{/install.sh$})
228
- "#{File.dirname(omnibus_url)}/"
229
- end
254
+ # Determine if we're using commercial/trial API
255
+ using_licensed_api = license_id && !license_id.to_s.empty?
256
+
257
+ if using_licensed_api
258
+ # Commercial/trial API: <base_url>/<channel>/<project>/metadata
259
+ # Use custom base_url if provided, otherwise determine from license type
260
+ endpoint_base = if @base_url
261
+ @base_url
262
+ elsif license_id.start_with?("free-", "trial-")
263
+ Mixlib::Install::Dist::TRIAL_API_ENDPOINT
264
+ else
265
+ Mixlib::Install::Dist::COMMERCIAL_API_ENDPOINT
266
+ end
267
+
268
+ product_name = @project
269
+ url = "#{endpoint_base}/#{@channel}/#{product_name}/metadata"
270
+ else
271
+ # Omnitruck API: use base from omnibus_url + endpoint
272
+ base = if omnibus_url_for_license.match?(%r{/install.sh})
273
+ # Ensure base URL ends with /
274
+ base_url = File.dirname(omnibus_url_for_license)
275
+ base_url += "/" unless base_url.end_with?("/")
276
+ base_url
277
+ end
278
+ url = "#{base}#{endpoint}"
279
+ end
230
280
 
231
- url = "#{base}#{endpoint}"
232
- url << "?p=windows&m=$platform_architecture&pv=$platform_version"
281
+ # chef-ice uses different parameters than chef
282
+ if @project.casecmp("chef-ice") == 0
283
+ # For chef-ice: p (platform), m (machine), pm (package_manager)
284
+ url << "?p=windows&m=$platform_architecture&pm=msi"
285
+ else
286
+ # For chef and other products: p (platform), pv (platform_version), m (machine)
287
+ url << "?p=windows&m=$platform_architecture&pv=$platform_version"
288
+ end
233
289
  url << "&v=#{CGI.escape(version)}" unless %w{latest true nightlies}.include?(version)
234
290
  url << "&prerelease=true" if prerelease
235
291
  url << "&nightlies=true" if nightlies
292
+ url << "&license_id=#{CGI.escape(license_id)}" if license_id && !license_id.to_s.empty?
236
293
  url
237
294
  end
238
295
 
@@ -172,6 +172,53 @@ module Mixlib
172
172
  architecture
173
173
  end
174
174
  end
175
+
176
+ #
177
+ # Determines package manager based on platform for commercial API
178
+ #
179
+ # @param [String] platform
180
+ #
181
+ # @return String [package_manager] (rpm, deb, tar, msi, dmg)
182
+ def determine_package_manager(platform)
183
+ case platform
184
+ when /^el/, /^centos/, /^rhel/, /^fedora/, /^amazon/, /^rocky/, /^opensuse/, /^sles/, /^scientific/
185
+ "rpm"
186
+ when /^debian/, /^ubuntu/, /^linuxmint/, /^raspbian/
187
+ "deb"
188
+ when /^mac_os_x/, /^macos/
189
+ "dmg"
190
+ when /^windows/
191
+ "msi"
192
+ when /^solaris/, /^smartos/, /^freebsd/, /^aix/, /^omnios/
193
+ "tar"
194
+ else
195
+ # Default to tar for unknown platforms
196
+ "tar"
197
+ end
198
+ end
199
+
200
+ #
201
+ # Normalizes platform name for commercial API (chef-ice)
202
+ # Maps specific platform names to generic categories
203
+ #
204
+ # @param [String] platform
205
+ #
206
+ # @return String [normalized_platform] (linux, macos, windows)
207
+ def normalize_platform_for_commercial(platform)
208
+ case platform
209
+ when /^el/, /^centos/, /^rhel/, /^fedora/, /^rocky/, /^scientific/, /^debian/, /^ubuntu/, /^linuxmint/, /^raspbian/, /^opensuse/, /^sles/, /^amazon/
210
+ "linux"
211
+ when /^mac_os_x/, /^macos/
212
+ "macos"
213
+ when /^windows/
214
+ "windows"
215
+ when /^freebsd/, /^aix/, /^solaris/, /^smartos/, /^omnios/
216
+ "unix"
217
+ else
218
+ # Default to linux for unknown platforms
219
+ "linux"
220
+ end
221
+ end
175
222
  end
176
223
  end
177
224
  end
@@ -1,5 +1,5 @@
1
1
  module Mixlib
2
2
  class Install
3
- VERSION = "3.14.0"
3
+ VERSION = "3.16.0"
4
4
  end
5
5
  end