diff options
-rwxr-xr-x | lib/puppet/provider/sshkey/parsed.rb | 56 | ||||
-rwxr-xr-x | lib/puppet/type/parsedtype/sshkey.rb | 129 | ||||
-rwxr-xr-x | lib/puppet/type/sshkey.rb | 60 | ||||
-rw-r--r-- | test/lib/puppettest/fileparsing.rb (renamed from test/lib/puppettest/parsing.rb) | 2 | ||||
-rwxr-xr-x[-rw-r--r--] | test/providers/parsedhost.rb | 4 | ||||
-rwxr-xr-x | test/providers/parsedsshkey.rb | 34 | ||||
-rwxr-xr-x | test/types/sshkey.rb | 88 |
7 files changed, 186 insertions, 187 deletions
diff --git a/lib/puppet/provider/sshkey/parsed.rb b/lib/puppet/provider/sshkey/parsed.rb new file mode 100755 index 000000000..e1dbeaad6 --- /dev/null +++ b/lib/puppet/provider/sshkey/parsed.rb @@ -0,0 +1,56 @@ +require 'puppet/provider/parsedfile' + +Puppet::Type.type(:sshkey).provide :parsed, :parent => Puppet::Provider::ParsedFile do + @filetype = Puppet::FileType.filetype(:flat) + @path = "/etc/ssh/ssh_known_hosts" + @fields = [:name, :type, :key] + + # Parse an sshknownhosts file + # + # This method also stores existing comments, and it stores all host + # jobs in order, mostly so that comments are retained in the order + # they were written and in proximity to the same jobs. + def self.parse(text) + count = 0 + instances = [] + text.chomp.split("\n").each { |line| + hash = {} + case line + when /^#/, /^\s*$/: + # add comments and blank lines to the list as they are + instances << line + else + hash = {} + fields().zip(line.split(" ")).each { |param, value| + hash[param] = value + } + + if hash[:name] =~ /,/ + names = hash[:name].split(",") + hash[:name] = names.shift + hash[:alias] = names + end + + if hash[:alias] == "" + hash.delete(:alias) + end + + instances << hash + count += 1 + end + } + + return instances + end + + # Convert the current object into an entry for a known-hosts file. + def self.to_record(hash) + name = hash[:name] + if hash.include?(:alias) + name += "," + hash[:alias].join(",") + end + [name, hash[:type], hash[:key]].join(" ") + end +end + +# $Id$ diff --git a/lib/puppet/type/parsedtype/sshkey.rb b/lib/puppet/type/parsedtype/sshkey.rb deleted file mode 100755 index d8fb6cda3..000000000 --- a/lib/puppet/type/parsedtype/sshkey.rb +++ /dev/null @@ -1,129 +0,0 @@ -require 'etc' -require 'facter' -require 'puppet/type/parsedtype' -require 'puppet/type/state' - -module Puppet - newtype(:sshkey, Puppet::Type::ParsedType) do - newstate(:type) do - desc "The encryption type used. Probably ssh-dss or ssh-rsa." - end - - newstate(:key) do - desc "The key itself; generally a long string of hex digits." - end - - # FIXME This should automagically check for aliases to the hosts, just - # to see if we can automatically glean any aliases. - newstate(:alias) do - desc "Any alias the host might have. Multiple values must be - specified as an array. Note that this state has the same name - as one of the metaparams; using this state to set aliases will - make those aliases available in your Puppet scripts." - - # We actually want to return the whole array here, not just the first - # value. - def should - if defined? @should - return @should - else - return nil - end - end - - validate do |value| - if value =~ /\s/ - raise Puppet::Error, "Aliases cannot include whitespace" - end - if value =~ /,/ - raise Puppet::Error, "Aliases cannot include whitespace" - end - end - - # Make a puppet alias in addition. - munge do |value| - # Add the :alias metaparam in addition to the state - @parent.newmetaparam(@parent.class.metaparamclass(:alias), value) - value - end - end - - newparam(:name) do - desc "The host name." - - isnamevar - end - - @doc = "Installs and manages ssh host keys. At this point, this type - only knows how to install keys into /etc/ssh/ssh_known_hosts, and - it cannot manage user authorized keys yet." - - @instances = [] - - # FIXME This should be configurable. - # Adding at least hard-coded alternative placement for Darwin - ajax - case Facter.value("operatingsystem") - when "Darwin": - @path = "/etc/ssh_known_hosts" - else - @path = "/etc/ssh/ssh_known_hosts" - end - @fields = [:name, :type, :key] - - @filetype = Puppet::FileType.filetype(:flat) -# case Facter["operatingsystem"].value -# when "Solaris": -# @filetype = Puppet::FileType::SunOS -# else -# @filetype = Puppet::CronType::Default -# end - - # Parse a host file - # - # This method also stores existing comments, and it stores all host - # jobs in order, mostly so that comments are retained in the order - # they were written and in proximity to the same jobs. - def self.parse(text) - count = 0 - hash = {} - text.chomp.split("\n").each { |line| - case line - when /^#/, /^\s*$/: - # add comments and blank lines to the list as they are - @instances << line - else - hash = {} - fields().zip(line.split(" ")).each { |param, value| - hash[param] = value - } - - if hash[:name] =~ /,/ - names = hash[:name].split(",") - hash[:name] = names.shift - hash[:alias] = names - end - - if hash[:alias] == "" - hash.delete(:alias) - end - - hash2obj(hash) - - hash.clear - count += 1 - end - } - end - - # Convert the current object into a host-style string. - def to_record - name = self[:name] - if @states.include?(:alias) - name += "," + @states[:alias].value.join(",") - end - [name, @states[:type].value, @states[:key].value].join(" ") - end - end -end - -# $Id$ diff --git a/lib/puppet/type/sshkey.rb b/lib/puppet/type/sshkey.rb new file mode 100755 index 000000000..102e792af --- /dev/null +++ b/lib/puppet/type/sshkey.rb @@ -0,0 +1,60 @@ +module Puppet + newtype(:sshkey, Puppet::Type::ParsedType) do + @doc = "Installs and manages ssh host keys. At this point, this type + only knows how to install keys into /etc/ssh/ssh_known_hosts, and + it cannot manage user authorized keys yet." + + newstate(:type) do + desc "The encryption type used. Probably ssh-dss or ssh-rsa." + end + + newstate(:key) do + desc "The key itself; generally a long string of hex digits." + end + + # FIXME This should automagically check for aliases to the hosts, just + # to see if we can automatically glean any aliases. + newstate(:alias) do + desc "Any alias the host might have. Multiple values must be + specified as an array. Note that this state has the same name + as one of the metaparams; using this state to set aliases will + make those aliases available in your Puppet scripts." + + # We actually want to return the whole array here, not just the first + # value. + def should + if defined? @should + return @should + else + return nil + end + end + + validate do |value| + if value =~ /\s/ + raise Puppet::Error, "Aliases cannot include whitespace" + end + if value =~ /,/ + raise Puppet::Error, "Aliases cannot include whitespace" + end + end + + # Make a puppet alias in addition. + munge do |value| + unless value == :absent + # Add the :alias metaparam in addition to the state + @parent.newmetaparam(@parent.class.metaparamclass(:alias), value) + end + value + end + end + + newparam(:name) do + desc "The host name." + + isnamevar + end + end +end + +# $Id$ diff --git a/test/lib/puppettest/parsing.rb b/test/lib/puppettest/fileparsing.rb index a98194bef..004a0c3b5 100644 --- a/test/lib/puppettest/parsing.rb +++ b/test/lib/puppettest/fileparsing.rb @@ -1,4 +1,4 @@ -module PuppetTest::Parsing +module PuppetTest::FileParsing # Run an isomorphism test on our parsing process. def fakedataparse(file) @provider.path = file diff --git a/test/providers/parsedhost.rb b/test/providers/parsedhost.rb index ab02fbeac..9836b90d1 100644..100755 --- a/test/providers/parsedhost.rb +++ b/test/providers/parsedhost.rb @@ -5,12 +5,12 @@ $:.unshift("../lib").unshift("../../lib") if __FILE__ =~ /\.rb$/ require 'etc' require 'puppet/type' require 'puppettest' -require 'puppettest/parsing' +require 'puppettest/fileparsing' require 'test/unit' class TestParsedHostProvider < Test::Unit::TestCase include PuppetTest - include PuppetTest::Parsing + include PuppetTest::FileParsing def setup super diff --git a/test/providers/parsedsshkey.rb b/test/providers/parsedsshkey.rb new file mode 100755 index 000000000..547e52e8b --- /dev/null +++ b/test/providers/parsedsshkey.rb @@ -0,0 +1,34 @@ +#!/usr/bin/env ruby + +$:.unshift("../lib").unshift("../../lib") if __FILE__ =~ /\.rb$/ + +require 'puppettest' +require 'puppettest/fileparsing' +require 'puppet' +require 'puppet/type/sshkey' + +class TestParsedSSHKey < Test::Unit::TestCase + include PuppetTest + include PuppetTest::FileParsing + + def setup + super + @provider = Puppet.type(:sshkey).provider(:parsed) + + @oldfiletype = @provider.filetype + end + + def teardown + Puppet::FileType.filetype(:ram).clear + @provider.filetype = @oldfiletype + super + end + + def test_keysparse + fakedata("data/types/sshkey").each { |file| + fakedataparse(file) + } + end +end + +# $Id$ diff --git a/test/types/sshkey.rb b/test/types/sshkey.rb index 5075ac88a..1a25c4cd0 100755 --- a/test/types/sshkey.rb +++ b/test/types/sshkey.rb @@ -2,11 +2,9 @@ $:.unshift("../lib").unshift("../../lib") if __FILE__ =~ /\.rb$/ -# Test key job creation, modification, and destruction - require 'puppettest' require 'puppet' -require 'puppet/type/parsedtype/sshkey' +require 'puppet/type/sshkey' require 'facter' class TestSSHKey < Test::Unit::TestCase @@ -14,21 +12,22 @@ class TestSSHKey < Test::Unit::TestCase def setup super # god i'm lazy - @sshtype = Puppet.type(:sshkey) - @oldfiletype = @sshtype.filetype - end + @sshkeytype = Puppet.type(:sshkey) - def teardown - Puppet::FileType.filetype(:ram).clear - @sshtype.filetype = @oldfiletype - Puppet.type(:file).clear - super - end + @provider = @sshkeytype.defaultprovider + + # Make sure they aren't using something funky like netinfo + unless @provider.name == :parsed + @sshkeytype.defaultprovider = @sshkeytype.provider(:parsed) + end - # Here we just create a fake key type that answers to all of the methods - # but does not modify our actual system. - def mkfaketype - @sshtype.filetype = Puppet::FileType.filetype(:ram) + cleanup do @sshkeytype.defaultprovider = nil end + + oldpath = @provider.path + cleanup do + @provider.path = oldpath + end + @provider.path = tempfile() end def mkkey @@ -41,7 +40,7 @@ class TestSSHKey < Test::Unit::TestCase end assert_nothing_raised { - key = @sshtype.create( + key = @sshkeytype.create( :name => "host%s.madstop.com" % @kcount, :key => "%sAAAAB3NzaC1kc3MAAACBAMnhSiku76y3EGkNCDsUlvpO8tRgS9wL4Eh54WZfQ2lkxqfd2uT/RTT9igJYDtm/+UHuBRdNGpJYW1Nw2i2JUQgQEEuitx4QKALJrBotejGOAWxxVk6xsh9xA0OW8Q3ZfuX2DDitfeC8ZTCl4xodUMD8feLtP+zEf8hxaNamLlt/AAAAFQDYJyf3vMCWRLjTWnlxLtOyj/bFpwAAAIEAmRxxXb4jjbbui9GYlZAHK00689DZuX0EabHNTl2yGO5KKxGC6Esm7AtjBd+onfu4Rduxut3jdI8GyQCIW8WypwpJofCIyDbTUY4ql0AQUr3JpyVytpnMijlEyr41FfIb4tnDqnRWEsh2H7N7peW+8DWZHDFnYopYZJ9Yu4/jHRYAAACAERG50e6aRRb43biDr7Ab9NUCgM9bC0SQscI/xdlFjac0B/kSWJYTGVARWBDWug705hTnlitY9cLC5Ey/t/OYOjylTavTEfd/bh/8FkAYO+pWdW3hx6p97TBffK0b6nrc6OORT2uKySbbKOn0681nNQh4a6ueR3JRppNkRPnTk5c=" % @kcount, :type => "ssh-dss", @@ -53,41 +52,25 @@ class TestSSHKey < Test::Unit::TestCase end def test_simplekey - mkfaketype assert_nothing_raised { - assert_nil(Puppet.type(:sshkey).retrieve) + Puppet.type(:sshkey).defaultprovider.retrieve + + count = 0 + @sshkeytype.each do |h| + count += 1 + end + + assert_equal(0, count, "Found sshkeys in empty file somehow") } key = mkkey assert_apply(key) - assert_nothing_raised { - Puppet.type(:sshkey).store - } - - assert_nothing_raised { - assert( - Puppet.type(:sshkey).to_file.include?( - Puppet.type(:sshkey).fileobj.read - ), - "File does not include all of our objects" - ) - } - end - - def test_keysparse - fakedata("data/types/sshkey").each { |file| - @sshtype.path = file - assert_nothing_raised { - @sshtype.retrieve - } - @sshtype.clear - } + assert(key.exists?, "Key did not get created") end def test_moddingkey - mkfaketype key = mkkey() assert_events([:sshkey_created], key) @@ -96,12 +79,11 @@ class TestSSHKey < Test::Unit::TestCase key[:alias] = %w{madstop kirby yayness} - Puppet.err :mark assert_events([:sshkey_changed], key) end def test_aliasisstate - assert_equal(:state, @sshtype.attrtype(:alias)) + assert_equal(:state, @sshkeytype.attrtype(:alias)) end def test_multivalues @@ -123,28 +105,24 @@ class TestSSHKey < Test::Unit::TestCase end def test_removal - mkfaketype sshkey = mkkey() assert_nothing_raised { sshkey[:ensure] = :present } assert_events([:sshkey_created], sshkey) - sshkey.retrieve - assert(sshkey.insync?) + assert(sshkey.exists?, "key was not created") assert_nothing_raised { sshkey[:ensure] = :absent } assert_events([:sshkey_removed], sshkey) - sshkey.retrieve + assert(! sshkey.exists?, "Key was not deleted") assert_events([], sshkey) end + # Make sure changes actually modify the file. def test_modifyingfile - keyfile = tempfile() - Puppet.type(:sshkey).path = keyfile - keys = [] names = [] 3.times { @@ -161,7 +139,7 @@ class TestSSHKey < Test::Unit::TestCase #newkey[:ensure] = :present names << newkey.name assert_apply(newkey) - Puppet.type(:sshkey).clear + # Verify we can retrieve that info assert_nothing_raised("Could not retrieve after second write") { newkey.retrieve @@ -169,9 +147,9 @@ class TestSSHKey < Test::Unit::TestCase # And verify that we have data for everything names.each { |name| - key = Puppet.type(:sshkey)[name] - assert(key) - assert(key[:type]) + key = Puppet.type(:sshkey)[name] || Puppet.type(:sshkey).create(:name => name) + assert(key, "Could not retrieve key for %s" % name) + assert(key.exists?, "key %s is missing" % name) } end end |