Vendor the external cookbooks
Knife-Zero doesn't include Berkshelf support, so vendoring everything in the repo is convenient again
This commit is contained in:
202
cookbooks/java/resources/adoptopenjdk_install.rb
Normal file
202
cookbooks/java/resources/adoptopenjdk_install.rb
Normal file
@@ -0,0 +1,202 @@
|
||||
#
|
||||
# Cookbook:: java
|
||||
# Resource:: adoptopenjdk_install
|
||||
#
|
||||
# Based on oracle_install.rb by Bryan W. Berry (<bryan.berry@gmail.com>)
|
||||
#
|
||||
|
||||
resource_name :adoptopenjdk_install
|
||||
|
||||
default_action :install
|
||||
|
||||
property :url, String
|
||||
property :checksum, String, regex: /^[0-9a-f]{32}$|^[a-zA-Z0-9]{40,64}$/
|
||||
property :md5, String, regex: /^[0-9a-f]{32}$|^[a-zA-Z0-9]{40,64}$/
|
||||
property :app_home, String
|
||||
property :app_home_mode, Integer, default: 0755
|
||||
property :bin_cmds, Array, default: []
|
||||
property :owner, String, default: 'root'
|
||||
property :group, String, default: lazy { node['root_group'] }
|
||||
property :default, [true, false], default: true
|
||||
property :alternatives_priority, Integer, default: 1
|
||||
property :reset_alternatives, [true, false], default: true
|
||||
property :variant, ['hotspot', 'openj9', 'openj9-large-heap'], default: 'openj9'
|
||||
|
||||
action :install do
|
||||
raise 'No URL provided to download AdoptOpenJDK\'s tar file!' if new_resource.url.nil? || new_resource.url.empty?
|
||||
app_dir_name, tarball_name, app_root, app_dir =
|
||||
parse_dir_names(new_resource.url,
|
||||
new_resource.app_home,
|
||||
new_resource.variant)
|
||||
app_group = new_resource.group
|
||||
app_home = new_resource.app_home
|
||||
Chef::Log.debug("processing #{new_resource.variant} variant")
|
||||
|
||||
directory app_root do
|
||||
owner new_resource.owner
|
||||
group app_group
|
||||
mode new_resource.app_home_mode
|
||||
recursive true
|
||||
action :nothing
|
||||
end.run_action(:create)
|
||||
|
||||
unless ::File.exist?(app_dir)
|
||||
download_path = "#{node['java']['download_path']}/#{tarball_name}"
|
||||
if adoptopendjk_downloaded?(download_path, new_resource)
|
||||
Chef::Log.debug('AdoptOpenJDK tarball already downloaded, not downloading again')
|
||||
else
|
||||
Chef::Log.debug("downloading tarball from #{URI.parse(new_resource.url).host}")
|
||||
remote_file "#{node['java']['download_path']}/#{tarball_name}" do
|
||||
source new_resource.url
|
||||
checksum new_resource.checksum
|
||||
retries new_resource.retries
|
||||
retry_delay new_resource.retry_delay
|
||||
mode 0o644
|
||||
action :nothing
|
||||
end.run_action(:create_if_missing)
|
||||
end
|
||||
|
||||
converge_by("extract compressed data into Chef file cache path and move extracted data to #{app_dir}") do
|
||||
package 'tar' do
|
||||
not_if { platform_family?('mac_os_x', 'windows') }
|
||||
action :nothing
|
||||
end.run_action(:install)
|
||||
|
||||
cmd = shell_out(%(tar xvzf "#{node['java']['download_path']}/#{tarball_name}" -C "#{node['java']['download_path']}" --no-same-owner)
|
||||
)
|
||||
unless cmd.exitstatus == 0
|
||||
Chef::Application.fatal!("Failed to extract file #{tarball_name}!")
|
||||
end
|
||||
|
||||
cmd = shell_out(
|
||||
%(mv "#{node['java']['download_path']}/#{app_dir_name}" "#{app_dir}" )
|
||||
)
|
||||
unless cmd.exitstatus == 0
|
||||
Chef::Application.fatal!(%( Command \' mv "#{node['java']['download_path']}/#{app_dir_name}" "#{app_dir}" \' failed ))
|
||||
end
|
||||
|
||||
# change ownership of extracted files
|
||||
FileUtils.chown_R new_resource.owner, app_group, app_dir
|
||||
end
|
||||
end
|
||||
|
||||
# set up .jinfo file for update-java-alternatives
|
||||
java_name, jinfo_file = alternatives_config_file(app_root, app_home)
|
||||
if platform_family?('debian') && !::File.exist?(jinfo_file)
|
||||
converge_by("Add #{jinfo_file} for debian") do
|
||||
template jinfo_file do
|
||||
cookbook 'java'
|
||||
source 'adoptopenjdk.jinfo.erb'
|
||||
owner new_resource.owner
|
||||
group app_group
|
||||
variables(
|
||||
priority: new_resource.alternatives_priority,
|
||||
bin_cmds: new_resource.bin_cmds,
|
||||
name: java_name,
|
||||
app_dir: app_home
|
||||
)
|
||||
action :nothing
|
||||
end.run_action(:create)
|
||||
end
|
||||
end
|
||||
|
||||
# link app_home to app_dir
|
||||
Chef::Log.debug "app_home is #{app_home} and app_dir is #{app_dir}"
|
||||
current_link = ::File.symlink?(app_home) ? ::File.readlink(app_home) : nil
|
||||
if current_link != app_dir
|
||||
converge_by("symlink #{app_dir} to #{app_home}") do
|
||||
FileUtils.rm_f app_home
|
||||
FileUtils.ln_sf app_dir, app_home
|
||||
FileUtils.chown new_resource.owner, app_group, app_home
|
||||
end
|
||||
end
|
||||
|
||||
# update-alternatives
|
||||
java_alternatives 'set-java-alternatives' do
|
||||
java_location app_home
|
||||
bin_cmds new_resource.bin_cmds
|
||||
priority new_resource.alternatives_priority
|
||||
default new_resource.default
|
||||
reset_alternatives new_resource.reset_alternatives
|
||||
action :set
|
||||
end
|
||||
end
|
||||
|
||||
action :remove do
|
||||
raise 'No URL provided for AdoptOpenJDK\'s tar file!' if new_resource.url.nil? || new_resource.url.empty?
|
||||
_app_dir_name, _tarball_name, _app_root, app_dir =
|
||||
parse_dir_names(new_resource.url,
|
||||
new_resource.app_home,
|
||||
new_resource.variant)
|
||||
app_home = new_resource.app_home
|
||||
Chef::Log.debug("processing #{new_resource.variant} variant")
|
||||
|
||||
if ::File.exist?(app_dir)
|
||||
java_alternatives 'unset-java-alternatives' do
|
||||
java_location app_home
|
||||
bin_cmds new_resource.bin_cmds
|
||||
action :unset
|
||||
end
|
||||
|
||||
directory "AdoptOpenJDK removal of #{app_home}" do
|
||||
path app_home
|
||||
recursive true
|
||||
action :delete
|
||||
end
|
||||
directory "AdoptOpenJDK removal of #{app_dir}" do
|
||||
path app_dir
|
||||
recursive true
|
||||
action :delete
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
action_class do
|
||||
require 'uri'
|
||||
|
||||
def parse_app_dir_name(url)
|
||||
uri = URI.parse(url)
|
||||
file_name = uri.path.split('/').last
|
||||
if file_name =~ /jdk\d+u\d+-b\d+/ # OpenJDK8
|
||||
dir_name_results = file_name.scan(/_(jdk\d+u\d+-b\d+)(?:_openj[-.\d]+)?\.tar\.gz$/)
|
||||
app_dir_name = dir_name_results[0][0] unless dir_name_results.empty?
|
||||
elsif file_name =~ /_\d+u\d+b\d+\.tar\.gz$/ # OpenJDK8U
|
||||
dir_name_results = file_name.scan(/_(\d+u\d+)(b\d+)\.tar\.gz$/)
|
||||
app_dir_name = "jdk#{dir_name_results[0][0]}-#{dir_name_results[0][1]}" unless dir_name_results.empty?
|
||||
else
|
||||
dir_name_results = file_name.scan(/[-_]([.\d]+)[._]([\d]+)(?:_openj[-.\d]+)?\.tar\.gz$/)
|
||||
app_dir_name = "jdk-#{dir_name_results[0][0]}+#{dir_name_results[0][1]}" unless dir_name_results.empty?
|
||||
end
|
||||
Chef::Application.fatal!("Failed to parse #{file_name} for application directory name!") if dir_name_results.empty?
|
||||
|
||||
[app_dir_name, file_name]
|
||||
end
|
||||
|
||||
def parse_dir_names(url, app_home, variant)
|
||||
app_dir_name, tarball_name = parse_app_dir_name(url)
|
||||
app_root = app_home.split('/')[0..-2].join('/')
|
||||
app_dir = "#{app_root}/#{app_dir_name}-#{variant}"
|
||||
[app_dir_name, tarball_name, app_root, app_dir]
|
||||
end
|
||||
|
||||
def alternatives_config_file(app_root, app_home)
|
||||
java_name = app_home.split('/')[-1]
|
||||
config_file = "#{app_root}/.#{java_name}.jinfo"
|
||||
[java_name, config_file]
|
||||
end
|
||||
|
||||
def adoptopendjk_downloaded?(download_path, new_resource)
|
||||
if ::File.exist? download_path
|
||||
require 'openssl'
|
||||
if new_resource.checksum =~ /^[0-9a-f]{32}$/
|
||||
downloaded_md5 = OpenSSL::Digest::MD5.file(download_path).hexdigest
|
||||
downloaded_md5 == new_resource.checksum
|
||||
else
|
||||
downloaded_sha = OpenSSL::Digest::SHA256.file(download_path).hexdigest
|
||||
downloaded_sha == new_resource.checksum
|
||||
end
|
||||
else
|
||||
false
|
||||
end
|
||||
end
|
||||
end
|
||||
89
cookbooks/java/resources/alternatives.rb
Normal file
89
cookbooks/java/resources/alternatives.rb
Normal file
@@ -0,0 +1,89 @@
|
||||
#
|
||||
# Cookbook:: java
|
||||
# Provider:: alternatives
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
property :java_location, String
|
||||
property :bin_cmds, Array
|
||||
property :default, [true, false], default: true
|
||||
property :priority, Integer, default: 1061
|
||||
property :reset_alternatives, [true, false], default: true
|
||||
|
||||
action :set do
|
||||
if new_resource.bin_cmds
|
||||
new_resource.bin_cmds.each do |cmd|
|
||||
bin_path = "/usr/bin/#{cmd}"
|
||||
alt_path = "#{new_resource.java_location}/bin/#{cmd}"
|
||||
priority = new_resource.priority
|
||||
|
||||
unless ::File.exist?(alt_path)
|
||||
Chef::Log.debug "Skipping setting alternative for #{cmd}. Command #{alt_path} does not exist."
|
||||
next
|
||||
end
|
||||
|
||||
alternative_exists_same_priority = shell_out("#{alternatives_cmd} --display #{cmd} | grep #{alt_path} | grep 'priority #{priority}$'").exitstatus == 0
|
||||
alternative_exists = shell_out("#{alternatives_cmd} --display #{cmd} | grep #{alt_path}").exitstatus == 0
|
||||
# remove alternative if priority is changed and install it with new priority
|
||||
if alternative_exists && !alternative_exists_same_priority
|
||||
converge_by("Removing alternative for #{cmd} with old priority") do
|
||||
Chef::Log.debug "Removing alternative for #{cmd} with old priority"
|
||||
remove_cmd = shell_out("#{alternatives_cmd} --remove #{cmd} #{alt_path}")
|
||||
alternative_exists = false
|
||||
unless remove_cmd.exitstatus == 0
|
||||
Chef::Application.fatal!(%( remove alternative failed ))
|
||||
end
|
||||
end
|
||||
end
|
||||
# install the alternative if needed
|
||||
unless alternative_exists
|
||||
converge_by("Add alternative for #{cmd}") do
|
||||
Chef::Log.debug "Adding alternative for #{cmd}"
|
||||
if new_resource.reset_alternatives
|
||||
shell_out("rm /var/lib/alternatives/#{cmd}")
|
||||
end
|
||||
install_cmd = shell_out("#{alternatives_cmd} --install #{bin_path} #{cmd} #{alt_path} #{priority}")
|
||||
unless install_cmd.exitstatus == 0
|
||||
Chef::Application.fatal!(%( install alternative failed ))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# set the alternative if default
|
||||
next unless new_resource.default
|
||||
alternative_is_set = shell_out("#{alternatives_cmd} --display #{cmd} | grep \"link currently points to #{alt_path}\"").exitstatus == 0
|
||||
next if alternative_is_set
|
||||
converge_by("Set alternative for #{cmd}") do
|
||||
Chef::Log.debug "Setting alternative for #{cmd}"
|
||||
set_cmd = shell_out("#{alternatives_cmd} --set #{cmd} #{alt_path}")
|
||||
unless set_cmd.exitstatus == 0
|
||||
Chef::Application.fatal!(%( set alternative failed ))
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
action :unset do
|
||||
new_resource.bin_cmds.each do |cmd|
|
||||
converge_by("Remove alternative for #{cmd}") do
|
||||
shell_out("#{alternatives_cmd} --remove #{cmd} #{new_resource.java_location}/bin/#{cmd}")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
action_class do
|
||||
def alternatives_cmd
|
||||
platform_family?('rhel', 'fedora', 'amazon') ? 'alternatives' : 'update-alternatives'
|
||||
end
|
||||
end
|
||||
144
cookbooks/java/resources/certificate.rb
Normal file
144
cookbooks/java/resources/certificate.rb
Normal file
@@ -0,0 +1,144 @@
|
||||
#
|
||||
# Author:: Mevan Samaratunga (<mevansam@gmail.com>)
|
||||
# Author:: Michael Goetz (<mpgoetz@gmail.com>)
|
||||
# Cookbook:: java
|
||||
# Resource:: certificate
|
||||
#
|
||||
# Copyright:: 2013, Mevan Samaratunga
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
property :java_home, String, default: lazy { node['java']['java_home'] }
|
||||
property :keystore_path, String, default: lazy { node['java']['jdk_version'].to_i < 11 ? "#{node['java']['java_home']}/jre/lib/security/cacerts" : "#{node['java']['java_home']}/lib/security/cacerts" }
|
||||
property :keystore_passwd, String, default: 'changeit'
|
||||
property :cert_alias, String, name_property: true
|
||||
property :cert_data, String
|
||||
property :cert_file, String
|
||||
property :ssl_endpoint, String
|
||||
|
||||
action :install do
|
||||
require 'openssl'
|
||||
|
||||
java_home = new_resource.java_home
|
||||
keytool = "#{java_home}/bin/keytool"
|
||||
truststore = if new_resource.keystore_path.empty?
|
||||
truststore_default_location
|
||||
else
|
||||
new_resource.keystore_path
|
||||
end
|
||||
truststore_passwd = new_resource.keystore_passwd
|
||||
certalias = new_resource.cert_alias
|
||||
certdata = new_resource.cert_data || fetch_certdata
|
||||
|
||||
hash = OpenSSL::Digest::SHA512.hexdigest(certdata)
|
||||
certfile = "#{node['java']['download_path']}/#{certalias}.cert.#{hash}"
|
||||
cmd = Mixlib::ShellOut.new("#{keytool} -list -keystore #{truststore} -storepass #{truststore_passwd} -rfc -alias \"#{certalias}\"")
|
||||
cmd.run_command
|
||||
keystore_cert = cmd.stdout.match(/^[-]+BEGIN.*END(\s|\w)+[-]+$/m).to_s
|
||||
|
||||
keystore_cert_digest = keystore_cert.empty? ? nil : OpenSSL::Digest::SHA512.hexdigest(OpenSSL::X509::Certificate.new(keystore_cert).to_der)
|
||||
certfile_digest = OpenSSL::Digest::SHA512.hexdigest(OpenSSL::X509::Certificate.new(certdata).to_der)
|
||||
if keystore_cert_digest == certfile_digest
|
||||
Chef::Log.debug("Certificate \"#{certalias}\" in keystore \"#{truststore}\" is up-to-date.")
|
||||
else
|
||||
cmd = Mixlib::ShellOut.new("#{keytool} -list -keystore #{truststore} -storepass #{truststore_passwd} -v")
|
||||
cmd.run_command
|
||||
Chef::Log.debug(cmd.format_for_exception)
|
||||
Chef::Application.fatal!("Error querying keystore for existing certificate: #{cmd.exitstatus}", cmd.exitstatus) unless cmd.exitstatus == 0
|
||||
|
||||
has_key = !cmd.stdout[/Alias name: \b#{certalias}/i].nil?
|
||||
|
||||
if has_key
|
||||
converge_by("delete existing certificate #{certalias} from #{truststore}") do
|
||||
cmd = Mixlib::ShellOut.new("#{keytool} -delete -alias \"#{certalias}\" -keystore #{truststore} -storepass #{truststore_passwd}")
|
||||
cmd.run_command
|
||||
Chef::Log.debug(cmd.format_for_exception)
|
||||
unless cmd.exitstatus == 0
|
||||
Chef::Application.fatal!("Error deleting existing certificate \"#{certalias}\" in " \
|
||||
"keystore so it can be updated: #{cmd.exitstatus}", cmd.exitstatus)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
::File.open(certfile, 'w', 0o644) { |f| f.write(certdata) }
|
||||
|
||||
converge_by("add certificate #{certalias} to keystore #{truststore}") do
|
||||
cmd = Mixlib::ShellOut.new("#{keytool} -import -trustcacerts -alias \"#{certalias}\" -file #{certfile} -keystore #{truststore} -storepass #{truststore_passwd} -noprompt")
|
||||
cmd.run_command
|
||||
Chef::Log.debug(cmd.format_for_exception)
|
||||
|
||||
unless cmd.exitstatus == 0
|
||||
FileUtils.rm_f(certfile)
|
||||
Chef::Application.fatal!("Error importing certificate into keystore: #{cmd.exitstatus}", cmd.exitstatus)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
action :remove do
|
||||
certalias = new_resource.name
|
||||
truststore = if new_resource.keystore_path.nil?
|
||||
truststore_default_location
|
||||
else
|
||||
new_resource.keystore_path
|
||||
end
|
||||
truststore_passwd = new_resource.keystore_passwd
|
||||
keytool = "#{node['java']['java_home']}/bin/keytool"
|
||||
|
||||
cmd = Mixlib::ShellOut.new("#{keytool} -list -keystore #{truststore} -storepass #{truststore_passwd} -v | grep \"#{certalias}\"")
|
||||
cmd.run_command
|
||||
has_key = !cmd.stdout[/Alias name: #{certalias}/].nil?
|
||||
Chef::Application.fatal!("Error querying keystore for existing certificate: #{cmd.exitstatus}", cmd.exitstatus) unless cmd.exitstatus == 0
|
||||
|
||||
if has_key
|
||||
converge_by("remove certificate #{certalias} from #{truststore}") do
|
||||
cmd = Mixlib::ShellOut.new("#{keytool} -delete -alias \"#{certalias}\" -keystore #{truststore} -storepass #{truststore_passwd}")
|
||||
cmd.run_command
|
||||
unless cmd.exitstatus == 0
|
||||
Chef::Application.fatal!("Error deleting existing certificate \"#{certalias}\" in " \
|
||||
"keystore so it can be updated: #{cmd.exitstatus}", cmd.exitstatus)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
FileUtils.rm_f("#{node['java']['download_path']}/#{certalias}.cert.*")
|
||||
end
|
||||
|
||||
action_class do
|
||||
def fetch_certdata
|
||||
return IO.read(new_resource.cert_file) unless new_resource.cert_file.nil?
|
||||
|
||||
certendpoint = new_resource.ssl_endpoint
|
||||
unless certendpoint.nil?
|
||||
cmd = Mixlib::ShellOut.new("echo QUIT | openssl s_client -showcerts -servername #{certendpoint.split(':').first} -connect #{certendpoint} 2> /dev/null | openssl x509")
|
||||
cmd.run_command
|
||||
Chef::Log.debug(cmd.format_for_exception)
|
||||
|
||||
Chef::Application.fatal!("Error returned when attempting to retrieve certificate from remote endpoint #{certendpoint}: #{cmd.exitstatus}", cmd.exitstatus) unless cmd.exitstatus == 0
|
||||
|
||||
certout = cmd.stdout
|
||||
return certout unless certout.empty?
|
||||
Chef::Application.fatal!("Unable to parse certificate from openssl query of #{certendpoint}.", 999)
|
||||
end
|
||||
|
||||
Chef::Application.fatal!('At least one of cert_data, cert_file or ssl_endpoint attributes must be provided.', 999)
|
||||
end
|
||||
|
||||
def truststore_default_location
|
||||
if node['java']['jdk_version'].to_i > 8
|
||||
"#{node['java']['java_home']}/lib/security/cacerts"
|
||||
else
|
||||
"#{node['java']['java_home']}/jre/lib/security/cacerts"
|
||||
end
|
||||
end
|
||||
end
|
||||
106
cookbooks/java/resources/jce.rb
Normal file
106
cookbooks/java/resources/jce.rb
Normal file
@@ -0,0 +1,106 @@
|
||||
#
|
||||
# Cookbook:: java
|
||||
# Provider:: jce
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
property :jdk_version, String, default: lazy { node['java']['jdk_version'].to_s }
|
||||
property :jce_url, String, default: lazy { node['java']['oracle']['jce'][jdk_version]['url'] }
|
||||
property :jce_checksum, String, default: lazy { node['java']['oracle']['jce'][jdk_version]['checksum'] }
|
||||
property :java_home, String, default: lazy { node['java']['java_home'] }
|
||||
property :jce_home, String, default: lazy { node['java']['oracle']['jce']['home'] }
|
||||
property :jce_cookie, String, default: lazy { node['java']['oracle']['accept_oracle_download_terms'] ? 'oraclelicense=accept-securebackup-cookie' : '' }
|
||||
property :principal, String, default: lazy { platform_family?('windows') ? node['java']['windows']['owner'] : 'administrator' }
|
||||
|
||||
action :install do
|
||||
jdk_version = new_resource.jdk_version
|
||||
jce_url = new_resource.jce_url
|
||||
jce_checksum = new_resource.jce_checksum
|
||||
java_home = new_resource.java_home
|
||||
jce_home = new_resource.jce_home
|
||||
jce_cookie = new_resource.jce_cookie
|
||||
principal = new_resource.principal
|
||||
|
||||
directory ::File.join(jce_home, jdk_version) do
|
||||
mode '0755'
|
||||
recursive true
|
||||
end
|
||||
|
||||
r = remote_file "#{node['java']['download_path']}/jce.zip" do
|
||||
source jce_url
|
||||
checksum jce_checksum
|
||||
headers(
|
||||
'Cookie' => jce_cookie
|
||||
)
|
||||
not_if { ::File.exist?(::File.join(jce_home, jdk_version, 'US_export_policy.jar')) }
|
||||
end
|
||||
|
||||
# JRE installation does not have a jre folder
|
||||
jre_path = node['java']['install_type'] == 'jdk' ? 'jre' : ''
|
||||
|
||||
if node['os'] == 'windows'
|
||||
|
||||
staging_path = ::File.join(jce_home, jdk_version)
|
||||
staging_local_policy = ::File.join(staging_path, "UnlimitedJCEPolicyJDK#{jdk_version}", 'local_policy.jar')
|
||||
staging_export_policy = ::File.join(staging_path, "UnlimitedJCEPolicyJDK#{jdk_version}", 'US_export_policy.jar')
|
||||
jre_final_path = ::File.join(java_home, jre_path, 'lib', 'security')
|
||||
final_local_policy = ::File.join(jre_final_path, 'local_policy.jar')
|
||||
final_export_policy = ::File.join(jre_final_path, 'US_export_policy.jar')
|
||||
|
||||
windows_zipfile staging_path do
|
||||
source r.path
|
||||
checksum jce_checksum
|
||||
action :unzip
|
||||
not_if { ::File.exist? staging_local_policy }
|
||||
end
|
||||
|
||||
remote_file final_local_policy do
|
||||
rights :full_control, principal
|
||||
source "file://#{staging_local_policy}"
|
||||
end
|
||||
|
||||
remote_file final_export_policy do
|
||||
rights :full_control, principal
|
||||
source "file://#{staging_export_policy}"
|
||||
end
|
||||
|
||||
else
|
||||
package 'unzip'
|
||||
package 'curl'
|
||||
|
||||
execute 'extract jce' do
|
||||
command <<-EOF
|
||||
rm -rf java_jce
|
||||
mkdir java_jce
|
||||
cd java_jce
|
||||
unzip -o ../jce.zip
|
||||
find ./ -name '*.jar' | xargs -I JCE_JAR mv JCE_JAR #{jce_home}/#{jdk_version}/
|
||||
chmod -R 0644 #{jce_home}/#{jdk_version}/*.jar
|
||||
EOF
|
||||
cwd node['java']['download_path']
|
||||
creates ::File.join(jce_home, jdk_version, 'US_export_policy.jar')
|
||||
end
|
||||
|
||||
%w(local_policy.jar US_export_policy.jar).each do |jar|
|
||||
jar_path = ::File.join(java_home, jre_path, 'lib', 'security', jar)
|
||||
# remove the jars already in the directory
|
||||
file jar_path do
|
||||
action :delete
|
||||
not_if { ::File.symlink? jar_path }
|
||||
end
|
||||
link jar_path do
|
||||
to ::File.join(jce_home, jdk_version, jar)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
285
cookbooks/java/resources/oracle_install.rb
Normal file
285
cookbooks/java/resources/oracle_install.rb
Normal file
@@ -0,0 +1,285 @@
|
||||
#
|
||||
# Author:: Bryan W. Berry (<bryan.berry@gmail.com>)
|
||||
# Cookbook:: java
|
||||
# Resource:: oracle_install
|
||||
#
|
||||
# Copyright:: 2011, Bryan w. Berry
|
||||
# Copyright:: 2017-2018, Chef Software, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
# backwards compatibility with the old name
|
||||
provides :java_oracle_install
|
||||
provides :java_ark
|
||||
|
||||
property :url, String
|
||||
property :mirrorlist, Array, default: []
|
||||
property :checksum, String, regex: /^[0-9a-f]{32}$|^[a-zA-Z0-9]{40,64}$/
|
||||
property :md5, String, regex: /^[0-9a-f]{32}$|^[a-zA-Z0-9]{40,64}$/
|
||||
property :app_home, String
|
||||
property :app_home_mode, Integer, default: 0755
|
||||
property :bin_cmds, Array, default: []
|
||||
property :owner, String, default: 'root'
|
||||
property :group, String, default: lazy { node['root_group'] }
|
||||
property :default, [true, false], default: true
|
||||
property :alternatives_priority, Integer, default: 1
|
||||
property :connect_timeout, Integer, default: 30 # => 30 seconds
|
||||
property :reset_alternatives, [true, false], default: true
|
||||
property :use_alt_suffix, [true, false], default: true
|
||||
property :download_timeout, Integer, default: 600 # => 600 seconds
|
||||
property :proxy, String
|
||||
property :accept_oracle_download_terms, [true, false], default: lazy { node['java']['oracle']['accept_oracle_download_terms'] }
|
||||
|
||||
action :install do
|
||||
app_dir_name, tarball_name = parse_app_dir_name(new_resource.url)
|
||||
app_root = new_resource.app_home.split('/')[0..-2].join('/')
|
||||
app_dir = app_root + '/' + app_dir_name
|
||||
app_group = new_resource.group
|
||||
|
||||
if !new_resource.default && new_resource.use_alt_suffix
|
||||
Chef::Log.debug('processing alternate jdk')
|
||||
app_dir += '_alt'
|
||||
app_home = new_resource.app_home + '_alt'
|
||||
else
|
||||
app_home = new_resource.app_home
|
||||
end
|
||||
|
||||
directory app_root do
|
||||
owner new_resource.owner
|
||||
group app_group
|
||||
mode new_resource.app_home_mode
|
||||
recursive true
|
||||
action :nothing
|
||||
end.run_action(:create)
|
||||
|
||||
unless ::File.exist?(app_dir)
|
||||
if new_resource.url =~ /oracle\.com.*$/
|
||||
download_path = "#{node['java']['download_path']}/#{tarball_name}"
|
||||
if oracle_downloaded?(download_path, new_resource)
|
||||
Chef::Log.debug('oracle tarball already downloaded, not downloading again')
|
||||
else
|
||||
Chef::Log.warn('Downloading directly from Oracle is unreliable as artifacts have been removed in the past. Change download url.')
|
||||
download_direct_from_oracle tarball_name, new_resource
|
||||
end
|
||||
else
|
||||
Chef::Log.debug('downloading tarball from an unofficial repository')
|
||||
remote_file "#{node['java']['download_path']}/#{tarball_name}" do
|
||||
source new_resource.url
|
||||
checksum new_resource.checksum
|
||||
retries new_resource.retries
|
||||
retry_delay new_resource.retry_delay
|
||||
mode '0755'
|
||||
action :nothing
|
||||
end.run_action(:create_if_missing)
|
||||
end
|
||||
|
||||
converge_by("extract compressed data into Chef file cache path and move extracted data to #{app_dir}") do
|
||||
case tarball_name
|
||||
when /^.*\.bin/
|
||||
cmd = shell_out(
|
||||
%(cd "#{node['java']['download_path']}";
|
||||
bash ./#{tarball_name} -noregister
|
||||
)
|
||||
)
|
||||
unless cmd.exitstatus == 0
|
||||
Chef::Application.fatal!("Failed to extract file #{tarball_name}!")
|
||||
end
|
||||
when /^.*\.zip/
|
||||
cmd = shell_out(
|
||||
%(unzip "#{node['java']['download_path']}/#{tarball_name}" -d "#{node['java']['download_path']}" )
|
||||
)
|
||||
unless cmd.exitstatus == 0
|
||||
Chef::Application.fatal!("Failed to extract file #{tarball_name}!")
|
||||
end
|
||||
when /^.*\.(tar.gz|tgz)/
|
||||
package 'tar' do
|
||||
not_if { platform_family?('mac_os_x', 'windows') }
|
||||
action :nothing
|
||||
end.run_action(:install)
|
||||
|
||||
cmd = shell_out(
|
||||
%(tar xvzf "#{node['java']['download_path']}/#{tarball_name}" -C "#{node['java']['download_path']}" --no-same-owner)
|
||||
)
|
||||
unless cmd.exitstatus == 0
|
||||
Chef::Application.fatal!("Failed to extract file #{tarball_name}!")
|
||||
end
|
||||
end
|
||||
|
||||
cmd = shell_out(
|
||||
%(mv "#{node['java']['download_path']}/#{app_dir_name}" "#{app_dir}" )
|
||||
)
|
||||
unless cmd.exitstatus == 0
|
||||
Chef::Application.fatal!(%( Command \' mv "#{node['java']['download_path']}/#{app_dir_name}" "#{app_dir}" \' failed ))
|
||||
end
|
||||
|
||||
# change ownership of extracted files
|
||||
FileUtils.chown_R new_resource.owner, app_group, app_dir
|
||||
end
|
||||
end
|
||||
|
||||
# set up .jinfo file for update-java-alternatives
|
||||
java_name = app_home.split('/')[-1]
|
||||
jinfo_file = "#{app_root}/.#{java_name}.jinfo"
|
||||
if platform_family?('debian') && !::File.exist?(jinfo_file)
|
||||
converge_by("Add #{jinfo_file} for debian") do
|
||||
template jinfo_file do
|
||||
cookbook 'java'
|
||||
source 'oracle.jinfo.erb'
|
||||
owner new_resource.owner
|
||||
group app_group
|
||||
variables(
|
||||
priority: new_resource.alternatives_priority,
|
||||
bin_cmds: new_resource.bin_cmds,
|
||||
name: java_name,
|
||||
app_dir: app_home
|
||||
)
|
||||
action :nothing
|
||||
end.run_action(:create)
|
||||
end
|
||||
end
|
||||
|
||||
# link app_home to app_dir
|
||||
Chef::Log.debug "app_home is #{app_home} and app_dir is #{app_dir}"
|
||||
current_link = ::File.symlink?(app_home) ? ::File.readlink(app_home) : nil
|
||||
if current_link != app_dir
|
||||
converge_by("symlink #{app_dir} to #{app_home}") do
|
||||
FileUtils.rm_f app_home
|
||||
FileUtils.ln_sf app_dir, app_home
|
||||
FileUtils.chown new_resource.owner, app_group, app_home
|
||||
end
|
||||
end
|
||||
|
||||
# update-alternatives
|
||||
java_alternatives 'set-java-alternatives' do
|
||||
java_location app_home
|
||||
bin_cmds new_resource.bin_cmds
|
||||
priority new_resource.alternatives_priority
|
||||
default new_resource.default
|
||||
reset_alternatives new_resource.reset_alternatives
|
||||
action :set
|
||||
end
|
||||
end
|
||||
|
||||
action :remove do
|
||||
app_dir_name, _tarball_name = parse_app_dir_name(new_resource.url)
|
||||
app_root = new_resource.app_home.split('/')[0..-2].join('/')
|
||||
app_dir = app_root + '/' + app_dir_name
|
||||
|
||||
if new_resource.default
|
||||
app_home = new_resource.app_home
|
||||
else
|
||||
Chef::Log.debug('processing alternate jdk')
|
||||
app_dir += '_alt'
|
||||
app_home = new_resource.app_home + '_alt'
|
||||
end
|
||||
|
||||
if ::File.exist?(app_dir)
|
||||
java_alternatives 'unset-java-alternatives' do
|
||||
java_location app_home
|
||||
bin_cmds new_resource.bin_cmds
|
||||
action :unset
|
||||
end
|
||||
|
||||
converge_by("remove #{new_resource.name} at #{app_dir}") do
|
||||
Chef::Log.info "Removing #{new_resource.name} at #{app_dir}"
|
||||
FileUtils.rm_rf app_dir
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
action_class do
|
||||
require 'uri'
|
||||
|
||||
def parse_app_dir_name(url)
|
||||
uri = URI.parse(url)
|
||||
file_name = uri.path.split('/').last
|
||||
# funky logic to parse oracle's non-standard naming convention
|
||||
# for jdk1.6 -> 1.9, 10.0.0->10.0.2, 11
|
||||
if file_name =~ /^(jre|jdk|server-jre).*$/
|
||||
major_num = file_name.scan(/\d{1,}/)[0]
|
||||
package_name = file_name =~ /^server-jre.*$/ ? 'jdk' : file_name.scan(/[a-z]+/)[0]
|
||||
if major_num.to_i >= 10
|
||||
# Versions 10 and above incorporate semantic versioning and/or single version numbers
|
||||
version_result = file_name.scan(/.*-([\d\.]+)_.*/)[0][0]
|
||||
app_dir_name = "#{package_name}-#{version_result}"
|
||||
else
|
||||
update_token = file_name.scan(/u(\d+)/)[0]
|
||||
update_num = update_token ? update_token[0] : '0'
|
||||
# pad a single digit number with a zero
|
||||
update_num = '0' + update_num if update_num.length < 2
|
||||
app_dir_name = if update_num == '00'
|
||||
"#{package_name}1.#{major_num}.0"
|
||||
else
|
||||
"#{package_name}1.#{major_num}.0_#{update_num}"
|
||||
end
|
||||
end
|
||||
else
|
||||
app_dir_name = file_name.split(/(.tgz|.tar.gz|.zip)/)[0]
|
||||
app_dir_name = app_dir_name.split('-bin')[0]
|
||||
end
|
||||
[app_dir_name, file_name]
|
||||
end
|
||||
|
||||
def oracle_downloaded?(download_path, new_resource)
|
||||
if ::File.exist? download_path
|
||||
require 'openssl'
|
||||
if new_resource.checksum =~ /^[0-9a-f]{32}$/
|
||||
downloaded_md5 = OpenSSL::Digest::MD5.file(download_path).hexdigest
|
||||
downloaded_md5 == new_resource.checksum
|
||||
else
|
||||
downloaded_sha = OpenSSL::Digest::SHA256.file(download_path).hexdigest
|
||||
downloaded_sha == new_resource.checksum
|
||||
end
|
||||
else
|
||||
false
|
||||
end
|
||||
end
|
||||
|
||||
def download_direct_from_oracle(tarball_name, new_resource)
|
||||
download_path = "#{node['java']['download_path']}/#{tarball_name}"
|
||||
cookie = 'oraclelicense=accept-securebackup-cookie'
|
||||
proxy = "-x #{new_resource.proxy}" unless new_resource.proxy.nil?
|
||||
if new_resource.accept_oracle_download_terms
|
||||
# install the curl package
|
||||
package 'curl' do
|
||||
action :nothing
|
||||
end.run_action(:install)
|
||||
|
||||
converge_by('download oracle tarball straight from the server') do
|
||||
Chef::Log.debug 'downloading oracle tarball straight from the source'
|
||||
shell_out!(
|
||||
%W(
|
||||
curl
|
||||
--fail
|
||||
--create-dirs
|
||||
-L
|
||||
--retry #{new_resource.retries}
|
||||
--retry-delay #{new_resource.retry_delay} --cookie "#{cookie}"
|
||||
#{new_resource.url}
|
||||
-o #{download_path}
|
||||
--connect-timeout #{new_resource.connect_timeout}
|
||||
#{proxy}
|
||||
).join(' '),
|
||||
timeout: new_resource.download_timeout
|
||||
)
|
||||
end
|
||||
# Can't verify anything with HTTP return codes from Oracle. For example, they return 200 for auth failure.
|
||||
# Do a generic verification of the download
|
||||
unless oracle_downloaded?(download_path, new_resource)
|
||||
Chef::Application.fatal!("Checksum verification failure. Possible wrong checksum or download from Oracle failed.\nVerify artifact checksum and/or verify #{download_path} is an archive and not an HTML response from Oracle")
|
||||
end
|
||||
else
|
||||
Chef::Application.fatal!("You must set the resource property 'accept_oracle_download_terms' or set the node attribute node['java']['oracle']['accept_oracle_download_terms'] to true if you want to download directly from the oracle site!")
|
||||
end
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user