mixlib-install 1.1.0 → 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +0 -1
- data/CHANGELOG.md +9 -0
- data/Gemfile +0 -2
- data/PRODUCT_MATRIX.md +2 -1
- data/README.md +19 -0
- data/Rakefile +21 -3
- data/lib/mixlib/install.rb +17 -0
- data/lib/mixlib/install/backend.rb +12 -6
- data/lib/mixlib/install/backend/artifactory.rb +106 -17
- data/lib/mixlib/install/backend/base.rb +69 -0
- data/lib/mixlib/install/backend/bintray.rb +20 -60
- data/lib/mixlib/install/generator/bourne.rb +3 -1
- data/lib/mixlib/install/generator/bourne/scripts/helpers.sh +4 -0
- data/lib/mixlib/install/generator/bourne/scripts/platform_detection.sh +4 -0
- data/lib/mixlib/install/generator/powershell.rb +5 -3
- data/lib/mixlib/install/generator/powershell/scripts/helpers.ps1 +80 -13
- data/lib/mixlib/install/generator/powershell/scripts/install_project.ps1 +43 -7
- data/lib/mixlib/install/options.rb +4 -3
- data/lib/mixlib/install/product.rb +36 -1
- data/lib/mixlib/install/script_generator.rb +2 -3
- data/lib/mixlib/install/version.rb +1 -1
- data/mixlib-install.gemspec +2 -0
- data/support/install_command.ps1 +125 -23
- metadata +31 -4
- data/.rubocop.yml +0 -10
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: af96827b91f93939e6376192d760548132394e7e
|
4
|
+
data.tar.gz: 39e849c94aebecb08b7f0f5e4328aeb8a45cb038
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0cb34501343fb8891d181076ef8c213d034cdcbad866fc758754fdf24830883660bbca4c77282b0006118d48f1c22748a74ec6aba3935482349ed0fe446ed8af
|
7
|
+
data.tar.gz: 7320f109233968d75a508f959fc3a5c71964c40eb7921563dd21a5c1cf353ed5a2a8103e04b2770755d1e05981c356f7504a5948c4eb9229453250cffceb656c
|
data/.travis.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,14 @@
|
|
1
1
|
# Change Log
|
2
2
|
|
3
|
+
## [1.2.0]
|
4
|
+
- Fix omnibus project mappings
|
5
|
+
- Add `available_versions` method to API
|
6
|
+
- Add `chef-automate` product
|
7
|
+
- Add install support for Arista EOS
|
8
|
+
- Add p5p package support
|
9
|
+
- Add s390x architecture support
|
10
|
+
- Add Nano support
|
11
|
+
|
3
12
|
## [1.1.0]
|
4
13
|
- Remove delivery-cli from Product Matrix since we are now shipping it within ChefDK
|
5
14
|
|
data/Gemfile
CHANGED
data/PRODUCT_MATRIX.md
CHANGED
@@ -3,6 +3,7 @@
|
|
3
3
|
| Analytics Platform | analytics |
|
4
4
|
| Angry Omnibus Toolchain | angry-omnibus-toolchain |
|
5
5
|
| Angry Chef Client | angrychef |
|
6
|
+
| Chef Automate | automate |
|
6
7
|
| Chef Client | chef |
|
7
8
|
| Chef Backend | chef-backend |
|
8
9
|
| Chef Server | chef-server |
|
@@ -15,7 +16,7 @@
|
|
15
16
|
| Chef Cloud Marketplace addon | marketplace |
|
16
17
|
| Omnibus Toolchain | omnibus-toolchain |
|
17
18
|
| Enterprise Chef (legacy) | private-chef |
|
18
|
-
| Chef Push
|
19
|
+
| Chef Push Client | push-jobs-client |
|
19
20
|
| Chef Push Server | push-jobs-server |
|
20
21
|
| Chef Server Reporting addon | reporting |
|
21
22
|
| Supermarket | supermarket |
|
data/README.md
CHANGED
@@ -67,9 +67,28 @@ artifact.platform # => "ubuntu"
|
|
67
67
|
artifact.platform_version # => "14.04"
|
68
68
|
```
|
69
69
|
|
70
|
+
### List the available versions for a product and channel
|
71
|
+
```ruby
|
72
|
+
# Note that this feature currently only works for :unstable channel
|
73
|
+
options = {
|
74
|
+
channel: :unstable,
|
75
|
+
product_name: 'chef',
|
76
|
+
}
|
77
|
+
|
78
|
+
Mixlib::Install.new(options).available_versions
|
79
|
+
|
80
|
+
# => ["12.13.3", "12.13.7", "12.13.8+20160721014124", "12.13.11+20160721165202"]
|
81
|
+
```
|
82
|
+
|
70
83
|
## Unstable channel
|
71
84
|
The `:unstable` channel is currently only available when connected to Chef's internal network.
|
72
85
|
|
86
|
+
## Feature Flags
|
87
|
+
|
88
|
+
Below are the environment variables you can set to tune certain aspects of mixlib-install. They enable some features that are currently under development. You should use these features with care.
|
89
|
+
|
90
|
+
`MIXLIB_INSTALL_UNIFIED_BACKEND` => Enables unified backend feature which uses Artifactory backend for all available channels.
|
91
|
+
|
73
92
|
## Development
|
74
93
|
Since mixlib-install needs to interact with Bintray and Artifactory and since Artifactory instances are only available in Chef's network, this project uses [vcr](https://github.com/vcr/vcr).
|
75
94
|
|
data/Rakefile
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
require "bundler/gem_tasks"
|
2
2
|
require "rspec/core/rake_task"
|
3
3
|
|
4
|
-
task default: :
|
4
|
+
task default: :ci
|
5
5
|
|
6
6
|
desc "Run specs"
|
7
7
|
RSpec::Core::RakeTask.new(:spec) do |spec|
|
@@ -18,11 +18,21 @@ rescue LoadError
|
|
18
18
|
puts "chefstyle/rubocop is not available. gem install chefstyle to do style checking."
|
19
19
|
end
|
20
20
|
|
21
|
+
desc "Run specs for unified_backend (artifactory)"
|
22
|
+
task :unified_backend do
|
23
|
+
ENV["MIXLIB_INSTALL_UNIFIED_BACKEND"] = "true"
|
24
|
+
ENV["ARTIFACTORY_ENDPOINT"] = "https://packages-acceptance.chef.io"
|
25
|
+
Rake::Task["spec"].reenable
|
26
|
+
Rake::Task["spec"].invoke
|
27
|
+
ENV.delete "MIXLIB_INSTALL_UNIFIED_BACKEND"
|
28
|
+
ENV.delete "ARTIFACTORY_ENDPOINT"
|
29
|
+
end
|
30
|
+
|
21
31
|
desc "Run all tests"
|
22
|
-
task test: [:style, :spec]
|
32
|
+
task test: [:style, :spec, :unified_backend]
|
23
33
|
|
24
34
|
desc "Run tests for Travis CI"
|
25
|
-
task ci: [:style, :spec]
|
35
|
+
task ci: [:style, :spec, :unified_backend]
|
26
36
|
|
27
37
|
desc "Render product matrix documentation"
|
28
38
|
task "matrix" do
|
@@ -42,3 +52,11 @@ task "matrix" do
|
|
42
52
|
f.puts("Do not modify this file manually. It is automatically rendered via a rake task.")
|
43
53
|
end
|
44
54
|
end
|
55
|
+
|
56
|
+
task :console do
|
57
|
+
require "irb"
|
58
|
+
require "irb/completion"
|
59
|
+
require "mixlib/install"
|
60
|
+
ARGV.clear
|
61
|
+
IRB.start
|
62
|
+
end
|
data/lib/mixlib/install.rb
CHANGED
@@ -46,6 +46,15 @@ module Mixlib
|
|
46
46
|
Backend.info(options)
|
47
47
|
end
|
48
48
|
|
49
|
+
#
|
50
|
+
# List available versions
|
51
|
+
#
|
52
|
+
# @return [Array<String>] list of available versions for the given
|
53
|
+
# product_name and channel.
|
54
|
+
def available_versions
|
55
|
+
Backend.available_versions(options)
|
56
|
+
end
|
57
|
+
|
49
58
|
#
|
50
59
|
# Returns an install script for the given options
|
51
60
|
#
|
@@ -174,5 +183,13 @@ module Mixlib
|
|
174
183
|
def self.install_ps1(context = {})
|
175
184
|
Mixlib::Install::Generator::PowerShell.install_ps1(context)
|
176
185
|
end
|
186
|
+
|
187
|
+
#
|
188
|
+
# Returns if unified_backend feature flag for mixlib-install is enabled
|
189
|
+
#
|
190
|
+
# @return [Boolean] true if feature is enabled, false otherwise.
|
191
|
+
def self.unified_backend?
|
192
|
+
!ENV["MIXLIB_INSTALL_UNIFIED_BACKEND"].nil?
|
193
|
+
end
|
177
194
|
end
|
178
195
|
end
|
@@ -22,14 +22,20 @@ require "mixlib/install/backend/bintray"
|
|
22
22
|
module Mixlib
|
23
23
|
class Install
|
24
24
|
class Backend
|
25
|
+
def self.available_versions(options)
|
26
|
+
backend(options).available_versions
|
27
|
+
end
|
28
|
+
|
25
29
|
def self.info(options)
|
26
|
-
backend
|
27
|
-
|
28
|
-
else
|
29
|
-
Backend::Bintray.new(options)
|
30
|
-
end
|
30
|
+
backend(options).info
|
31
|
+
end
|
31
32
|
|
32
|
-
|
33
|
+
def self.backend(options)
|
34
|
+
if options.for_artifactory?
|
35
|
+
Backend::Artifactory.new(options)
|
36
|
+
else
|
37
|
+
Backend::Bintray.new(options)
|
38
|
+
end
|
33
39
|
end
|
34
40
|
end
|
35
41
|
end
|
@@ -43,11 +43,45 @@ module Mixlib
|
|
43
43
|
# @return [Array<ArtifactInfo>] list of artifacts for the configured
|
44
44
|
# channel, product name, and product version.
|
45
45
|
def available_artifacts
|
46
|
-
if options.latest_version?
|
47
|
-
|
48
|
-
|
49
|
-
|
46
|
+
artifacts = if options.latest_version?
|
47
|
+
artifactory_latest
|
48
|
+
else
|
49
|
+
artifactory_artifacts(options.product_version)
|
50
|
+
end
|
51
|
+
|
52
|
+
windows_artifact_fixup!(artifacts)
|
53
|
+
end
|
54
|
+
|
55
|
+
#
|
56
|
+
# Gets available versions from Artifactory via AQL.
|
57
|
+
#
|
58
|
+
# @return [Array<String>] Array of available versions
|
59
|
+
def available_versions
|
60
|
+
query = <<-QUERY
|
61
|
+
items.find(
|
62
|
+
{"repo": "omnibus-#{options.channel}-local"},
|
63
|
+
{"@omnibus.project": "#{omnibus_project}"},
|
64
|
+
{"name": {"$nmatch": "*.metadata.json" }}
|
65
|
+
).include("@omnibus.version", "artifact.module.build")
|
66
|
+
QUERY
|
67
|
+
items = artifactory_query(query)
|
68
|
+
|
69
|
+
# Filter out the partial builds if we are in :unstable channel
|
70
|
+
# In other channels we do not need to do this since all builds are
|
71
|
+
# always complete. Infact we should not do this since for some arcane
|
72
|
+
# builds like Chef Client 10.X we do not have build record created in
|
73
|
+
# artifactory.
|
74
|
+
if options.channel == :unstable
|
75
|
+
# We check if "artifacts" field contains something since it is only
|
76
|
+
# populated with the build record if "artifact.module.build" exists.
|
77
|
+
items.reject! { |i| i["artifacts"].nil? }
|
50
78
|
end
|
79
|
+
|
80
|
+
# We are only including a single property, version and that exists
|
81
|
+
# under the properties in the following structure:
|
82
|
+
# "properties" => [ {"key"=>"omnibus.version", "value"=>"12.13.3"} ]
|
83
|
+
items.map! { |i| i["properties"].first["value"] }
|
84
|
+
items.uniq
|
51
85
|
end
|
52
86
|
|
53
87
|
#
|
@@ -58,7 +92,7 @@ module Mixlib
|
|
58
92
|
# Get the list of builds from the REST api.
|
59
93
|
# We do this because a user in the readers group does not have
|
60
94
|
# permissions to run aql against builds.
|
61
|
-
builds = client.get("/api/build/#{
|
95
|
+
builds = client.get("/api/build/#{omnibus_project}")
|
62
96
|
|
63
97
|
if builds.nil?
|
64
98
|
raise NoArtifactsError, <<-MSG
|
@@ -100,16 +134,19 @@ Can not find any builds for #{options.product_name} in #{::Artifactory.endpoint}
|
|
100
134
|
results = artifactory_query(<<-QUERY
|
101
135
|
items.find(
|
102
136
|
{"repo": "omnibus-#{options.channel}-local"},
|
103
|
-
{"@omnibus.project": "#{
|
137
|
+
{"@omnibus.project": "#{omnibus_project}"},
|
104
138
|
{"@omnibus.version": "#{version}"},
|
105
139
|
{"name": {"$nmatch": "*.metadata.json" }}
|
106
140
|
).include("repo", "path", "name", "property")
|
107
141
|
QUERY
|
108
142
|
)
|
109
143
|
|
110
|
-
# Merge artifactory properties
|
144
|
+
# Merge artifactory properties to a flat Hash
|
111
145
|
results.collect! do |result|
|
112
|
-
{
|
146
|
+
{
|
147
|
+
"artifactory_standard_path" => generate_artifactory_standard_path(result),
|
148
|
+
"filename" => result["name"],
|
149
|
+
}.merge(
|
113
150
|
map_properties(result["properties"])
|
114
151
|
)
|
115
152
|
end
|
@@ -130,15 +167,42 @@ items.find(
|
|
130
167
|
results["results"]
|
131
168
|
end
|
132
169
|
|
170
|
+
#
|
171
|
+
# Artifactory GET request
|
172
|
+
#
|
173
|
+
def get(url)
|
174
|
+
results = artifactory_request do
|
175
|
+
client.get(url)
|
176
|
+
end
|
177
|
+
|
178
|
+
results["results"]
|
179
|
+
end
|
180
|
+
|
133
181
|
def create_artifact(artifact_map)
|
182
|
+
platform, platform_version = normalize_platform(artifact_map["omnibus.platform"],
|
183
|
+
artifact_map["omnibus.platform_version"])
|
184
|
+
|
185
|
+
chef_standard_path = generate_chef_standard_path(options.channel,
|
186
|
+
platform,
|
187
|
+
platform_version,
|
188
|
+
artifact_map["filename"]
|
189
|
+
)
|
190
|
+
|
134
191
|
ArtifactInfo.new(
|
135
192
|
md5: artifact_map["omnibus.md5"],
|
136
193
|
sha256: artifact_map["omnibus.sha256"],
|
194
|
+
sha1: artifact_map["omnibus.sha1"],
|
137
195
|
version: artifact_map["omnibus.version"],
|
138
|
-
platform:
|
139
|
-
platform_version:
|
140
|
-
architecture: artifact_map["omnibus.architecture"],
|
141
|
-
url
|
196
|
+
platform: platform,
|
197
|
+
platform_version: platform_version,
|
198
|
+
architecture: normalize_architecture(artifact_map["omnibus.architecture"]),
|
199
|
+
# Select what type of url we are going to display based on the enabled
|
200
|
+
# feature flags.
|
201
|
+
url: if Mixlib::Install.unified_backend?
|
202
|
+
chef_standard_path
|
203
|
+
else
|
204
|
+
artifact_map["artifactory_standard_path"]
|
205
|
+
end
|
142
206
|
)
|
143
207
|
end
|
144
208
|
|
@@ -154,9 +218,20 @@ items.find(
|
|
154
218
|
end
|
155
219
|
end
|
156
220
|
|
157
|
-
#
|
158
|
-
#
|
159
|
-
def
|
221
|
+
# Generates a chef standard download uri in the form of
|
222
|
+
# http://endpoint/channel/platform/platform_version/filename
|
223
|
+
def generate_chef_standard_path(channel, platform, platform_version, filename)
|
224
|
+
uri = []
|
225
|
+
uri << endpoint.sub(/\/$/, "")
|
226
|
+
uri << channel
|
227
|
+
uri << platform
|
228
|
+
uri << platform_version
|
229
|
+
uri << filename
|
230
|
+
uri.join("/")
|
231
|
+
end
|
232
|
+
|
233
|
+
# Generates an artifactory standard download uri
|
234
|
+
def generate_artifactory_standard_path(result)
|
160
235
|
uri = []
|
161
236
|
uri << endpoint.sub(/\/$/, "")
|
162
237
|
uri << result["repo"]
|
@@ -196,8 +271,22 @@ the endpoint is correct and there is an open connection to Chef's private networ
|
|
196
271
|
results
|
197
272
|
end
|
198
273
|
|
199
|
-
def
|
200
|
-
@
|
274
|
+
def omnibus_project
|
275
|
+
@omnibus_project ||= PRODUCT_MATRIX.lookup(options.product_name, options.product_version).omnibus_project
|
276
|
+
end
|
277
|
+
|
278
|
+
#
|
279
|
+
# Normalizes architecture information that we receive.
|
280
|
+
#
|
281
|
+
# @param [String] architecture
|
282
|
+
#
|
283
|
+
# @return String [architecture]
|
284
|
+
def normalize_architecture(architecture)
|
285
|
+
if %w{ sun4u sun4v }.include?(architecture)
|
286
|
+
architecture = "sparc"
|
287
|
+
end
|
288
|
+
|
289
|
+
architecture
|
201
290
|
end
|
202
291
|
end
|
203
292
|
end
|
@@ -38,6 +38,20 @@ module Mixlib
|
|
38
38
|
raise "Must implement available_artifacts method that returns Array<ArtifactInfo>"
|
39
39
|
end
|
40
40
|
|
41
|
+
#
|
42
|
+
# Returns the list of available versions for a given product_name
|
43
|
+
# and channel.
|
44
|
+
#
|
45
|
+
# @abstract Subclasses should define this method.
|
46
|
+
# Currently this method is only available in the Artifactory
|
47
|
+
# subclass.
|
48
|
+
#
|
49
|
+
# @return Array<String>
|
50
|
+
# List of available versions as strings.
|
51
|
+
def available_versions
|
52
|
+
raise "available_versions API is only available for Artifactory backend."
|
53
|
+
end
|
54
|
+
|
41
55
|
#
|
42
56
|
# See #filter_artifacts
|
43
57
|
def info
|
@@ -106,6 +120,61 @@ module Mixlib
|
|
106
120
|
return []
|
107
121
|
end
|
108
122
|
|
123
|
+
# On windows, if we do not have a native 64-bit package available
|
124
|
+
# in the discovered artifacts, we will make 32-bit artifacts available
|
125
|
+
# for 64-bit architecture.
|
126
|
+
def windows_artifact_fixup!(artifacts)
|
127
|
+
new_artifacts = [ ]
|
128
|
+
native_artifacts = [ ]
|
129
|
+
|
130
|
+
artifacts.each do |r|
|
131
|
+
next if r.platform != "windows"
|
132
|
+
|
133
|
+
# Store all native 64-bit artifacts and clone 32-bit artifacts to
|
134
|
+
# be used as 64-bit.
|
135
|
+
case r.architecture
|
136
|
+
when "i386"
|
137
|
+
new_artifacts << r.clone_with(architecture: "x86_64")
|
138
|
+
when "x86_64"
|
139
|
+
native_artifacts << r.clone
|
140
|
+
else
|
141
|
+
puts "Unknown architecture '#{r.architecture}' for windows."
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
# Now discard the cloned artifacts if we find an equivalent native
|
146
|
+
# artifact
|
147
|
+
native_artifacts.each do |r|
|
148
|
+
new_artifacts.delete_if do |x|
|
149
|
+
x.platform_version == r.platform_version
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
# add the remaining cloned artifacts to the original set
|
154
|
+
artifacts += new_artifacts
|
155
|
+
end
|
156
|
+
|
157
|
+
#
|
158
|
+
# Normalizes platform and platform_version information that we receive.
|
159
|
+
# There are a few entries that we historically published
|
160
|
+
# that we need to normalize. They are:
|
161
|
+
# * solaris -> solaris2 & 10 -> 5.10 for solaris.
|
162
|
+
#
|
163
|
+
# @param [String] platform
|
164
|
+
# @param [String] platform_version
|
165
|
+
#
|
166
|
+
# @return Array<String> [platform, platform_version]
|
167
|
+
def normalize_platform(platform, platform_version)
|
168
|
+
if platform == "solaris"
|
169
|
+
platform = "solaris2"
|
170
|
+
|
171
|
+
# Here platform_version is set to either 10 or 11 and we would like
|
172
|
+
# to normalize that to 5.10 and 5.11.
|
173
|
+
platform_version = "5.#{platform_version}"
|
174
|
+
end
|
175
|
+
|
176
|
+
[platform, platform_version]
|
177
|
+
end
|
109
178
|
end
|
110
179
|
end
|
111
180
|
end
|
@@ -81,7 +81,7 @@ module Mixlib
|
|
81
81
|
# @return [String] latest version value
|
82
82
|
#
|
83
83
|
def latest_version
|
84
|
-
result = bintray_get("#{options.channel}/#{
|
84
|
+
result = bintray_get("#{options.channel}/#{bintray_product_name}/versions/_latest")
|
85
85
|
result["name"]
|
86
86
|
end
|
87
87
|
|
@@ -93,11 +93,11 @@ module Mixlib
|
|
93
93
|
def available_artifacts
|
94
94
|
version = options.latest_version? ? latest_version : options.product_version
|
95
95
|
begin
|
96
|
-
results = bintray_get("#{options.channel}/#{
|
96
|
+
results = bintray_get("#{options.channel}/#{bintray_product_name}/versions/#{version}/files")
|
97
97
|
rescue Net::HTTPServerException => e
|
98
98
|
if e.message =~ /404 "Not Found"/
|
99
99
|
raise VersionNotFound,
|
100
|
-
"Specified version (#{version}) not found for #{
|
100
|
+
"Specified version (#{version}) not found for #{bintray_product_name} in #{options.channel} channel."
|
101
101
|
else
|
102
102
|
raise
|
103
103
|
end
|
@@ -119,40 +119,6 @@ module Mixlib
|
|
119
119
|
windows_artifact_fixup!(results)
|
120
120
|
end
|
121
121
|
|
122
|
-
# On windows, if we do not have a native 64-bit package available
|
123
|
-
# in the discovered artifacts, we will make 32-bit artifacts available
|
124
|
-
# for 64-bit architecture.
|
125
|
-
def windows_artifact_fixup!(artifacts)
|
126
|
-
new_artifacts = [ ]
|
127
|
-
native_artifacts = [ ]
|
128
|
-
|
129
|
-
artifacts.each do |r|
|
130
|
-
next if r.platform != "windows"
|
131
|
-
|
132
|
-
# Store all native 64-bit artifacts and clone 32-bit artifacts to
|
133
|
-
# be used as 64-bit.
|
134
|
-
case r.architecture
|
135
|
-
when "i386"
|
136
|
-
new_artifacts << r.clone_with(architecture: "x86_64")
|
137
|
-
when "x86_64"
|
138
|
-
native_artifacts << r.clone
|
139
|
-
else
|
140
|
-
puts "Unknown architecture '#{r.architecture}' for windows."
|
141
|
-
end
|
142
|
-
end
|
143
|
-
|
144
|
-
# Now discard the cloned artifacts if we find an equivalent native
|
145
|
-
# artifact
|
146
|
-
native_artifacts.each do |r|
|
147
|
-
new_artifacts.delete_if do |x|
|
148
|
-
x.platform_version == r.platform_version
|
149
|
-
end
|
150
|
-
end
|
151
|
-
|
152
|
-
# add the remaining cloned artifacts to the original set
|
153
|
-
artifacts += new_artifacts
|
154
|
-
end
|
155
|
-
|
156
122
|
#
|
157
123
|
# Creates an instance of ArtifactInfo
|
158
124
|
#
|
@@ -238,29 +204,6 @@ module Mixlib
|
|
238
204
|
}
|
239
205
|
end
|
240
206
|
|
241
|
-
#
|
242
|
-
# Normalizes platform and platform_version information that we receive
|
243
|
-
# from bintray. There are a few entries that we historically published
|
244
|
-
# that we need to normalize. They are:
|
245
|
-
# * solaris -> solaris2 & 10 -> 5.10 for solaris.
|
246
|
-
#
|
247
|
-
# @param [String] platform
|
248
|
-
# @param [String] platform_version
|
249
|
-
#
|
250
|
-
# @return Array<String> [platform, platform_version]
|
251
|
-
def normalize_platform(platform, platform_version)
|
252
|
-
if platform == "solaris"
|
253
|
-
platform = "solaris2"
|
254
|
-
|
255
|
-
# Here platform_version is set to either 10 or 11 and we would like
|
256
|
-
# to normalize that to 5.10 and 5.11.
|
257
|
-
|
258
|
-
platform_version = "5.#{platform_version}"
|
259
|
-
end
|
260
|
-
|
261
|
-
[platform, platform_version]
|
262
|
-
end
|
263
|
-
|
264
207
|
#
|
265
208
|
# Determines the architecture for which a file is published from from
|
266
209
|
# filename.
|
@@ -290,6 +233,8 @@ module Mixlib
|
|
290
233
|
"powerpc"
|
291
234
|
elsif %w{ sparc sun4u sun4v }.fuzzy_include?(filename)
|
292
235
|
"sparc"
|
236
|
+
elsif %w{ s390x }.fuzzy_include?(filename)
|
237
|
+
"s390x"
|
293
238
|
# Note that ppc64le should come before ppc64 otherwise our search
|
294
239
|
# will think ppc64le matches ppc64. Ubuntu also calls it ppc64el.
|
295
240
|
elsif %w{ ppc64le ppc64el }.fuzzy_include?(filename)
|
@@ -332,6 +277,21 @@ module Mixlib
|
|
332
277
|
"architecture can not be determined for '#{filename}'"
|
333
278
|
end
|
334
279
|
end
|
280
|
+
|
281
|
+
private
|
282
|
+
|
283
|
+
#
|
284
|
+
# This is a temporary workaround until we move to the unified backend
|
285
|
+
# for all channels. Some products are published to Bintray using their
|
286
|
+
# Omnibus project name as opposed to their mixlib-install product key.
|
287
|
+
#
|
288
|
+
def bintray_product_name
|
289
|
+
if %w{automate}.include?(options.product_name)
|
290
|
+
PRODUCT_MATRIX.lookup(options.product_name).omnibus_project
|
291
|
+
else
|
292
|
+
options.product_name
|
293
|
+
end
|
294
|
+
end
|
335
295
|
end
|
336
296
|
end
|
337
297
|
end
|
@@ -46,7 +46,9 @@ module Mixlib
|
|
46
46
|
install_command << get_script("helpers.sh")
|
47
47
|
install_command << render_variables
|
48
48
|
install_command << get_script("platform_detection.sh")
|
49
|
-
|
49
|
+
# Since omnitruck can not resolve unstable we need to inject direct
|
50
|
+
# urls for the packages here.
|
51
|
+
if options.for_unstable?
|
50
52
|
install_command << artifactory_urls
|
51
53
|
else
|
52
54
|
install_command << get_script("fetch_metadata.sh")
|
@@ -96,6 +96,10 @@ elif test "x$os" = "xAIX"; then
|
|
96
96
|
platform="aix"
|
97
97
|
platform_version="`uname -v`.`uname -r`"
|
98
98
|
machine="powerpc"
|
99
|
+
elif test -f "/etc/Eos-release"; then
|
100
|
+
platform=arista_eos
|
101
|
+
platform_version=`awk '{print $4}' /etc/Eos-release`
|
102
|
+
machine="i386"
|
99
103
|
elif test -f "/etc/os-release"; then
|
100
104
|
. /etc/os-release
|
101
105
|
if test "x$CISCO_RELEASE_INFO" != "x"; then
|
@@ -46,7 +46,9 @@ module Mixlib
|
|
46
46
|
def install_command
|
47
47
|
install_project_module = []
|
48
48
|
install_project_module << get_script("helpers.ps1")
|
49
|
-
|
49
|
+
# Since omnitruck can not resolve unstable we need to inject direct
|
50
|
+
# urls for the packages here.
|
51
|
+
install_project_module << if options.for_unstable?
|
50
52
|
artifactory_urls
|
51
53
|
else
|
52
54
|
get_script("get_project_metadata.ps1")
|
@@ -73,7 +75,7 @@ module Mixlib
|
|
73
75
|
|
74
76
|
def artifactory_urls
|
75
77
|
get_script("get_project_metadata_for_artifactory.ps1",
|
76
|
-
artifacts: artifacts)
|
78
|
+
artifacts: Array(artifacts))
|
77
79
|
end
|
78
80
|
|
79
81
|
def artifacts
|
@@ -81,7 +83,7 @@ module Mixlib
|
|
81
83
|
end
|
82
84
|
|
83
85
|
def product_version
|
84
|
-
if options.
|
86
|
+
if options.for_unstable?
|
85
87
|
artifacts.first.version
|
86
88
|
else
|
87
89
|
options.product_version
|
@@ -1,16 +1,22 @@
|
|
1
1
|
function Get-PlatformVersion {
|
2
|
-
switch -regex ((
|
3
|
-
'10\.0\.\d+' {$platform_version = '
|
2
|
+
switch -regex ((Get-WMIQuery win32_operatingsystem).version) {
|
3
|
+
'10\.0\.\d+' {$platform_version = '2016'}
|
4
4
|
'6\.3\.\d+' {$platform_version = '2012r2'}
|
5
5
|
'6\.2\.\d+' {$platform_version = '2012'}
|
6
6
|
'6\.1\.\d+' {$platform_version = '2008r2'}
|
7
7
|
'6\.0\.\d+' {$platform_version = '2008'}
|
8
8
|
}
|
9
|
+
|
10
|
+
if(Test-Path 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Server\ServerLevels') {
|
11
|
+
$levels = Get-ItemProperty 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Server\ServerLevels'
|
12
|
+
if($levels.NanoServer -eq 1) { $platform_version += 'nano' }
|
13
|
+
}
|
14
|
+
|
9
15
|
return $platform_version
|
10
16
|
}
|
11
17
|
|
12
18
|
function Get-PlatformArchitecture {
|
13
|
-
if ((
|
19
|
+
if ((Get-WMIQuery win32_operatingsystem).osarchitecture -like '64-bit') {
|
14
20
|
$architecture = 'x86_64'
|
15
21
|
} else {
|
16
22
|
$architecture = 'i386'
|
@@ -22,7 +28,8 @@ function New-Uri {
|
|
22
28
|
param ($baseuri, $newuri)
|
23
29
|
|
24
30
|
try {
|
25
|
-
|
31
|
+
$base = new-object System.Uri $baseuri
|
32
|
+
new-object System.Uri $base, $newuri
|
26
33
|
}
|
27
34
|
catch [System.Management.Automation.MethodInvocationException]{
|
28
35
|
Write-Error "$($_.exception.message)"
|
@@ -32,17 +39,13 @@ function New-Uri {
|
|
32
39
|
|
33
40
|
function Get-WebContent {
|
34
41
|
param ($uri, $filepath)
|
35
|
-
$proxy = New-Object -TypeName System.Net.WebProxy
|
36
|
-
$wc = new-object System.Net.WebClient
|
37
|
-
$proxy.Address = $env:http_proxy
|
38
|
-
$wc.Proxy = $proxy
|
39
42
|
|
40
43
|
try {
|
41
|
-
if
|
42
|
-
$
|
44
|
+
if($PSVersionTable.PSEdition -eq 'Core') {
|
45
|
+
Get-WebContentOnCore $uri $filepath
|
43
46
|
}
|
44
47
|
else {
|
45
|
-
$
|
48
|
+
Get-WebContentOnFullNet $uri $filepath
|
46
49
|
}
|
47
50
|
}
|
48
51
|
catch {
|
@@ -56,17 +59,61 @@ function Get-WebContent {
|
|
56
59
|
}
|
57
60
|
}
|
58
61
|
|
62
|
+
function Get-WebContentOnFullNet {
|
63
|
+
param ($uri, $filepath)
|
64
|
+
|
65
|
+
$proxy = New-Object -TypeName System.Net.WebProxy
|
66
|
+
$wc = new-object System.Net.WebClient
|
67
|
+
$proxy.Address = $env:http_proxy
|
68
|
+
$wc.Proxy = $proxy
|
69
|
+
|
70
|
+
if ([string]::IsNullOrEmpty($filepath)) {
|
71
|
+
$wc.downloadstring($uri)
|
72
|
+
}
|
73
|
+
else {
|
74
|
+
$wc.downloadfile($uri, $filepath)
|
75
|
+
}
|
76
|
+
}
|
77
|
+
|
78
|
+
function Get-WebContentOnCore {
|
79
|
+
param ($uri, $filepath)
|
80
|
+
|
81
|
+
$handler = New-Object System.Net.Http.HttpClientHandler
|
82
|
+
$client = New-Object System.Net.Http.HttpClient($handler)
|
83
|
+
$client.Timeout = New-Object System.TimeSpan(0, 30, 0)
|
84
|
+
$cancelTokenSource = [System.Threading.CancellationTokenSource]::new()
|
85
|
+
$responseMsg = $client.GetAsync([System.Uri]::new($uri), $cancelTokenSource.Token)
|
86
|
+
$responseMsg.Wait()
|
87
|
+
if (!$responseMsg.IsCanceled) {
|
88
|
+
$response = $responseMsg.Result
|
89
|
+
if ($response.IsSuccessStatusCode) {
|
90
|
+
if ([string]::IsNullOrEmpty($filepath)) {
|
91
|
+
$response.Content.ReadAsStringAsync().Result
|
92
|
+
}
|
93
|
+
else {
|
94
|
+
$downloadedFileStream = [System.IO.FileStream]::new($filepath, [System.IO.FileMode]::Create, [System.IO.FileAccess]::Write)
|
95
|
+
$copyStreamOp = $response.Content.CopyToAsync($downloadedFileStream)
|
96
|
+
$copyStreamOp.Wait()
|
97
|
+
$downloadedFileStream.Close()
|
98
|
+
if ($copyStreamOp.Exception -ne $null) {
|
99
|
+
throw $copyStreamOp.Exception
|
100
|
+
}
|
101
|
+
}
|
102
|
+
}
|
103
|
+
}
|
104
|
+
}
|
105
|
+
|
59
106
|
function Test-ProjectPackage {
|
60
107
|
[cmdletbinding()]
|
61
108
|
param ($Path, $Algorithm = 'SHA256', $Hash)
|
62
109
|
|
63
|
-
if (-not (get-command get-filehash))
|
110
|
+
if (-not (get-command get-filehash -ErrorAction 'SilentlyContinue')) {
|
64
111
|
function disposable($o){($o -is [IDisposable]) -and (($o | get-member | foreach-object {$_.name}) -contains 'Dispose')}
|
65
112
|
function use($obj, [scriptblock]$sb){try {& $sb} catch [exception]{throw $_} finally {if (disposable $obj) {$obj.Dispose()}} }
|
66
113
|
function Get-FileHash ($Path, $Algorithm) {
|
67
114
|
$Path = (resolve-path $path).providerpath
|
68
115
|
$hash = @{Algorithm = $Algorithm; Path = $Path}
|
69
|
-
use ($c =
|
116
|
+
use ($c = Get-SHA256Converter) {
|
70
117
|
use ($in = (gi $path).OpenRead()) {
|
71
118
|
$hash.Hash = ([BitConverter]::ToString($c.ComputeHash($in))).Replace("-", "").ToUpper()
|
72
119
|
}
|
@@ -84,3 +131,23 @@ function Test-ProjectPackage {
|
|
84
131
|
}
|
85
132
|
return $Valid
|
86
133
|
}
|
134
|
+
|
135
|
+
function Get-SHA256Converter {
|
136
|
+
if($PSVersionTable.PSEdition -eq 'Core') {
|
137
|
+
[System.Security.Cryptography.SHA256]::Create()
|
138
|
+
}
|
139
|
+
else {
|
140
|
+
New-Object -TypeName Security.Cryptography.SHA256Managed
|
141
|
+
}
|
142
|
+
}
|
143
|
+
|
144
|
+
function Get-WMIQuery {
|
145
|
+
param ($class)
|
146
|
+
|
147
|
+
if(Get-Command -Name Get-CimInstance -ErrorAction SilentlyContinue) {
|
148
|
+
Get-CimInstance $class
|
149
|
+
}
|
150
|
+
else {
|
151
|
+
Get-WmiObject $class
|
152
|
+
}
|
153
|
+
}
|
@@ -83,14 +83,15 @@ function Install-Project {
|
|
83
83
|
$installingProject = $True
|
84
84
|
$installAttempts = 0
|
85
85
|
while ($installingProject) {
|
86
|
-
$
|
87
|
-
$
|
88
|
-
if
|
89
|
-
|
90
|
-
continue
|
91
|
-
} elseif ($p.ExitCode -ne 0) {
|
92
|
-
throw "msiexec was not successful. Received exit code $($p.ExitCode)"
|
86
|
+
$installAttempts++
|
87
|
+
$result = $false
|
88
|
+
if($download_destination.EndsWith(".appx")) {
|
89
|
+
$result = Install-ChefAppx $download_destination $project
|
93
90
|
}
|
91
|
+
else {
|
92
|
+
$result = Install-ChefMsi $download_destination
|
93
|
+
}
|
94
|
+
if(!$result) { continue }
|
94
95
|
$installingProject = $False
|
95
96
|
}
|
96
97
|
}
|
@@ -100,4 +101,39 @@ function Install-Project {
|
|
100
101
|
}
|
101
102
|
}
|
102
103
|
set-alias install -value Install-Project
|
104
|
+
|
105
|
+
Function Install-ChefMsi($msi) {
|
106
|
+
$p = Start-Process -FilePath "msiexec.exe" -ArgumentList "/qn /i $msi" -Passthru -Wait
|
107
|
+
$p.WaitForExit()
|
108
|
+
if ($p.ExitCode -eq 1618) {
|
109
|
+
Write-Host "Another msi install is in progress (exit code 1618), retrying ($($installAttempts))..."
|
110
|
+
return $false
|
111
|
+
} elseif ($p.ExitCode -ne 0) {
|
112
|
+
throw "msiexec was not successful. Received exit code $($p.ExitCode)"
|
113
|
+
}
|
114
|
+
return $true
|
115
|
+
}
|
116
|
+
|
117
|
+
Function Install-ChefAppx($appx, $project) {
|
118
|
+
Add-AppxPackage -Path $appx -ErrorAction Stop
|
119
|
+
$package = (Get-AppxPackage -Name $project).InstallLocation
|
120
|
+
$installRoot = "$env:SystemDrive/opscode"
|
121
|
+
$link = Join-Path $installRoot $project
|
122
|
+
|
123
|
+
# Remove link from a previous install
|
124
|
+
# There is currently a bug in removing symbolic links from Powershell
|
125
|
+
# so we use the fisher-price cmd shell to do it
|
126
|
+
if(Test-Path $link) {
|
127
|
+
cmd /c rmdir $link
|
128
|
+
}
|
129
|
+
|
130
|
+
if(!(Test-Path $installRoot)) {
|
131
|
+
New-Item -ItemType Directory -Path $installRoot
|
132
|
+
}
|
133
|
+
push-Location $installRoot
|
134
|
+
New-Item -ItemType SymbolicLink -Name $project -Target $package
|
135
|
+
Pop-Location
|
136
|
+
return $true
|
137
|
+
}
|
138
|
+
|
103
139
|
export-modulemember -function 'Install-Project','Get-ProjectMetadata' -alias 'install'
|
@@ -71,11 +71,11 @@ module Mixlib
|
|
71
71
|
end
|
72
72
|
|
73
73
|
def for_artifactory?
|
74
|
-
ARTIFACTORY_CHANNELS.include?(channel)
|
74
|
+
Mixlib::Install.unified_backend? || ARTIFACTORY_CHANNELS.include?(channel)
|
75
75
|
end
|
76
76
|
|
77
|
-
def
|
78
|
-
|
77
|
+
def for_unstable?
|
78
|
+
channel == :unstable
|
79
79
|
end
|
80
80
|
|
81
81
|
def for_omnitruck?
|
@@ -109,6 +109,7 @@ module Mixlib
|
|
109
109
|
{
|
110
110
|
shell_type: :sh,
|
111
111
|
platform_version_compatibility_mode: false,
|
112
|
+
product_version: :latest,
|
112
113
|
}
|
113
114
|
end
|
114
115
|
|
@@ -66,6 +66,33 @@ module Mixlib
|
|
66
66
|
end
|
67
67
|
end
|
68
68
|
|
69
|
+
#
|
70
|
+
# Set omnibus_project when configured, otherwise fall back to
|
71
|
+
# package_name
|
72
|
+
#
|
73
|
+
def omnibus_project(value = nil)
|
74
|
+
if value.nil?
|
75
|
+
@omnibus_project || package_name
|
76
|
+
else
|
77
|
+
@omnibus_project = value
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
#
|
82
|
+
# Return all known omnibus project names for a product
|
83
|
+
#
|
84
|
+
def known_omnibus_projects
|
85
|
+
# iterate through min/max versions for all product names
|
86
|
+
# and collect the name for both versions
|
87
|
+
projects = %w{ 0.0.0 1000.1000.1000 }.collect do |v|
|
88
|
+
@version = v
|
89
|
+
omnibus_project
|
90
|
+
end
|
91
|
+
# remove duplicates and return multiple known names or return the single
|
92
|
+
# project name
|
93
|
+
projects.uniq || projects
|
94
|
+
end
|
95
|
+
|
69
96
|
#
|
70
97
|
# Sets or retrieves the version for the product. This is used later
|
71
98
|
# when we are reading the value of a property if a Proc is specified
|
@@ -160,6 +187,13 @@ PRODUCT_MATRIX = Mixlib::Install::ProductMatrix.new do
|
|
160
187
|
package_name "angrychef"
|
161
188
|
end
|
162
189
|
|
190
|
+
product "automate" do
|
191
|
+
product_name "Chef Automate"
|
192
|
+
package_name "delivery"
|
193
|
+
ctl_command "delivery-ctl"
|
194
|
+
config_file "/etc/delivery/delivery.rb"
|
195
|
+
end
|
196
|
+
|
163
197
|
product "chef" do
|
164
198
|
product_name "Chef Client"
|
165
199
|
package_name "chef"
|
@@ -181,6 +215,7 @@ PRODUCT_MATRIX = Mixlib::Install::ProductMatrix.new do
|
|
181
215
|
"chef-server-core"
|
182
216
|
end
|
183
217
|
end
|
218
|
+
omnibus_project "chef-server"
|
184
219
|
ctl_command "chef-server-ctl"
|
185
220
|
config_file "/etc/opscode/chef-server.rb"
|
186
221
|
end
|
@@ -252,7 +287,7 @@ PRODUCT_MATRIX = Mixlib::Install::ProductMatrix.new do
|
|
252
287
|
end
|
253
288
|
|
254
289
|
product "push-jobs-client" do
|
255
|
-
product_name "Chef Push
|
290
|
+
product_name "Chef Push Client"
|
256
291
|
package_name do |v|
|
257
292
|
v < version_for("1.3.0") ? "opscode-push-jobs-client" : "push-jobs-client"
|
258
293
|
end
|
@@ -132,8 +132,7 @@ module Mixlib
|
|
132
132
|
def install_command_vars_for_powershell
|
133
133
|
[
|
134
134
|
shell_var("chef_omnibus_root", root),
|
135
|
-
|
136
|
-
].tap { |vars|
|
135
|
+
].tap do |vars|
|
137
136
|
if install_msi_url
|
138
137
|
vars << shell_var("chef_msi_url", install_msi_url)
|
139
138
|
else
|
@@ -141,7 +140,7 @@ module Mixlib
|
|
141
140
|
vars << shell_var("pretty_version", Util.pretty_version(version))
|
142
141
|
vars << shell_var("version", version)
|
143
142
|
end
|
144
|
-
|
143
|
+
end.join("\n")
|
145
144
|
end
|
146
145
|
|
147
146
|
def validate_opts!(opt)
|
data/mixlib-install.gemspec
CHANGED
@@ -25,6 +25,8 @@ Gem::Specification.new do |spec|
|
|
25
25
|
spec.add_development_dependency "rake", "~> 10.0"
|
26
26
|
spec.add_development_dependency "rspec", "~> 3.3"
|
27
27
|
spec.add_development_dependency "pry"
|
28
|
+
spec.add_development_dependency "rb-readline"
|
28
29
|
spec.add_development_dependency "vcr"
|
29
30
|
spec.add_development_dependency "webmock", "~> 1.0"
|
31
|
+
spec.add_development_dependency "chefstyle", "~> 0.3"
|
30
32
|
end
|
data/support/install_command.ps1
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
Function Check-UpdateChef($root, $version) {
|
2
|
-
if (-Not (Test-Path $root)) { return $true }
|
2
|
+
if (-Not (Test-Path "$root\embedded")) { return $true }
|
3
3
|
elseif ("$version" -eq "true") { return $false }
|
4
4
|
elseif ("$version" -eq "latest") { return $true }
|
5
5
|
|
@@ -14,8 +14,7 @@ Function Check-UpdateChef($root, $version) {
|
|
14
14
|
}
|
15
15
|
|
16
16
|
Function Get-ChefMetadata($url) {
|
17
|
-
|
18
|
-
Finally { if ($c -ne $null) { $c.Dispose() } }
|
17
|
+
$response = Get-WebContent $url
|
19
18
|
|
20
19
|
$md = ConvertFrom-StringData $response.Replace("`t", "=")
|
21
20
|
return @($md.url, $md.sha256)
|
@@ -23,52 +22,154 @@ Function Get-ChefMetadata($url) {
|
|
23
22
|
|
24
23
|
Function Get-SHA256($src) {
|
25
24
|
Try {
|
26
|
-
$c =
|
25
|
+
$c = Get-SHA256Converter
|
27
26
|
$bytes = $c.ComputeHash(($in = (Get-Item $src).OpenRead()))
|
28
27
|
return ([System.BitConverter]::ToString($bytes)).Replace("-", "").ToLower()
|
29
28
|
} Finally { if (($c -ne $null) -and ($c.GetType().GetMethod("Dispose") -ne $null)) { $c.Dispose() }; if ($in -ne $null) { $in.Dispose() } }
|
30
29
|
}
|
31
30
|
|
31
|
+
function Get-SHA256Converter {
|
32
|
+
if($PSVersionTable.PSEdition -eq 'Core') {
|
33
|
+
[System.Security.Cryptography.SHA256]::Create()
|
34
|
+
}
|
35
|
+
else {
|
36
|
+
New-Object -TypeName Security.Cryptography.SHA256Managed
|
37
|
+
}
|
38
|
+
}
|
39
|
+
|
32
40
|
Function Download-Chef($url, $sha256, $dst) {
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
Log "Download complete."
|
37
|
-
} Finally { if ($c -ne $null) { $c.Dispose() } }
|
41
|
+
Log "Downloading package from $url"
|
42
|
+
Get-WebContent $url $dst
|
43
|
+
Log "Download complete."
|
38
44
|
|
39
45
|
if ($sha256 -eq $null) { Log "Skipping sha256 verification" }
|
40
46
|
elseif (($dsha256 = Get-SHA256 $dst) -eq $sha256) { Log "Successfully verified $dst" }
|
41
47
|
else { throw "SHA256 for $dst $dsha256 does not match $sha256" }
|
42
48
|
}
|
43
49
|
|
44
|
-
Function Install-Chef($msi) {
|
50
|
+
Function Install-Chef($msi, $chef_omnibus_root) {
|
45
51
|
Log "Installing Chef Omnibus package $msi"
|
46
52
|
$installingChef = $True
|
47
53
|
$installAttempts = 0
|
48
54
|
while ($installingChef) {
|
49
55
|
$installAttempts++
|
50
|
-
$
|
51
|
-
$
|
52
|
-
|
53
|
-
Log "Another msi install is in progress (exit code 1618), retrying ($($installAttempts))..."
|
54
|
-
continue
|
55
|
-
} elseif ($p.ExitCode -ne 0) {
|
56
|
-
throw "msiexec was not successful. Received exit code $($p.ExitCode)"
|
56
|
+
$result = $false
|
57
|
+
if($msi.EndsWith(".appx")) {
|
58
|
+
$result = Install-ChefAppx $msi $chef_omnibus_root
|
57
59
|
}
|
60
|
+
else {
|
61
|
+
$result = Install-ChefMsi $msi
|
62
|
+
}
|
63
|
+
if(!$result) { continue }
|
58
64
|
$installingChef = $False
|
59
65
|
}
|
60
66
|
Remove-Item $msi -Force
|
61
67
|
Log "Installation complete"
|
62
68
|
}
|
63
69
|
|
70
|
+
Function Install-ChefMsi($msi) {
|
71
|
+
$p = Start-Process -FilePath "msiexec.exe" -ArgumentList "/qn /i $msi" -Passthru -Wait
|
72
|
+
$p.WaitForExit()
|
73
|
+
if ($p.ExitCode -eq 1618) {
|
74
|
+
Log "Another msi install is in progress (exit code 1618), retrying ($($installAttempts))..."
|
75
|
+
return $false
|
76
|
+
} elseif ($p.ExitCode -ne 0) {
|
77
|
+
throw "msiexec was not successful. Received exit code $($p.ExitCode)"
|
78
|
+
}
|
79
|
+
return $true
|
80
|
+
}
|
81
|
+
|
82
|
+
Function Install-ChefAppx($appx, $chef_omnibus_root) {
|
83
|
+
Add-AppxPackage -Path $appx -ErrorAction Stop
|
84
|
+
|
85
|
+
$rootParent = Split-Path $chef_omnibus_root -Parent
|
86
|
+
$rootFolder = Split-Path $chef_omnibus_root -Leaf
|
87
|
+
$link = Join-Path $rootParent $rootFolder
|
88
|
+
|
89
|
+
# Remove link from a previous install
|
90
|
+
# There is currently a bug in removing symbolic links from Powershell
|
91
|
+
# so we use the fisher-price cmd shell to do it
|
92
|
+
if(Test-Path $link) {
|
93
|
+
cmd /c rmdir $link
|
94
|
+
}
|
95
|
+
|
96
|
+
$package = (Get-AppxPackage -Name chef).InstallLocation
|
97
|
+
if(!(Test-Path $rootParent)) {
|
98
|
+
New-Item -ItemType Directory -Path $rootParent
|
99
|
+
}
|
100
|
+
push-Location $rootParent
|
101
|
+
New-Item -ItemType SymbolicLink -Name $rootFolder -Target $package
|
102
|
+
Pop-Location
|
103
|
+
|
104
|
+
return $true
|
105
|
+
}
|
106
|
+
|
64
107
|
Function Log($m) { Write-Host " $m`n" }
|
65
108
|
|
66
|
-
|
109
|
+
function Get-WebContent {
|
110
|
+
param ($uri, $filepath)
|
111
|
+
|
112
|
+
try {
|
113
|
+
if($PSVersionTable.PSEdition -eq 'Core') {
|
114
|
+
Get-WebContentOnCore $uri $filepath
|
115
|
+
}
|
116
|
+
else {
|
117
|
+
Get-WebContentOnFullNet $uri $filepath
|
118
|
+
}
|
119
|
+
}
|
120
|
+
catch {
|
121
|
+
$exception = $_.Exception
|
122
|
+
Write-Host "There was an error: "
|
123
|
+
do {
|
124
|
+
Write-Host "`t$($exception.message)"
|
125
|
+
$exception = $exception.innerexception
|
126
|
+
} while ($exception)
|
127
|
+
throw "Failed to download from $uri."
|
128
|
+
}
|
129
|
+
}
|
130
|
+
|
131
|
+
function Get-WebContentOnFullNet {
|
132
|
+
param ($uri, $filepath)
|
133
|
+
|
67
134
|
$proxy = New-Object -TypeName System.Net.WebProxy
|
135
|
+
$wc = new-object System.Net.WebClient
|
68
136
|
$proxy.Address = $env:http_proxy
|
69
|
-
$
|
70
|
-
|
71
|
-
|
137
|
+
$wc.Proxy = $proxy
|
138
|
+
|
139
|
+
if ([string]::IsNullOrEmpty($filepath)) {
|
140
|
+
$wc.downloadstring($uri)
|
141
|
+
}
|
142
|
+
else {
|
143
|
+
$wc.downloadfile($uri, $filepath)
|
144
|
+
}
|
145
|
+
}
|
146
|
+
|
147
|
+
function Get-WebContentOnCore {
|
148
|
+
param ($uri, $filepath)
|
149
|
+
|
150
|
+
$handler = New-Object System.Net.Http.HttpClientHandler
|
151
|
+
$client = New-Object System.Net.Http.HttpClient($handler)
|
152
|
+
$client.Timeout = New-Object System.TimeSpan(0, 30, 0)
|
153
|
+
$cancelTokenSource = [System.Threading.CancellationTokenSource]::new()
|
154
|
+
$responseMsg = $client.GetAsync([System.Uri]::new($uri), $cancelTokenSource.Token)
|
155
|
+
$responseMsg.Wait()
|
156
|
+
if (!$responseMsg.IsCanceled) {
|
157
|
+
$response = $responseMsg.Result
|
158
|
+
if ($response.IsSuccessStatusCode) {
|
159
|
+
if ([string]::IsNullOrEmpty($filepath)) {
|
160
|
+
$response.Content.ReadAsStringAsync().Result
|
161
|
+
}
|
162
|
+
else {
|
163
|
+
$downloadedFileStream = [System.IO.FileStream]::new($filepath, [System.IO.FileMode]::Create, [System.IO.FileAccess]::Write)
|
164
|
+
$copyStreamOp = $response.Content.CopyToAsync($downloadedFileStream)
|
165
|
+
$copyStreamOp.Wait()
|
166
|
+
$downloadedFileStream.Close()
|
167
|
+
if ($copyStreamOp.Exception -ne $null) {
|
168
|
+
throw $copyStreamOp.Exception
|
169
|
+
}
|
170
|
+
}
|
171
|
+
}
|
172
|
+
}
|
72
173
|
}
|
73
174
|
|
74
175
|
Function Unresolve-Path($p) {
|
@@ -77,7 +178,6 @@ Function Unresolve-Path($p) {
|
|
77
178
|
}
|
78
179
|
|
79
180
|
$chef_omnibus_root = Unresolve-Path $chef_omnibus_root
|
80
|
-
$msi = Unresolve-Path $msi
|
81
181
|
|
82
182
|
if (Check-UpdateChef $chef_omnibus_root $version) {
|
83
183
|
Write-Host "-----> Installing Chef Omnibus ($pretty_version)`n"
|
@@ -87,8 +187,10 @@ if (Check-UpdateChef $chef_omnibus_root $version) {
|
|
87
187
|
$url = $chef_msi_url
|
88
188
|
$sha256 = $null
|
89
189
|
}
|
190
|
+
$msi = Join-Path $env:temp "$url".Split("/")[-1]
|
191
|
+
$msi = Unresolve-Path $msi
|
90
192
|
Download-Chef "$url" $sha256 $msi
|
91
|
-
Install-Chef $msi
|
193
|
+
Install-Chef $msi $chef_omnibus_root
|
92
194
|
} else {
|
93
195
|
Write-Host "-----> Chef Omnibus installation detected ($pretty_version)`n"
|
94
196
|
}
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mixlib-install
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Thom May
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2016-
|
12
|
+
date: 2016-09-15 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: artifactory
|
@@ -109,6 +109,20 @@ dependencies:
|
|
109
109
|
- - ">="
|
110
110
|
- !ruby/object:Gem::Version
|
111
111
|
version: '0'
|
112
|
+
- !ruby/object:Gem::Dependency
|
113
|
+
name: rb-readline
|
114
|
+
requirement: !ruby/object:Gem::Requirement
|
115
|
+
requirements:
|
116
|
+
- - ">="
|
117
|
+
- !ruby/object:Gem::Version
|
118
|
+
version: '0'
|
119
|
+
type: :development
|
120
|
+
prerelease: false
|
121
|
+
version_requirements: !ruby/object:Gem::Requirement
|
122
|
+
requirements:
|
123
|
+
- - ">="
|
124
|
+
- !ruby/object:Gem::Version
|
125
|
+
version: '0'
|
112
126
|
- !ruby/object:Gem::Dependency
|
113
127
|
name: vcr
|
114
128
|
requirement: !ruby/object:Gem::Requirement
|
@@ -137,6 +151,20 @@ dependencies:
|
|
137
151
|
- - "~>"
|
138
152
|
- !ruby/object:Gem::Version
|
139
153
|
version: '1.0'
|
154
|
+
- !ruby/object:Gem::Dependency
|
155
|
+
name: chefstyle
|
156
|
+
requirement: !ruby/object:Gem::Requirement
|
157
|
+
requirements:
|
158
|
+
- - "~>"
|
159
|
+
- !ruby/object:Gem::Version
|
160
|
+
version: '0.3'
|
161
|
+
type: :development
|
162
|
+
prerelease: false
|
163
|
+
version_requirements: !ruby/object:Gem::Requirement
|
164
|
+
requirements:
|
165
|
+
- - "~>"
|
166
|
+
- !ruby/object:Gem::Version
|
167
|
+
version: '0.3'
|
140
168
|
description:
|
141
169
|
email:
|
142
170
|
- thom@chef.io
|
@@ -147,7 +175,6 @@ extra_rdoc_files: []
|
|
147
175
|
files:
|
148
176
|
- ".gitignore"
|
149
177
|
- ".rspec"
|
150
|
-
- ".rubocop.yml"
|
151
178
|
- ".travis.yml"
|
152
179
|
- CHANGELOG.md
|
153
180
|
- CONTRIBUTING.md
|
@@ -222,7 +249,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
222
249
|
version: '0'
|
223
250
|
requirements: []
|
224
251
|
rubyforge_project:
|
225
|
-
rubygems_version: 2.
|
252
|
+
rubygems_version: 2.6.6
|
226
253
|
signing_key:
|
227
254
|
specification_version: 4
|
228
255
|
summary: A mixin to help with omnitruck installs
|