mixlib-install 0.8.0.alpha.2 → 0.8.0.alpha.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (32) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +9 -2
  3. data/Rakefile +5 -0
  4. data/acceptance/Gemfile +3 -1
  5. data/acceptance/Gemfile.lock +37 -5
  6. data/acceptance/current/.acceptance/acceptance-cookbook/recipes/provision.rb +3 -1
  7. data/acceptance/current/.kitchen.yml +18 -23
  8. data/acceptance/unstable/.acceptance/acceptance-cookbook/.gitignore +2 -0
  9. data/acceptance/unstable/.acceptance/acceptance-cookbook/metadata.rb +1 -0
  10. data/acceptance/unstable/.acceptance/acceptance-cookbook/recipes/destroy.rb +3 -0
  11. data/acceptance/unstable/.acceptance/acceptance-cookbook/recipes/provision.rb +3 -0
  12. data/acceptance/unstable/.acceptance/acceptance-cookbook/recipes/verify.rb +3 -0
  13. data/acceptance/unstable/.kitchen.yml +40 -0
  14. data/lib/mixlib/install.rb +35 -3
  15. data/lib/mixlib/install/backend/artifactory.rb +108 -34
  16. data/lib/mixlib/install/backend/omnitruck.rb +2 -2
  17. data/lib/mixlib/install/generator.rb +6 -1
  18. data/lib/mixlib/install/generator/base.rb +65 -0
  19. data/lib/mixlib/install/generator/bourne.rb +23 -14
  20. data/lib/mixlib/install/generator/bourne/scripts/artifactory_urls.sh.erb +31 -0
  21. data/lib/mixlib/install/generator/bourne/scripts/{fetch_metadata.sh → fetch_metadata.sh.erb} +1 -1
  22. data/lib/mixlib/install/generator/bourne/scripts/helpers.sh +7 -2
  23. data/lib/mixlib/install/generator/bourne/scripts/platform_detection.sh +8 -0
  24. data/lib/mixlib/install/generator/bourne/scripts/script_cli_parameters.sh +36 -0
  25. data/lib/mixlib/install/generator/powershell.rb +94 -0
  26. data/lib/mixlib/install/generator/powershell/scripts/get_project_metadata.ps1.erb +87 -0
  27. data/lib/mixlib/install/generator/powershell/scripts/get_project_metadata_for_artifactory.ps1.erb +83 -0
  28. data/lib/mixlib/install/generator/powershell/scripts/helpers.ps1 +69 -0
  29. data/lib/mixlib/install/generator/powershell/scripts/install_project.ps1 +96 -0
  30. data/lib/mixlib/install/options.rb +86 -23
  31. data/lib/mixlib/install/version.rb +1 -1
  32. metadata +17 -4
@@ -0,0 +1,83 @@
1
+ function Get-ProjectMetadata {
2
+ <#
3
+ .SYNOPSIS
4
+ Get metadata for a Chef Software, Inc. project
5
+ .DESCRIPTION
6
+ Get metadata for project
7
+ .EXAMPLE
8
+ iex (new-object net.webclient).downloadstring('https:/omnitruck.chef.io/install.ps1'); Get-ProjectMetadata -project chef -channel stable
9
+
10
+ Gets the download url, MD5 checksum, and SHA256 checksum for the latest stable release of Chef.
11
+ .EXAMPLE
12
+ iex (irm 'https://omnitruck.chef.io/install.ps1'); Get-ProjectMetadata -project chefdk -channel stable -version 0.8.0
13
+
14
+ Gets the download url, MD5 checksum, and SHA256 checksum for ChefDK 0.8.0.
15
+ #>
16
+ [cmdletbinding()]
17
+ param (
18
+ # Base url to retrieve metadata from.
19
+ [uri]$base_server_uri = '<%= base_url %>',
20
+ [string]
21
+ # Project to install
22
+ # chef - Chef Client
23
+ # chefdk - Chef Development Kit
24
+ # angrychef - AngryChef
25
+ # server and container are not valid windows targets
26
+ [validateset('chef', 'chefdk', 'angrychef')]
27
+ [string]
28
+ $project = 'chef',
29
+ # Version of the application to install
30
+ # This parameter is optional, if not supplied it will provide the latest version,
31
+ # and if an iteration number is not specified, it will grab the latest available iteration.
32
+ # Partial version numbers are also acceptable (using v=11
33
+ # will grab the latest 11.x client which matches the other flags).
34
+ [string]
35
+ $version,
36
+ # Release channel to install from
37
+ $channel = 'unstable',
38
+ # The following legacy switches are just aliases for the current channel
39
+ [switch]
40
+ $prerelease,
41
+ [switch]
42
+ $nightlies
43
+ )
44
+
45
+ # PowerShell is only on Windows ATM
46
+ $platform = 'windows'
47
+ Write-Verbose "Platform: $platform"
48
+
49
+ # TODO: No Win10 build endpoint yet
50
+ switch -regex ((get-wmiobject win32_operatingsystem).version) {
51
+ '10\.0\.\d+' {$platform_version = '2012r2'}
52
+ '6\.3\.\d+' {$platform_version = '2012r2'}
53
+ '6\.2\.\d+' {$platform_version = '2012'}
54
+ '6\.1\.\d+' {$platform_version = '2008r2'}
55
+ '6\.0\.\d+' {$platform_version = '2008'}
56
+ }
57
+ Write-Verbose "Platform Version: $platform_version"
58
+
59
+ # TODO: When we ship a 64 bit ruby for Windows.
60
+ $machine = 'i386'
61
+ Write-Verbose "Machine: $machine"
62
+ Write-Verbose "Project: $project"
63
+
64
+ <% artifacts.each do |artifact| %>
65
+ $artifact_info_dir = "$($env:temp)/artifact_info/<%= File.join(artifact.platform, artifact.platform_version, artifact.architecture)%>"
66
+ New-Item -ItemType directory -Path $artifact_info_dir -force
67
+ New-Item -ItemType file "$($artifact_info_dir)/artifact_info" -force
68
+ "url <%= artifact.url%>" | out-file "$artifact_info_dir/artifact_info"
69
+ "md5 <%= artifact.md5%>" | out-file "$artifact_info_dir/artifact_info" -Append
70
+ "sha256 <%= artifact.sha256%>" | out-file "$artifact_info_dir/artifact_info" -Append
71
+ <% end %>
72
+
73
+ $artifact_info_for_platform = Get-Content "$($env:temp)/artifact_info/$($platform)/$($platform_version)/$($machine)/artifact_info"
74
+
75
+ $package_metadata = ($artifact_info_for_platform).trim() -split '\n' |
76
+ foreach { $hash = @{} } {$key, $value = $_ -split '\s+'; $hash.Add($key, $value)} {$hash}
77
+
78
+ Write-Verbose "Project details: "
79
+ foreach ($key in $package_metadata.keys) {
80
+ Write-Verbose "`t$key = $($package_metadata[$key])"
81
+ }
82
+ $package_metadata
83
+ }
@@ -0,0 +1,69 @@
1
+ function New-Uri {
2
+ param ($baseuri, $newuri)
3
+
4
+ new-object System.Uri $baseuri, $newuri
5
+ }
6
+
7
+ function Get-WebContent {
8
+ param ($uri, $filepath)
9
+ $proxy = New-Object -TypeName System.Net.WebProxy
10
+ $wc = new-object System.Net.WebClient
11
+ $proxy.Address = $env:http_proxy
12
+ $wc.Proxy = $proxy
13
+
14
+ try {
15
+ if ([string]::IsNullOrEmpty($filepath)) {
16
+ $wc.downloadstring($uri)
17
+ }
18
+ else {
19
+ $wc.downloadfile($uri, $filepath)
20
+ }
21
+ }
22
+ catch {
23
+ $exception = $_.Exception
24
+ Write-Host "There was an error: "
25
+ do {
26
+ Write-Host "`t$($exception.message)"
27
+ $exception = $exception.innerexception
28
+ } while ($exception)
29
+ throw "Failed to download from $uri."
30
+ }
31
+ }
32
+
33
+ function Test-ProjectPackage {
34
+ [cmdletbinding()]
35
+ param ($Path, $Algorithm = 'SHA256', $Hash)
36
+
37
+ if (-not (get-command get-filehash)) {
38
+ function disposable($o){($o -is [IDisposable]) -and (($o | get-member | foreach-object {$_.name}) -contains 'Dispose')}
39
+ function use($obj, [scriptblock]$sb){try {& $sb} catch [exception]{throw $_} finally {if (disposable $obj) {$obj.Dispose()}} }
40
+ function Get-FileHash ($Path, $Algorithm) {
41
+ $Path = (resolve-path $path).providerpath
42
+ $hash = @{Algorithm = $Algorithm; Path = $Path}
43
+ if ($Algorithm -like 'MD5') {
44
+ use ($c = New-Object -TypeName Security.Cryptography.MD5CryptoServiceProvider) {
45
+ use ($in = (gi $path).OpenRead()) {
46
+ $hash.Hash = ([BitConverter]::ToString($c.ComputeHash($in))).Replace("-", "").ToUpper()
47
+ }
48
+ }
49
+ }
50
+ elseif ($Algorithm -like 'SHA256') {
51
+ use ($c = New-Object -TypeName Security.Cryptography.SHA256CryptoServiceProvider) {
52
+ use ($in = (gi $path).OpenRead()) {
53
+ $hash.Hash = ([BitConverter]::ToString($c.ComputeHash($in))).Replace("-", "").ToUpper()
54
+ }
55
+ }
56
+ }
57
+ new-object PSObject -Property $hash
58
+ }
59
+ }
60
+ Write-Verbose "Testing the $Algorithm hash for $path."
61
+ $ActualHash = (Get-FileHash -Algorithm $Algorithm -Path $Path).Hash.ToLower()
62
+ Write-Verbose "`tDesired Hash - '$hash'"
63
+ Write-Verbose "`tActual Hash - '$ActualHash'"
64
+ $Valid = $ActualHash -eq $Hash
65
+ if (-not $Valid) {
66
+ Write-Error "Failed to validate the downloaded installer. The expected $Algorithm hash was '$Hash' and the actual hash was '$ActualHash' for $path"
67
+ }
68
+ return $Valid
69
+ }
@@ -0,0 +1,96 @@
1
+ function Install-Project {
2
+ <#
3
+ .SYNOPSIS
4
+ Install a Chef Software, Inc. product
5
+ .DESCRIPTION
6
+ Install a Chef Software, Inc. product
7
+ .EXAMPLE
8
+ iex (new-object net.webclient).downloadstring('https:/omnitruck.chef.io/install.ps1'); Install-Project -project chef -channel stable
9
+
10
+ Installs the latest stable version of Chef.
11
+ .EXAMPLE
12
+ iex (irm 'https://omnitruck.chef.io/install.ps1'); Install-Project -project chefdk -channel current
13
+
14
+ Installs the latest integration build of the Chef Development Kit
15
+ #>
16
+ [cmdletbinding(SupportsShouldProcess=$true)]
17
+ param (
18
+ # Project to install
19
+ # chef - Chef Client
20
+ # chefdk - Chef Development Kit
21
+ # angrychef - AngryChef
22
+ # server and container are not valid windows targets
23
+ [validateset('chef', 'chefdk', 'angrychef')]
24
+ [string]
25
+ $project = 'chef',
26
+ # Release channel to install from
27
+ [validateset('current', 'stable', 'unstable')]
28
+ [string]
29
+ $channel = 'stable',
30
+ # Version of the application to install
31
+ # This parameter is optional, if not supplied it will provide the latest version,
32
+ # and if an iteration number is not specified, it will grab the latest available iteration.
33
+ # Partial version numbers are also acceptable (using v=11
34
+ # will grab the latest 11.x client which matches the other flags).
35
+ [string]
36
+ $version,
37
+ # Full path for the downloaded installer.
38
+ [string]
39
+ $filename,
40
+ # Full path to the location to download the installer
41
+ [string]
42
+ $download_directory = $env:temp,
43
+ # The following legacy switches are just aliases for the current channel
44
+ [switch]
45
+ $prerelease,
46
+ [switch]
47
+ $nightlies
48
+ )
49
+
50
+ $package_metadata = Get-ProjectMetadata -project $project -channel $channel -version $version -prerelease:$prerelease -nightlies:$nightlies
51
+
52
+ if (-not [string]::IsNullOrEmpty($filename)) {
53
+ $download_directory = split-path $filename
54
+ $filename = split-path $filename -leaf
55
+ if ([string]::IsNullOrEmpty($download_directory)) {
56
+ $download_directory = $pwd
57
+ }
58
+ }
59
+ else {
60
+ $filename = ($package_metadata.url -split '/')[-1]
61
+ }
62
+ Write-Verbose "Download directory: $download_directory"
63
+ Write-Verbose "Filename: $filename"
64
+
65
+ if (-not (test-path $download_directory)) {
66
+ mkdir $download_directory
67
+ }
68
+ $download_directory = (resolve-path $download_directory).providerpath
69
+ $download_destination = join-path $download_directory $filename
70
+
71
+ if ((test-path $download_destination) -and
72
+ (Test-ProjectPackage -Path $download_destination -Algorithm 'SHA256' -Hash $package_metadata.sha256 -ea SilentlyContinue)){
73
+ Write-Verbose "Found existing valid installer at $download_destination."
74
+ }
75
+ else {
76
+ if ($pscmdlet.ShouldProcess("$($package_metadata.url)", "Download $project")) {
77
+ Write-Verbose "Downloading $project from $($package_metadata.url) to $download_destination."
78
+ Get-WebContent $package_metadata.url -filepath $download_destination
79
+ }
80
+ }
81
+
82
+ if ($pscmdlet.ShouldProcess("$download_destination", "Installing")){
83
+ if (Test-ProjectPackage -Path $download_destination -Algorithm 'SHA256' -Hash $package_metadata.sha256) {
84
+ Write-Host "Installing $project from $download_destination"
85
+ $p = Start-Process -FilePath "msiexec" -ArgumentList "/qn /i $download_destination" -Passthru -Wait
86
+ if ($p.ExitCode -ne 0) {
87
+ throw "msiexec was not successful. Received exit code $($p.ExitCode)"
88
+ }
89
+ }
90
+ else {
91
+ throw "Failed to validate the downloaded installer for $project."
92
+ }
93
+ }
94
+ }
95
+ set-alias install -value Install-Project
96
+ export-modulemember -function 'Install-Project','Get-ProjectMetadata' -alias 'install'
@@ -16,41 +16,62 @@
16
16
  # limitations under the License.
17
17
  #
18
18
 
19
+ require "mixlib/versioning"
20
+
19
21
  module Mixlib
20
22
  class Install
21
23
  class Options
22
24
  class InvalidOptions < ArgumentError; end
25
+ class ArtifactoryCredentialsNotFound < StandardError; end
23
26
 
24
27
  attr_reader :options
25
- attr_reader :errors
28
+ attr_reader :defaults
26
29
 
27
30
  OMNITRUCK_CHANNELS = [:stable, :current]
28
31
  ARTIFACTORY_CHANNELS = [:unstable]
29
32
  ALL_SUPPORTED_CHANNELS = OMNITRUCK_CHANNELS + ARTIFACTORY_CHANNELS
30
33
  SUPPORTED_PRODUCT_NAMES = %w[chef chefdk]
31
- SUPPORTED_OPTIONS = [:channel, :product_name, :product_version,
32
- :platform, :platform_version, :architecture]
34
+ SUPPORTED_SHELL_TYPES = [:ps1, :sh]
35
+ SUPPORTED_OPTIONS = [
36
+ :architecture,
37
+ :channel,
38
+ :platform,
39
+ :platform_version,
40
+ :product_name,
41
+ :product_version,
42
+ :shell_type
43
+ ]
33
44
 
34
45
  def initialize(options)
35
46
  @options = options
36
- @errors = []
47
+ @defaults = {
48
+ shell_type: :sh
49
+ }
50
+
51
+ validate!
52
+ end
53
+
54
+ def validate!
37
55
  validate_options!
56
+ validate_unstable_channel! if for_artifactory?
38
57
  end
39
58
 
40
59
  def validate_options!
41
- validate_product_names
42
- validate_channels
43
- validate_unstable_version
44
- validate_platform_info
60
+ errors = []
61
+
62
+ errors << validate_product_names
63
+ errors << validate_channels
64
+ errors << validate_platform_info
65
+ errors << validate_shell_type
45
66
 
46
- unless errors.empty?
67
+ unless errors.compact.empty?
47
68
  raise InvalidOptions, errors.join("\n")
48
69
  end
49
70
  end
50
71
 
51
72
  SUPPORTED_OPTIONS.each do |option|
52
73
  define_method option do
53
- options[option] || options[option.to_s]
74
+ options[option] || options[option.to_s] || defaults[option]
54
75
  end
55
76
  end
56
77
 
@@ -62,26 +83,48 @@ module Mixlib
62
83
  OMNITRUCK_CHANNELS.include?(channel)
63
84
  end
64
85
 
86
+ def for_ps1?
87
+ platform == "windows" || shell_type == :ps1
88
+ end
89
+
90
+ def latest_version?
91
+ product_version.to_sym == :latest
92
+ end
93
+
94
+ def resolved_version(artifacts)
95
+ @resolved_version ||= begin
96
+ if latest_version?
97
+ all_versions = artifacts.collect(&:version)
98
+ # params: list of all versions, no version filtering, no pre-releases, use build version
99
+ Mixlib::Versioning.find_target_version(
100
+ all_versions,
101
+ nil,
102
+ false,
103
+ true
104
+ ).to_s
105
+ else
106
+ product_version
107
+ end
108
+ end
109
+ end
110
+
65
111
  private
66
112
 
67
113
  def validate_product_names
68
114
  unless SUPPORTED_PRODUCT_NAMES.include? product_name
69
- errors << "Unknown product name #{product_name}. \
70
- Must be one of: #{SUPPORTED_PRODUCT_NAMES.join(", ")}"
115
+ <<-EOS
116
+ Unknown product name #{product_name}.
117
+ Must be one of: #{SUPPORTED_PRODUCT_NAMES.join(", ")}
118
+ EOS
71
119
  end
72
120
  end
73
121
 
74
122
  def validate_channels
75
123
  unless ALL_SUPPORTED_CHANNELS.include? channel
76
- errors << "Unknown channel #{channel}. \
77
- Must be one of: #{ALL_SUPPORTED_CHANNELS.join(", ")}"
78
- end
79
- end
80
-
81
- def validate_unstable_version
82
- if for_artifactory? && product_version !~ /^\d+.\d+.\d+\+[0-9]{14}$/
83
- errors << "Version must match pattern '1.2.3+12345678901234' when \
84
- using channels #{ARTIFACTORY_CHANNELS.join(", ")}"
124
+ <<-EOS
125
+ Unknown channel #{channel}.
126
+ Must be one of: #{ALL_SUPPORTED_CHANNELS.join(", ")}
127
+ EOS
85
128
  end
86
129
  end
87
130
 
@@ -89,8 +132,28 @@ using channels #{ARTIFACTORY_CHANNELS.join(", ")}"
89
132
  platform_opts = [platform, platform_version, architecture]
90
133
  if (platform_opts.any?(&:nil?)) &&
91
134
  (platform_opts.any? { |opt| !opt.nil? })
92
- errors << "platform, platform version, and architecture are all \
93
- required when specifying Platform options."
135
+ <<-EOS
136
+ platform, platform version, and architecture are all required when specifying Platform options.
137
+ EOS
138
+ end
139
+ end
140
+
141
+ def validate_shell_type
142
+ unless SUPPORTED_SHELL_TYPES.include? shell_type
143
+ <<-EOS
144
+ Unknown shell type.
145
+ Must be one of: #{SUPPORTED_SHELL_TYPES.join(", ")}
146
+ EOS
147
+ end
148
+ end
149
+
150
+ def validate_unstable_channel!
151
+ if ENV["ARTIFACTORY_USERNAME"].nil? || ENV["ARTIFACTORY_PASSWORD"].nil?
152
+ raise ArtifactoryCredentialsNotFound,
153
+ <<-EOS
154
+ Must set ARTIFACTORY_USERNAME and ARTIFACTORY_PASSWORD environment variables
155
+ when using the unstable channel.
156
+ EOS
94
157
  end
95
158
  end
96
159
  end
@@ -1,5 +1,5 @@
1
1
  module Mixlib
2
2
  class Install
3
- VERSION = "0.8.0.alpha.2"
3
+ VERSION = "0.8.0.alpha.3"
4
4
  end
5
5
  end
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: 0.8.0.alpha.2
4
+ version: 0.8.0.alpha.3
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: 2015-12-04 00:00:00.000000000 Z
12
+ date: 2015-12-22 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: artifactory
@@ -121,18 +121,32 @@ files:
121
121
  - acceptance/current/.acceptance/acceptance-cookbook/recipes/provision.rb
122
122
  - acceptance/current/.acceptance/acceptance-cookbook/recipes/verify.rb
123
123
  - acceptance/current/.kitchen.yml
124
+ - acceptance/unstable/.acceptance/acceptance-cookbook/.gitignore
125
+ - acceptance/unstable/.acceptance/acceptance-cookbook/metadata.rb
126
+ - acceptance/unstable/.acceptance/acceptance-cookbook/recipes/destroy.rb
127
+ - acceptance/unstable/.acceptance/acceptance-cookbook/recipes/provision.rb
128
+ - acceptance/unstable/.acceptance/acceptance-cookbook/recipes/verify.rb
129
+ - acceptance/unstable/.kitchen.yml
124
130
  - lib/mixlib/install.rb
125
131
  - lib/mixlib/install/artifact_info.rb
126
132
  - lib/mixlib/install/backend.rb
127
133
  - lib/mixlib/install/backend/artifactory.rb
128
134
  - lib/mixlib/install/backend/omnitruck.rb
129
135
  - lib/mixlib/install/generator.rb
136
+ - lib/mixlib/install/generator/base.rb
130
137
  - lib/mixlib/install/generator/bourne.rb
131
- - lib/mixlib/install/generator/bourne/scripts/fetch_metadata.sh
138
+ - lib/mixlib/install/generator/bourne/scripts/artifactory_urls.sh.erb
139
+ - lib/mixlib/install/generator/bourne/scripts/fetch_metadata.sh.erb
132
140
  - lib/mixlib/install/generator/bourne/scripts/fetch_package.sh
133
141
  - lib/mixlib/install/generator/bourne/scripts/helpers.sh
134
142
  - lib/mixlib/install/generator/bourne/scripts/install_package.sh
135
143
  - lib/mixlib/install/generator/bourne/scripts/platform_detection.sh
144
+ - lib/mixlib/install/generator/bourne/scripts/script_cli_parameters.sh
145
+ - lib/mixlib/install/generator/powershell.rb
146
+ - lib/mixlib/install/generator/powershell/scripts/get_project_metadata.ps1.erb
147
+ - lib/mixlib/install/generator/powershell/scripts/get_project_metadata_for_artifactory.ps1.erb
148
+ - lib/mixlib/install/generator/powershell/scripts/helpers.ps1
149
+ - lib/mixlib/install/generator/powershell/scripts/install_project.ps1
136
150
  - lib/mixlib/install/options.rb
137
151
  - lib/mixlib/install/product.rb
138
152
  - lib/mixlib/install/script_generator.rb
@@ -166,4 +180,3 @@ signing_key:
166
180
  specification_version: 4
167
181
  summary: A mixin to help with omnitruck installs
168
182
  test_files: []
169
- has_rdoc: