mixlib-install 0.7.1 → 0.8.0.alpha.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +3 -0
- data/CONTRIBUTING.md +14 -0
- data/Gemfile +1 -0
- data/README.md +30 -21
- data/Rakefile +5 -1
- data/acceptance/.gitignore +2 -0
- data/acceptance/Gemfile +10 -0
- data/acceptance/Gemfile.lock +57 -0
- data/acceptance/current/.acceptance/acceptance-cookbook/.chef/config.rb +1 -0
- data/acceptance/current/.acceptance/acceptance-cookbook/metadata.rb +1 -0
- data/acceptance/current/.acceptance/acceptance-cookbook/recipes/destroy.rb +3 -0
- data/acceptance/current/.acceptance/acceptance-cookbook/recipes/provision.rb +1 -0
- data/acceptance/current/.acceptance/acceptance-cookbook/recipes/verify.rb +3 -0
- data/acceptance/current/.kitchen.yml +45 -0
- data/lib/mixlib/install.rb +50 -173
- data/lib/mixlib/install/artifact_info.rb +76 -0
- data/lib/mixlib/install/backend.rb +36 -0
- data/lib/mixlib/install/backend/artifactory.rb +90 -0
- data/lib/mixlib/install/backend/omnitruck.rb +76 -0
- data/lib/mixlib/install/generator.rb +28 -0
- data/lib/mixlib/install/generator/bourne.rb +62 -0
- data/lib/mixlib/install/generator/bourne/scripts/fetch_metadata.sh +47 -0
- data/lib/mixlib/install/generator/bourne/scripts/fetch_package.sh +53 -0
- data/lib/mixlib/install/generator/bourne/scripts/helpers.sh +335 -0
- data/lib/mixlib/install/generator/bourne/scripts/install_package.sh +33 -0
- data/lib/mixlib/install/generator/bourne/scripts/platform_detection.sh +157 -0
- data/lib/mixlib/install/options.rb +98 -0
- data/lib/mixlib/install/script_generator.rb +217 -0
- data/lib/mixlib/install/version.rb +1 -1
- data/mixlib-install.gemspec +5 -3
- data/support/install_command.ps1 +4 -4
- metadata +71 -5
@@ -0,0 +1,76 @@
|
|
1
|
+
#
|
2
|
+
# Author:: Patrick Wright (<patrick@chef.io>)
|
3
|
+
# Copyright:: Copyright (c) 2015 Chef, Inc.
|
4
|
+
# License:: Apache License, Version 2.0
|
5
|
+
#
|
6
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
7
|
+
# you may not use this file except in compliance with the License.
|
8
|
+
# You may obtain a copy of the License at
|
9
|
+
#
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
11
|
+
#
|
12
|
+
# Unless required by applicable law or agreed to in writing, software
|
13
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
14
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
15
|
+
# See the License for the specific language governing permissions and
|
16
|
+
# limitations under the License.
|
17
|
+
#
|
18
|
+
|
19
|
+
module Mixlib
|
20
|
+
class Install
|
21
|
+
class ArtifactInfo
|
22
|
+
attr_accessor :url
|
23
|
+
attr_accessor :md5
|
24
|
+
attr_accessor :sha256
|
25
|
+
attr_accessor :version
|
26
|
+
|
27
|
+
attr_accessor :platform
|
28
|
+
attr_accessor :platform_version
|
29
|
+
attr_accessor :architecture
|
30
|
+
|
31
|
+
def initialize(data)
|
32
|
+
@url = data[:url]
|
33
|
+
@md5 = data[:md5]
|
34
|
+
@sha256 = data[:sha256]
|
35
|
+
@version = data[:version]
|
36
|
+
@platform = data[:platform]
|
37
|
+
@platform_version = data[:platform_version]
|
38
|
+
@architecture = data[:architecture]
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.from_json(json, platform_info)
|
42
|
+
ArtifactInfo.new(JSON.parse(json, symbolize_names: true).merge(platform_info))
|
43
|
+
end
|
44
|
+
|
45
|
+
def self.from_metadata_map(json)
|
46
|
+
artifacts = []
|
47
|
+
|
48
|
+
JSON.parse(json, symbolize_names: true).each do |p, p_data|
|
49
|
+
p_data.each do |pv, pv_data|
|
50
|
+
pv_data.each do |m, metadata|
|
51
|
+
artifacts << ArtifactInfo.new(metadata.merge(
|
52
|
+
platform: p,
|
53
|
+
platform_version: pv,
|
54
|
+
architecture: m
|
55
|
+
))
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
artifacts
|
61
|
+
end
|
62
|
+
|
63
|
+
def to_hash
|
64
|
+
{
|
65
|
+
url: url,
|
66
|
+
md5: md5,
|
67
|
+
sha256: sha256,
|
68
|
+
version: version,
|
69
|
+
platform: platform,
|
70
|
+
platform_version: platform_version,
|
71
|
+
architecture: architecture
|
72
|
+
}
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
#
|
2
|
+
# Author:: Patrick Wright (<patrick@chef.io>)
|
3
|
+
# Copyright:: Copyright (c) 2015 Chef, Inc.
|
4
|
+
# License:: Apache License, Version 2.0
|
5
|
+
#
|
6
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
7
|
+
# you may not use this file except in compliance with the License.
|
8
|
+
# You may obtain a copy of the License at
|
9
|
+
#
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
11
|
+
#
|
12
|
+
# Unless required by applicable law or agreed to in writing, software
|
13
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
14
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
15
|
+
# See the License for the specific language governing permissions and
|
16
|
+
# limitations under the License.
|
17
|
+
#
|
18
|
+
|
19
|
+
require "mixlib/install/backend/omnitruck"
|
20
|
+
require "mixlib/install/backend/artifactory"
|
21
|
+
|
22
|
+
module Mixlib
|
23
|
+
class Install
|
24
|
+
class Backend
|
25
|
+
def self.info(options)
|
26
|
+
backend = if options.for_omnitruck?
|
27
|
+
Backend::Omnitruck.new(options)
|
28
|
+
elsif options.for_artifactory?
|
29
|
+
Backend::Artifactory.new(options)
|
30
|
+
end
|
31
|
+
|
32
|
+
backend.info
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
#
|
2
|
+
# Author:: Patrick Wright (<patrick@chef.io>)
|
3
|
+
# Copyright:: Copyright (c) 2015 Chef, Inc.
|
4
|
+
# License:: Apache License, Version 2.0
|
5
|
+
#
|
6
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
7
|
+
# you may not use this file except in compliance with the License.
|
8
|
+
# You may obtain a copy of the License at
|
9
|
+
#
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
11
|
+
#
|
12
|
+
# Unless required by applicable law or agreed to in writing, software
|
13
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
14
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
15
|
+
# See the License for the specific language governing permissions and
|
16
|
+
# limitations under the License.
|
17
|
+
#
|
18
|
+
|
19
|
+
require "net/http"
|
20
|
+
require "json"
|
21
|
+
require "mixlib/install/artifact_info"
|
22
|
+
require "artifactory"
|
23
|
+
|
24
|
+
module Mixlib
|
25
|
+
class Install
|
26
|
+
class Backend
|
27
|
+
class Artifactory
|
28
|
+
ARTIFACTORY_ENDPOINT = "http://artifactory.chef.co".freeze
|
29
|
+
|
30
|
+
attr_reader :options
|
31
|
+
attr_reader :client
|
32
|
+
|
33
|
+
def initialize(options)
|
34
|
+
@options = options
|
35
|
+
@client = ::Artifactory::Client.new(endpoint: ARTIFACTORY_ENDPOINT)
|
36
|
+
end
|
37
|
+
|
38
|
+
def info
|
39
|
+
begin
|
40
|
+
results = client.get("/api/search/prop", params, headers)["results"]
|
41
|
+
rescue Errno::ETIMEDOUT => e
|
42
|
+
raise e, "unstable channel uses endpoint #{ARTIFACTORY_ENDPOINT} \
|
43
|
+
which is currently only accessible through Chef's internal network."
|
44
|
+
end
|
45
|
+
|
46
|
+
if options.platform
|
47
|
+
artifact(results.first)
|
48
|
+
else
|
49
|
+
results.collect do |result|
|
50
|
+
artifact(result)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
private
|
56
|
+
|
57
|
+
def artifact(result)
|
58
|
+
ArtifactInfo.new(
|
59
|
+
md5: result["properties"]["omnibus.md5"].first,
|
60
|
+
sha256: result["properties"]["omnibus.sha256"].first,
|
61
|
+
version: result["properties"]["omnibus.version"].first,
|
62
|
+
platform: result["properties"]["omnibus.platform"].first,
|
63
|
+
platform_version: result["properties"]["omnibus.platform_version"].first,
|
64
|
+
architecture: result["properties"]["omnibus.architecture"].first,
|
65
|
+
url: result["uri"]
|
66
|
+
)
|
67
|
+
end
|
68
|
+
|
69
|
+
def params
|
70
|
+
params = {
|
71
|
+
"repos" => "omnibus-current-local",
|
72
|
+
"omnibus.version" => options.product_version
|
73
|
+
}
|
74
|
+
|
75
|
+
if options.platform
|
76
|
+
params["omnibus.platform"] = options.platform
|
77
|
+
params["omnibus.platform_version"] = options.platform_version
|
78
|
+
params["omnibus.architecture"] = options.architecture
|
79
|
+
end
|
80
|
+
|
81
|
+
params
|
82
|
+
end
|
83
|
+
|
84
|
+
def headers
|
85
|
+
{ "X-Result-Detail" => "properties" }
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
#
|
2
|
+
# Author:: Patrick Wright (<patrick@chef.io>)
|
3
|
+
# Copyright:: Copyright (c) 2015 Chef, Inc.
|
4
|
+
# License:: Apache License, Version 2.0
|
5
|
+
#
|
6
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
7
|
+
# you may not use this file except in compliance with the License.
|
8
|
+
# You may obtain a copy of the License at
|
9
|
+
#
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
11
|
+
#
|
12
|
+
# Unless required by applicable law or agreed to in writing, software
|
13
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
14
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
15
|
+
# See the License for the specific language governing permissions and
|
16
|
+
# limitations under the License.
|
17
|
+
#
|
18
|
+
|
19
|
+
require "net/http"
|
20
|
+
require "json"
|
21
|
+
require "mixlib/install/artifact_info"
|
22
|
+
|
23
|
+
module Mixlib
|
24
|
+
class Install
|
25
|
+
class Backend
|
26
|
+
class Omnitruck
|
27
|
+
OMNITRUCK_ENDPOINT = "https://omnitruck.chef.io"
|
28
|
+
|
29
|
+
attr_accessor :options
|
30
|
+
|
31
|
+
def initialize(options)
|
32
|
+
@options = options
|
33
|
+
end
|
34
|
+
|
35
|
+
def info
|
36
|
+
# If we are querying a single platform we need to call metadata
|
37
|
+
# endpoint otherwise we need to call versions endpoint in omnitruck
|
38
|
+
if options.platform
|
39
|
+
build = omnitruck_get("metadata", p: options.platform,
|
40
|
+
pv: options.platform_version,
|
41
|
+
m: options.architecture,
|
42
|
+
v: options.product_version
|
43
|
+
)
|
44
|
+
ArtifactInfo.from_json(build,
|
45
|
+
platform: options.platform,
|
46
|
+
platform_version: options.platform_version,
|
47
|
+
architecture: options.architecture
|
48
|
+
)
|
49
|
+
else
|
50
|
+
builds = omnitruck_get("versions", v: options.product_version)
|
51
|
+
ArtifactInfo.from_metadata_map(builds)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
private
|
56
|
+
|
57
|
+
def omnitruck_get(resource, parameters)
|
58
|
+
uri = URI.parse(OMNITRUCK_ENDPOINT)
|
59
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
60
|
+
http.use_ssl = (uri.scheme == "https")
|
61
|
+
|
62
|
+
path = "/#{options.channel}/#{options.product_name}/#{resource}"
|
63
|
+
full_path = [path, URI.encode_www_form(parameters)].join("?")
|
64
|
+
request = Net::HTTP::Get.new(full_path)
|
65
|
+
request["Accept"] = "application/json"
|
66
|
+
|
67
|
+
res = http.request(request)
|
68
|
+
|
69
|
+
# Raise if response is not 2XX
|
70
|
+
res.value
|
71
|
+
res.body
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
#
|
2
|
+
# Copyright:: Copyright (c) 2015 Chef, Inc.
|
3
|
+
# License:: Apache License, Version 2.0
|
4
|
+
#
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
# you may not use this file except in compliance with the License.
|
7
|
+
# You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
# See the License for the specific language governing permissions and
|
15
|
+
# limitations under the License.
|
16
|
+
#
|
17
|
+
|
18
|
+
require "mixlib/install/generator/bourne"
|
19
|
+
|
20
|
+
module Mixlib
|
21
|
+
class Install
|
22
|
+
class Generator
|
23
|
+
def self.install_command(options)
|
24
|
+
Bourne.new(options).install_command
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
#
|
2
|
+
# Copyright:: Copyright (c) 2015 Chef, Inc.
|
3
|
+
# License:: Apache License, Version 2.0
|
4
|
+
#
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
# you may not use this file except in compliance with the License.
|
7
|
+
# You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
# See the License for the specific language governing permissions and
|
15
|
+
# limitations under the License.
|
16
|
+
#
|
17
|
+
|
18
|
+
module Mixlib
|
19
|
+
class Install
|
20
|
+
class Generator
|
21
|
+
class Bourne
|
22
|
+
attr_reader :options
|
23
|
+
|
24
|
+
def initialize(options)
|
25
|
+
@options = options
|
26
|
+
end
|
27
|
+
|
28
|
+
def install_command
|
29
|
+
install_command = []
|
30
|
+
install_command << get_script(:helpers)
|
31
|
+
install_command << render_variables
|
32
|
+
install_command << get_script(:platform_detection)
|
33
|
+
if options.for_artifactory?
|
34
|
+
install_command << artifactory_urls
|
35
|
+
else
|
36
|
+
install_command << get_script(:fetch_metadata)
|
37
|
+
end
|
38
|
+
install_command << get_script(:fetch_package)
|
39
|
+
install_command << get_script(:install_package)
|
40
|
+
|
41
|
+
install_command.join("\n\n")
|
42
|
+
end
|
43
|
+
|
44
|
+
def render_variables
|
45
|
+
<<EOS
|
46
|
+
project=#{options.product_name}
|
47
|
+
version=#{options.product_version}
|
48
|
+
channel=#{options.channel}
|
49
|
+
EOS
|
50
|
+
end
|
51
|
+
|
52
|
+
def artifactory_urls
|
53
|
+
raise "not implemented yet"
|
54
|
+
end
|
55
|
+
|
56
|
+
def get_script(name)
|
57
|
+
File.read(File.join(File.dirname(__FILE__), "bourne/scripts/#{name}.sh"))
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# fetch_metadata.sh
|
2
|
+
############
|
3
|
+
# This section calls omnitruck to get the information about the build to be
|
4
|
+
# installed.
|
5
|
+
#
|
6
|
+
# Inputs:
|
7
|
+
# $channel:
|
8
|
+
# $project:
|
9
|
+
# $version:
|
10
|
+
# $platform:
|
11
|
+
# $platform_version:
|
12
|
+
# $machine:
|
13
|
+
# $tmp_dir:
|
14
|
+
#
|
15
|
+
# Outputs:
|
16
|
+
# $download_url:
|
17
|
+
# $sha256:
|
18
|
+
# $md5:
|
19
|
+
############
|
20
|
+
|
21
|
+
echo "Getting information for $project $channel $version for $platform..."
|
22
|
+
|
23
|
+
metadata_filename="$tmp_dir/metadata.txt"
|
24
|
+
metadata_url="https://omnitruck.chef.io/$channel/$project/metadata?v=$version&p=$platform&pv=$platform_version&m=$machine"
|
25
|
+
|
26
|
+
do_download "$metadata_url" "$metadata_filename"
|
27
|
+
|
28
|
+
cat "$metadata_filename"
|
29
|
+
|
30
|
+
# check that all the mandatory fields in the downloaded metadata are there
|
31
|
+
if grep '^url' $metadata_filename > /dev/null && grep '^sha256' $metadata_filename > /dev/null && grep '^md5' $metadata_filename > /dev/null; then
|
32
|
+
echo "downloaded metadata file looks valid..."
|
33
|
+
else
|
34
|
+
echo "downloaded metadata file is corrupted or an uncaught error was encountered in downloading the file..."
|
35
|
+
# this generally means one of the download methods downloaded a 404 or something like that and then reported a successful exit code,
|
36
|
+
# and this should be fixed in the function that was doing the download.
|
37
|
+
report_bug
|
38
|
+
exit 1
|
39
|
+
fi
|
40
|
+
|
41
|
+
download_url=`awk '$1 == "url" { print $2 }' "$metadata_filename"`
|
42
|
+
sha256=`awk '$1 == "sha256" { print $2 }' "$metadata_filename"`
|
43
|
+
md5=`awk '$1 == "md5" { print $2 }' "$metadata_filename"`
|
44
|
+
|
45
|
+
############
|
46
|
+
# end of fetch_metadata.sh
|
47
|
+
############
|
@@ -0,0 +1,53 @@
|
|
1
|
+
# fetch_package.sh
|
2
|
+
############
|
3
|
+
# This section fetchs a package from $download_url and verifies its metadata.
|
4
|
+
#
|
5
|
+
# Inputs:
|
6
|
+
# $download_url:
|
7
|
+
# $tmp_dir:
|
8
|
+
# Optional Inputs:
|
9
|
+
# $cmdline_filename: Name of the package downloaded on local disk.
|
10
|
+
# $cmdline_dl_dir: Name of the directory downloaded package will be saved to on local disk.
|
11
|
+
#
|
12
|
+
# Outputs:
|
13
|
+
# $download_filename: Name of the downloaded file on local disk.
|
14
|
+
# $filetype: Type of the file downloaded.
|
15
|
+
############
|
16
|
+
|
17
|
+
filename=`echo $download_url | sed -e 's/^.*\///'`
|
18
|
+
filetype=`echo $filename | sed -e 's/^.*\.//'`
|
19
|
+
|
20
|
+
# use either $tmp_dir, the provided directory (-d) or the provided filename (-f)
|
21
|
+
if test "x$cmdline_filename" != "x"; then
|
22
|
+
download_filename="$cmdline_filename"
|
23
|
+
elif test "x$cmdline_dl_dir" != "x"; then
|
24
|
+
download_filename="$cmdline_dl_dir/$filename"
|
25
|
+
else
|
26
|
+
download_filename="$tmp_dir/$filename"
|
27
|
+
fi
|
28
|
+
|
29
|
+
# ensure the parent directory where to download the installer always exists
|
30
|
+
download_dir=`dirname $download_filename`
|
31
|
+
(umask 077 && mkdir -p $download_dir) || exit 1
|
32
|
+
|
33
|
+
# check if we have that file locally available and if so verify the checksum
|
34
|
+
cached_file_available="false"
|
35
|
+
if test -f $download_filename; then
|
36
|
+
echo "$download_filename already exists, verifiying checksum..."
|
37
|
+
if do_checksum "$download_filename" "$sha256" "$md5"; then
|
38
|
+
echo "checksum compare succeeded, using existing file!"
|
39
|
+
cached_file_available="true"
|
40
|
+
else
|
41
|
+
echo "checksum mismatch, downloading latest version of the file"
|
42
|
+
fi
|
43
|
+
fi
|
44
|
+
|
45
|
+
# download if no local version of the file available
|
46
|
+
if test "x$cached_file_available" != "xtrue"; then
|
47
|
+
do_download "$download_url" "$download_filename"
|
48
|
+
do_checksum "$download_filename" "$sha256" "$md5" || checksum_mismatch
|
49
|
+
fi
|
50
|
+
|
51
|
+
############
|
52
|
+
# end of fetch_package.sh
|
53
|
+
############
|