property :repository, String, name_property: true property :master_token, String property :force_os, String property :force_dist, String property :type, String, equal_to: %w(deb rpm gem), default: lazy { node['packagecloud']['default_type'] } property :base_url, String, default: 'https://packagecloud.io' property :priority, [Integer, TrueClass, FalseClass], default: false property :metadata_expire, String, regex: [/^\d+[d|h|m]?$/], default: '300' action :add do case new_resource.type when 'deb' install_deb when 'rpm' install_rpm when 'gem' install_gem else raise "#{new_resource.type} is an unknown package type." end end action_class.class_eval do include ::PackageCloud::Helper require 'uri' def gpg_url(base_url, repo, format, master_token) base_install_url = ::File.join(base_url, node['packagecloud']['base_repo_path']) ext = (format == :deb) ? 'list' : 'repo' gpg_key_url_endpoint = construct_uri_with_options(base_url: base_install_url, repo: repo, endpoint: "gpg_key_url.#{ext}") unless master_token.nil? gpg_key_url_endpoint.user = master_token gpg_key_url_endpoint.password = '' end URI(get(gpg_key_url_endpoint, install_endpoint_params).body.chomp) end def install_deb base_url = new_resource.base_url repo_url = construct_uri_with_options(base_url: base_url, repo: new_resource.repository, endpoint: os_platform) Chef::Log.debug("#{new_resource.name} deb repo url = #{repo_url}") package 'wget' package 'apt-transport-https' package 'lsb-release' ohai "reload-lsb-#{filename}" do plugin 'lsb' action :nothing subscribes :reload, 'package[lsb-release]', :immediately end repo_url = read_token(repo_url) template "/etc/apt/sources.list.d/#{filename}.list" do source 'apt.erb' cookbook 'packagecloud' mode '0644' variables lazy { { base_url: repo_url.to_s, distribution: dist_name, component: 'main' } } notifies :run, "execute[apt-key-add-#{filename}]", :immediately notifies :run, "execute[apt-get-update-#{filename}]", :immediately end execute "apt-key-add-#{filename}" do # ~FC041 command lazy { gpg_url = gpg_url(new_resource.base_url, new_resource.repository, :deb, new_resource.master_token) "wget --auth-no-challenge -qO - #{gpg_url} | apt-key add -" } action :nothing end execute "apt-get-update-#{filename}" do command "apt-get update -o Dir::Etc::sourcelist=\"sources.list.d/#{filename}.list\"" \ ' -o Dir::Etc::sourceparts="-"' \ ' -o APT::Get::List-Cleanup="0"' action :nothing end end def install_rpm given_base_url = new_resource.base_url base_repo_url = ::File.join(given_base_url, node['packagecloud']['base_repo_path']) base_url_endpoint = construct_uri_with_options(base_url: base_repo_url, repo: new_resource.repository, endpoint: 'rpm_base_url') if new_resource.master_token base_url_endpoint.user = new_resource.master_token base_url_endpoint.password = '' end base_url = URI(get(base_url_endpoint, install_endpoint_params).body.chomp) Chef::Log.debug("#{new_resource.name} rpm base url = #{base_url}") package 'pygpgme' do ignore_failure true end log 'pygpgme_warning' do message 'The pygpgme package could not be installed. This means GPG verification is not possible for any RPM installed on your system. ' \ 'To fix this, add a repository with pygpgme. Usualy, the EPEL repository for your system will have this. ' \ 'More information: https://fedoraproject.org/wiki/EPEL#How_can_I_use_these_extra_packages.3F and https://github.com/opscode-cookbooks/yum-epel' level :warn not_if 'rpm -qa | grep -qw pygpgme' end ruby_block 'disable repo_gpgcheck if no pygpgme' do block do template = run_context.resource_collection.find(template: "/etc/yum.repos.d/#{filename}.repo") template.variables[:repo_gpgcheck] = 0 end not_if 'rpm -qa | grep -qw pygpgme' end gpg_url = gpg_url(new_resource.base_url, new_resource.repository, :rpm, new_resource.master_token) template "/etc/yum.repos.d/#{filename}.repo" do source 'yum.erb' cookbook 'packagecloud' mode '0644' variables base_url: base_url.to_s, name: filename, gpg_url: gpg_url.to_s, repo_gpgcheck: 1, description: filename, priority: new_resource.priority, metadata_expire: new_resource.metadata_expire notifies :run, "execute[yum-makecache-#{filename}]", :immediately notifies :run, "ruby_block[yum-cache-reload-#{filename}]", :immediately end # get the metadata for this repo only execute "yum-makecache-#{filename}" do command "yum -q makecache -y --disablerepo=* --enablerepo=#{filename}" action :nothing end # reload internal Chef yum cache ruby_block "yum-cache-reload-#{filename}" do block { Chef::Provider::Package::Yum::YumCache.instance.reload } action :nothing end end def install_gem base_url = new_resource.base_url repo_url = construct_uri_with_options(base_url: base_url, repo: new_resource.repository) repo_url = read_token(repo_url, true).to_s execute "install packagecloud #{new_resource.name} repo as gem source" do command "gem source --add #{repo_url}" not_if "gem source --list | grep #{repo_url}" end end def read_token(repo_url, gems = false) return repo_url unless new_resource.master_token base_url = new_resource.base_url base_repo_url = ::File.join(base_url, node['packagecloud']['base_repo_path']) uri = construct_uri_with_options(base_url: base_repo_url, repo: new_resource.repository, endpoint: 'tokens.text') uri.user = new_resource.master_token uri.password = '' resp = post(uri, install_endpoint_params) Chef::Log.debug("#{new_resource.name} TOKEN = #{resp.body.chomp}") if rhel5? && !gems repo_url else repo_url.user = resp.body.chomp repo_url.password = '' repo_url end end def install_endpoint_params dist = dist_name hostname = node['packagecloud']['hostname_override'] || node['fqdn'] || node['hostname'] if !hostname || hostname.empty? raise("Can't determine hostname! Set node['packagecloud']['hostname_override'] " \ 'if it cannot be automatically determined by Ohai.') end { os: os_platform, dist: dist, name: hostname } end def os_platform new_resource.force_os || node['platform'] end def dist_name new_resource.force_dist || value_for_platform_family( 'debian' => node['lsb']['codename'], 'amazon' => '6', %w(rhel fedora) => node['platform_version'] ) end def filename new_resource.name.gsub(/[^0-9A-z.\-]/, '_') end def rhel5? platform_family?('rhel') && node['platform_version'].to_i == 5 end def construct_uri_with_options(options) required_options = [:base_url, :repo] required_options.each do |opt| unless options[opt] raise ArgumentError, "A required option :#{opt} was not specified" end end options[:base_url] = append_trailing_slash(options[:base_url]) options[:repo] = append_trailing_slash(options[:repo]) URI.join(options.delete(:base_url), options.inject([]) { |mem, opt| mem << opt[1] }.join) end def append_trailing_slash(str) str.end_with?('/') ? str : str + '/' end end