vagrant-omnibus 1.4.1 → 1.5.0

Sign up to get free protection for your applications and to get access to all the features.
data/TODO.md CHANGED
@@ -1,5 +1,5 @@
1
- # TODO
2
-
3
- * Add support for installing pre-release versions of Chef.
4
- * Better acceptance test coverage.
5
- * Unit test coverage.
1
+ # TODO
2
+
3
+ - Add support for installing pre-release versions of Chef.
4
+ - Better acceptance test coverage.
5
+ - Unit test coverage.
@@ -1,31 +1,31 @@
1
- #
2
- # Copyright (c) 2013, Seth Chisamore
3
- #
4
- # Licensed under the Apache License, Version 2.0 (the "License");
5
- # you may not use this file except in compliance with the License.
6
- # You may obtain a copy of the License at
7
- #
8
- # http://www.apache.org/licenses/LICENSE-2.0
9
- #
10
- # Unless required by applicable law or agreed to in writing, software
11
- # distributed under the License is distributed on an "AS IS" BASIS,
12
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
- # See the License for the specific language governing permissions and
14
- # limitations under the License.
15
- #
16
-
17
- require 'vagrant'
18
- require 'vagrant-omnibus/plugin'
19
- require 'vagrant-omnibus/config'
20
-
21
- module VagrantPlugins
22
- #
23
- module Omnibus
24
- def self.source_root
25
- @source_root ||= Pathname.new(File.expand_path('../../', __FILE__))
26
- end
27
-
28
- I18n.load_path << File.expand_path('locales/en.yml', source_root)
29
- I18n.reload!
30
- end
31
- end
1
+ #
2
+ # Copyright (c) 2013, Seth Chisamore
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+ #
16
+
17
+ require "vagrant"
18
+ require "vagrant-omnibus/plugin"
19
+ require "vagrant-omnibus/config"
20
+
21
+ module VagrantPlugins
22
+ #
23
+ module Omnibus
24
+ def self.source_root
25
+ @source_root ||= Pathname.new(File.expand_path("../../", __FILE__))
26
+ end
27
+
28
+ I18n.load_path << File.expand_path("locales/en.yml", source_root)
29
+ I18n.reload!
30
+ end
31
+ end
@@ -1,258 +1,272 @@
1
- #
2
- # Copyright (c) 2013, Seth Chisamore
3
- #
4
- # Licensed under the Apache License, Version 2.0 (the "License");
5
- # you may not use this file except in compliance with the License.
6
- # You may obtain a copy of the License at
7
- #
8
- # http://www.apache.org/licenses/LICENSE-2.0
9
- #
10
- # Unless required by applicable law or agreed to in writing, software
11
- # distributed under the License is distributed on an "AS IS" BASIS,
12
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
- # See the License for the specific language governing permissions and
14
- # limitations under the License.
15
- #
16
-
17
- require 'log4r'
18
- require 'shellwords'
19
-
20
- require 'vagrant/util/downloader'
21
-
22
- module VagrantPlugins
23
- module Omnibus
24
- module Action
25
- # @author Seth Chisamore <schisamo@opscode.com>
26
- #
27
- # This action installs Chef Omnibus packages at the desired version.
28
- class InstallChef
29
- def initialize(app, env)
30
- @app = app
31
- @logger =
32
- Log4r::Logger.new('vagrantplugins::omnibus::action::installchef')
33
- @machine = env[:machine]
34
- @install_script = find_install_script
35
- end
36
-
37
- def call(env)
38
- @app.call(env)
39
-
40
- return unless @machine.communicate.ready? && provision_enabled?(env)
41
-
42
- # Perform delayed validation
43
- @machine.config.omnibus.validate!(@machine)
44
-
45
- desired_version = @machine.config.omnibus.chef_version
46
- unless desired_version.nil?
47
- if installed_version == desired_version
48
- env[:ui].info I18n.t(
49
- 'vagrant-omnibus.action.installed',
50
- version: desired_version
51
- )
52
- else
53
- fetch_or_create_install_script(env)
54
- env[:ui].info I18n.t(
55
- 'vagrant-omnibus.action.installing',
56
- version: desired_version
57
- )
58
- install(desired_version, env)
59
- recover(env)
60
- end
61
- end
62
- end
63
-
64
- private
65
-
66
- # Determines which install script should be used to install the
67
- # Omnibus Chef package. Order of precedence:
68
- # 1. from config
69
- # 2. from env var
70
- # 3. default
71
- def find_install_script
72
- config_install_url || env_install_url || default_install_url
73
- end
74
-
75
- def default_install_url
76
- if windows_guest?
77
- 'http://www.getchef.com/chef/install.msi'
78
- else
79
- 'https://www.getchef.com/chef/install.sh'
80
- end
81
- end
82
-
83
- def config_install_url
84
- @machine.config.omnibus.install_url
85
- end
86
-
87
- def env_install_url
88
- ENV['OMNIBUS_INSTALL_URL']
89
- end
90
-
91
- def cached_omnibus_download_dir
92
- '/tmp/vagrant-cache/vagrant_omnibus'
93
- end
94
-
95
- def cache_packages?
96
- @machine.config.omnibus.cache_packages
97
- end
98
-
99
- def cachier_present?
100
- defined?(VagrantPlugins::Cachier::Plugin)
101
- end
102
-
103
- def cachier_autodetect_enabled?
104
- @machine.config.cache.auto_detect
105
- end
106
-
107
- def download_to_cached_dir?
108
- cache_packages? && cachier_present? && cachier_autodetect_enabled?
109
- end
110
-
111
- def install_script_name
112
- if windows_guest?
113
- 'install.bat'
114
- else
115
- 'install.sh'
116
- end
117
- end
118
-
119
- def windows_guest?
120
- @machine.config.vm.guest.eql?(:windows)
121
- end
122
-
123
- def provision_enabled?(env)
124
- env.fetch(:provision_enabled, true)
125
- end
126
-
127
- def communication_opts
128
- if windows_guest?
129
- { shell: 'cmd' }
130
- else
131
- { shell: 'sh' }
132
- end
133
- end
134
-
135
- def installed_version
136
- version = nil
137
- opts = communication_opts
138
- if windows_guest?
139
- command = 'cmd.exe /c chef-solo -v'
140
- opts[:error_check] = false
141
- else
142
- command = 'echo $(chef-solo -v)'
143
- end
144
- @machine.communicate.sudo(command, opts) do |type, data|
145
- if [:stderr, :stdout].include?(type)
146
- version_match = data.match(/^Chef: (.+)/)
147
- version = version_match.captures[0].strip if version_match
148
- end
149
- end
150
- version
151
- end
152
-
153
- #
154
- # Upload install script from Host's Vagrant TMP directory to guest
155
- # and executes.
156
- #
157
- def install(version, env)
158
- shell_escaped_version = Shellwords.escape(version)
159
-
160
- @machine.communicate.tap do |comm|
161
- comm.upload(@script_tmp_path, install_script_name)
162
- if windows_guest?
163
- install_cmd = "cmd.exe /c #{install_script_name} #{version}"
164
- else
165
- install_cmd = "sh #{install_script_name}"
166
- install_cmd << " -v #{shell_escaped_version}"
167
- if download_to_cached_dir?
168
- install_cmd << " -d #{cached_omnibus_download_dir}"
169
- end
170
- install_cmd << ' 2>&1'
171
- end
172
- comm.sudo(install_cmd, communication_opts) do |type, data|
173
- if [:stderr, :stdout].include?(type)
174
- next if data =~ /stdin: is not a tty/
175
- env[:ui].info(data)
176
- end
177
- end
178
- end
179
- end
180
-
181
- #
182
- # Fetches or creates a platform specific install script to the Host's
183
- # Vagrant TMP directory.
184
- #
185
- def fetch_or_create_install_script(env)
186
- @script_tmp_path =
187
- env[:tmp_path].join("#{Time.now.to_i.to_s}-#{install_script_name}")
188
-
189
- @logger.info("Generating install script at: #{@script_tmp_path}")
190
-
191
- url = @install_script
192
-
193
- if File.file?(url) || url !~ /^[a-z0-9]+:.*$/i
194
- @logger.info('Assuming URL is a file.')
195
- file_path = File.expand_path(url)
196
- file_path = Vagrant::Util::Platform.cygwin_windows_path(file_path)
197
- url = "file:#{file_path}"
198
- end
199
-
200
- # Download the install.sh or create install.bat file to a temporary
201
- # path. We store the temporary path as an instance variable so that
202
- # the `#recover` method can access it.
203
- begin
204
- if windows_guest?
205
- # generate a install.bat file at the `@script_tmp_path` location
206
- #
207
- # We'll also disable Rubocop for this embedded PowerShell code:
208
- #
209
- # rubocop:disable LineLength, SpaceAroundBlockBraces
210
- #
211
- File.open(@script_tmp_path, 'w') do |f|
212
- f.puts <<-EOH.gsub(/^\s{18}/, '')
213
- @echo off
214
- set version=%1
215
- set dest=%~dp0chef-client-%version%-1.windows.msi
216
- echo Downloading Chef %version% for Windows...
217
- powershell -command "(New-Object System.Net.WebClient).DownloadFile('#{url}?v=%version%', '%dest%')"
218
- echo Installing Chef %version%
219
- msiexec /q /i %dest%
220
- EOH
221
- end
222
- # rubocop:enable LineLength, SpaceAroundBlockBraces
223
- else
224
- downloader = Vagrant::Util::Downloader.new(
225
- url,
226
- @script_tmp_path,
227
- {}
228
- )
229
- downloader.download!
230
- end
231
- rescue Vagrant::Errors::DownloaderInterrupted
232
- # The downloader was interrupted, so just return, because that
233
- # means we were interrupted as well.
234
- env[:ui].info(I18n.t('vagrant-omnibus.download.interrupted'))
235
- return
236
- end
237
- end
238
-
239
- def recover(env)
240
- if @script_tmp_path && File.exist?(@script_tmp_path)
241
- # Try extra hard to unlink the file so that it reliably works
242
- # on Windows hosts as well, see:
243
- # http://alx.github.io/2009/01/27/ruby-wundows-unlink.html
244
- file_deleted = false
245
- until file_deleted
246
- begin
247
- File.unlink(@script_tmp_path)
248
- file_deleted = true
249
- rescue Errno::EACCES
250
- @logger.debug("failed to unlink #{@script_tmp_path}. retry...")
251
- end
252
- end
253
- end
254
- end
255
- end
256
- end
257
- end
258
- end
1
+ #
2
+ # Copyright (c) 2013, Seth Chisamore
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+ #
16
+
17
+ require "log4r"
18
+ require "shellwords"
19
+
20
+ require "vagrant/util/downloader"
21
+
22
+ module VagrantPlugins
23
+ module Omnibus
24
+ module Action
25
+ # @author Seth Chisamore <schisamo@chef.io>
26
+ #
27
+ # This action installs Chef Omnibus packages at the desired version.
28
+ class InstallChef
29
+ def initialize(app, env)
30
+ @app = app
31
+ @logger =
32
+ Log4r::Logger.new("vagrantplugins::omnibus::action::installchef")
33
+ @machine = env[:machine]
34
+ @install_script = find_install_script
35
+ end
36
+
37
+ def call(env)
38
+ @app.call(env)
39
+
40
+ return unless @machine.communicate.ready? && provision_enabled?(env)
41
+
42
+ # Perform delayed validation
43
+ @machine.config.omnibus.validate!(@machine)
44
+
45
+ desired_version = @machine.config.omnibus.chef_version
46
+ unless desired_version.nil?
47
+ if installed_version == desired_version
48
+ env[:ui].info I18n.t(
49
+ "vagrant-omnibus.action.installed",
50
+ version: desired_version
51
+ )
52
+ else
53
+ fetch_or_create_install_script(env)
54
+ env[:ui].info I18n.t(
55
+ "vagrant-omnibus.action.installing",
56
+ version: desired_version
57
+ )
58
+ install(desired_version, env)
59
+ recover(env)
60
+ end
61
+ end
62
+ end
63
+
64
+ private
65
+
66
+ # Determines which install script should be used to install the
67
+ # Omnibus Chef package. Order of precedence:
68
+ # 1. from config
69
+ # 2. from env var
70
+ # 3. default
71
+ def find_install_script
72
+ config_install_url || env_install_url || default_install_url
73
+ end
74
+
75
+ def default_install_url
76
+ if windows_guest?
77
+ "http://www.chef.io/chef/install.msi"
78
+ else
79
+ "https://www.chef.io/chef/install.sh"
80
+ end
81
+ end
82
+
83
+ def config_install_url
84
+ @machine.config.omnibus.install_url
85
+ end
86
+
87
+ def env_install_url
88
+ ENV["OMNIBUS_INSTALL_URL"]
89
+ end
90
+
91
+ def cached_omnibus_download_dir
92
+ "/tmp/vagrant-cache/vagrant_omnibus"
93
+ end
94
+
95
+ def cache_packages?
96
+ @machine.config.omnibus.cache_packages
97
+ end
98
+
99
+ def cachier_present?
100
+ defined?(VagrantPlugins::Cachier::Plugin)
101
+ end
102
+
103
+ def cachier_autodetect_enabled?
104
+ @machine.config.cache.auto_detect
105
+ end
106
+
107
+ def download_to_cached_dir?
108
+ cache_packages? && cachier_present? && cachier_autodetect_enabled?
109
+ end
110
+
111
+ def install_script_name
112
+ if windows_guest?
113
+ "install.bat"
114
+ else
115
+ "install.sh"
116
+ end
117
+ end
118
+
119
+ def install_script_folder
120
+ if windows_guest?
121
+ "$env:temp/vagrant-omnibus"
122
+ else
123
+ "/tmp/vagrant-omnibus"
124
+ end
125
+ end
126
+
127
+ def install_script_path
128
+ File.join(install_script_folder, install_script_name)
129
+ end
130
+
131
+ def windows_guest?
132
+ @machine.config.vm.guest.eql?(:windows)
133
+ end
134
+
135
+ def provision_enabled?(env)
136
+ env.fetch(:provision_enabled, true)
137
+ end
138
+
139
+ def communication_opts
140
+ if windows_guest?
141
+ { shell: "powershell" }
142
+ else
143
+ { shell: "sh" }
144
+ end
145
+ end
146
+
147
+ def installed_version
148
+ version = nil
149
+ opts = communication_opts
150
+ opts[:error_check] = false if windows_guest?
151
+ command = "echo $(chef-solo -v)"
152
+ @machine.communicate.sudo(command, opts) do |type, data|
153
+ if [:stderr, :stdout].include?(type)
154
+ version_match = data.match(/^Chef: (.+)/)
155
+ version = version_match.captures[0].strip if version_match
156
+ end
157
+ end
158
+ version
159
+ end
160
+
161
+ #
162
+ # Upload install script from Host's Vagrant TMP directory to guest
163
+ # and executes.
164
+ #
165
+ def install(version, env)
166
+ shell_escaped_version = Shellwords.escape(version)
167
+
168
+ @machine.communicate.tap do |comm|
169
+ unless windows_guest?
170
+ comm.execute("mkdir -p #{install_script_folder}")
171
+ end
172
+
173
+ comm.upload(@script_tmp_path, install_script_path)
174
+
175
+ if windows_guest?
176
+ install_cmd = "& #{install_script_path} #{version}"
177
+ else
178
+ install_cmd = "sh #{install_script_path}"
179
+ install_cmd << " -v #{shell_escaped_version}"
180
+ if download_to_cached_dir?
181
+ install_cmd << " -d #{cached_omnibus_download_dir}"
182
+ end
183
+ install_cmd << " 2>&1"
184
+ end
185
+ comm.sudo(install_cmd, communication_opts) do |type, data|
186
+ if [:stderr, :stdout].include?(type)
187
+ next if data =~ /stdin: is not a tty/
188
+ env[:ui].info(data)
189
+ end
190
+ end
191
+ end
192
+ end
193
+
194
+ #
195
+ # Fetches or creates a platform specific install script to the Host's
196
+ # Vagrant TMP directory.
197
+ #
198
+ def fetch_or_create_install_script(env)
199
+ @script_tmp_path = env[:tmp_path].join(
200
+ "#{Time.now.to_i}-#{install_script_name}"
201
+ ).to_s
202
+
203
+ @logger.info("Generating install script at: #{@script_tmp_path}")
204
+
205
+ url = @install_script
206
+
207
+ if File.file?(url) || url !~ /^[a-z0-9]+:.*$/i
208
+ @logger.info("Assuming URL is a file.")
209
+ file_path = File.expand_path(url)
210
+ file_path = Vagrant::Util::Platform.cygwin_windows_path(file_path)
211
+ url = "file:#{file_path}"
212
+ end
213
+
214
+ # Download the install.sh or create install.bat file to a temporary
215
+ # path. We store the temporary path as an instance variable so that
216
+ # the `#recover` method can access it.
217
+ begin
218
+ if windows_guest?
219
+ # generate a install.bat file at the `@script_tmp_path` location
220
+ #
221
+ # We'll also disable Rubocop for this embedded PowerShell code:
222
+ #
223
+ # rubocop:disable LineLength, SpaceAroundBlockBraces
224
+ #
225
+ File.open(@script_tmp_path, "w") do |f|
226
+ f.puts <<-EOH.gsub(/^\s{18}/, "")
227
+ @echo off
228
+ set version=%1
229
+ set dest=%~dp0chef-client-%version%-1.windows.msi
230
+ echo Downloading Chef %version% for Windows...
231
+ powershell -command "(New-Object System.Net.WebClient).DownloadFile('#{url}?v=%version%', '%dest%')"
232
+ echo Installing Chef %version%
233
+ msiexec /q /i %dest%
234
+ EOH
235
+ end
236
+ # rubocop:enable LineLength, SpaceAroundBlockBraces
237
+ else
238
+ downloader = Vagrant::Util::Downloader.new(
239
+ url,
240
+ @script_tmp_path,
241
+ {}
242
+ )
243
+ downloader.download!
244
+ end
245
+ rescue Vagrant::Errors::DownloaderInterrupted
246
+ # The downloader was interrupted, so just return, because that
247
+ # means we were interrupted as well.
248
+ env[:ui].info(I18n.t("vagrant-omnibus.download.interrupted"))
249
+ return
250
+ end
251
+ end
252
+
253
+ def recover(env)
254
+ if @script_tmp_path && File.exist?(@script_tmp_path)
255
+ # Try extra hard to unlink the file so that it reliably works
256
+ # on Windows hosts as well, see:
257
+ # http://alx.github.io/2009/01/27/ruby-wundows-unlink.html
258
+ file_deleted = false
259
+ until file_deleted
260
+ begin
261
+ File.unlink(@script_tmp_path)
262
+ file_deleted = true
263
+ rescue Errno::EACCES
264
+ @logger.debug("failed to unlink #{@script_tmp_path}. retry...")
265
+ end
266
+ end
267
+ end
268
+ end
269
+ end
270
+ end
271
+ end
272
+ end