kitchen-cinc 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,86 @@
1
+ #
2
+ # Copyright (C) 2013, Fletcher Nichol
3
+ # Copyright (C) 2026, Oregon State University
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
+ # https://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
+ require_relative "cinc_base"
18
+
19
+ module Kitchen
20
+ module Provisioner
21
+ # Cinc Solo provisioner.
22
+ #
23
+ # @author Cinc Project
24
+ class CincSolo < CincBase
25
+ kitchen_provisioner_api_version 2
26
+
27
+ plugin_version Kitchen::VERSION
28
+
29
+ # CincSolo is dependent on Berkshelf, which is not thread-safe.
30
+ # See discussion on https://github.com/test-kitchen/test-kitchen/issues/1307
31
+ no_parallel_for :converge
32
+
33
+ default_config :solo_rb, {}
34
+
35
+ default_config :cinc_solo_path do |provisioner|
36
+ provisioner
37
+ .remote_path_join(%W{#{provisioner[:cinc_omnibus_root]} bin cinc-solo})
38
+ .tap { |path| path.concat(".bat") if provisioner.windows_os? }
39
+ end
40
+
41
+ default_config :ruby_bindir do |provisioner|
42
+ provisioner
43
+ .remote_path_join(%W{#{provisioner[:cinc_omnibus_root]} embedded bin})
44
+ end
45
+
46
+ # (see Base#config_filename)
47
+ def config_filename
48
+ "solo.rb"
49
+ end
50
+
51
+ # (see Base#create_sandbox)
52
+ def create_sandbox
53
+ super
54
+ prepare_config_rb
55
+ end
56
+
57
+ # (see Base#run_command)
58
+ def run_command
59
+ cmd = sudo(config[:cinc_solo_path]).dup
60
+ .tap { |str| str.insert(0, "& ") if powershell_shell? }
61
+
62
+ chef_cmd(cmd)
63
+ end
64
+
65
+ private
66
+
67
+ # Returns an Array of command line arguments for the cinc-solo client.
68
+ #
69
+ # @return [Array<String>] an array of command line arguments
70
+ # @api private
71
+ def chef_args(solo_rb_filename)
72
+ args = [
73
+ "--config #{remote_path_join(config[:root_path], solo_rb_filename)}",
74
+ "--log_level #{config[:log_level]}",
75
+ "--force-formatter",
76
+ "--no-color",
77
+ "--json-attributes #{remote_path_join(config[:root_path], "dna.json")}",
78
+ ]
79
+ args << "--logfile #{config[:log_file]}" if config[:log_file]
80
+ args << "--profile-ruby" if config[:profile_ruby]
81
+ args << "--legacy-mode" if config[:legacy_mode]
82
+ args
83
+ end
84
+ end
85
+ end
86
+ end
@@ -0,0 +1,131 @@
1
+ #
2
+ # Copyright (C) 2023, Thomas Heinen
3
+ # Copyright (C) 2026, Oregon State University
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
+ # https://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
+ require_relative "cinc_infra"
18
+
19
+ module Kitchen
20
+ module Provisioner
21
+ # Cinc Target Mode provisioner for remote execution.
22
+ #
23
+ # Requires Cinc Client 19.0.0+ and Train-based transport.
24
+ #
25
+ # @author Cinc Project
26
+ class CincTarget < CincInfra
27
+ MIN_VERSION_REQUIRED = "19.0.0".freeze
28
+ class CincVersionTooLow < UserError; end
29
+ class CincClientNotFound < UserError; end
30
+ class RequireTrainTransport < UserError; end
31
+
32
+ default_config :install_strategy, "none"
33
+ default_config :sudo, true
34
+
35
+ def install_command; ""; end
36
+ def init_command; ""; end
37
+ def prepare_command; ""; end
38
+
39
+ def chef_args(client_rb_filename)
40
+ # Dummy execution to initialize and test remote connection
41
+ connection = instance.remote_exec("echo Connection established")
42
+
43
+ check_transport(connection)
44
+ check_local_cinc_client
45
+
46
+ instance_name = instance.name
47
+ credentials_file = File.join(kitchen_basepath, ".kitchen", instance_name + ".ini")
48
+ File.write(credentials_file, connection.credentials_file)
49
+
50
+ super.push(
51
+ "--target #{instance_name}",
52
+ "--credentials #{credentials_file}"
53
+ )
54
+ end
55
+
56
+ def check_transport(connection)
57
+ debug("Checking for active transport")
58
+
59
+ unless connection.respond_to? "train_uri"
60
+ error("Cinc Target Mode provisioner requires a Train-based transport like kitchen-transport-train")
61
+ raise RequireTrainTransport.new("No Train transport")
62
+ end
63
+
64
+ debug("Kitchen transport responds to train_uri function call, as required")
65
+ end
66
+
67
+ def check_local_cinc_client
68
+ debug("Checking for cinc-client version")
69
+
70
+ begin
71
+ client_version = `cinc-client -v`.chop.split(":")[-1]
72
+ rescue Errno::ENOENT => e
73
+ error("Error determining Cinc Client version: #{e.exception.message}")
74
+ raise CincClientNotFound.new("Need cinc-client installed locally")
75
+ end
76
+
77
+ minimum_version = Gem::Version.new(MIN_VERSION_REQUIRED)
78
+ installed_version = Gem::Version.new(client_version)
79
+
80
+ if installed_version < minimum_version
81
+ error("Found Cinc Client version #{installed_version}, but require #{minimum_version} for Target Mode")
82
+ raise CincVersionTooLow.new("Need version #{MIN_VERSION_REQUIRED} or higher")
83
+ end
84
+
85
+ debug("Cinc Client found and version constraints match")
86
+ end
87
+
88
+ def kitchen_basepath
89
+ instance.driver.config[:kitchen_root]
90
+ end
91
+
92
+ def create_sandbox
93
+ super
94
+
95
+ # Change config.rb to point to the local sandbox path, not to /tmp/kitchen
96
+ config[:root_path] = sandbox_path
97
+ prepare_config_rb
98
+ end
99
+
100
+ def call(state)
101
+ remote_connection = instance.transport.connection(state)
102
+
103
+ config[:uploads].to_h.each do |locals, remote|
104
+ debug("Uploading #{Array(locals).join(", ")} to #{remote}")
105
+ remote_connection.upload(locals.to_s, remote)
106
+ end
107
+
108
+ # no installation
109
+ create_sandbox
110
+ # no prepare command
111
+
112
+ # Stream output to logger
113
+ require "open3"
114
+ Open3.popen2e(run_command) do |_stdin, output, _thread|
115
+ output.each { |line| logger << line }
116
+ end
117
+
118
+ info("Downloading files from #{instance.to_str}")
119
+ config[:downloads].to_h.each do |remotes, local|
120
+ debug("Downloading #{Array(remotes).join(", ")} to #{local}")
121
+ remote_connection.download(remotes, local)
122
+ end
123
+ debug("Download complete")
124
+ rescue Kitchen::Transport::TransportFailed => ex
125
+ raise ActionFailed, ex.message
126
+ ensure
127
+ cleanup_sandbox
128
+ end
129
+ end
130
+ end
131
+ end
@@ -0,0 +1,5 @@
1
+ module Kitchen
2
+ module Provisioner
3
+ CINC_VERSION = "1.0.0".freeze
4
+ end
5
+ end
@@ -0,0 +1,18 @@
1
+ # Deprecated - use CincInfra instead
2
+ require_relative "cinc_infra"
3
+
4
+ module Kitchen
5
+ module Provisioner
6
+ # Cinc Zero provisioner (deprecated, use CincInfra instead).
7
+ #
8
+ # This provisioner is maintained for backward compatibility and delegates
9
+ # to CincInfra.
10
+ #
11
+ # @author Cinc Project
12
+ class CincZero < CincInfra
13
+ kitchen_provisioner_api_version 2
14
+
15
+ plugin_version Kitchen::VERSION
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,15 @@
1
+ # Handler to kill the run if any resource is updated
2
+ class UpdatedResources < ::Chef::Handler
3
+ def report
4
+ if updated_resources.size > 0
5
+ puts "First cinc run should have reached a converged state."
6
+ puts "Resources updated in a second cinc-client run:"
7
+ updated_resources.each do |r|
8
+ puts "- #{r}"
9
+ end
10
+ # exit 203 # chef handler catch Exception instead of StandardException
11
+ Process.kill("KILL", Process.pid)
12
+ end
13
+ end
14
+ end
15
+ report_handlers << UpdatedResources.new
@@ -0,0 +1,18 @@
1
+ Function Delete-AllDirs($dirs) {
2
+ $dirs | ForEach-Object {
3
+ if (Test-Path ($path = Unresolve-Path $_)) { Remove-Item $path -Recurse -Force }
4
+ }
5
+ }
6
+
7
+ Function Unresolve-Path($p) {
8
+ if ($p -eq $null) { return $null }
9
+ else { return $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($p) }
10
+ }
11
+
12
+ Function Make-RootPath($p) {
13
+ $p = Unresolve-Path $p
14
+ if (-Not (Test-Path $p)) { New-Item $p -ItemType directory | Out-Null }
15
+ }
16
+
17
+ Delete-AllDirs $dirs
18
+ Make-RootPath $root_path
@@ -0,0 +1,2 @@
1
+ $sudo_rm -rf $dirs
2
+ mkdir -p $root_path
@@ -0,0 +1,86 @@
1
+ $ErrorActionPreference = "stop"
2
+
3
+ Function Check-UpdateCinc($root, $version) {
4
+ if (-Not (Test-Path $root)) { return $true }
5
+ elseif ("$version" -eq "true") { return $false }
6
+ elseif ("$version" -eq "latest") { return $true }
7
+ Try { $cinc_version = (Get-Content $root\version-manifest.txt | select-object -first 1) }
8
+ Catch {
9
+ Try { $cinc_version = (& $root\bin\cinc-solo.bat -v) }
10
+ Catch { $cinc_version = " " }
11
+ }
12
+
13
+ if ($cinc_version.split(" ", 2)[1].StartsWith($version)) { return $false }
14
+ else { return $true }
15
+ }
16
+
17
+ Function Get-CincMetadata($url) {
18
+ Try { $response = ($c = Make-WebClient).DownloadString($url) }
19
+ Finally { if ($c -ne $null) { $c.Dispose() } }
20
+
21
+ $md = ConvertFrom-StringData $response.Replace("`t", "=")
22
+ return @($md.url, $md.md5)
23
+ }
24
+
25
+ Function Get-MD5Sum($src) {
26
+ Try {
27
+ $c = New-Object -TypeName System.Security.Cryptography.MD5CryptoServiceProvider
28
+ $bytes = $c.ComputeHash(($in = (Get-Item $src).OpenRead()))
29
+ return ([System.BitConverter]::ToString($bytes)).Replace("-", "").ToLower()
30
+ } Finally { if (($c -ne $null) -and ($c.GetType().GetMethod("Dispose") -ne $null)) { $c.Dispose() }; if ($in -ne $null) { $in.Dispose() } }
31
+ }
32
+
33
+ Function Download-Cinc($md_url, $dst) {
34
+ $url, $md5 = Get-CincMetadata $md_url
35
+
36
+ Try {
37
+ Log "Downloading package from $url"
38
+ ($c = Make-WebClient).DownloadFile($url, $dst)
39
+ Log "Download complete."
40
+ } Finally { if ($c -ne $null) { $c.Dispose() } }
41
+
42
+ if (($dmd5 = Get-MD5Sum $dst) -eq $md5) { Log "Successfully verified $dst" }
43
+ else { throw "MD5 for $dst $dmd5 does not match $md5" }
44
+ }
45
+
46
+ Function Install-Cinc($msi) {
47
+ Log "Installing Cinc Client package $msi"
48
+ $p = Start-Process -FilePath "msiexec.exe" -ArgumentList "/qn /i $msi" -Passthru -Wait
49
+
50
+ if ($p.ExitCode -ne 0) { throw "msiexec was not successful. Received exit code $($p.ExitCode)" }
51
+
52
+ Remove-Item $msi -Force
53
+ Log "Installation complete"
54
+ }
55
+
56
+ Function Log($m) { Write-Host " $m`n" }
57
+
58
+ Function Make-WebClient {
59
+ $proxy = New-Object -TypeName System.Net.WebProxy
60
+ $proxy.Address = $env:http_proxy
61
+ $client = New-Object -TypeName System.Net.WebClient
62
+ $client.Proxy = $proxy
63
+ return $client
64
+ }
65
+
66
+ Function Unresolve-Path($p) {
67
+ if ($p -eq $null) { return $null }
68
+ else { return $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($p) }
69
+ }
70
+
71
+ Try {
72
+ $chef_omnibus_root = Unresolve-Path $chef_omnibus_root
73
+ $msi = Unresolve-Path $msi
74
+
75
+ if (Check-UpdateCinc $chef_omnibus_root $version) {
76
+ Write-Host "-----> Installing Cinc Client package ($pretty_version)`n"
77
+ Download-Cinc "$chef_metadata_url" $msi
78
+ Install-Cinc $msi
79
+ } else {
80
+ Write-Host "-----> Cinc Client package installation detected ($pretty_version)`n"
81
+ }
82
+ }
83
+ Catch {
84
+ Write-Error ($_ | ft -Property * | out-string) -ErrorAction Continue
85
+ exit 1
86
+ }
@@ -0,0 +1,229 @@
1
+ tmp_stderr="/tmp/stderr";
2
+
3
+ # capture_tmp_stderr SOURCE
4
+ capture_tmp_stderr() {
5
+ # spool up $tmp_stderr from all the commands we called
6
+ if test -f "$tmp_stderr"; then
7
+ output="`cat $tmp_stderr`";
8
+ stderr_results="${stderr_results}\nSTDERR from $1:\n\n${output}\n";
9
+ rm $tmp_stderr;
10
+ fi
11
+ }
12
+
13
+ # do_curl URL FILENAME
14
+ do_curl() {
15
+ echo "Trying curl...";
16
+ curl -sL -D "$tmp_stderr" "$1" > "$2";
17
+ ec=$?;
18
+ # check for 404
19
+ grep "404 Not Found" "$tmp_stderr" 2>&1 >/dev/null;
20
+ if test $? -eq 0; then
21
+ http_404_error "$1";
22
+ fi
23
+
24
+ # check for bad return status or empty output
25
+ if test $ec -ne 0 || test ! -s "$2"; then
26
+ capture_tmp_stderr "curl";
27
+ return 1;
28
+ else
29
+ echo "Download complete.";
30
+ return 0;
31
+ fi
32
+ }
33
+
34
+ # do_download URL FILENAME
35
+ do_download() {
36
+ echo "Downloading ${1} to file ${2}";
37
+
38
+ exists wget;
39
+ if test $? -eq 0; then
40
+ do_wget "$1" "$2" && return 0;
41
+ fi
42
+
43
+ exists curl;
44
+ if test $? -eq 0; then
45
+ do_curl "$1" "$2" && return 0;
46
+ fi
47
+
48
+ exists fetch;
49
+ if test $? -eq 0; then
50
+ do_fetch "$1" "$2" && return 0;
51
+ fi
52
+
53
+ exists python;
54
+ if test $? -eq 0; then
55
+ do_python "$1" "$2" && return 0;
56
+ fi
57
+
58
+ exists perl;
59
+ if test $? -eq 0; then
60
+ do_perl "$1" "$2" && return 0;
61
+ fi
62
+
63
+ unable_to_download "$1" "$2";
64
+ }
65
+
66
+ # do_fetch URL FILENAME
67
+ do_fetch() {
68
+ echo "Trying fetch...";
69
+ fetch -o "$2" "$1" 2>"$tmp_stderr";
70
+ ec=$?;
71
+ # check for 404
72
+ grep "Not Found" "$tmp_stderr" 2>&1 >/dev/null;
73
+ if test $? -eq 0; then
74
+ http_404_error "$1";
75
+ fi
76
+
77
+ # check for bad return status or empty output
78
+ if test $ec -ne 0 || test ! -s "$2"; then
79
+ capture_tmp_stderr "fetch";
80
+ return 1;
81
+ else
82
+ echo "Download complete.";
83
+ return 0;
84
+ fi
85
+ }
86
+
87
+ # do_perl URL FILENAME
88
+ do_perl() {
89
+ echo "Trying perl...";
90
+ perl -e "use LWP::Simple; getprint(\$ARGV[0]);" "$1" > "$2" 2>"$tmp_stderr";
91
+ ec=$?;
92
+ # check for 404
93
+ grep "404 Not Found" "$tmp_stderr" 2>&1 >/dev/null;
94
+ if test $? -eq 0; then
95
+ http_404_error "$1";
96
+ fi
97
+
98
+ # check for bad return status or empty output
99
+ if test $ec -ne 0 || test ! -s "$2"; then
100
+ capture_tmp_stderr "perl";
101
+ return 1;
102
+ else
103
+ echo "Download complete.";
104
+ return 0;
105
+ fi
106
+ }
107
+
108
+ # do_python URL FILENAME
109
+ do_python() {
110
+ echo "Trying python...";
111
+ python -c "import sys,urllib2 ; sys.stdout.write(urllib2.urlopen(sys.argv[1]).read())" "$1" > "$2" 2>"$tmp_stderr";
112
+ ec=$?;
113
+ # check for 404
114
+ grep "HTTP Error 404" "$tmp_stderr" 2>&1 >/dev/null;
115
+ if test $? -eq 0; then
116
+ http_404_error "$1";
117
+ fi
118
+
119
+ # check for bad return status or empty output
120
+ if test $ec -ne 0 || test ! -s "$2"; then
121
+ capture_tmp_stderr "python";
122
+ return 1;
123
+ else
124
+ echo "Download complete.";
125
+ return 0;
126
+ fi
127
+ }
128
+
129
+ # do_wget URL FILENAME
130
+ do_wget() {
131
+ echo "Trying wget...";
132
+ wget -O "$2" "$1" 2>"$tmp_stderr";
133
+ ec=$?;
134
+ # check for 404
135
+ grep "ERROR 404" "$tmp_stderr" 2>&1 >/dev/null;
136
+ if test $? -eq 0; then
137
+ http_404_error "$1";
138
+ fi
139
+
140
+ # check for bad return status or empty output
141
+ if test $ec -ne 0 || test ! -s "$2"; then
142
+ capture_tmp_stderr "wget";
143
+ return 1;
144
+ else
145
+ echo "Download complete.";
146
+ return 0;
147
+ fi
148
+ }
149
+
150
+ # exists COMMAND
151
+ exists() {
152
+ if command -v "$1" >/dev/null 2>&1; then
153
+ return 0;
154
+ else
155
+ return 1;
156
+ fi
157
+ }
158
+
159
+ # http_404_error URL
160
+ http_404_error() {
161
+ echo ">>>>>> Downloading ${1} resulted in an HTTP/404, aborting";
162
+ exit 40;
163
+ }
164
+
165
+ # should_update_cinc ROOT VERSION
166
+ should_update_cinc() {
167
+ if test ! -d "$1"; then
168
+ return 0;
169
+ elif test "$2" = "true"; then
170
+ return 1;
171
+ elif test "$2" = "latest"; then
172
+ return 0;
173
+ fi
174
+
175
+ if test -f "${1}/version-manifest.txt"; then
176
+ cinc_version="`head -n 1 ${1}/version-manifest.txt | cut -d \" \" -f 2`";
177
+ else
178
+ cinc_version="`${1}/bin/cinc-solo -v | cut -d \" \" -f 2`";
179
+ fi
180
+
181
+ echo "$cinc_version" | grep "^${2}" 2>&1 >/dev/null;
182
+ if test $? -eq 0; then
183
+ return 1;
184
+ else
185
+ echo "${2}" | grep "^$cinc_version" 2>&1 >/dev/null;
186
+ if test $? -eq 0; then
187
+ return 1;
188
+ else
189
+ return 0;
190
+ fi
191
+ fi
192
+ }
193
+
194
+ # unable_to_download URL FILE
195
+ unable_to_download() {
196
+ echo "Unable to download $1 to $2, aborting";
197
+
198
+ if test "x${stderr_results}" != "x"; then
199
+ echo "\nDEBUG OUTPUT FOLLOWS:\n${stderr_results}";
200
+ fi
201
+
202
+ exit 10;
203
+ }
204
+
205
+ # main
206
+ main() {
207
+ should_update_cinc "$chef_omnibus_root" "$version"
208
+ if test $? -eq 0; then
209
+ echo "-----> Installing Cinc Client package (${pretty_version})";
210
+
211
+ # solaris 10 lacks recent enough credentials, so http url is used
212
+ platform="`/usr/bin/uname -s 2>/dev/null`";
213
+ platform_version="`/usr/bin/uname -r 2>/dev/null`";
214
+ if test "x${platform}" = "xSunOS" && test "x${platform_version}" = "x5.10"; then
215
+ chef_omnibus_url=`echo "$chef_omnibus_url" | sed -e "s/https/http/"`;
216
+ fi
217
+
218
+ do_download "$chef_omnibus_url" /tmp/install.sh;
219
+ $sudo_sh /tmp/install.sh $install_flags;
220
+ else
221
+ echo "-----> Cinc Client package installation detected (${pretty_version})";
222
+ fi
223
+ }
224
+
225
+ # augment path in an attempt to find a download program
226
+ PATH="${PATH}:/opt/local/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/usr/sfw/bin";
227
+ export PATH;
228
+
229
+ main
@@ -0,0 +1,99 @@
1
+ # Check whether a command exists - returns 0 if it does, 1 if it does not
2
+ exists() {
3
+ if command -v $1 >/dev/null 2>&1
4
+ then
5
+ return 0
6
+ else
7
+ return 1
8
+ fi
9
+ }
10
+
11
+ # do_wget URL FILENAME
12
+ do_wget() {
13
+ echo "trying wget..."
14
+ wget -O "$2" "$1" 2>/tmp/stderr
15
+ # check for bad return status
16
+ test $? -ne 0 && return 1
17
+ # check for 404 or empty file
18
+ grep "ERROR 404" /tmp/stderr 2>&1 >/dev/null
19
+ if test $? -eq 0 || test ! -s "$2"; then
20
+ return 1
21
+ fi
22
+ return 0
23
+ }
24
+
25
+ # do_curl URL FILENAME
26
+ do_curl() {
27
+ echo "trying curl..."
28
+ curl -L "$1" > "$2"
29
+ # check for bad return status
30
+ [ $? -ne 0 ] && return 1
31
+ # check for bad output or empty file
32
+ grep "The specified key does not exist." "$2" 2>&1 >/dev/null
33
+ if test $? -eq 0 || test ! -s "$2"; then
34
+ return 1
35
+ fi
36
+ return 0
37
+ }
38
+
39
+ # do_fetch URL FILENAME
40
+ do_fetch() {
41
+ echo "trying fetch..."
42
+ fetch -o "$2" "$1" 2>/tmp/stderr
43
+ # check for bad return status
44
+ test $? -ne 0 && return 1
45
+ return 0
46
+ }
47
+
48
+ # do_perl URL FILENAME
49
+ do_perl() {
50
+ echo "trying perl..."
51
+ perl -e "use LWP::Simple; getprint($ARGV[0]);" "$1" > "$2"
52
+ # check for bad return status
53
+ test $? -ne 0 && return 1
54
+ return 0
55
+ }
56
+
57
+ # do_python URL FILENAME
58
+ do_python() {
59
+ echo "trying python..."
60
+ python -c "import sys,urllib2 ; sys.stdout.write(urllib2.urlopen(sys.argv[1]).read())" "$1" > "$2"
61
+ # check for bad return status
62
+ test $? -ne 0 && return 1
63
+ return 0
64
+ }
65
+
66
+ # do_download URL FILENAME
67
+ do_download() {
68
+ PATH=/opt/local/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
69
+ export PATH
70
+
71
+ echo "downloading $1"
72
+ echo " to file $2"
73
+
74
+ # we try all of these until we get success.
75
+ # perl, in particular may be present but LWP::Simple may not be installed
76
+
77
+ if exists wget; then
78
+ do_wget $1 $2 && return 0
79
+ fi
80
+
81
+ if exists curl; then
82
+ do_curl $1 $2 && return 0
83
+ fi
84
+
85
+ if exists fetch; then
86
+ do_fetch $1 $2 && return 0
87
+ fi
88
+
89
+ if exists perl; then
90
+ do_perl $1 $2 && return 0
91
+ fi
92
+
93
+ if exists python; then
94
+ do_python $1 $2 && return 0
95
+ fi
96
+
97
+ echo ">>>>>> wget, curl, fetch, perl or python not found on this instance."
98
+ return 16
99
+ }