voxpupuli / puppet-dhcp

Puppet module for deploying dhcp
https://forge.puppet.com/puppet/dhcp
Apache License 2.0
41 stars 137 forks source link

All Numeric MAC causes Detail: undefined method `upcase' #109

Closed ppouliot closed 8 years ago

ppouliot commented 8 years ago

Affected Puppet, Ruby, OS and module versions/distributions

When a host mac address contains only numeric values processing fails. For example: mac: 00:07:43:14:16:70

What are you seeing

The following line in the template lcoated in puppetlabs-dhcp/templates/dhcpd.host.erb causes the issue, because it can't do the operation when only numeric values exist. hardware ethernet <%= @mac.upcase %>;

What behaviour did you expect instead

It should work on any valid mac address.

Output log

Debug: template[/etc/puppet/modules/dhcp/templates/dhcpd.host.erb]: Bound template variables for /etc/puppet/modules/dhcp/templates/dhcpd.host.erb in 0.00 seconds
Error: Failed to parse template dhcp/dhcpd.host.erb:
  Filepath: /etc/puppet/modules/dhcp/templates/dhcpd.host.erb
  Line: 2
  Detail: undefined method `upcase' for 6535303:Fixnum
 at /etc/puppet/modules/dhcp/manifests/host.pp:20 on node aa7edca96e89.c2r1.openstack.tld
/usr/share/ruby/vendor_ruby/puppet/parser/functions/template.rb:26:in `rescue in block (2 levels) in <top (required)>'
/usr/share/ruby/vendor_ruby/puppet/parser/functions/template.rb:22:in `block (2 levels) in <top (required)>'
/usr/share/ruby/vendor_ruby/puppet/parser/functions/template.rb:15:in `collect'
/usr/share/ruby/vendor_ruby/puppet/parser/functions/template.rb:15:in `block in <top (required)>'
/usr/share/ruby/vendor_ruby/puppet/parser/functions.rb:164:in `block (2 levels) in newfunction'
/usr/share/ruby/vendor_ruby/puppet/util/profiler/around_profiler.rb:58:in `profile'
/usr/share/ruby/vendor_ruby/puppet/util/profiler.rb:51:in `profile'
/usr/share/ruby/vendor_ruby/puppet/parser/functions.rb:157:in `block in newfunction'
/usr/share/ruby/vendor_ruby/puppet/parser/ast/function.rb:42:in `evaluate'
/usr/share/ruby/vendor_ruby/puppet/parser/ast.rb:61:in `safeevaluate'
/usr/share/ruby/vendor_ruby/puppet/parser/ast/resourceparam.rb:14:in `evaluate'
/usr/share/ruby/vendor_ruby/puppet/parser/ast.rb:61:in `safeevaluate'
/usr/share/ruby/vendor_ruby/puppet/parser/ast/resource.rb:29:in `block (2 levels) in evaluate'
/usr/share/ruby/vendor_ruby/puppet/parser/ast/branch.rb:12:in `block in each'
/usr/share/ruby/vendor_ruby/puppet/parser/ast/branch.rb:11:in `each'
/usr/share/ruby/vendor_ruby/puppet/parser/ast/branch.rb:11:in `each'
/usr/share/ruby/vendor_ruby/puppet/parser/ast/resource.rb:28:in `collect'
/usr/share/ruby/vendor_ruby/puppet/parser/ast/resource.rb:28:in `block in evaluate'
/usr/share/ruby/vendor_ruby/puppet/parser/ast/branch.rb:12:in `block in each'
/usr/share/ruby/vendor_ruby/puppet/parser/ast/branch.rb:11:in `each'
/usr/share/ruby/vendor_ruby/puppet/parser/ast/branch.rb:11:in `each'
/usr/share/ruby/vendor_ruby/puppet/parser/ast/resource.rb:25:in `collect'
/usr/share/ruby/vendor_ruby/puppet/parser/ast/resource.rb:25:in `evaluate'
/usr/share/ruby/vendor_ruby/puppet/parser/ast.rb:61:in `safeevaluate'
/usr/share/ruby/vendor_ruby/puppet/parser/ast/block_expression.rb:11:in `block in evaluate'
/usr/share/ruby/vendor_ruby/puppet/parser/ast/block_expression.rb:10:in `each'
/usr/share/ruby/vendor_ruby/puppet/parser/ast/block_expression.rb:10:in `evaluate'
/usr/share/ruby/vendor_ruby/puppet/parser/ast.rb:61:in `safeevaluate'
/usr/share/ruby/vendor_ruby/puppet/resource/type.rb:129:in `evaluate_code'
/usr/share/ruby/vendor_ruby/puppet/parser/resource.rb:81:in `block in evaluate'
/usr/share/ruby/vendor_ruby/puppet/util/profiler/around_profiler.rb:58:in `profile'
/usr/share/ruby/vendor_ruby/puppet/util/profiler.rb:51:in `profile'
/usr/share/ruby/vendor_ruby/puppet/parser/resource.rb:77:in `evaluate'
/usr/share/ruby/vendor_ruby/puppet/parser/compiler.rb:386:in `block (3 levels) in evaluate_definitions'
/usr/share/ruby/vendor_ruby/puppet/parser/compiler.rb:385:in `each'
/usr/share/ruby/vendor_ruby/puppet/parser/compiler.rb:385:in `block (2 levels) in evaluate_definitions'
/usr/share/ruby/vendor_ruby/puppet/util/profiler/around_profiler.rb:58:in `profile'
/usr/share/ruby/vendor_ruby/puppet/util/profiler.rb:51:in `profile'
/usr/share/ruby/vendor_ruby/puppet/parser/compiler.rb:384:in `block in evaluate_definitions'
/usr/share/ruby/vendor_ruby/puppet/util/errors.rb:64:in `exceptwrap'
/usr/share/ruby/vendor_ruby/puppet/parser/compiler.rb:383:in `evaluate_definitions'
/usr/share/ruby/vendor_ruby/puppet/parser/compiler.rb:404:in `block (2 levels) in evaluate_generators'
/usr/share/ruby/vendor_ruby/puppet/util/profiler/around_profiler.rb:58:in `profile'
/usr/share/ruby/vendor_ruby/puppet/util/profiler.rb:51:in `profile'
/usr/share/ruby/vendor_ruby/puppet/parser/compiler.rb:401:in `block in evaluate_generators'
/usr/share/ruby/vendor_ruby/puppet/parser/compiler.rb:398:in `loop'
/usr/share/ruby/vendor_ruby/puppet/parser/compiler.rb:398:in `evaluate_generators'
/usr/share/ruby/vendor_ruby/puppet/parser/compiler.rb:141:in `block (2 levels) in compile'
/usr/share/ruby/vendor_ruby/puppet/util/profiler/around_profiler.rb:58:in `profile'
/usr/share/ruby/vendor_ruby/puppet/util/profiler.rb:51:in `profile'
/usr/share/ruby/vendor_ruby/puppet/parser/compiler.rb:141:in `block in compile'
/usr/share/ruby/vendor_ruby/puppet/context.rb:64:in `override'
/usr/share/ruby/vendor_ruby/puppet.rb:246:in `override'
/usr/share/ruby/vendor_ruby/puppet/parser/compiler.rb:121:in `compile'
/usr/share/ruby/vendor_ruby/puppet/parser/compiler.rb:34:in `compile'
/usr/share/ruby/vendor_ruby/puppet/indirector/catalog/compiler.rb:95:in `block (2 levels) in compile'
/usr/share/ruby/vendor_ruby/puppet/util/profiler/around_profiler.rb:58:in `profile'
/usr/share/ruby/vendor_ruby/puppet/util/profiler.rb:51:in `profile'
/usr/share/ruby/vendor_ruby/puppet/indirector/catalog/compiler.rb:93:in `block in compile'
/usr/share/ruby/vendor_ruby/puppet/util.rb:161:in `block in benchmark'
/usr/share/ruby/benchmark.rb:296:in `realtime'
/usr/share/ruby/vendor_ruby/puppet/util.rb:160:in `benchmark'
/usr/share/ruby/vendor_ruby/puppet/indirector/catalog/compiler.rb:92:in `compile'
/usr/share/ruby/vendor_ruby/puppet/indirector/catalog/compiler.rb:52:in `find'
/usr/share/ruby/vendor_ruby/puppet/indirector/indirection.rb:201:in `find'
/usr/share/ruby/vendor_ruby/puppet/application/apply.rb:222:in `block in main'
/usr/share/ruby/vendor_ruby/puppet/context.rb:64:in `override'
/usr/share/ruby/vendor_ruby/puppet.rb:246:in `override'
/usr/share/ruby/vendor_ruby/puppet/application/apply.rb:198:in `main'
/usr/share/ruby/vendor_ruby/puppet/application/apply.rb:159:in `run_command'
/usr/share/ruby/vendor_ruby/puppet/application.rb:381:in `block (2 levels) in run'
/usr/share/ruby/vendor_ruby/puppet/application.rb:507:in `plugin_hook'
/usr/share/ruby/vendor_ruby/puppet/application.rb:381:in `block in run'
/usr/share/ruby/vendor_ruby/puppet/util.rb:496:in `exit_on_fail'
/usr/share/ruby/vendor_ruby/puppet/application.rb:381:in `run'
/usr/share/ruby/vendor_ruby/puppet/util/command_line.rb:146:in `run'
/usr/share/ruby/vendor_ruby/puppet/util/command_line.rb:92:in `execute'
/usr/bin/puppet:8:in `<main>'
Error: Failed to parse template dhcp/dhcpd.host.erb:
  Filepath: /etc/puppet/modules/dhcp/templates/dhcpd.host.erb
  Line: 2
  Detail: undefined method `upcase' for 6535303:Fixnum
 at /etc/puppet/modules/dhcp/manifests/host.pp:20 on node aa7edca96e89.c2r1.openstack.tld
/usr/share/ruby/vendor_ruby/puppet/parser/functions/template.rb:26:in `rescue in block (2 levels) in <top (required)>'
/usr/share/ruby/vendor_ruby/puppet/parser/functions/template.rb:22:in `block (2 levels) in <top (required)>'
/usr/share/ruby/vendor_ruby/puppet/parser/functions/template.rb:15:in `collect'
/usr/share/ruby/vendor_ruby/puppet/parser/functions/template.rb:15:in `block in <top (required)>'
/usr/share/ruby/vendor_ruby/puppet/parser/functions.rb:164:in `block (2 levels) in newfunction'
/usr/share/ruby/vendor_ruby/puppet/util/profiler/around_profiler.rb:58:in `profile'
/usr/share/ruby/vendor_ruby/puppet/util/profiler.rb:51:in `profile'
/usr/share/ruby/vendor_ruby/puppet/parser/functions.rb:157:in `block in newfunction'
/usr/share/ruby/vendor_ruby/puppet/parser/ast/function.rb:42:in `evaluate'
/usr/share/ruby/vendor_ruby/puppet/parser/ast.rb:61:in `safeevaluate'
/usr/share/ruby/vendor_ruby/puppet/parser/ast/resourceparam.rb:14:in `evaluate'
/usr/share/ruby/vendor_ruby/puppet/parser/ast.rb:61:in `safeevaluate'
/usr/share/ruby/vendor_ruby/puppet/parser/ast/resource.rb:29:in `block (2 levels) in evaluate'
/usr/share/ruby/vendor_ruby/puppet/parser/ast/branch.rb:12:in `block in each'
/usr/share/ruby/vendor_ruby/puppet/parser/ast/branch.rb:11:in `each'
/usr/share/ruby/vendor_ruby/puppet/parser/ast/branch.rb:11:in `each'
/usr/share/ruby/vendor_ruby/puppet/parser/ast/resource.rb:28:in `collect'
/usr/share/ruby/vendor_ruby/puppet/parser/ast/resource.rb:28:in `block in evaluate'
/usr/share/ruby/vendor_ruby/puppet/parser/ast/branch.rb:12:in `block in each'
/usr/share/ruby/vendor_ruby/puppet/parser/ast/branch.rb:11:in `each'
/usr/share/ruby/vendor_ruby/puppet/parser/ast/branch.rb:11:in `each'
/usr/share/ruby/vendor_ruby/puppet/parser/ast/resource.rb:25:in `collect'
/usr/share/ruby/vendor_ruby/puppet/parser/ast/resource.rb:25:in `evaluate'
/usr/share/ruby/vendor_ruby/puppet/parser/ast.rb:61:in `safeevaluate'
/usr/share/ruby/vendor_ruby/puppet/parser/ast/block_expression.rb:11:in `block in evaluate'
/usr/share/ruby/vendor_ruby/puppet/parser/ast/block_expression.rb:10:in `each'
/usr/share/ruby/vendor_ruby/puppet/parser/ast/block_expression.rb:10:in `evaluate'
/usr/share/ruby/vendor_ruby/puppet/parser/ast.rb:61:in `safeevaluate'
/usr/share/ruby/vendor_ruby/puppet/resource/type.rb:129:in `evaluate_code'
/usr/share/ruby/vendor_ruby/puppet/parser/resource.rb:81:in `block in evaluate'
/usr/share/ruby/vendor_ruby/puppet/util/profiler/around_profiler.rb:58:in `profile'
/usr/share/ruby/vendor_ruby/puppet/util/profiler.rb:51:in `profile'
/usr/share/ruby/vendor_ruby/puppet/parser/resource.rb:77:in `evaluate'
/usr/share/ruby/vendor_ruby/puppet/parser/compiler.rb:386:in `block (3 levels) in evaluate_definitions'
/usr/share/ruby/vendor_ruby/puppet/parser/compiler.rb:385:in `each'
/usr/share/ruby/vendor_ruby/puppet/parser/compiler.rb:385:in `block (2 levels) in evaluate_definitions'
/usr/share/ruby/vendor_ruby/puppet/util/profiler/around_profiler.rb:58:in `profile'
/usr/share/ruby/vendor_ruby/puppet/util/profiler.rb:51:in `profile'
/usr/share/ruby/vendor_ruby/puppet/parser/compiler.rb:384:in `block in evaluate_definitions'
/usr/share/ruby/vendor_ruby/puppet/util/errors.rb:64:in `exceptwrap'
/usr/share/ruby/vendor_ruby/puppet/parser/compiler.rb:383:in `evaluate_definitions'
/usr/share/ruby/vendor_ruby/puppet/parser/compiler.rb:404:in `block (2 levels) in evaluate_generators'
/usr/share/ruby/vendor_ruby/puppet/util/profiler/around_profiler.rb:58:in `profile'
/usr/share/ruby/vendor_ruby/puppet/util/profiler.rb:51:in `profile'
/usr/share/ruby/vendor_ruby/puppet/parser/compiler.rb:401:in `block in evaluate_generators'
/usr/share/ruby/vendor_ruby/puppet/parser/compiler.rb:398:in `loop'
/usr/share/ruby/vendor_ruby/puppet/parser/compiler.rb:398:in `evaluate_generators'
/usr/share/ruby/vendor_ruby/puppet/parser/compiler.rb:141:in `block (2 levels) in compile'
/usr/share/ruby/vendor_ruby/puppet/util/profiler/around_profiler.rb:58:in `profile'
/usr/share/ruby/vendor_ruby/puppet/util/profiler.rb:51:in `profile'
/usr/share/ruby/vendor_ruby/puppet/parser/compiler.rb:141:in `block in compile'
/usr/share/ruby/vendor_ruby/puppet/context.rb:64:in `override'
/usr/share/ruby/vendor_ruby/puppet.rb:246:in `override'
/usr/share/ruby/vendor_ruby/puppet/parser/compiler.rb:121:in `compile'
/usr/share/ruby/vendor_ruby/puppet/parser/compiler.rb:34:in `compile'
/usr/share/ruby/vendor_ruby/puppet/indirector/catalog/compiler.rb:95:in `block (2 levels) in compile'
/usr/share/ruby/vendor_ruby/puppet/util/profiler/around_profiler.rb:58:in `profile'
/usr/share/ruby/vendor_ruby/puppet/util/profiler.rb:51:in `profile'
/usr/share/ruby/vendor_ruby/puppet/indirector/catalog/compiler.rb:93:in `block in compile'
/usr/share/ruby/vendor_ruby/puppet/util.rb:161:in `block in benchmark'
/usr/share/ruby/benchmark.rb:296:in `realtime'
/usr/share/ruby/vendor_ruby/puppet/util.rb:160:in `benchmark'
/usr/share/ruby/vendor_ruby/puppet/indirector/catalog/compiler.rb:92:in `compile'
/usr/share/ruby/vendor_ruby/puppet/indirector/catalog/compiler.rb:52:in `find'
/usr/share/ruby/vendor_ruby/puppet/indirector/indirection.rb:201:in `find'
/usr/share/ruby/vendor_ruby/puppet/application/apply.rb:222:in `block in main'
/usr/share/ruby/vendor_ruby/puppet/context.rb:64:in `override'
/usr/share/ruby/vendor_ruby/puppet.rb:246:in `override'
/usr/share/ruby/vendor_ruby/puppet/application/apply.rb:198:in `main'
/usr/share/ruby/vendor_ruby/puppet/application/apply.rb:159:in `run_command'
/usr/share/ruby/vendor_ruby/puppet/application.rb:381:in `block (2 levels) in run'
/usr/share/ruby/vendor_ruby/puppet/application.rb:507:in `plugin_hook'
/usr/share/ruby/vendor_ruby/puppet/application.rb:381:in `block in run'
/usr/share/ruby/vendor_ruby/puppet/util.rb:496:in `exit_on_fail'
/usr/share/ruby/vendor_ruby/puppet/application.rb:381:in `run'
/usr/share/ruby/vendor_ruby/puppet/util/command_line.rb:146:in `run'
/usr/share/ruby/vendor_ruby/puppet/util/command_line.rb:92:in `execute'
/usr/bin/puppet:8:in `<main>'

Any additional information you'd like to impart

petems commented 8 years ago

@ppouliot What does the code you're using look like? Are you passing the mac address within quotes? It looks like its turning the mac address into a number

I'm trying to recreate in tests and I can get it to fail.

It'd be easy enough to fix IMO:

hardware ethernet   <%= @mac.to_s.upcase %>;
alexjfisher commented 8 years ago

I'm trying to recreate in tests and I can get it to fail.

@petems You can get it to fail? I've not been able to yet.

petems commented 8 years ago

Typo, shoudve been cant :)

ppouliot commented 8 years ago

So we're using hiera to push all data into the module. No quotes used on the mac address in the yaml files.

ppouliot commented 8 years ago

Hiera i'm using is as follows:

dhcp::dnsdomain:
      - contoso.ltd
      - 0.168.192.in-addr.arpa

dhcp::nameservers:
      - 192.168.0.1
      - 192.168.0.2

dhcp::ntpservers:
  - bonehed.lsc.mit.edu
dhcp::interfaces:
  - eth0

dhcpdata:
  contoso.ltd:
    failover: dhcp-failover
    network: 192.168.0.0
    mask: 255.255.255.0
    gateway: 192.168.0.254
    range:
      - 192.168.0.100
      - 192.168.0.220
    options:
      - domain-name-servers 192.168.0.1
      - domain-name "contoso.ltd"
      - ntp-servers bonehed.lcs.mit.edu
    parameters:
      - ddns-domainname "contoso.ltd, 0.168.192.in-addr.arpa"

static_leases:
  myhost:
    mac: 00:1a:2b:3c:4d:5e
    ip: 192.168.0.3
# Uncomment this entry to test mac addresses that are only numeric
#  allnumericmac:
#    mac: 00:07:43:14:15
petems commented 8 years ago

Ah, that would explain it. You might want to obfuscate the data btw, just in case.

Can you try putting quotes around the mac addresses in the yaml?

ppouliot commented 8 years ago

so I'm trying that now, here's the output from data, and it's not actually my working data, it's just basics for testing the modules. I've got 15000 lines of hiera we feed into the module with our specifics.

When I add quotes to my code defining the record I get this as output in the dhcpd.hosts file.

host allnumericmac { hardware ethernet 6535303; fixed-address 192.168.0.4; ddns-hostname "allnumericmac"; }

ppouliot commented 8 years ago

So quotes in the hiera appears to work. Output after adding quotes for the record is as follows.

host allnumericmac { hardware ethernet 00:07:43:14:15:30; fixed-address 192.168.0.4; ddns-hostname "allnumericmac"; }

ekohl commented 8 years ago

Now https://github.com/voxpupuli/puppet-dhcp/issues/110 is merged, can this be closed?

alexjfisher commented 8 years ago

@ekohl I think so. @ppouliot has a solution and we've got extra validation in the module from now on.