mixlib-install 3.15.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.
- checksums.yaml +4 -4
- data/Gemfile +0 -14
- data/lib/mixlib/install/backend/base.rb +15 -1
- data/lib/mixlib/install/backend/package_router.rb +60 -17
- data/lib/mixlib/install/dist.rb +24 -4
- data/lib/mixlib/install/generator/base.rb +1 -14
- data/lib/mixlib/install/generator/bourne/scripts/check_product.sh +1 -1
- data/lib/mixlib/install/generator/bourne/scripts/fetch_metadata.sh.erb +89 -19
- data/lib/mixlib/install/generator/bourne/scripts/fetch_package.sh +47 -23
- data/lib/mixlib/install/generator/bourne/scripts/helpers.sh.erb +30 -32
- data/lib/mixlib/install/generator/bourne/scripts/install_package.sh +2 -2
- data/lib/mixlib/install/generator/bourne/scripts/platform_detection.sh +22 -22
- data/lib/mixlib/install/generator/bourne/scripts/proxy_env.sh +4 -4
- data/lib/mixlib/install/generator/bourne/scripts/script_cli_parameters.sh.erb +5 -3
- data/lib/mixlib/install/generator/bourne.rb +5 -20
- data/lib/mixlib/install/generator/powershell/scripts/get_project_metadata.ps1.erb +52 -36
- data/lib/mixlib/install/generator/powershell/scripts/helpers.ps1.erb +8 -4
- data/lib/mixlib/install/generator/powershell/scripts/install_project.ps1.erb +33 -16
- data/lib/mixlib/install/generator/powershell/scripts/platform_detection.ps1 +1 -0
- data/lib/mixlib/install/generator/powershell.rb +5 -9
- data/lib/mixlib/install/generator.rb +5 -4
- data/lib/mixlib/install/options.rb +40 -0
- data/lib/mixlib/install/product_matrix.rb +1 -1
- data/lib/mixlib/install/script_generator.rb +80 -23
- data/lib/mixlib/install/util.rb +47 -0
- data/lib/mixlib/install/version.rb +1 -1
- data/lib/mixlib/install.rb +82 -11
- data/support/install_command.ps1 +3 -0
- 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://
|
|
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://
|
|
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,9 +57,12 @@ 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
68
|
# Use CHEF_LICENSE_KEY environment variable if license_id not provided
|
|
@@ -103,7 +106,7 @@ function Install-Project {
|
|
|
103
106
|
$download_url = $download_url_override
|
|
104
107
|
$sha256 = $checksum
|
|
105
108
|
} else {
|
|
106
|
-
$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
|
|
107
110
|
$download_url = $package_metadata.url
|
|
108
111
|
$sha256 = $package_metadata.sha256
|
|
109
112
|
}
|
|
@@ -116,12 +119,18 @@ function Install-Project {
|
|
|
116
119
|
}
|
|
117
120
|
}
|
|
118
121
|
else {
|
|
119
|
-
#
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
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) {
|
|
123
130
|
$filename = "chef-download-temp-$PID"
|
|
124
|
-
Write-Host "Using temporary filename for
|
|
131
|
+
Write-Host "Using temporary filename for content-disposition download: $filename"
|
|
132
|
+
} else {
|
|
133
|
+
$filename = $urlPath
|
|
125
134
|
}
|
|
126
135
|
}
|
|
127
136
|
Write-Host "Download directory: $download_directory"
|
|
@@ -162,8 +171,8 @@ function Install-Project {
|
|
|
162
171
|
Write-Host "Downloading $project from $($download_url) to $download_destination."
|
|
163
172
|
$download_result = Get-WebContent $download_url -filepath $download_destination
|
|
164
173
|
|
|
165
|
-
#
|
|
166
|
-
if (-
|
|
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) {
|
|
167
176
|
$actual_filename = $download_result.Filename
|
|
168
177
|
Write-Host "Extracted filename from Content-Disposition: $actual_filename"
|
|
169
178
|
|
|
@@ -178,8 +187,8 @@ function Install-Project {
|
|
|
178
187
|
move-item $download_destination $final_destination -force
|
|
179
188
|
$download_destination = $final_destination
|
|
180
189
|
}
|
|
181
|
-
} elseif (-
|
|
182
|
-
Write-Host "Warning: Could not extract filename from Content-Disposition header
|
|
190
|
+
} elseif ($filename -like "chef-download-temp-*") {
|
|
191
|
+
Write-Host "Warning: Could not extract filename from Content-Disposition header."
|
|
183
192
|
Write-Host "Using temporary filename. Package installation may fail."
|
|
184
193
|
}
|
|
185
194
|
}
|
|
@@ -193,17 +202,25 @@ function Install-Project {
|
|
|
193
202
|
Write-Host "Installing $project from $download_destination"
|
|
194
203
|
$installingProject = $True
|
|
195
204
|
$installAttempts = 0
|
|
205
|
+
$maxAttempts = 5
|
|
196
206
|
while ($installingProject) {
|
|
197
207
|
$installAttempts++
|
|
198
208
|
$result = $false
|
|
199
|
-
if($download_destination.EndsWith(".appx")) {
|
|
209
|
+
if ($download_destination.EndsWith(".appx")) {
|
|
200
210
|
$result = Install-ChefAppx $download_destination $project
|
|
201
211
|
}
|
|
202
212
|
else {
|
|
203
213
|
$result = Install-ChefMsi $download_destination $daemon
|
|
204
214
|
}
|
|
205
|
-
if(!$result) {
|
|
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
|
+
}
|
|
206
222
|
$installingProject = $False
|
|
223
|
+
Write-Host "$project installation completed successfully."
|
|
207
224
|
}
|
|
208
225
|
}
|
|
209
226
|
}
|
|
@@ -25,15 +25,10 @@ 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")
|
|
32
|
-
# If license_id is provided in context, add it to the default install command
|
|
33
|
-
if context[:license_id] && !context[:license_id].to_s.empty?
|
|
34
|
-
install_command << "# License ID provided via context - adding to install command"
|
|
35
|
-
install_command << "install -license_id '#{context[:license_id]}'"
|
|
36
|
-
end
|
|
37
32
|
install_command.join("\n\n")
|
|
38
33
|
end
|
|
39
34
|
|
|
@@ -51,8 +46,8 @@ module Mixlib
|
|
|
51
46
|
def install_command
|
|
52
47
|
install_project_module = []
|
|
53
48
|
install_project_module << get_script("helpers.ps1", user_agent_headers: options.user_agent_headers)
|
|
54
|
-
install_project_module << get_script("get_project_metadata.ps1")
|
|
55
|
-
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)
|
|
56
51
|
install_command = []
|
|
57
52
|
install_command << ps1_modularize(install_project_module.join("\n"), "Installer-Module")
|
|
58
53
|
install_command << render_command
|
|
@@ -72,10 +67,11 @@ module Mixlib
|
|
|
72
67
|
end
|
|
73
68
|
|
|
74
69
|
def render_command
|
|
75
|
-
cmd = "
|
|
70
|
+
cmd = "Install-Project -project #{options.product_name}"
|
|
76
71
|
cmd << " -version #{options.product_version}"
|
|
77
72
|
cmd << " -channel #{options.channel}"
|
|
78
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?
|
|
79
75
|
cmd << " -license_id #{options.license_id}" if options.license_id && !options.license_id.to_s.empty?
|
|
80
76
|
cmd << install_command_params if options.install_command_options
|
|
81
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
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
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
|
|
|
@@ -257,6 +260,43 @@ Must provide platform (-p), platform version (-l) and architecture (-a) when spe
|
|
|
257
260
|
def all_or_none?(items)
|
|
258
261
|
items.all? || items.compact.empty?
|
|
259
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
|
|
260
300
|
end
|
|
261
301
|
end
|
|
262
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 "
|
|
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 = "
|
|
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::
|
|
95
|
+
"$env:systemdrive\\#{Mixlib::Install::Dist::OMNIBUS_WINDOWS_INSTALL_DIR}\\#{Mixlib::Install::Dist::DEFAULT_PRODUCT}"
|
|
89
96
|
else
|
|
90
|
-
"#{Mixlib::Install::Dist::
|
|
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",
|
|
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(
|
|
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
|
-
|
|
228
|
-
|
|
229
|
-
|
|
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
|
-
|
|
232
|
-
|
|
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
|
|
data/lib/mixlib/install/util.rb
CHANGED
|
@@ -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
|
data/lib/mixlib/install.rb
CHANGED
|
@@ -103,6 +103,7 @@ module Mixlib
|
|
|
103
103
|
uri = URI.parse(artifact.url)
|
|
104
104
|
filename = nil
|
|
105
105
|
final_body = nil
|
|
106
|
+
final_uri = uri
|
|
106
107
|
|
|
107
108
|
Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == "https") do |http|
|
|
108
109
|
# Build the request path including query string
|
|
@@ -112,23 +113,27 @@ module Mixlib
|
|
|
112
113
|
# Get the response, following redirects
|
|
113
114
|
response = http.request_get(request_path)
|
|
114
115
|
|
|
116
|
+
# Try to extract filename from Content-Disposition in initial response
|
|
117
|
+
if response["content-disposition"]
|
|
118
|
+
filename = response["content-disposition"][/filename="?([^"]+)"?/, 1]
|
|
119
|
+
end
|
|
120
|
+
|
|
115
121
|
# Follow redirects
|
|
116
122
|
redirect_limit = 5
|
|
117
123
|
while response.is_a?(Net::HTTPRedirection) && redirect_limit > 0
|
|
118
124
|
redirect_uri = URI.parse(response["location"])
|
|
119
125
|
# Handle relative redirects
|
|
120
126
|
redirect_uri = uri + redirect_uri if redirect_uri.relative?
|
|
127
|
+
final_uri = redirect_uri
|
|
121
128
|
|
|
122
129
|
Net::HTTP.start(redirect_uri.host, redirect_uri.port, use_ssl: redirect_uri.scheme == "https") do |redirect_http|
|
|
123
130
|
redirect_path = redirect_uri.path
|
|
124
131
|
redirect_path += "?#{redirect_uri.query}" if redirect_uri.query
|
|
125
132
|
response = redirect_http.request_get(redirect_path)
|
|
126
133
|
|
|
127
|
-
# Try to get filename from Content-Disposition
|
|
128
|
-
if response["content-disposition"]
|
|
134
|
+
# Try to get filename from Content-Disposition in redirect response
|
|
135
|
+
if response["content-disposition"] && filename.nil?
|
|
129
136
|
filename = response["content-disposition"][/filename="?([^"]+)"?/, 1]
|
|
130
|
-
else
|
|
131
|
-
filename = File.basename(redirect_uri.path)
|
|
132
137
|
end
|
|
133
138
|
end
|
|
134
139
|
|
|
@@ -136,9 +141,23 @@ module Mixlib
|
|
|
136
141
|
end
|
|
137
142
|
|
|
138
143
|
final_body = response.body
|
|
144
|
+
|
|
145
|
+
# Try Content-Disposition from final successful response
|
|
146
|
+
if response["content-disposition"] && filename.nil?
|
|
147
|
+
filename = response["content-disposition"][/filename="?([^"]+)"?/, 1]
|
|
148
|
+
end
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
# Fallback: extract filename from final URL path (works for direct package URLs)
|
|
152
|
+
if filename.nil?
|
|
153
|
+
path_filename = File.basename(final_uri.path.split("?").first)
|
|
154
|
+
# Only use path filename if it looks like a package file
|
|
155
|
+
if /\.(rpm|deb|pkg|msi|dmg|bff|p5p|sh|tar|gz|appx)$/.match?(path_filename)
|
|
156
|
+
filename = path_filename
|
|
157
|
+
end
|
|
139
158
|
end
|
|
140
159
|
|
|
141
|
-
#
|
|
160
|
+
# Final fallback: use basename of original URL
|
|
142
161
|
filename ||= File.basename(uri.path)
|
|
143
162
|
file = File.join(directory, filename)
|
|
144
163
|
|
|
@@ -158,10 +177,19 @@ module Mixlib
|
|
|
158
177
|
def root
|
|
159
178
|
# This only works for chef and chefdk but they are the only projects
|
|
160
179
|
# we are supporting as of now.
|
|
161
|
-
|
|
162
|
-
|
|
180
|
+
# chef-ice uses Habitat install directories
|
|
181
|
+
if options.product_name.casecmp("chef-ice") == 0
|
|
182
|
+
if options.for_ps1?
|
|
183
|
+
"$env:systemdrive\\#{Mixlib::Install::Dist::HABITAT_WINDOWS_INSTALL_DIR}\\chef\\chef-infra-client\\*\\*"
|
|
184
|
+
else
|
|
185
|
+
"#{Mixlib::Install::Dist::HABITAT_LINUX_INSTALL_DIR}/chef/chef-infra-client/*/*"
|
|
186
|
+
end
|
|
163
187
|
else
|
|
164
|
-
|
|
188
|
+
if options.for_ps1?
|
|
189
|
+
"$env:systemdrive\\#{Mixlib::Install::Dist::OMNIBUS_WINDOWS_INSTALL_DIR}\\#{options.product_name}"
|
|
190
|
+
else
|
|
191
|
+
"#{Mixlib::Install::Dist::OMNIBUS_LINUX_INSTALL_DIR}/#{options.product_name}"
|
|
192
|
+
end
|
|
165
193
|
end
|
|
166
194
|
end
|
|
167
195
|
|
|
@@ -175,10 +203,19 @@ module Mixlib
|
|
|
175
203
|
# install directory which can be different than the product name (e.g.
|
|
176
204
|
# chef-server -> /opt/opscode). But this is OK for now since
|
|
177
205
|
# chef & chefdk are the only supported products.
|
|
178
|
-
|
|
179
|
-
|
|
206
|
+
# chef-ice uses Habitat install directories
|
|
207
|
+
version_manifest_file = if options.product_name.casecmp("chef-ice") == 0
|
|
208
|
+
if options.for_ps1?
|
|
209
|
+
"$env:systemdrive\\#{Mixlib::Install::Dist::HABITAT_WINDOWS_INSTALL_DIR}\\chef\\chef-infra-client\\*\\*\\version-manifest.json"
|
|
210
|
+
else
|
|
211
|
+
"#{Mixlib::Install::Dist::HABITAT_LINUX_INSTALL_DIR}/chef/chef-infra-client/*/*/version-manifest.json"
|
|
212
|
+
end
|
|
180
213
|
else
|
|
181
|
-
|
|
214
|
+
if options.for_ps1?
|
|
215
|
+
"$env:systemdrive\\#{Mixlib::Install::Dist::OMNIBUS_WINDOWS_INSTALL_DIR}\\#{options.product_name}\\version-manifest.json"
|
|
216
|
+
else
|
|
217
|
+
"/opt/#{options.product_name}/version-manifest.json"
|
|
218
|
+
end
|
|
182
219
|
end
|
|
183
220
|
|
|
184
221
|
if File.exist? version_manifest_file
|
|
@@ -258,8 +295,25 @@ module Mixlib
|
|
|
258
295
|
# ------------------
|
|
259
296
|
# base_url [String]
|
|
260
297
|
# url pointing to the omnitruck to be queried by the script.
|
|
298
|
+
# license_id [String]
|
|
299
|
+
# license ID for commercial or trial API access.
|
|
300
|
+
# If license_id starts with 'free-' or 'trial-', trial API defaults are enforced.
|
|
261
301
|
#
|
|
262
302
|
def self.install_sh(context = {})
|
|
303
|
+
# Apply trial API defaults if license_id indicates trial
|
|
304
|
+
if context[:license_id] && Mixlib::Install::Dist.trial_license?(context[:license_id])
|
|
305
|
+
# Warn and override if non-compliant values provided
|
|
306
|
+
if context[:channel] && context[:channel].to_s != "stable"
|
|
307
|
+
warn "WARNING: Trial API only supports 'stable' channel. Changing from '#{context[:channel]}' to 'stable'."
|
|
308
|
+
context[:channel] = "stable"
|
|
309
|
+
end
|
|
310
|
+
|
|
311
|
+
if context[:version] && !["latest", nil].include?(context[:version].to_s)
|
|
312
|
+
warn "WARNING: Trial API only supports 'latest' version. Changing from '#{context[:version]}' to 'latest'."
|
|
313
|
+
context[:version] = "latest"
|
|
314
|
+
end
|
|
315
|
+
end
|
|
316
|
+
|
|
263
317
|
Mixlib::Install::Generator::Bourne.install_sh(context)
|
|
264
318
|
end
|
|
265
319
|
|
|
@@ -269,8 +323,25 @@ module Mixlib
|
|
|
269
323
|
# ------------------
|
|
270
324
|
# base_url [String]
|
|
271
325
|
# url pointing to the omnitruck to be queried by the script.
|
|
326
|
+
# license_id [String]
|
|
327
|
+
# license ID for commercial or trial API access.
|
|
328
|
+
# If license_id starts with 'free-' or 'trial-', trial API defaults are enforced.
|
|
272
329
|
#
|
|
273
330
|
def self.install_ps1(context = {})
|
|
331
|
+
# Apply trial API defaults if license_id indicates trial
|
|
332
|
+
if context[:license_id] && Mixlib::Install::Dist.trial_license?(context[:license_id])
|
|
333
|
+
# Warn and override if non-compliant values provided
|
|
334
|
+
if context[:channel] && context[:channel].to_s != "stable"
|
|
335
|
+
warn "WARNING: Trial API only supports 'stable' channel. Changing from '#{context[:channel]}' to 'stable'."
|
|
336
|
+
context[:channel] = "stable"
|
|
337
|
+
end
|
|
338
|
+
|
|
339
|
+
if context[:version] && !["latest", nil].include?(context[:version].to_s)
|
|
340
|
+
warn "WARNING: Trial API only supports 'latest' version. Changing from '#{context[:version]}' to 'latest'."
|
|
341
|
+
context[:version] = "latest"
|
|
342
|
+
end
|
|
343
|
+
end
|
|
344
|
+
|
|
274
345
|
Mixlib::Install::Generator::PowerShell.install_ps1(context)
|
|
275
346
|
end
|
|
276
347
|
end
|