inkblot/puppet-bind

resource_record error can't convert Symbol into String

Closed this issue · 26 comments

Hi,

I' getting the following error when trying to use the resource_record.

Wrapped exception:
May 19 23:28:20 puppet puppet-agent[9818]: can't convert Symbol into String
May 19 23:28:20 puppet puppet-agent[9818]: (/Stage[main]/Profiles::Dns/Resource_record[A ns01.test.dlbnet.us 192.168.2.53]/ensure) change from absent to present failed: Could not set 'present' on ensure: can't convert Symbol into String at 63:/etc/puppet/environments/test/dist/profiles/manifests/dns.pp

Here's a fragment of the code. The bind class and zones have already been defined.

  resource_record { "A ${name} ${address}" :
    record => $name,
    type   => 'A',
    data   => $address,
  }

The $name and $address variables are derived from hiera data.

I might be doing something wrong, but can't figure out what it is. If I explicitly specify ensure, I still get the same error.

Thanks - David

Can you show me the hiera data?

Hi,

I've isolated the resource_record call into a fie I can apply with puppet apply --debug. It has the data explicitly specified and doesn't use hiera. I'm still getting the same error, but based on the debug output it is getting to the point of executing dig to see if the record already exists. The dig seems to execute okay.

Here's the test.pp contents:

$node_name = 'foo.dlbnet.us'
$node_address = '192.168.2.55'

resource_record { "A ${node_name} ${node_address}" :
  ensure => present,
  record => $node_name,
  type   => 'A',
  data   => $node_address,
  zone   => 'dlbnet.us',
  rrclass => 'IN',
  ttl    => 86400,
  keyname => 'update',
  hmac   => 'hmac-md5',
  server => 'localhost',
  secret => 'MY BIG SECRET',
}

Thanks - David

What's happening is that the ruby code that implements the resource is throwing an exception, and this is reported as an error on the line of the manifest where the resource type is used. Unfortunately, the message in puppet's logs does not include any information about the source of the error in the ruby code.

When you run dig, is it identical to the invocation that puppet is running? You can find it in puppet's debug logging if you add the --debug command line option to either a puppet apply or puppet agent --test. Also, are you able to manually update records in this zone using nsupdate with your key?

Yeah, I ws getting the dig command from the debug output.

I tried using nsupdate and was getting a NOTAUTH response, then realized that I had my view messed up. I fixed that, got the nsupdate to work, then went back and tried my resource_record example. above.

That seems to still be having the same problem as above it the record is not present in the zone file.

However, if I use nsupdate to put the record in the zone There also seem to be some problems.

If the address is different then I get the following after the dig lin in the debug output:

Notice: //puppet.test.dlbnet.us//Stage[main]/Main/Resource_record[A foo.dlbnet.us 192.168.2.56]/data: data changed ['192.168.2.100'] to '192.168.2.56'
Error: //puppet.test.dlbnet.us//Stage[main]/Main/Resource_record[A foo.dlbnet.us 192.168.2.56]: Could not evaluate: can't convert Symbol into String
Debug: //puppet.test.dlbnet.us/Puppet: Finishing transaction 30859300
Debug: //puppet.test.dlbnet.us/Puppet: Storing state

However, running dig shows that the address wasn't actually changed.

If I rerun nsupdate to set the address back to what the resource_record.pp has but give it a different TTL, then when I rerun resource_record,pp I get the following:

Debug: //puppet.test.dlbnet.us/Puppet: Executing '/usr/bin/dig @localhost +noall +nosearch +norecurse +answer foo.dlbnet.us A -c IN -y hmac-md5:update:MYSECRET'
Notice: //puppet.test.dlbnet.us//Stage[main]/Main/Resource_record[A foo.dlbnet.us 192.168.2.56]/ttl: ttl changed '10000' to '86400'
Debug: //puppet.test.dlbnet.us/Puppet: Executing '/usr/bin/nsupdate -y hmac-md5:update:MYSECRET /tmp/dns_rr-nsupdate-20150520-22210-1xqe0xc'
Debug: //puppet.test.dlbnet.us//Stage[main]/Main/Resource_record[A foo.dlbnet.us 192.168.2.56]: The container Class[Main] will propagate my refresh event

But again, the data is not changed according to dig.

If the nsupdate script sets the record to what's in my resource_record.pp then the apply runs with no problems. But ....

Thanks - David

I suggest is simply go back to the previous version of the module

If that works, I would love to know what versions of the module are involved.

I use 4.1.0

Do you mean to say that version 4.1.0 is working for you and a different version produces the "can't convert Symbol into String" error? What version produces the error?

Only 4.1.1

Release 4.1.1 was giving me the "can't convert Symbol into String" error.

I pinned the version at 4.1.0 in the Puppetfile for my test environment and ran a bunch of tests.

Creating and updating records seems to work fine, with the exception of changing the TTL on an existing record. Puppet says that it changes the TTL, but dig still shows it at the previous value. I can live with that for now.

If ensure is set to absent and you specify the data as an empty array, all of the records for the named record are deleted, which makes sense.

if you specify say an address or addresses for an 'A' record with ensure set to absent it deletes all but the records with the specified address(es). I would have expected it to delete those records and leave the others. In practice, however, I don't think this will be an issue. I think I'll either be:

  • deleting all instances of a record
  • changing its value to something that might or might not include previous addresses, which is same as deleting not included addresses.

If you want me to test newer versions of the module, let me know and I can spin up another VM to test with.

Thanks - David

I have reproduced the "can't convert Symbol into String" error.

@davidlballenger, the problems with ensure => absent I think are a side effect of the fix for #33. I'll be sure to fix these issues, too.

Thanks! Let me know if you want me to test anything.

On the provider-fixes-41 branch I have a fix for the type issue, but not the ensure => absent issues. I'll be continuing work on that branch.

Okay, pulled that branch into my test environment and ran some tests. I no longer get the "can't convert Symbol into String" error. Thanks!

However, I've also noticed another problem, which is actually in the 4.1.0 release. If you are creating PTR records, resource_record trys to create them every time it runs. It actual is creating the records, I've verified that with dig. I ran a puppet apply --debug and noticed that when it is checking the PTR it seems to run dig twice, once for an 'A' record and once for a PTR. I don't know if that is the issue, but here's the output:

Debug: //puppet.test.dlbnet.us/Puppet: Executing '/usr/bin/dig @localhost +noall +nosearch +norecurse +answer ns01.test.dlbnet.us A -c IN -y hmac-md5:update:SECRET'
Debug: //puppet.test.dlbnet.us/Puppet: Executing '/usr/bin/dig @localhost +noall +nosearch +norecurse +answer 53.2.168.192.in-addr.arpa PTR -c IN -y hmac-md5:update:SECRET'
Debug: //puppet.test.dlbnet.us/Puppet: Executing '/usr/bin/nsupdate -y hmac-md5:update:SECRETs= /tmp/dns_rr-nsupdate-20150522-5898-1a0tzc0'
Notice: //puppet.test.dlbnet.us//Stage[runtime]/Profiles::Dns::Server::Static_records/Profiles::Dns::Record[PTR 192.168.2.53 ns01.test.dlbnet.us]/Resource_record[localhost - PTR 53.2.168.192.in-addr.arpa ns01.test.dlbnet.us]/ensure: created

Let me know if you want to track this in a separate issue.

The first query for the A record is probably for the other resource_record, but does not result in an update of any kind because the record already exists in good order. I'll see if I can figure out the PTR thing.

I have pushed another commit to the provider-fixes-41 branch which should handle ensure => absent correctly.

I'm seeing idempotence with PTR records, can you provide more detail about the case you're experiencing?

Hi,
Another poser.
A dot is added to the CNAME records

from syslog:

May 22 18:16:29 test02 named[3808]: client 10.120.2.99#46607: view internet: updating zone 'fm.example.ru/IN': deleting an RR at aia.fm.example.ru CNAME
May 22 18:16:29 test02 named[3808]: client 10.120.2.99#46607: view internet: updating zone 'fm.example.ru/IN': adding an RR at 'aia.fm.example.ru' CNAME

from puppet.log:

Fri May 22 17:16:28 +0300 2015 Stage[main]/Bind/Resource_record[internet@fm.example.ru@aia@CNAME]/data (notice): data changed ['admin.'] to 'admin'

Hi Nate,

I ran some tests for the problems that I'm having with PTR records.

Based on what I seeing in syslog:

  • if the PTR doesn't exist resource_record adds.
  • If the record does exist, it adds it then deletes it. This is what I'm seeing from
    named in syslog

Here the .pp file I'm using:

$record = '42.2.168.192.in-addr.arpa'
$data = 'myptr.dlbnet.us'

resource_record { "PTR: ${record} ${data}" :
  record => $record,
  type   => 'PTR',
  data   => $data,
  keyname => 'update',
  hmac   => 'hmac-md5',
  secret => 'SECRET',
  server => 'localhost',
}

Here's the test script:

#!/bin/bash
#

Y_ARG="-y hmac-md5:update:SECRET"
DIG_ARGS="@localhost +noall +nosearch +norecurse +answer 42.2.168.192.in-addr.arpa PTR -c IN "

logger -t PtrTest "Start test"
(echo -n "DIG Results:  " ;dig $DIG_ARGS $Y_ARG) | logger -t PtrTest
puppet apply /vagrant/test/add-ptr-record.pp | logger -t PtrTest
(echo -n "DIG Results:  " ;dig $DIG_ARGS $Y_ARG) | logger -t PtrTest
puppet apply /vagrant/test/add-ptr-record.pp | logger -t PtrTest
(echo -n "DIG Results:  " ;dig $DIG_ARGS $Y_ARG) | logger -t PtrTest
puppet apply /vagrant/test/add-ptr-record.pp | logger -t PtrTest
(echo -n "DIG Results:  " ;dig $DIG_ARGS $Y_ARG) | logger -t PtrTest
puppet apply /vagrant/test/add-ptr-record.pp | logger -t PtrTest
(echo -n "DIG Results:  " ;dig $DIG_ARGS $Y_ARG) | logger -t PtrTest
logger -t PtrTest "End test"

The log ouput is below. You'll notice that if DIG Results is blank (i.e. no
output from dig) that named logs just an add during the puppet run. On the
subsequent puppet run when the record exists and DIG REsults is not blank that
named log an add then a delete. Maybe those are in the wrong order in the
nsupdate input.

May 22 07:54:30 puppet PtrTest: Start test
May 22 07:54:30 puppet PtrTest: DIG Results:
May 22 07:54:33 puppet PtrTest: Notice: Compiled catalog for puppet.test.dlbnet.us in environment test in 0.44 seconds[0m
May 22 07:54:34 puppet named[5234]: client 127.0.0.1#38096/key update: view private: signer "update" approved
May 22 07:54:34 puppet named[5234]: client 127.0.0.1#38096/key update: view private: updating zone '168.192.in-addr.arpa/IN': adding an RR at '42.2.168.192.in-addr.arpa' PTR
May 22 07:54:34 puppet PtrTest: Notice: /Stageain]/Main/Resource_record[PTR: 42.2.168.192.in-addr.arpa myptr.dlbnet.us]/ensure: created[0m
May 22 07:54:34 puppet PtrTest: Notice: Finished catalog run in 0.17 seconds[0m
May 22 07:54:34 puppet PtrTest: Notice: //puppet.test.dlbnet.us//Stageain]/Main/Resource_record[PTR: 42.2.168.192.in-addr.arpa myptr.dlbnet.us]/ensure: created[0m
May 22 07:54:34 puppet PtrTest: Notice: //puppet.test.dlbnet.us/Puppet: Finished catalog run in 0.17 seconds[0m
May 22 07:54:34 puppet PtrTest: DIG Results: 42.2.168.192.in-addr.arpa. 43200 IN#011PTR#011myptr.dlbnet.us.
May 22 07:54:37 puppet PtrTest: Notice: Compiled catalog for puppet.test.dlbnet.us in environment test in 0.45 seconds[0m
May 22 07:54:37 puppet PtrTest: Notice: /Stageain]/Main/Resource_record[PTR: 42.2.168.192.in-addr.arpa myptr.dlbnet.us]/data: data changed ['myptr.dlbnet.us.'] to 'myptr.dlbnet.us'[0m
May 22 07:54:37 puppet named[5234]: client 127.0.0.1#20116/key update: view private: signer "update" approved
May 22 07:54:37 puppet named[5234]: client 127.0.0.1#20116/key update: view private: updating zone '168.192.in-addr.arpa/IN': adding an RR at '42.2.168.192.in-addr.arpa' PTR
May 22 07:54:37 puppet named[5234]: client 127.0.0.1#20116/key update: view private: updating zone '168.192.in-addr.arpa/IN': deleting an RR at 42.2.168.192.in-addr.arpa PTR
May 22 07:54:38 puppet PtrTest: Notice: Finished catalog run in 0.18 seconds[0m
May 22 07:54:38 puppet PtrTest: Notice: //puppet.test.dlbnet.us//Stageain]/Main/Resource_record[PTR: 42.2.168.192.in-addr.arpa myptr.dlbnet.us]/data: data changed ['myptr.dlbnet.us.'] to 'myptr.dlbnet.us'[0m
May 22 07:54:38 puppet PtrTest: Notice: //puppet.test.dlbnet.us/Puppet: Finished catalog run in 0.18 seconds[0m
May 22 07:54:38 puppet PtrTest: DIG Results:
May 22 07:54:41 puppet PtrTest: Notice: Compiled catalog for puppet.test.dlbnet.us in environment test in 0.43 seconds[0m
May 22 07:54:41 puppet named[5234]: client 127.0.0.1#11184/key update: view private: signer "update" approved
May 22 07:54:41 puppet named[5234]: client 127.0.0.1#11184/key update: view private: updating zone '168.192.in-addr.arpa/IN': adding an RR at '42.2.168.192.in-addr.arpa' PTR
May 22 07:54:41 puppet PtrTest: Notice: /Stageain]/Main/Resource_record[PTR: 42.2.168.192.in-addr.arpa myptr.dlbnet.us]/ensure: created[0m
May 22 07:54:41 puppet PtrTest: Notice: Finished catalog run in 0.18 seconds[0m
May 22 07:54:41 puppet PtrTest: Notice: //puppet.test.dlbnet.us//Stageain]/Main/Resource_record[PTR: 42.2.168.192.in-addr.arpa myptr.dlbnet.us]/ensure: created[0m
May 22 07:54:41 puppet PtrTest: Notice: //puppet.test.dlbnet.us/Puppet: Finished catalog run in 0.18 seconds[0m
May 22 07:54:41 puppet PtrTest: DIG Results: 42.2.168.192.in-addr.arpa. 43200 IN#011PTR#011myptr.dlbnet.us.
May 22 07:54:44 puppet PtrTest: Notice: Compiled catalog for puppet.test.dlbnet.us in environment test in 0.43 seconds[0m
May 22 07:54:44 puppet PtrTest: Notice: /Stageain]/Main/Resource_record[PTR: 42.2.168.192.in-addr.arpa myptr.dlbnet.us]/data: data changed ['myptr.dlbnet.us.'] to 'myptr.dlbnet.us'[0m
May 22 07:54:44 puppet named[5234]: client 127.0.0.1#58043/key update: view private: signer "update" approved
May 22 07:54:44 puppet named[5234]: client 127.0.0.1#58043/key update: view private: updating zone '168.192.in-addr.arpa/IN': adding an RR at '42.2.168.192.in-addr.arpa' PTR
May 22 07:54:44 puppet named[5234]: client 127.0.0.1#58043/key update: view private: updating zone '168.192.in-addr.arpa/IN': deleting an RR at 42.2.168.192.in-addr.arpa PTR
May 22 07:54:45 puppet PtrTest: Notice: Finished catalog run in 0.18 seconds[0m
May 22 07:54:45 puppet PtrTest: Notice: //puppet.test.dlbnet.us//Stageain]/Main/Resource_record[PTR: 42.2.168.192.in-addr.arpa myptr.dlbnet.us]/data: data changed ['myptr.dlbnet.us.'] to 'myptr.dlbnet.us'[0m
May 22 07:54:45 puppet PtrTest: Notice: //puppet.test.dlbnet.us/Puppet: Finished catalog run in 0.18 seconds[0m
May 22 07:54:45 puppet PtrTest: DIG Results:
May 22 07:54:48 puppet PtrTest: Notice: Compiled catalog for puppet.test.dlbnet.us in environment test in 0.46 seconds[0m
May 22 07:54:48 puppet named[5234]: client 127.0.0.1#34061/key update: view private: signer "update" approved
May 22 07:54:48 puppet named[5234]: client 127.0.0.1#34061/key update: view private: updating zone '168.192.in-addr.arpa/IN': adding an RR at '42.2.168.192.in-addr.arpa' PTR
May 22 07:54:48 puppet PtrTest: Notice: /Stageain]/Main/Resource_record[PTR: 42.2.168.192.in-addr.arpa myptr.dlbnet.us]/ensure: created[0m
May 22 07:54:48 puppet PtrTest: Notice: Finished catalog run in 0.17 seconds[0m
May 22 07:54:48 puppet PtrTest: Notice: //puppet.test.dlbnet.us//Stageain]/Main/Resource_record[PTR: 42.2.168.192.in-addr.arpa myptr.dlbnet.us]/ensure: created[0m
May 22 07:54:48 puppet PtrTest: Notice: //puppet.test.dlbnet.us/Puppet: Finished catalog run in 0.17 seconds[0m
May 22 07:54:48 puppet PtrTest: DIG Results: 42.2.168.192.in-addr.arpa. 43200 IN#011PTR#011myptr.dlbnet.us.
May 22 07:54:48 puppet PtrTest: End test

Thanks - David

There is a trailing . in dig's rendering of the PTR data. This is because BIND uses this to denote a fully-qualified name versus a name relative to the "current" zone (whatever that is). Since the update does not specify a zone, it is the root zone by default, and so the relative name myptr.dlbnet.us gets qualified to myptr.dlbnet.us.. This produces a correct record as far as you are concerned, but puppet does not see these two values as equal, because strictly speaking as strings they aren't. I think fixing it would require a fancy insync? method in the data property definition, but it would need to know what type is set, and I don't know if there are any guarantees about the availability of the values of other properties and parameters at the time when insync? is called.

I recommend working around the issue with a fully-qualified name in the manifest. Just specify the trailing dot in to make myptr.dlbnet.us. instead of myptr.dlbnet.us (this is also currently necessary for CNAME records as @pankrat-bel points out).

Okay that makes sense. I will try that. I saw the comment about CNAMEs but didn't make the connection.

If there is no way to handle this in resource_record, a note in the documentation would be helpful.

Indeed. I'll include one.

As I write this note, I'm realizing that several record types are affected. I'll try to be thorough.

Indeed, the data in the CNAME records are name and sometimes the fqdn.
And within DNS it would be logical to supplement these data with dot.
But the question is - where would be the best to do it ?

I have published version 4.1.2 to the puppet forge which includes the fix for this issue.

I recreated my test VM and reloaded version 4.1.2 from puppet forge. Everything seems to be fine.

Thanks!!!