chef-provisioning 0.15

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +207 -0
  3. data/LICENSE +201 -0
  4. data/README.md +260 -0
  5. data/Rakefile +6 -0
  6. data/lib/chef/provider/load_balancer.rb +77 -0
  7. data/lib/chef/provider/machine.rb +176 -0
  8. data/lib/chef/provider/machine_batch.rb +191 -0
  9. data/lib/chef/provider/machine_execute.rb +35 -0
  10. data/lib/chef/provider/machine_file.rb +54 -0
  11. data/lib/chef/provider/machine_image.rb +60 -0
  12. data/lib/chef/provisioning.rb +95 -0
  13. data/lib/chef/provisioning/action_handler.rb +68 -0
  14. data/lib/chef/provisioning/add_prefix_action_handler.rb +31 -0
  15. data/lib/chef/provisioning/chef_image_spec.rb +108 -0
  16. data/lib/chef/provisioning/chef_load_balancer_spec.rb +108 -0
  17. data/lib/chef/provisioning/chef_machine_spec.rb +84 -0
  18. data/lib/chef/provisioning/chef_provider_action_handler.rb +74 -0
  19. data/lib/chef/provisioning/chef_run_data.rb +139 -0
  20. data/lib/chef/provisioning/convergence_strategy.rb +28 -0
  21. data/lib/chef/provisioning/convergence_strategy/install_cached.rb +156 -0
  22. data/lib/chef/provisioning/convergence_strategy/install_msi.rb +58 -0
  23. data/lib/chef/provisioning/convergence_strategy/install_sh.rb +55 -0
  24. data/lib/chef/provisioning/convergence_strategy/no_converge.rb +39 -0
  25. data/lib/chef/provisioning/convergence_strategy/precreate_chef_objects.rb +183 -0
  26. data/lib/chef/provisioning/driver.rb +304 -0
  27. data/lib/chef/provisioning/image_spec.rb +72 -0
  28. data/lib/chef/provisioning/load_balancer_spec.rb +86 -0
  29. data/lib/chef/provisioning/machine.rb +112 -0
  30. data/lib/chef/provisioning/machine/basic_machine.rb +84 -0
  31. data/lib/chef/provisioning/machine/unix_machine.rb +278 -0
  32. data/lib/chef/provisioning/machine/windows_machine.rb +104 -0
  33. data/lib/chef/provisioning/machine_spec.rb +82 -0
  34. data/lib/chef/provisioning/recipe_dsl.rb +103 -0
  35. data/lib/chef/provisioning/transport.rb +95 -0
  36. data/lib/chef/provisioning/transport/ssh.rb +343 -0
  37. data/lib/chef/provisioning/transport/winrm.rb +151 -0
  38. data/lib/chef/provisioning/version.rb +5 -0
  39. data/lib/chef/resource/chef_data_bag_resource.rb +148 -0
  40. data/lib/chef/resource/load_balancer.rb +57 -0
  41. data/lib/chef/resource/machine.rb +124 -0
  42. data/lib/chef/resource/machine_batch.rb +78 -0
  43. data/lib/chef/resource/machine_execute.rb +28 -0
  44. data/lib/chef/resource/machine_file.rb +34 -0
  45. data/lib/chef/resource/machine_image.rb +35 -0
  46. data/lib/chef_metal.rb +1 -0
  47. metadata +217 -0
@@ -0,0 +1,72 @@
1
+ class Chef
2
+ module Provisioning
3
+ #
4
+ # Specification for a image. Sufficient information to find and contact it
5
+ # after it has been set up.
6
+ #
7
+ class ImageSpec
8
+ def initialize(image_data)
9
+ @image_data = image_data
10
+ end
11
+
12
+ attr_reader :image_data
13
+
14
+ #
15
+ # Globally unique identifier for this image. Does not depend on the image's
16
+ # location or existence.
17
+ #
18
+ def id
19
+ raise "id unimplemented"
20
+ end
21
+
22
+ #
23
+ # Name of the image. Corresponds to the name in "image 'name' do" ...
24
+ #
25
+ def name
26
+ image_data['id']
27
+ end
28
+
29
+ #
30
+ # Location of this image. This should be a freeform hash, with enough
31
+ # information for the driver to look it up and create a image object to
32
+ # access it.
33
+ #
34
+ # This MUST include a 'driver_url' attribute with the driver's URL in it.
35
+ #
36
+ # chef-provisioning will do its darnedest to not lose this information.
37
+ #
38
+ def location
39
+ image_data['location']
40
+ end
41
+
42
+ #
43
+ # Set the location for this image.
44
+ #
45
+ def location=(value)
46
+ image_data['location'] = value
47
+ end
48
+
49
+ def machine_options
50
+ image_data['machine_options']
51
+ end
52
+
53
+ def machine_options=(value)
54
+ image_data['machine_options'] = value
55
+ end
56
+
57
+ # URL to the driver. Convenience for location['driver_url']
58
+ def driver_url
59
+ location ? location['driver_url'] : nil
60
+ end
61
+
62
+ #
63
+ # Save this image_data to the server. If you have significant information that
64
+ # could be lost, you should do this as quickly as possible. image_data will be
65
+ # saved automatically for you after allocate_image and ready_image.
66
+ #
67
+ def save(action_handler)
68
+ raise "save unimplemented"
69
+ end
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,86 @@
1
+ class Chef
2
+ module Provisioning
3
+ #
4
+ # Specification for a machine. Sufficient information to find and contact it
5
+ # after it has been set up.
6
+ #
7
+ # TODO: This is pretty similar to image_spec, generalize this.
8
+ class LoadBalancerSpec
9
+ def initialize(load_balancer_data)
10
+ @load_balancer_data = load_balancer_data
11
+ # Upgrade from metal to chef_provisioning ASAP.
12
+ if @load_balancer_data['normal'] && !@load_balancer_data['normal']['chef_provisioning'] && @load_balancer_data['normal']['metal']
13
+ @load_balancer_data['normal']['chef_provisioning'] = @load_balancer_data['normal'].delete('metal')
14
+ end
15
+ end
16
+
17
+ attr_reader :load_balancer_data
18
+ attr_reader :machines
19
+
20
+ #
21
+ # Globally unique identifier for this machine. Does not depend on the machine's
22
+ # location or existence.
23
+ #
24
+ def id
25
+ raise "id unimplemented"
26
+ end
27
+
28
+ #
29
+ # Name of the machine. Corresponds to the name in "machine 'name' do" ...
30
+ #
31
+ def name
32
+ load_balancer_data['id']
33
+ end
34
+
35
+ #
36
+ # Location of this machine. This should be a freeform hash, with enough
37
+ # information for the driver to look it up and create a Machine object to
38
+ # access it.
39
+ #
40
+ # This MUST include a 'driver_url' attribute with the driver's URL in it.
41
+ #
42
+ # chef-provisioning will do its darnedest to not lose this information.
43
+ #
44
+ def location
45
+ load_balancer_data['location']
46
+ end
47
+
48
+ #
49
+ # Set the location for this machine.
50
+ #
51
+ def location=(value)
52
+ load_balancer_data['location'] = value
53
+ end
54
+
55
+ def load_balancer_options
56
+ load_balancer_data['load_balancer_options']
57
+ end
58
+
59
+ def load_balancer_options=(value)
60
+ load_balancer_data['load_balancer_options'] = value
61
+ end
62
+
63
+ # URL to the driver. Convenience for location['driver_url']
64
+ def driver_url
65
+ location ? location['driver_url'] : nil
66
+ end
67
+
68
+
69
+ def machines
70
+ load_balancer_data['machines'] || []
71
+ end
72
+
73
+ def machines=(value)
74
+ load_balancer_data['machines'] = value
75
+ end
76
+
77
+ #
78
+ # Save this node to the server. If you have significant information that
79
+ # could be lost, you should do this as quickly as possible. Data will be
80
+ # saved automatically for you after allocate_machine and ready_machine.
81
+ #
82
+ def save(action_handler)
83
+ raise "save unimplemented"
84
+ end
85
+ end
86
+ end
@@ -0,0 +1,112 @@
1
+ class Chef
2
+ module Provisioning
3
+ class Machine
4
+ def initialize(machine_spec)
5
+ @machine_spec = machine_spec
6
+ end
7
+
8
+ attr_reader :machine_spec
9
+
10
+ def name
11
+ machine_spec.name
12
+ end
13
+
14
+ def node
15
+ machine_spec.node
16
+ end
17
+
18
+ # Sets up everything necessary for convergence to happen on the machine.
19
+ # The node MUST be saved as part of this procedure. Other than that,
20
+ # nothing is guaranteed except that converge() will work when this is done.
21
+ def setup_convergence(action_handler)
22
+ raise "setup_convergence not overridden on #{self.class}"
23
+ end
24
+
25
+ def converge(action_handler)
26
+ raise "converge not overridden on #{self.class}"
27
+ end
28
+
29
+ def cleanup_convergence(action_handler)
30
+ raise "cleanup_convergence not overridden on #{self.class}"
31
+ end
32
+
33
+ def execute(action_handler, command, options = {})
34
+ raise "execute not overridden on #{self.class}"
35
+ end
36
+
37
+ def execute_always(command, options = {})
38
+ raise "execute_always not overridden on #{self.class}"
39
+ end
40
+
41
+ def read_file(path)
42
+ raise "read_file not overridden on #{self.class}"
43
+ end
44
+
45
+ def download_file(action_handler, path, local_path)
46
+ raise "read_file not overridden on #{self.class}"
47
+ end
48
+
49
+ def write_file(action_handler, path, content)
50
+ raise "write_file not overridden on #{self.class}"
51
+ end
52
+
53
+ def upload_file(action_handler, local_path, path)
54
+ raise "write_file not overridden on #{self.class}"
55
+ end
56
+
57
+ def create_dir(action_handler, path)
58
+ raise "create_dir not overridden on #{self.class}"
59
+ end
60
+
61
+ # Delete file
62
+ def delete_file(action_handler, path)
63
+ raise "delete_file not overridden on #{self.class}"
64
+ end
65
+
66
+ # Return true if directory, false/nil if not
67
+ def is_directory?(path)
68
+ raise "is_directory? not overridden on #{self.class}"
69
+ end
70
+
71
+ # Return true or false depending on whether file exists
72
+ def file_exists?(path)
73
+ raise "file_exists? not overridden on #{self.class}"
74
+ end
75
+
76
+ # Return true or false depending on whether remote file differs from local path or content
77
+ def files_different?(path, local_path, content=nil)
78
+ raise "file_different? not overridden on #{self.class}"
79
+ end
80
+
81
+ # Set file attributes { mode, :owner, :group }
82
+ def set_attributes(action_handler, path, attributes)
83
+ raise "set_attributes not overridden on #{self.class}"
84
+ end
85
+
86
+ # Get file attributes { :mode, :owner, :group }
87
+ def get_attributes(path)
88
+ raise "get_attributes not overridden on #{self.class}"
89
+ end
90
+
91
+ # Ensure the given URL can be reached by the remote side (possibly by port forwarding)
92
+ # Must return the URL that the remote side can use to reach the local_url
93
+ def make_url_available_to_remote(local_url)
94
+ raise "make_url_available_to_remote not overridden on #{self.class}"
95
+ end
96
+
97
+ def disconnect
98
+ raise "disconnect not overridden on #{self.class}"
99
+ end
100
+
101
+ # TODO get rid of the action_handler attribute, that is ridiculous
102
+ # Detect the OS on the machine (assumes the machine is up)
103
+ # Returns a triplet:
104
+ # platform, platform_version, machine_architecture = machine.detect_os(action_handler)
105
+ # This triplet is suitable for passing to the Chef metadata API:
106
+ # https://www.opscode.com/chef/metadata?p=PLATFORM&pv=PLATFORM_VERSION&m=MACHINE_ARCHITECTURE
107
+ def detect_os(action_handler)
108
+ raise "detect_os not overridden on #{self.class}"
109
+ end
110
+ end
111
+ end
112
+ end
@@ -0,0 +1,84 @@
1
+ require 'chef/provisioning/machine'
2
+
3
+ class Chef
4
+ module Provisioning
5
+ class Machine
6
+ class BasicMachine < Machine
7
+ def initialize(machine_spec, transport, convergence_strategy)
8
+ super(machine_spec)
9
+ @transport = transport
10
+ @convergence_strategy = convergence_strategy
11
+ end
12
+
13
+ attr_reader :transport
14
+ attr_reader :convergence_strategy
15
+
16
+ def setup_convergence(action_handler)
17
+ convergence_strategy.setup_convergence(action_handler, self)
18
+ end
19
+
20
+ def converge(action_handler)
21
+ convergence_strategy.converge(action_handler, self)
22
+ end
23
+
24
+ def cleanup_convergence(action_handler)
25
+ convergence_strategy.cleanup_convergence(action_handler, machine_spec)
26
+ end
27
+
28
+ def execute(action_handler, command, options = {})
29
+ action_handler.perform_action "run '#{command}' on #{machine_spec.name}" do
30
+ result = transport.execute(command, options)
31
+ result.error!
32
+ result
33
+ end
34
+ end
35
+
36
+ def execute_always(command, options = {})
37
+ transport.execute(command, options)
38
+ end
39
+
40
+ def read_file(path)
41
+ transport.read_file(path)
42
+ end
43
+
44
+ def download_file(action_handler, path, local_path)
45
+ if files_different?(path, local_path)
46
+ action_handler.perform_action "download file #{path} on #{machine_spec.name} to #{local_path}" do
47
+ transport.download_file(path, local_path)
48
+ end
49
+ end
50
+ end
51
+
52
+ def write_file(action_handler, path, content, options = {})
53
+ if files_different?(path, nil, content)
54
+ if options[:ensure_dir]
55
+ create_dir(action_handler, dirname_on_machine(path))
56
+ end
57
+ action_handler.perform_action "write file #{path} on #{machine_spec.name}" do
58
+ transport.write_file(path, content)
59
+ end
60
+ end
61
+ end
62
+
63
+ def upload_file(action_handler, local_path, path, options = {})
64
+ if files_different?(path, local_path)
65
+ if options[:ensure_dir]
66
+ create_dir(action_handler, dirname_on_machine(path))
67
+ end
68
+ action_handler.perform_action "upload file #{local_path} to #{path} on #{machine_spec.name}" do
69
+ transport.upload_file(local_path, path)
70
+ end
71
+ end
72
+ end
73
+
74
+ def make_url_available_to_remote(local_url)
75
+ transport.make_url_available_to_remote(local_url)
76
+ end
77
+
78
+ def disconnect
79
+ transport.disconnect
80
+ end
81
+ end
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,278 @@
1
+ require 'chef/provisioning/machine/basic_machine'
2
+ require 'digest'
3
+
4
+ class Chef
5
+ module Provisioning
6
+ class Machine
7
+ class UnixMachine < BasicMachine
8
+ def initialize(machine_spec, transport, convergence_strategy)
9
+ super
10
+
11
+ @tmp_dir = '/tmp'
12
+ end
13
+
14
+ # Options include:
15
+ #
16
+ # command_prefix - prefix to put in front of any command, e.g. sudo
17
+ attr_reader :options
18
+
19
+ # Delete file
20
+ def delete_file(action_handler, path)
21
+ if file_exists?(path)
22
+ action_handler.perform_action "delete file #{path} on #{machine_spec.name}" do
23
+ transport.execute("rm -f #{path}").error!
24
+ end
25
+ end
26
+ end
27
+
28
+ def is_directory?(path)
29
+ result = transport.execute("stat -c '%F' #{path}", :read_only => true)
30
+ return nil if result.exitstatus != 0
31
+ result.stdout.chomp == 'directory'
32
+ end
33
+
34
+ # Return true or false depending on whether file exists
35
+ def file_exists?(path)
36
+ result = transport.execute("ls -d #{path}", :read_only => true)
37
+ result.exitstatus == 0 && result.stdout != ''
38
+ end
39
+
40
+ def files_different?(path, local_path, content=nil)
41
+ if !file_exists?(path) || (local_path && !File.exists?(local_path))
42
+ return true
43
+ end
44
+
45
+ # Get remote checksum of file
46
+ result = transport.execute("md5sum -b #{path}", :read_only => true)
47
+ result.error!
48
+ remote_sum = result.stdout.split(' ')[0]
49
+
50
+ digest = Digest::MD5.new
51
+ if content
52
+ digest.update(content)
53
+ else
54
+ File.open(local_path, 'rb') do |io|
55
+ while (buf = io.read(4096)) && buf.length > 0
56
+ digest.update(buf)
57
+ end
58
+ end
59
+ end
60
+ remote_sum != digest.hexdigest
61
+ end
62
+
63
+ def create_dir(action_handler, path)
64
+ if !file_exists?(path)
65
+ action_handler.perform_action "create directory #{path} on #{machine_spec.name}" do
66
+ transport.execute("mkdir -p #{path}").error!
67
+ end
68
+ end
69
+ end
70
+
71
+ # Set file attributes { mode, :owner, :group }
72
+ def set_attributes(action_handler, path, attributes)
73
+ if attributes[:mode] || attributes[:owner] || attributes[:group]
74
+ current_attributes = get_attributes(path)
75
+ if attributes[:mode] && current_attributes[:mode].to_i != attributes[:mode].to_i
76
+ action_handler.perform_action "change mode of #{path} on #{machine_spec.name} from #{current_attributes[:mode].to_i} to #{attributes[:mode].to_i}" do
77
+ transport.execute("chmod #{attributes[:mode].to_i} #{path}").error!
78
+ end
79
+ end
80
+ if attributes[:owner] && current_attributes[:owner] != attributes[:owner]
81
+ action_handler.perform_action "change group of #{path} on #{machine_spec.name} from #{current_attributes[:owner]} to #{attributes[:owner]}" do
82
+ transport.execute("chown #{attributes[:owner]} #{path}").error!
83
+ end
84
+ end
85
+ if attributes[:group] && current_attributes[:group] != attributes[:group]
86
+ action_handler.perform_action "change group of #{path} on #{machine_spec.name} from #{current_attributes[:group]} to #{attributes[:group]}" do
87
+ transport.execute("chgrp #{attributes[:group]} #{path}").error!
88
+ end
89
+ end
90
+ end
91
+ end
92
+
93
+ # Get file attributes { :mode, :owner, :group }
94
+ def get_attributes(path)
95
+ result = transport.execute("stat -c '%a %U %G %n' #{path}", :read_only => true)
96
+ return nil if result.exitstatus != 0
97
+ file_info = result.stdout.split(/\s+/)
98
+ if file_info.size <= 1
99
+ raise "#{path} does not exist in set_attributes()"
100
+ end
101
+ result = {
102
+ :mode => file_info[0],
103
+ :owner => file_info[1],
104
+ :group => file_info[2]
105
+ }
106
+ end
107
+
108
+ def dirname_on_machine(path)
109
+ path.split('/')[0..-2].join('/')
110
+ end
111
+ end
112
+
113
+ def detect_os(action_handler)
114
+ #
115
+ # Use detect.sh to detect the operating system of the remote machine
116
+ #
117
+ # TODO do this in terms of commands rather than writing a shell script
118
+ self.write_file(action_handler, "#{@tmp_dir}/detect.sh", detect_sh)
119
+ detected = self.execute_always("sh #{@tmp_dir}/detect.sh")
120
+ if detected.exitstatus != 0
121
+ raise "detect.sh exited with nonzero exit status: #{detected.exitstatus}"
122
+ end
123
+ platform = nil
124
+ platform_version = nil
125
+ machine_architecture = nil
126
+ detected.stdout.each_line do |line|
127
+ if line =~ /^PLATFORM: (.+)/
128
+ platform = $1
129
+ elsif line =~ /^PLATFORM_VERSION: (.+)/
130
+ platform_version = $1
131
+ elsif line =~ /^MACHINE: (.+)/
132
+ machine_architecture = $1
133
+ end
134
+ end
135
+ [ platform, platform_version, machine_architecture ]
136
+ end
137
+
138
+ private
139
+
140
+ def detect_sh
141
+ result = <<EOM
142
+ prerelease="false"
143
+
144
+ project="chef"
145
+
146
+ report_bug() {
147
+ echo "Please file a bug report at http://tickets.opscode.com"
148
+ echo "Project: Chef"
149
+ echo "Component: Packages"
150
+ echo "Label: Omnibus"
151
+ echo "Version: $version"
152
+ echo " "
153
+ echo "Please detail your operating system type, version and any other relevant details"
154
+ }
155
+
156
+
157
+ machine=`uname -m`
158
+ os=`uname -s`
159
+
160
+ # Retrieve Platform and Platform Version
161
+ if test -f "/etc/lsb-release" && grep -q DISTRIB_ID /etc/lsb-release; then
162
+ platform=`grep DISTRIB_ID /etc/lsb-release | cut -d "=" -f 2 | tr '[A-Z]' '[a-z]'`
163
+ platform_version=`grep DISTRIB_RELEASE /etc/lsb-release | cut -d "=" -f 2`
164
+ elif test -f "/etc/debian_version"; then
165
+ platform="debian"
166
+ platform_version=`cat /etc/debian_version`
167
+ elif test -f "/etc/redhat-release"; then
168
+ platform=`sed 's/^\\(.\\+\\) release.*/\\1/' /etc/redhat-release | tr '[A-Z]' '[a-z]'`
169
+ platform_version=`sed 's/^.\\+ release \\([.0-9]\\+\\).*/\\1/' /etc/redhat-release`
170
+
171
+ # If /etc/redhat-release exists, we act like RHEL by default
172
+ if test "$platform" = "fedora"; then
173
+ # Change platform version for use below.
174
+ platform_version="6.0"
175
+ fi
176
+ platform="el"
177
+ elif test -f "/etc/system-release"; then
178
+ platform=`sed 's/^\\(.\\+\\) release.\\+/\\1/' /etc/system-release | tr '[A-Z]' '[a-z]'`
179
+ platform_version=`sed 's/^.\\+ release \\([.0-9]\\+\\).*/\\1/' /etc/system-release | tr '[A-Z]' '[a-z]'`
180
+ # amazon is built off of fedora, so act like RHEL
181
+ if test "$platform" = "amazon linux ami"; then
182
+ platform="el"
183
+ platform_version="6.0"
184
+ fi
185
+ # Apple OS X
186
+ elif test -f "/usr/bin/sw_vers"; then
187
+ platform="mac_os_x"
188
+ # Matching the tab-space with sed is error-prone
189
+ platform_version=`sw_vers | awk '/^ProductVersion:/ { print $2 }'`
190
+
191
+ major_version=`echo $platform_version | cut -d. -f1,2`
192
+ case $major_version in
193
+ "10.6") platform_version="10.6" ;;
194
+ "10.7"|"10.8"|"10.9") platform_version="10.7" ;;
195
+ *) echo "No builds for platform: $major_version"
196
+ report_bug
197
+ exit 1
198
+ ;;
199
+ esac
200
+
201
+ # x86_64 Apple hardware often runs 32-bit kernels (see OHAI-63)
202
+ x86_64=`sysctl -n hw.optional.x86_64`
203
+ if test $x86_64 -eq 1; then
204
+ machine="x86_64"
205
+ fi
206
+ elif test -f "/etc/release"; then
207
+ platform="solaris2"
208
+ machine=`/usr/bin/uname -p`
209
+ platform_version=`/usr/bin/uname -r`
210
+ elif test -f "/etc/SuSE-release"; then
211
+ if grep -q 'Enterprise' /etc/SuSE-release;
212
+ then
213
+ platform="sles"
214
+ platform_version=`awk '/^VERSION/ {V = $3}; /^PATCHLEVEL/ {P = $3}; END {print V "." P}' /etc/SuSE-release`
215
+ else
216
+ platform="suse"
217
+ platform_version=`awk '/^VERSION =/ { print $3 }' /etc/SuSE-release`
218
+ fi
219
+ elif test "x$os" = "xFreeBSD"; then
220
+ platform="freebsd"
221
+ platform_version=`uname -r | sed 's/-.*//'`
222
+ elif test "x$os" = "xAIX"; then
223
+ platform="aix"
224
+ platform_version=`uname -v`
225
+ machine="ppc"
226
+ fi
227
+
228
+ if test "x$platform" = "x"; then
229
+ echo "Unable to determine platform version!"
230
+ report_bug
231
+ exit 1
232
+ fi
233
+
234
+ # Mangle $platform_version to pull the correct build
235
+ # for various platforms
236
+ major_version=`echo $platform_version | cut -d. -f1`
237
+ case $platform in
238
+ "el")
239
+ platform_version=$major_version
240
+ ;;
241
+ "debian")
242
+ case $major_version in
243
+ "5") platform_version="6";;
244
+ "6") platform_version="6";;
245
+ "7") platform_version="6";;
246
+ esac
247
+ ;;
248
+ "freebsd")
249
+ platform_version=$major_version
250
+ ;;
251
+ "sles")
252
+ platform_version=$major_version
253
+ ;;
254
+ "suse")
255
+ platform_version=$major_version
256
+ ;;
257
+ esac
258
+
259
+ if test "x$platform_version" = "x"; then
260
+ echo "Unable to determine platform version!"
261
+ report_bug
262
+ exit 1
263
+ fi
264
+
265
+ if test "x$platform" = "xsolaris2"; then
266
+ # hack up the path on Solaris to find wget
267
+ PATH=/usr/sfw/bin:$PATH
268
+ export PATH
269
+ fi
270
+
271
+ echo "PLATFORM: $platform"
272
+ echo "PLATFORM_VERSION: $platform_version"
273
+ echo "MACHINE: $machine"
274
+ EOM
275
+ end
276
+ end
277
+ end
278
+ end