require 'spec_helper' FakeHostProvider = Struct.new(:ip, :host_aliases, :comment) describe Puppet::Type.type(:host) do let(:provider) { FakeHostProvider.new } let(:resource) { instance_double('Puppet::Type::Host', provider: provider) } it 'has :name be its namevar' do expect(described_class.key_attributes).to eq([:name]) end describe 'when validating attributes' do [:name, :provider].each do |param| it "should have a #{param} parameter" do expect(described_class.attrtype(param)).to eq(:param) end end [:ip, :target, :host_aliases, :comment, :ensure].each do |property| it "should have a #{property} property" do expect(described_class.attrtype(property)).to eq(:property) end end it 'has a list host_aliases' do expect(described_class.attrclass(:host_aliases).ancestors).to be_include(Puppet::Property::OrderedList) end end describe 'when validating values' do it 'supports present as a value for ensure' do expect { described_class.new(name: 'foo', ensure: :present) }.not_to raise_error end it 'supports absent as a value for ensure' do expect { described_class.new(name: 'foo', ensure: :absent) }.not_to raise_error end it 'accepts IPv4 addresses' do expect { described_class.new(name: 'foo', ip: '10.96.0.1') }.not_to raise_error end it 'accepts long IPv6 addresses' do # Taken from wikipedia article about ipv6 expect { described_class.new(name: 'foo', ip: '2001:0db8:85a3:08d3:1319:8a2e:0370:7344') }.not_to raise_error end it 'accepts one host_alias' do expect { described_class.new(name: 'foo', host_aliases: 'alias1') }.not_to raise_error end it 'accepts multiple host_aliases' do expect { described_class.new(name: 'foo', host_aliases: ['alias1', 'alias2']) }.not_to raise_error end it 'accepts shortened IPv6 addresses' do expect { described_class.new(name: 'foo', ip: '2001:db8:0:8d3:0:8a2e:70:7344') }.not_to raise_error expect { described_class.new(name: 'foo', ip: '::ffff:192.0.2.128') }.not_to raise_error expect { described_class.new(name: 'foo', ip: '::1') }.not_to raise_error end it 'does not accept malformed IPv4 addresses like 192.168.0.300' do expect { described_class.new(name: 'foo', ip: '192.168.0.300') }.to raise_error(Puppet::ResourceError, %r{Parameter ip failed}) end it 'rejects over-long IPv4 addresses' do expect { described_class.new(name: 'foo', ip: '10.10.10.10.10') }.to raise_error(Puppet::ResourceError, %r{Parameter ip failed}) end it 'does not accept malformed IP addresses like 2001:0dg8:85a3:08d3:1319:8a2e:0370:7344' do expect { described_class.new(name: 'foo', ip: '2001:0dg8:85a3:08d3:1319:8a2e:0370:7344') }.to raise_error(Puppet::ResourceError, %r{Parameter ip failed}) end # Assorted, annotated IPv6 passes. ['::1', # loopback, compressed, non-routable '::', # unspecified, compressed, non-routable '0:0:0:0:0:0:0:1', # loopback, full '0:0:0:0:0:0:0:0', # unspecified, full '2001:DB8:0:0:8:800:200C:417A', # unicast, full 'FF01:0:0:0:0:0:0:101', # multicast, full '2001:DB8::8:800:200C:417A', # unicast, compressed 'FF01::101', # multicast, compressed # Some more test cases that should pass. '2001:0000:1234:0000:0000:C1C0:ABCD:0876', '3ffe:0b00:0000:0000:0001:0000:0000:000a', 'FF02:0000:0000:0000:0000:0000:0000:0001', '0000:0000:0000:0000:0000:0000:0000:0001', '0000:0000:0000:0000:0000:0000:0000:0000', # Assorted valid, compressed IPv6 addresses. '2::10', 'ff02::1', 'fe80::', '2002::', '2001:db8::', '2001:0db8:1234::', '::ffff:0:0', '::1', '1:2:3:4:5:6:7:8', '1:2:3:4:5:6::8', '1:2:3:4:5::8', '1:2:3:4::8', '1:2:3::8', '1:2::8', '1::8', '1::2:3:4:5:6:7', '1::2:3:4:5:6', '1::2:3:4:5', '1::2:3:4', '1::2:3', '1::8', '::2:3:4:5:6:7:8', '::2:3:4:5:6:7', '::2:3:4:5:6', '::2:3:4:5', '::2:3:4', '::2:3', '::8', '1:2:3:4:5:6::', '1:2:3:4:5::', '1:2:3:4::', '1:2:3::', '1:2::', '1::', '1:2:3:4:5::7:8', '1:2:3:4::7:8', '1:2:3::7:8', '1:2::7:8', '1::7:8', # IPv4 addresses as dotted-quads '1:2:3:4:5:6:1.2.3.4', '1:2:3:4:5::1.2.3.4', '1:2:3:4::1.2.3.4', '1:2:3::1.2.3.4', '1:2::1.2.3.4', '1::1.2.3.4', '1:2:3:4::5:1.2.3.4', '1:2:3::5:1.2.3.4', '1:2::5:1.2.3.4', '1::5:1.2.3.4', '1::5:11.22.33.44', 'fe80::217:f2ff:254.7.237.98', '::ffff:192.168.1.26', '::ffff:192.168.1.1', '0:0:0:0:0:0:13.1.68.3', # IPv4-compatible IPv6 address, full, deprecated '0:0:0:0:0:FFFF:129.144.52.38', # IPv4-mapped IPv6 address, full '::13.1.68.3', # IPv4-compatible IPv6 address, compressed, deprecated '::FFFF:129.144.52.38', # IPv4-mapped IPv6 address, compressed 'fe80:0:0:0:204:61ff:254.157.241.86', 'fe80::204:61ff:254.157.241.86', '::ffff:12.34.56.78', '::ffff:192.0.2.128', # this is OK, since there's a single zero digit in IPv4 'fe80:0000:0000:0000:0204:61ff:fe9d:f156', 'fe80:0:0:0:204:61ff:fe9d:f156', 'fe80::204:61ff:fe9d:f156', '::1', 'fe80::', 'fe80::1', '::ffff:c000:280', # Additional test cases from http://rt.cpan.org/Public/Bug/Display.html?id=50693 '2001:0db8:85a3:0000:0000:8a2e:0370:7334', '2001:db8:85a3:0:0:8a2e:370:7334', '2001:db8:85a3::8a2e:370:7334', '2001:0db8:0000:0000:0000:0000:1428:57ab', '2001:0db8:0000:0000:0000::1428:57ab', '2001:0db8:0:0:0:0:1428:57ab', '2001:0db8:0:0::1428:57ab', '2001:0db8::1428:57ab', '2001:db8::1428:57ab', '0000:0000:0000:0000:0000:0000:0000:0001', '::1', '::ffff:0c22:384e', '2001:0db8:1234:0000:0000:0000:0000:0000', '2001:0db8:1234:ffff:ffff:ffff:ffff:ffff', '2001:db8:a::123', 'fe80::', '1111:2222:3333:4444:5555:6666:7777:8888', '1111:2222:3333:4444:5555:6666:7777::', '1111:2222:3333:4444:5555:6666::', '1111:2222:3333:4444:5555::', '1111:2222:3333:4444::', '1111:2222:3333::', '1111:2222::', '1111::', '1111:2222:3333:4444:5555:6666::8888', '1111:2222:3333:4444:5555::8888', '1111:2222:3333:4444::8888', '1111:2222:3333::8888', '1111:2222::8888', '1111::8888', '::8888', '1111:2222:3333:4444:5555::7777:8888', '1111:2222:3333:4444::7777:8888', '1111:2222:3333::7777:8888', '1111:2222::7777:8888', '1111::7777:8888', '::7777:8888', '1111:2222:3333:4444::6666:7777:8888', '1111:2222:3333::6666:7777:8888', '1111:2222::6666:7777:8888', '1111::6666:7777:8888', '::6666:7777:8888', '1111:2222:3333::5555:6666:7777:8888', '1111:2222::5555:6666:7777:8888', '1111::5555:6666:7777:8888', '::5555:6666:7777:8888', '1111:2222::4444:5555:6666:7777:8888', '1111::4444:5555:6666:7777:8888', '::4444:5555:6666:7777:8888', '1111::3333:4444:5555:6666:7777:8888', '::3333:4444:5555:6666:7777:8888', '::2222:3333:4444:5555:6666:7777:8888', '1111:2222:3333:4444:5555:6666:123.123.123.123', '1111:2222:3333:4444:5555::123.123.123.123', '1111:2222:3333:4444::123.123.123.123', '1111:2222:3333::123.123.123.123', '1111:2222::123.123.123.123', '1111::123.123.123.123', '::123.123.123.123', '1111:2222:3333:4444::6666:123.123.123.123', '1111:2222:3333::6666:123.123.123.123', '1111:2222::6666:123.123.123.123', '1111::6666:123.123.123.123', '::6666:123.123.123.123', '1111:2222:3333::5555:6666:123.123.123.123', '1111:2222::5555:6666:123.123.123.123', '1111::5555:6666:123.123.123.123', '::5555:6666:123.123.123.123', '1111:2222::4444:5555:6666:123.123.123.123', '1111::4444:5555:6666:123.123.123.123', '::4444:5555:6666:123.123.123.123', '1111::3333:4444:5555:6666:123.123.123.123', '::2222:3333:4444:5555:6666:123.123.123.123', # Playing with combinations of "0" and "::"; these are all sytactically # correct, but are bad form because "0" adjacent to "::" should be # combined into "::" '::0:0:0:0:0:0:0', '::0:0:0:0:0:0', '::0:0:0:0:0', '::0:0:0:0', '::0:0:0', '::0:0', '::0', '0:0:0:0:0:0:0::', '0:0:0:0:0:0::', '0:0:0:0:0::', '0:0:0:0::', '0:0:0::', '0:0::', '0::', # Additional cases: http://crisp.tweakblogs.net/blog/2031/ipv6-validation-%28and-caveats%29.html '0:a:b:c:d:e:f::', '::0:a:b:c:d:e:f', # syntactically correct, but bad form (::0:... could be combined) 'a:b:c:d:e:f:0::'].each do |ip| it "should accept #{ip.inspect} as an IPv6 address" do expect { described_class.new(name: 'foo', ip: ip) }.not_to raise_error end end # ...aaaand, some failure cases. [':', '02001:0000:1234:0000:0000:C1C0:ABCD:0876', # extra 0 not allowed! '2001:0000:1234:0000:00001:C1C0:ABCD:0876', # extra 0 not allowed! '2001:0000:1234:0000:0000:C1C0:ABCD:0876 0', # junk after valid address '2001:0000:1234: 0000:0000:C1C0:ABCD:0876', # internal space '3ffe:0b00:0000:0001:0000:0000:000a', # seven segments 'FF02:0000:0000:0000:0000:0000:0000:0000:0001', # nine segments '3ffe:b00::1::a', # double "::" '::1111:2222:3333:4444:5555:6666::', # double "::" '1:2:3::4:5::7:8', # Double "::" '12345::6:7:8', # IPv4 embedded, but bad... '1::5:400.2.3.4', '1::5:260.2.3.4', '1::5:256.2.3.4', '1::5:1.256.3.4', '1::5:1.2.256.4', '1::5:1.2.3.256', '1::5:300.2.3.4', '1::5:1.300.3.4', '1::5:1.2.300.4', '1::5:1.2.3.300', '1::5:900.2.3.4', '1::5:1.900.3.4', '1::5:1.2.900.4', '1::5:1.2.3.900', '1::5:300.300.300.300', '1::5:3000.30.30.30', '1::400.2.3.4', '1::260.2.3.4', '1::256.2.3.4', '1::1.256.3.4', '1::1.2.256.4', '1::1.2.3.256', '1::300.2.3.4', '1::1.300.3.4', '1::1.2.300.4', '1::1.2.3.300', '1::900.2.3.4', '1::1.900.3.4', '1::1.2.900.4', '1::1.2.3.900', '1::300.300.300.300', '1::3000.30.30.30', '::400.2.3.4', '::260.2.3.4', '::256.2.3.4', '::1.256.3.4', '::1.2.256.4', '::1.2.3.256', '::300.2.3.4', '::1.300.3.4', '::1.2.300.4', '::1.2.3.300', '::900.2.3.4', '::1.900.3.4', '::1.2.900.4', '::1.2.3.900', '::300.300.300.300', '::3000.30.30.30', '2001:1:1:1:1:1:255Z255X255Y255', # garbage instead of "." in IPv4 '::ffff:192x168.1.26', # ditto '::ffff:2.3.4', '::ffff:257.1.2.3', '1.2.3.4:1111:2222:3333:4444::5555', '1.2.3.4:1111:2222:3333::5555', '1.2.3.4:1111:2222::5555', '1.2.3.4:1111::5555', '1.2.3.4::5555', '1.2.3.4::', # Testing IPv4 addresses represented as dotted-quads Leading zero's in # IPv4 addresses not allowed: some systems treat the leading "0" in # ".086" as the start of an octal number Update: The BNF in RFC-3986 # explicitly defines the dec-octet (for IPv4 addresses) not to have a # leading zero 'fe80:0000:0000:0000:0204:61ff:254.157.241.086', 'XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:1.2.3.4', '1111:2222:3333:4444:5555:6666:00.00.00.00', '1111:2222:3333:4444:5555:6666:000.000.000.000', '1111:2222:3333:4444:5555:6666:256.256.256.256', '1111:2222:3333:4444::5555:', '1111:2222:3333::5555:', '1111:2222::5555:', '1111::5555:', '::5555:', ':::', '1111:', ':', ':1111:2222:3333:4444::5555', ':1111:2222:3333::5555', ':1111:2222::5555', ':1111::5555', ':::5555', ':::', # Additional test cases from http://rt.cpan.org/Public/Bug/Display.html?id=50693 '123', 'ldkfj', '2001::FFD3::57ab', '2001:db8:85a3::8a2e:37023:7334', '2001:db8:85a3::8a2e:370k:7334', '1:2:3:4:5:6:7:8:9', '1::2::3', '1:::3:4:5', '1:2:3::4:5:6:7:8:9', # Invalid data 'XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX', # Too many components '1111:2222:3333:4444:5555:6666:7777:8888:9999', '1111:2222:3333:4444:5555:6666:7777:8888::', '::2222:3333:4444:5555:6666:7777:8888:9999', # Too few components '1111:2222:3333:4444:5555:6666:7777', '1111:2222:3333:4444:5555:6666', '1111:2222:3333:4444:5555', '1111:2222:3333:4444', '1111:2222:3333', '1111:2222', '1111', # Missing : '11112222:3333:4444:5555:6666:7777:8888', '1111:22223333:4444:5555:6666:7777:8888', '1111:2222:33334444:5555:6666:7777:8888', '1111:2222:3333:44445555:6666:7777:8888', '1111:2222:3333:4444:55556666:7777:8888', '1111:2222:3333:4444:5555:66667777:8888', '1111:2222:3333:4444:5555:6666:77778888', # Missing : intended for :: '1111:2222:3333:4444:5555:6666:7777:8888:', '1111:2222:3333:4444:5555:6666:7777:', '1111:2222:3333:4444:5555:6666:', '1111:2222:3333:4444:5555:', '1111:2222:3333:4444:', '1111:2222:3333:', '1111:2222:', '1111:', ':', ':8888', ':7777:8888', ':6666:7777:8888', ':5555:6666:7777:8888', ':4444:5555:6666:7777:8888', ':3333:4444:5555:6666:7777:8888', ':2222:3333:4444:5555:6666:7777:8888', ':1111:2222:3333:4444:5555:6666:7777:8888', # ::: ':::2222:3333:4444:5555:6666:7777:8888', '1111:::3333:4444:5555:6666:7777:8888', '1111:2222:::4444:5555:6666:7777:8888', '1111:2222:3333:::5555:6666:7777:8888', '1111:2222:3333:4444:::6666:7777:8888', '1111:2222:3333:4444:5555:::7777:8888', '1111:2222:3333:4444:5555:6666:::8888', '1111:2222:3333:4444:5555:6666:7777:::', # Double ::", '::2222::4444:5555:6666:7777:8888', '::2222:3333::5555:6666:7777:8888', '::2222:3333:4444::6666:7777:8888', '::2222:3333:4444:5555::7777:8888', '::2222:3333:4444:5555:7777::8888', '::2222:3333:4444:5555:7777:8888::', '1111::3333::5555:6666:7777:8888', '1111::3333:4444::6666:7777:8888', '1111::3333:4444:5555::7777:8888', '1111::3333:4444:5555:6666::8888', '1111::3333:4444:5555:6666:7777::', '1111:2222::4444::6666:7777:8888', '1111:2222::4444:5555::7777:8888', '1111:2222::4444:5555:6666::8888', '1111:2222::4444:5555:6666:7777::', '1111:2222:3333::5555::7777:8888', '1111:2222:3333::5555:6666::8888', '1111:2222:3333::5555:6666:7777::', '1111:2222:3333:4444::6666::8888', '1111:2222:3333:4444::6666:7777::', '1111:2222:3333:4444:5555::7777::', # Too many components" '1111:2222:3333:4444:5555:6666:7777:8888:1.2.3.4', '1111:2222:3333:4444:5555:6666:7777:1.2.3.4', '1111:2222:3333:4444:5555:6666::1.2.3.4', '::2222:3333:4444:5555:6666:7777:1.2.3.4', '1111:2222:3333:4444:5555:6666:1.2.3.4.5', # Too few components '1111:2222:3333:4444:5555:1.2.3.4', '1111:2222:3333:4444:1.2.3.4', '1111:2222:3333:1.2.3.4', '1111:2222:1.2.3.4', '1111:1.2.3.4', # Missing : '11112222:3333:4444:5555:6666:1.2.3.4', '1111:22223333:4444:5555:6666:1.2.3.4', '1111:2222:33334444:5555:6666:1.2.3.4', '1111:2222:3333:44445555:6666:1.2.3.4', '1111:2222:3333:4444:55556666:1.2.3.4', '1111:2222:3333:4444:5555:66661.2.3.4', # Missing . '1111:2222:3333:4444:5555:6666:255255.255.255', '1111:2222:3333:4444:5555:6666:255.255255.255', '1111:2222:3333:4444:5555:6666:255.255.255255', # Missing : intended for :: ':1.2.3.4', ':6666:1.2.3.4', ':5555:6666:1.2.3.4', ':4444:5555:6666:1.2.3.4', ':3333:4444:5555:6666:1.2.3.4', ':2222:3333:4444:5555:6666:1.2.3.4', ':1111:2222:3333:4444:5555:6666:1.2.3.4', # ::: ':::2222:3333:4444:5555:6666:1.2.3.4', '1111:::3333:4444:5555:6666:1.2.3.4', '1111:2222:::4444:5555:6666:1.2.3.4', '1111:2222:3333:::5555:6666:1.2.3.4', '1111:2222:3333:4444:::6666:1.2.3.4', '1111:2222:3333:4444:5555:::1.2.3.4', # Double :: '::2222::4444:5555:6666:1.2.3.4', '::2222:3333::5555:6666:1.2.3.4', '::2222:3333:4444::6666:1.2.3.4', '::2222:3333:4444:5555::1.2.3.4', '1111::3333::5555:6666:1.2.3.4', '1111::3333:4444::6666:1.2.3.4', '1111::3333:4444:5555::1.2.3.4', '1111:2222::4444::6666:1.2.3.4', '1111:2222::4444:5555::1.2.3.4', '1111:2222:3333::5555::1.2.3.4', # Missing parts '::.', '::..', '::...', '::1...', '::1.2..', '::1.2.3.', '::.2..', '::.2.3.', '::.2.3.4', '::..3.', '::..3.4', '::...4', # Extra : in front ':1111:2222:3333:4444:5555:6666:7777::', ':1111:2222:3333:4444:5555:6666::', ':1111:2222:3333:4444:5555::', ':1111:2222:3333:4444::', ':1111:2222:3333::', ':1111:2222::', ':1111::', ':::', ':1111:2222:3333:4444:5555:6666::8888', ':1111:2222:3333:4444:5555::8888', ':1111:2222:3333:4444::8888', ':1111:2222:3333::8888', ':1111:2222::8888', ':1111::8888', ':::8888', ':1111:2222:3333:4444:5555::7777:8888', ':1111:2222:3333:4444::7777:8888', ':1111:2222:3333::7777:8888', ':1111:2222::7777:8888', ':1111::7777:8888', ':::7777:8888', ':1111:2222:3333:4444::6666:7777:8888', ':1111:2222:3333::6666:7777:8888', ':1111:2222::6666:7777:8888', ':1111::6666:7777:8888', ':::6666:7777:8888', ':1111:2222:3333::5555:6666:7777:8888', ':1111:2222::5555:6666:7777:8888', ':1111::5555:6666:7777:8888', ':::5555:6666:7777:8888', ':1111:2222::4444:5555:6666:7777:8888', ':1111::4444:5555:6666:7777:8888', ':::4444:5555:6666:7777:8888', ':1111::3333:4444:5555:6666:7777:8888', ':::3333:4444:5555:6666:7777:8888', ':::2222:3333:4444:5555:6666:7777:8888', ':1111:2222:3333:4444:5555:6666:1.2.3.4', ':1111:2222:3333:4444:5555::1.2.3.4', ':1111:2222:3333:4444::1.2.3.4', ':1111:2222:3333::1.2.3.4', ':1111:2222::1.2.3.4', ':1111::1.2.3.4', ':::1.2.3.4', ':1111:2222:3333:4444::6666:1.2.3.4', ':1111:2222:3333::6666:1.2.3.4', ':1111:2222::6666:1.2.3.4', ':1111::6666:1.2.3.4', ':::6666:1.2.3.4', ':1111:2222:3333::5555:6666:1.2.3.4', ':1111:2222::5555:6666:1.2.3.4', ':1111::5555:6666:1.2.3.4', ':::5555:6666:1.2.3.4', ':1111:2222::4444:5555:6666:1.2.3.4', ':1111::4444:5555:6666:1.2.3.4', ':::4444:5555:6666:1.2.3.4', ':1111::3333:4444:5555:6666:1.2.3.4', ':::2222:3333:4444:5555:6666:1.2.3.4', # Extra : at end '1111:2222:3333:4444:5555:6666:7777:::', '1111:2222:3333:4444:5555:6666:::', '1111:2222:3333:4444:5555:::', '1111:2222:3333:4444:::', '1111:2222:3333:::', '1111:2222:::', '1111:::', ':::', '1111:2222:3333:4444:5555:6666::8888:', '1111:2222:3333:4444:5555::8888:', '1111:2222:3333:4444::8888:', '1111:2222:3333::8888:', '1111:2222::8888:', '1111::8888:', '::8888:', '1111:2222:3333:4444:5555::7777:8888:', '1111:2222:3333:4444::7777:8888:', '1111:2222:3333::7777:8888:', '1111:2222::7777:8888:', '1111::7777:8888:', '::7777:8888:', '1111:2222:3333:4444::6666:7777:8888:', '1111:2222:3333::6666:7777:8888:', '1111:2222::6666:7777:8888:', '1111::6666:7777:8888:', '::6666:7777:8888:', '1111:2222:3333::5555:6666:7777:8888:', '1111:2222::5555:6666:7777:8888:', '1111::5555:6666:7777:8888:', '::5555:6666:7777:8888:', '1111:2222::4444:5555:6666:7777:8888:', '1111::4444:5555:6666:7777:8888:', '::4444:5555:6666:7777:8888:', '1111::3333:4444:5555:6666:7777:8888:', '::3333:4444:5555:6666:7777:8888:', '::2222:3333:4444:5555:6666:7777:8888:'].each do |ip| it "should reject #{ip.inspect} as an IPv6 address" do expect { described_class.new(name: 'foo', ip: ip) }.to raise_error(Puppet::ResourceError, %r{Parameter ip failed}) end end it 'does not accept newlines in resourcename' do expect { described_class.new(name: "fo\no", ip: '127.0.0.1') }.to raise_error(Puppet::ResourceError, %r{Hostname cannot include newline}) end it 'does not accept newlines in ipaddress' do expect { described_class.new(name: 'foo', ip: "127.0.0.1\n") }.to raise_error(Puppet::ResourceError, %r{Invalid IP address}) end it 'does not accept newlines in host_aliases' do expect { described_class.new(name: 'foo', ip: '127.0.0.1', host_aliases: ['well_formed', "thisalias\nhavenewline"]) }.to raise_error(Puppet::ResourceError, %r{Host aliases cannot include whitespace}) end it 'does not accept newlines in comment' do expect { described_class.new(name: 'foo', ip: '127.0.0.1', comment: "Test of comment blah blah \n test 123") }.to raise_error(Puppet::ResourceError, %r{Comment cannot include newline}) end it 'does not accept spaces in resourcename' do expect { described_class.new(name: 'foo bar') }.to raise_error(Puppet::ResourceError, %r{Invalid host name}) end it 'does not accept host_aliases with spaces' do expect { described_class.new(name: 'foo', host_aliases: ['well_formed', 'not wellformed']) }.to raise_error(Puppet::ResourceError, %r{Host aliases cannot include whitespace}) end it 'does not accept empty host_aliases' do expect { described_class.new(name: 'foo', host_aliases: ['alias1', '']) }.to raise_error(Puppet::ResourceError, %r{Host aliases cannot be an empty string}) end end describe 'when syncing' do it 'sends the first value to the provider for ip property' do ip = described_class.attrclass(:ip).new(resource: resource, should: ['192.168.0.1', '192.168.0.2']) ip.sync expect(provider.ip).to eq('192.168.0.1') end it 'sends the first value to the provider for comment property' do comment = described_class.attrclass(:comment).new(resource: resource, should: ['Bazinga', 'Notme']) comment.sync expect(provider.comment).to eq('Bazinga') end it 'sends the joined array to the provider for host_alias' do host_aliases = described_class.attrclass(:host_aliases).new(resource: resource, should: ['foo', 'bar']) host_aliases.sync expect(provider.host_aliases).to eq('foo bar') end it 'alsoes use the specified delimiter for joining' do host_aliases = described_class.attrclass(:host_aliases).new(resource: resource, should: ['foo', 'bar']) allow(host_aliases).to receive(:delimiter).and_return "\t" host_aliases.sync expect(provider.host_aliases).to eq("foo\tbar") end it 'cares about the order of host_aliases' do host_aliases = described_class.attrclass(:host_aliases).new(resource: resource, should: ['foo', 'bar']) expect(host_aliases.insync?(['foo', 'bar'])).to eq(true) expect(host_aliases.insync?(['bar', 'foo'])).to eq(false) end it 'does not consider aliases to be in sync if should is a subset of current' do host_aliases = described_class.attrclass(:host_aliases).new(resource: resource, should: ['foo', 'bar']) expect(host_aliases.insync?(['foo', 'bar', 'anotherone'])).to eq(false) end end end