WillemToorenburgh
WillemToorenburgh

Reputation: 125

OpsWorks Ruby returning nil for valid regex test

In OpsWorks, I'm trying to test the number suffix on a hostname of a given node, and to extract that number if it isn't 1. If the number isn't 1, I have this regex to match the number:

/([\d]+)$­/

Which is run against a node naming scheme that follows this pattern:

I've verified this works using Rubular: http://rubular.com/r/Ei0kqjaxQn

However, when I run this against an instance with OpsWorks, this match returns nil, no matter what number the hostname has at the end. The OpsWorks agent version is the latest at time of writing (4023), using Chef 12.13.37.

This is the code in the cookbook trying use the matched number:

short_app_name.to_s + node['hostname'][/([\d]+)$­/, 1].to_s + '.' + app['domains'].first

The run fails with type error no implicit conversion of nil into String. However, regex searches against that property work earlier in the recipe, when checking the node's number suffix. Is there a different method I should be using to extract the node's suffix?


Edit: app['domains'].first is populated. This line still fails with the same type error if it is swapped out with domain.com.

Upvotes: 0

Views: 113

Answers (3)

engineersmnky
engineersmnky

Reputation: 29488

You error has nothing to do with the regex. The issue is when you try to concatenate your existing String with

app['domains'].first

This is the only place this error would be raised because even if your String#slice returned nil you are calling to_s so it is an empty String but String + nil as would be the case if app['domains'].first is nil will raise this error.

breakdown

#short_app_name can be nil because of explicit #to_s
short_app_name.to_s 
####
# assuming node is a Hash
# node must have 'hostname' key 
# or NoMethodError: undefined method `[]' for nil:NilClass wil be raised
# node['hostname'][/([\d]+)$­/, 1] can be nil because of explicit #to_s
node['hostname'][/([\d]+)$­/, 1].to_s 
#####
# assuming app is a Hash
# app must contain 'domains' key and the value must respond to first
# and the first value must be a String or be implicitly coercible (#to_str) or it will fail with 
# TypeError: no implicit conversion of ClassName into String
# could explicitly coerce (#to_s) like you do previously  
app['domains'].first

Example:

node = {"hostname" => 'nodable'}
app = {"domains" => []}
node['hostname'][/([\d]+)$­/, 1]
#=> nil
node['hostname'][/([\d]+)$­/, 1].to_s
#=> ""
app["domains"].first
#=> nil
node['hostname'][/([\d]+)$­/, 1].to_s + '.' + app["domains"].first
#=> TypeError: no implicit conversion of nil into String
node = {"hostname" => 'node2'}
app = {"domains" => ['here.com']}
node['hostname'][/([\d]+)$­/, 1].to_s + '.' + app["domains"].first
#=> "2.here.com"

Upvotes: 0

Simple Lime
Simple Lime

Reputation: 11060

When I copy your regex and paste it into my terminal to test, there's a soft hyphen character after the dollar sign at the end of the regex, removing this makes things work:

The website isn't showing it even when I copy it from my terminal, but a screenshot shows the issue:

enter image description here

That second line ('irb(main):002:0') is what I copy/pasted from your cookbook code, the character is "\xc2\xad"

Upvotes: 1

gettalong
gettalong

Reputation: 830

Judging from the cookbook code and the error message, the problem may be that app['domains'] is an empty array during the run. So you may want to verify that its value is correct.

Upvotes: 1

Related Questions