--- /dev/null
+require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', 'puppet_x', 'apt_key', 'resource_api.rb'))
+
+require 'open-uri'
+require 'net/ftp'
+require 'tempfile'
+
+if RUBY_VERSION == '1.8.7'
+ # Mothers cry, puppies die and Ruby 1.8.7's open-uri needs to be
+ # monkeypatched to support passing in :ftp_passive_mode.
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..',
+ 'puppet_x', 'apt_key', 'patch_openuri.rb'))
+ OpenURI::Options.merge!({:ftp_active_mode => false,})
+end
+
+register_provider('apt_key2') do
+ commands apt_key: 'apt-key'
+ commands gpg: '/usr/bin/gpg'
+
+ def canonicalize(resources)
+ resources.collect do |r|
+ r[:id] = r[:id].upcase
+ end
+ end
+
+ def get(names = [])
+ cli_args = %w(adv --list-keys --with-colons --fingerprint --fixed-list-mode)
+ key_output = apt_key(cli_args).encode('UTF-8', 'binary', :invalid => :replace, :undef => :replace, :replace => '')
+ pub_line = nil
+ fpr_line = nil
+
+ result = key_output.split("\n").collect do |line|
+ if line.start_with?('pub')
+ pub_line = line
+ elsif line.start_with?('fpr')
+ fpr_line = line
+ end
+
+ next unless (pub_line and fpr_line)
+
+ hash = key_line_to_hash(pub_line, fpr_line)
+
+ # reset scanning
+ pub_line = nil
+ fpr_line = nil
+
+ hash
+ end.compact!
+
+ result
+ end
+
+ def self.key_line_to_hash(pub_line, fpr_line)
+ pub_split = pub_line.split(':')
+ fpr_split = fpr_line.split(':')
+
+ # set key type based on types defined in /usr/share/doc/gnupg/DETAILS.gz
+ key_type = case pub_split[3]
+ when '1'
+ :rsa
+ when '17'
+ :dsa
+ when '18'
+ :ecc
+ when '19'
+ :ecdsa
+ else
+ :unrecognized
+ end
+
+ fingerprint = fpr_split.last
+ expiry = pub_split[6].empty? ? nil : Time.at(pub_split[6].to_i)
+
+ {
+ ensure: 'present',
+ id: fingerprint,
+ fingerprint: fingerprint,
+ long: fingerprint[-16..-1], # last 16 characters of fingerprint
+ short: fingerprint[-8..-1], # last 8 characters of fingerprint
+ size: pub_split[2].to_i,
+ type: key_type,
+ created: Time.at(pub_split[5].to_i),
+ expiry: expiry,
+ expired: !!(expiry && Time.now >= expiry),
+ }
+ end
+
+ def set(current_state, target_state, noop = false)
+ target_state.each do |title, resource|
+ logger.warning(title, 'The id should be a full fingerprint (40 characters) to avoid collision attacks, see the README for details.') if title.length < 40
+ if resource[:source] and resource[:content]
+ logger.fail(title, 'The properties content and source are mutually exclusive')
+ next
+ end
+
+ current = current_state[title]
+ if current && resource[:ensure].to_s == 'absent'
+ logger.deleting(title) do
+ begin
+ apt_key('del', resource[:short], noop: noop)
+ r = execute(["#{command(:apt_key)} list | grep '/#{resource[:short]}\s'"], :failonfail => false)
+ end while r.exitstatus == 0
+ end
+ elsif current && resource[:ensure].to_s == 'present'
+ # No updating implemented
+ # update(key, noop: noop)
+ elsif !current && resource[:ensure].to_s == 'present'
+ create(title, resource, noop: noop)
+ end
+ end
+ end
+
+ def create(title, resource, noop = false)
+ logger.creating(title) do |logger|
+ if resource[:source].nil? and resource[:content].nil?
+ # Breaking up the command like this is needed because it blows up
+ # if --recv-keys isn't the last argument.
+ args = ['adv', '--keyserver', resource[:server]]
+ if resource[:options]
+ args.push('--keyserver-options', resource[:options])
+ end
+ args.push('--recv-keys', resource[:id])
+ apt_key(*args, noop: noop)
+ elsif resource[:content]
+ temp_key_file(resource[:content], logger) do |key_file|
+ apt_key('add', key_file, noop: noop)
+ end
+ elsif resource[:source]
+ key_file = source_to_file(resource[:source])
+ apt_key('add', key_file.path, noop: noop)
+ # In case we really screwed up, better safe than sorry.
+ else
+ logger.fail("an unexpected condition occurred while trying to add the key: #{title} (content: #{resource[:content].inspect}, source: #{resource[:source].inspect})")
+ end
+ end
+ end
+
+ # This method writes out the specified contents to a temporary file and
+ # confirms that the fingerprint from the file, matches the long key that is in the manifest
+ def temp_key_file(resource, logger)
+ file = Tempfile.new('apt_key')
+ begin
+ file.write resource[:content]
+ file.close
+ if name.size == 40
+ if File.executable? command(:gpg)
+ extracted_key = execute(["#{command(:gpg)} --with-fingerprint --with-colons #{file.path} | awk -F: '/^fpr:/ { print $10 }'"], :failonfail => false)
+ extracted_key = extracted_key.chomp
+
+ unless extracted_key.match(/^#{name}$/)
+ logger.fail("The id in your manifest #{resource[:id]} and the fingerprint from content/source do not match. Please check there is not an error in the id or check the content/source is legitimate.")
+ end
+ else
+ logger.warning('/usr/bin/gpg cannot be found for verification of the id.')
+ end
+ end
+ yield file.path
+ ensure
+ file.close
+ file.unlink
+ end
+ end
+end
--- /dev/null
+require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'puppet_x', 'apt_key', 'resource_api.rb'))
+
+register_type({
+ name: 'apt_key2',
+ docs: <<-EOS,
+ This type provides Puppet with the capabilities to manage GPG keys needed
+ by apt to perform package validation. Apt has it's own GPG keyring that can
+ be manipulated through the `apt-key` command.
+
+ apt_key { '6F6B15509CF8E59E6E469F327F438280EF8D349F':
+ source => 'http://apt.puppetlabs.com/pubkey.gpg'
+ }
+
+ **Autorequires**:
+ If Puppet is given the location of a key file which looks like an absolute
+ path this type will autorequire that file.
+ EOS
+ attributes: {
+ ensure: {
+ type: 'Enum[present, absent]',
+ docs: 'Whether this apt key should be present or absent on the target system.'
+ },
+ id: {
+ type: 'Variant[Pattern[/\A(0x)?[0-9a-fA-F]{8}\Z/], Pattern[/\A(0x)?[0-9a-fA-F]{16}\Z/], Pattern[/\A(0x)?[0-9a-fA-F]{40}\Z/]]',
+ docs: 'The ID of the key you want to manage.',
+ namevar: true,
+ },
+ content: {
+ type: 'Optional[String]',
+ docs: 'The content of, or string representing, a GPG key.',
+ },
+ source: {
+ type: 'Variant[Stdlib::Absolutepath, Pattern[/\A(https?|ftp):\/\//]]',
+ docs: 'Location of a GPG key file, /path/to/file, ftp://, http:// or https://',
+ },
+ server: {
+ type: 'Pattern[/\A((hkp|http|https):\/\/)?([a-z\d])([a-z\d-]{0,61}\.)+[a-z\d]+(:\d{2,5})?$/]',
+ docs: 'The key server to fetch the key from based on the ID. It can either be a domain name or url.',
+ default: :'keyserver.ubuntu.com'
+ },
+ options: {
+ type: 'Optional[String]',
+ docs: 'Additional options to pass to apt-key\'s --keyserver-options.',
+ },
+ fingerprint: {
+ type: 'Pattern[/[a-f]{40}/]',
+ docs: 'The 40-digit hexadecimal fingerprint of the specified GPG key.',
+ read_only: true,
+ },
+ long: {
+ type: 'Pattern[/[a-f]{16}/]',
+ docs: 'The 16-digit hexadecimal id of the specified GPG key.',
+ read_only: true,
+ },
+ short: {
+ type: 'Pattern[/[a-f]{8}/]',
+ docs: 'The 8-digit hexadecimal id of the specified GPG key.',
+ read_only: true,
+ },
+ expired: {
+ type: 'Boolean',
+ docs: 'Indicates if the key has expired.',
+ read_only: true,
+ },
+ expiry: {
+ # TODO: should be DateTime
+ type: 'String',
+ docs: 'The date the key will expire, or nil if it has no expiry date, in ISO format.',
+ read_only: true,
+ },
+ size: {
+ type: 'Integer',
+ docs: 'The key size, usually a multiple of 1024.',
+ read_only: true,
+ },
+ type: {
+ type: 'String',
+ docs: 'The key type, one of: rsa, dsa, ecc, ecdsa.',
+ read_only: true,
+ },
+ created: {
+ type: 'String',
+ docs: 'Date the key was created, in ISO format.',
+ read_only: true,
+ },
+ },
+ autorequires: {
+ file: '$source', # will evaluate to the value of the `source` attribute
+ package: 'apt',
+ },
+})
--- /dev/null
+require 'pathname'
+require 'pry'
+
+module Puppet::SimpleResource
+ class TypeShim
+ attr_reader :values
+
+ def initialize(title, resource_hash)
+ # internalize and protect - needs to go deeper
+ @values = resource_hash.dup
+ # "name" is a privileged key
+ @values[:name] = title
+ @values.freeze
+ end
+
+ def to_resource
+ ResourceShim.new(@values)
+ end
+
+ def name
+ values[:name]
+ end
+ end
+
+ class ResourceShim
+ attr_reader :values
+
+ def initialize(resource_hash)
+ @values = resource_hash.dup.freeze # whatevs
+ end
+
+ def title
+ values[:name]
+ end
+
+ def prune_parameters(*args)
+ # puts "not pruning #{args.inspect}" if args.length > 0
+ self
+ end
+
+ def to_manifest
+ [
+ "apt_key { #{values[:name].inspect}: ",
+ ] + values.keys.select { |k| k != :name }.collect { |k| " #{k} => #{values[k].inspect}," } + ['}']
+ end
+ end
+end
+
+def register_type(definition)
+ Puppet::Type.newtype(definition[:name].to_sym) do
+ @docs = definition[:docs]
+ has_namevar = false
+ namevar_name = nil
+
+ definition[:attributes].each do |name, options|
+ # puts "#{name}: #{options.inspect}"
+
+ # TODO: using newparam everywhere would suppress change reporting
+ # that would allow more fine-grained reporting through logger,
+ # but require more invest in hooking up the infrastructure to emulate existing data
+ param_or_property = if options[:read_only] || options[:namevar]
+ :newparam
+ else
+ :newproperty
+ end
+ send(param_or_property, name.to_sym) do
+ unless options[:type]
+ fail("#{definition[:name]}.#{name} has no type")
+ end
+
+ if options[:docs]
+ desc "#{options[:docs]} (a #{options[:type]}"
+ else
+ warn("#{definition[:name]}.#{name} has no docs")
+ end
+
+ if options[:namevar]
+ # puts 'setting namevar'
+ isnamevar
+ has_namevar = true
+ namevar_name = name
+ end
+
+ # read-only values do not need type checking, but can have default values
+ if not options[:read_only]
+ # TODO: this should use Pops infrastructure to avoid hardcoding stuff, and enhance type fidelity
+ # validate do |v|
+ # type = Puppet::Pops::Types::TypeParser.singleton.parse(options[:type]).normalize
+ # if type.instance?(v)
+ # return true
+ # else
+ # inferred_type = Puppet::Pops::Types::TypeCalculator.infer_set(value)
+ # error_msg = Puppet::Pops::Types::TypeMismatchDescriber.new.describe_mismatch("#{DEFINITION[:name]}.#{name}", type, inferred_type)
+ # raise Puppet::ResourceError, error_msg
+ # end
+ # end
+
+ if options.has_key? :default
+ defaultto options[:default]
+ end
+
+ case options[:type]
+ when 'String'
+ # require any string value
+ newvalue // do
+ end
+ when 'Boolean'
+ ['true', 'false', :true, :false, true, false].each do |v|
+ newvalue v do
+ end
+ end
+
+ munge do |v|
+ case v
+ when 'true', :true
+ true
+ when 'false', :false
+ false
+ else
+ v
+ end
+ end
+ when 'Integer'
+ newvalue /^\d+$/ do
+ end
+ munge do |v|
+ Puppet::Pops::Utils.to_n(v)
+ end
+ when 'Float', 'Numeric'
+ newvalue Puppet::Pops::Patterns::NUMERIC do
+ end
+ munge do |v|
+ Puppet::Pops::Utils.to_n(v)
+ end
+ when 'Enum[present, absent]'
+ newvalue :absent do
+ end
+ newvalue :present do
+ end
+ when 'Variant[Pattern[/\A(0x)?[0-9a-fA-F]{8}\Z/], Pattern[/\A(0x)?[0-9a-fA-F]{16}\Z/], Pattern[/\A(0x)?[0-9a-fA-F]{40}\Z/]]'
+ # the namevar needs to be a Parameter, which only has newvalue*s*
+ newvalues(/\A(0x)?[0-9a-fA-F]{8}\Z/, /\A(0x)?[0-9a-fA-F]{16}\Z/, /\A(0x)?[0-9a-fA-F]{40}\Z/)
+ when 'Optional[String]'
+ newvalue :undef do
+ end
+ newvalue // do
+ end
+ when 'Variant[Stdlib::Absolutepath, Pattern[/\A(https?|ftp):\/\//]]'
+ # TODO: this is wrong, but matches original implementation
+ [/^\//, /\A(https?|ftp):\/\//].each do |v|
+ newvalue v do
+ end
+ end
+ when /^(Enum|Optional|Variant)/
+ fail("#{$1} is not currently supported")
+ end
+ end
+ end
+ end
+
+ def self.instances
+ puts 'instances'
+ # klass = Puppet::Type.type(:api)
+ get.collect do |resource_hash|
+ Puppet::SimpleResource::TypeShim.new(resource_hash[namevar_name], resource_hash)
+ end
+ end
+
+ def retrieve
+ puts 'retrieve'
+ result = Puppet::Resource.new(self.class, title)
+ current_state = self.class.get.find { |h| h[namevar_name] == title }
+
+ if current_state
+ current_state.each do |k, v|
+ result[k]=v
+ end
+ else
+ result[:ensure] = :absent
+ end
+
+ @rapi_current_state = current_state
+ result
+ end
+
+ def flush
+ puts 'flush'
+ # binding.pry
+ target_state = self.class.canonicalize([Hash[@parameters.collect { |k, v| [k, v.value] }]])
+ if @rapi_current_state != target_state
+ self.class.set({title => @rapi_current_state}, {title => target_state}, false)
+ else
+ puts 'no changes'
+ end
+ end
+
+ def self.commands(*args)
+ puts "registering command: #{args.inspect}"
+ end
+ end
+end
+
+def register_provider(typename, &block)
+ type = Puppet::Type.type(typename.to_sym)
+ type.instance_eval &block
+end
require 'spec_helper'
require 'puppet'
-describe Puppet::Type::type(:apt_key) do
- context 'only namevar 32bit key id' do
- let(:resource) { Puppet::Type.type(:apt_key).new(
- :id => 'EF8D349F'
- )}
- it 'id is set' do
- expect(resource[:id]).to eq 'EF8D349F'
- end
-
- it 'name is set to id' do
- expect(resource[:name]).to eq 'EF8D349F'
- end
-
- it 'keyserver is default' do
- expect(resource[:server]).to eq :'keyserver.ubuntu.com'
- end
-
- it 'source is not set' do
- expect(resource[:source]).to eq nil
- end
-
- it 'content is not set' do
- expect(resource[:content]).to eq nil
- end
- end
-
- context 'with a lowercase 32bit key id' do
- let(:resource) { Puppet::Type.type(:apt_key).new(
- :id => 'ef8d349f'
- )}
- it 'id is set' do
- expect(resource[:id]).to eq 'EF8D349F'
- end
- end
-
- context 'with a 64bit key id' do
- let(:resource) { Puppet::Type.type(:apt_key).new(
- :id => 'FFFFFFFFEF8D349F'
- )}
- it 'id is set' do
- expect(resource[:id]).to eq 'FFFFFFFFEF8D349F'
- end
- end
-
- context 'with a 0x formatted key id' do
- let(:resource) { Puppet::Type.type(:apt_key).new(
- :id => '0xEF8D349F'
- )}
- it 'id is set' do
- expect(resource[:id]).to eq 'EF8D349F'
- end
- end
-
- context 'with a 0x formatted lowercase key id' do
- let(:resource) { Puppet::Type.type(:apt_key).new(
- :id => '0xef8d349f'
- )}
- it 'id is set' do
- expect(resource[:id]).to eq 'EF8D349F'
- end
- end
-
- context 'with a 0x formatted 64bit key id' do
- let(:resource) { Puppet::Type.type(:apt_key).new(
- :id => '0xFFFFFFFFEF8D349F'
- )}
- it 'id is set' do
- expect(resource[:id]).to eq 'FFFFFFFFEF8D349F'
- end
- end
-
- context 'with source' do
- let(:resource) { Puppet::Type.type(:apt_key).new(
- :id => 'EF8D349F',
- :source => 'http://apt.puppetlabs.com/pubkey.gpg'
- )}
-
- it 'source is set to the URL' do
- expect(resource[:source]).to eq 'http://apt.puppetlabs.com/pubkey.gpg'
- end
- end
-
- context 'with content' do
- let(:resource) { Puppet::Type.type(:apt_key).new(
- :id => 'EF8D349F',
- :content => 'http://apt.puppetlabs.com/pubkey.gpg'
- )}
-
- it 'content is set to the string' do
- expect(resource[:content]).to eq 'http://apt.puppetlabs.com/pubkey.gpg'
- end
- end
-
- context 'with keyserver' do
- let(:resource) { Puppet::Type.type(:apt_key).new(
- :id => 'EF8D349F',
- :server => 'http://keyring.debian.org'
- )}
-
- it 'keyserver is set to Debian' do
- expect(resource[:server]).to eq 'http://keyring.debian.org'
- end
- end
-
- context 'validation' do
- it 'raises an error if content and source are set' do
- expect { Puppet::Type.type(:apt_key).new(
- :id => 'EF8D349F',
- :source => 'http://apt.puppetlabs.com/pubkey.gpg',
- :content => 'Completely invalid as a GPG key'
- )}.to raise_error(/content and source are mutually exclusive/)
- end
-
- it 'raises an error if a weird length key is used' do
- expect { Puppet::Type.type(:apt_key).new(
- :id => 'FEF8D349F',
- :source => 'http://apt.puppetlabs.com/pubkey.gpg',
- :content => 'Completely invalid as a GPG key'
- )}.to raise_error(/Valid values match/)
- end
-
- it 'raises an error when an invalid URI scheme is used in source' do
- expect { Puppet::Type.type(:apt_key).new(
- :id => 'EF8D349F',
- :source => 'hkp://pgp.mit.edu'
- )}.to raise_error(/Valid values match/)
- end
-
- it 'allows the http URI scheme in source' do
- expect { Puppet::Type.type(:apt_key).new(
- :id => 'EF8D349F',
- :source => 'http://pgp.mit.edu'
- )}.to_not raise_error
- end
-
- it 'allows the http URI with username and password' do
- expect { Puppet::Type.type(:apt_key).new(
- :id => '4BD6EC30',
- :source => 'http://testme:Password2@pgp.mit.edu'
- )}.to_not raise_error
- end
-
- it 'allows the https URI scheme in source' do
- expect { Puppet::Type.type(:apt_key).new(
- :id => 'EF8D349F',
- :source => 'https://pgp.mit.edu'
- )}.to_not raise_error
- end
-
- it 'allows the https URI with username and password' do
- expect { Puppet::Type.type(:apt_key).new(
+[:apt_key, :apt_key2].each do |typename|
+ describe Puppet::Type::type(typename) do
+ context 'only namevar 32bit key id' do
+ let(:resource) { Puppet::Type.type(typename).new(
+ :id => 'EF8D349F'
+ )}
+ it 'id is set' do
+ expect(resource[:id]).to eq 'EF8D349F'
+ end
+
+ it 'name is set to id' do
+ expect(resource[:name]).to eq 'EF8D349F'
+ end
+
+ it 'keyserver is default' do
+ expect(resource[:server]).to eq :'keyserver.ubuntu.com'
+ end
+
+ it 'source is not set' do
+ expect(resource[:source]).to eq nil
+ end
+
+ it 'content is not set' do
+ expect(resource[:content]).to eq nil
+ end
+ end
+
+ context 'with a lowercase 32bit key id' do
+ let(:resource) { Puppet::Type.type(typename).new(
+ :id => 'ef8d349f'
+ )}
+ it 'id is set' do
+ expect(resource[:id]).to eq 'EF8D349F'
+ end
+ end
+
+ context 'with a 64bit key id' do
+ let(:resource) { Puppet::Type.type(typename).new(
+ :id => 'FFFFFFFFEF8D349F'
+ )}
+ it 'id is set' do
+ expect(resource[:id]).to eq 'FFFFFFFFEF8D349F'
+ end
+ end
+
+ context 'with a 0x formatted key id' do
+ let(:resource) { Puppet::Type.type(typename).new(
+ :id => '0xEF8D349F'
+ )}
+ it 'id is set' do
+ expect(resource[:id]).to eq 'EF8D349F'
+ end
+ end
+
+ context 'with a 0x formatted lowercase key id' do
+ let(:resource) { Puppet::Type.type(typename).new(
+ :id => '0xef8d349f'
+ )}
+ it 'id is set' do
+ expect(resource[:id]).to eq 'EF8D349F'
+ end
+ end
+
+ context 'with a 0x formatted 64bit key id' do
+ let(:resource) { Puppet::Type.type(typename).new(
+ :id => '0xFFFFFFFFEF8D349F'
+ )}
+ it 'id is set' do
+ expect(resource[:id]).to eq 'FFFFFFFFEF8D349F'
+ end
+ end
+
+ context 'with source' do
+ let(:resource) { Puppet::Type.type(typename).new(
+ :id => 'EF8D349F',
+ :source => 'http://apt.puppetlabs.com/pubkey.gpg'
+ )}
+
+ it 'source is set to the URL' do
+ expect(resource[:source]).to eq 'http://apt.puppetlabs.com/pubkey.gpg'
+ end
+ end
+
+ context 'with content' do
+ let(:resource) { Puppet::Type.type(typename).new(
+ :id => 'EF8D349F',
+ :content => 'http://apt.puppetlabs.com/pubkey.gpg'
+ )}
+
+ it 'content is set to the string' do
+ expect(resource[:content]).to eq 'http://apt.puppetlabs.com/pubkey.gpg'
+ end
+ end
+
+ context 'with keyserver' do
+ let(:resource) { Puppet::Type.type(typename).new(
+ :id => 'EF8D349F',
+ :server => 'http://keyring.debian.org'
+ )}
+
+ it 'keyserver is set to Debian' do
+ expect(resource[:server]).to eq 'http://keyring.debian.org'
+ end
+ end
+
+ context 'validation' do
+ it 'raises an error if content and source are set' do
+ expect { Puppet::Type.type(typename).new(
:id => 'EF8D349F',
- :source => 'https://testme:Password2@pgp.mit.edu'
- )}.to_not raise_error
- end
+ :source => 'http://apt.puppetlabs.com/pubkey.gpg',
+ :content => 'Completely invalid as a GPG key'
+ )}.to raise_error(/content and source are mutually exclusive/)
+ end
+
+ it 'raises an error if a weird length key is used' do
+ expect { Puppet::Type.type(typename).new(
+ :id => 'FEF8D349F',
+ :source => 'http://apt.puppetlabs.com/pubkey.gpg',
+ :content => 'Completely invalid as a GPG key'
+ )}.to raise_error(/Valid values match/)
+ end
+
+ it 'raises an error when an invalid URI scheme is used in source' do
+ expect { Puppet::Type.type(typename).new(
+ :id => 'EF8D349F',
+ :source => 'hkp://pgp.mit.edu'
+ )}.to raise_error(/Valid values match/)
+ end
- it 'allows the ftp URI scheme in source' do
- expect { Puppet::Type.type(:apt_key).new(
- :id => 'EF8D349F',
- :source => 'ftp://pgp.mit.edu'
- )}.to_not raise_error
- end
+ it 'allows the http URI scheme in source' do
+ expect { Puppet::Type.type(typename).new(
+ :id => 'EF8D349F',
+ :source => 'http://pgp.mit.edu'
+ )}.to_not raise_error
+ end
+
+ it 'allows the http URI with username and password' do
+ expect { Puppet::Type.type(typename).new(
+ :id => '4BD6EC30',
+ :source => 'http://testme:Password2@pgp.mit.edu'
+ )}.to_not raise_error
+ end
+
+ it 'allows the https URI scheme in source' do
+ expect { Puppet::Type.type(typename).new(
+ :id => 'EF8D349F',
+ :source => 'https://pgp.mit.edu'
+ )}.to_not raise_error
+ end
+
+ it 'allows the https URI with username and password' do
+ expect { Puppet::Type.type(typename).new(
+ :id => 'EF8D349F',
+ :source => 'https://testme:Password2@pgp.mit.edu'
+ )}.to_not raise_error
+ end
+
+ it 'allows the ftp URI scheme in source' do
+ expect { Puppet::Type.type(typename).new(
+ :id => 'EF8D349F',
+ :source => 'ftp://pgp.mit.edu'
+ )}.to_not raise_error
+ end
- it 'allows an absolute path in source' do
- expect { Puppet::Type.type(:apt_key).new(
- :id => 'EF8D349F',
- :source => '/path/to/a/file'
- )}.to_not raise_error
- end
+ it 'allows an absolute path in source' do
+ expect { Puppet::Type.type(typename).new(
+ :id => 'EF8D349F',
+ :source => '/path/to/a/file'
+ )}.to_not raise_error
+ end
- it 'allows 5-digit ports' do
- expect { Puppet::Type.type(:apt_key).new(
- :id => 'EF8D349F',
- :source => 'http://pgp.mit.edu:12345/key'
- )}.to_not raise_error
- end
+ it 'allows 5-digit ports' do
+ expect { Puppet::Type.type(typename).new(
+ :id => 'EF8D349F',
+ :source => 'http://pgp.mit.edu:12345/key'
+ )}.to_not raise_error
+ end
- it 'allows 5-digit ports when using key servers' do
- expect { Puppet::Type.type(:apt_key).new(
- :id => 'EF8D349F',
- :server => 'http://pgp.mit.edu:12345'
- )}.to_not raise_error
+ it 'allows 5-digit ports when using key servers' do
+ expect { Puppet::Type.type(typename).new(
+ :id => 'EF8D349F',
+ :server => 'http://pgp.mit.edu:12345'
+ )}.to_not raise_error
+ end
end
end
end