# Builds node name from mask. Mask could be passed in server's +cid:node-name-mask+ tag, # default mask is used otherwise. Mask is a string with possible several variables inserted, e.g. # +':project/:env/:instanceid/:instancename/:increment-group1:'+ # Variables meanings: # - +:project+ is replaced with project name (given in constructor) # - +:env+ is replaced with env name (given in constructor) # - +:time+ is replaced with current timestamp # - +:instanceid+ is replaced with provider instance id (fetched from server info) # - +:instancename+ is replaced with value of Name tag (fetched from server info) # - +:increment-groupname:+ is replaced with incremented number tied to group name. There could be several groups in one stack. # P.S. Colons are used instead of dollar signs, because stacks don't support dollar signs in tags (unlike EC2 instances), # but it's convenient to set mask tag directly to a stack (not in template): you set tag once and it propagates to all instances. class ChefNodeNameBuilder # We need to ensure that node name is uniq by default. We can't use :time to provide uniqueness because # several servers are persisting at once on stack creating at it's likely that Time.now.to_i will give similar values # to different servers. So (by default) we should use :instanceid. DEFAULT_MASK = ':project-:env-:instanceid' # @param attrs [Hash] should contain # +:provider_server_info+ # +:project_id+ # +:env_id+ def initialize(attrs) @server_info = attrs[:provider_server_info] @project, @env = attrs[:project_id], attrs[:env_id] @mask = @server_info['tags']['cid:node-name-mask'] || DEFAULT_MASK end # @param incrementers_values [Hash] is a hash in which key is name of a variable and value is last substituted number for that var. # This method modifies +incrementers_values+, updating values for substituted variables. # # Examples (assume mask is set to +':project-master-:increment-group1:'+): # incremeters_values = {} # builder.build_node_name!(incremeters_values) # returns 'mpda-master-01' # puts incremeters_values # {'group1' => 1} # builder.build_node_name!(incremeters_values) # returns 'mpda-master-02' # puts incremeters_values # {'group1' => 2} def build_node_name!(incrementers_values) result = @mask.dup replace_variables!(result) replace_incrementers!(result, incrementers_values) result end private def replace_variables!(result) result.gsub!(':project', @project) result.gsub!(':env', @env) result.gsub!(':instanceid', @server_info['id']) result.gsub!(':instancename', @server_info['tags']['Name'] || '') result.gsub!(':time', Time.now.to_i.to_s) end def replace_incrementers!(result, incrementers_values) groupname_regexp = /(?<=:increment-)\w+(?=:)/ result.gsub!(/:increment-\w+:/) do |incrementer| group_name = groupname_regexp.match(incrementer)[0] prev_value = incrementers_values[group_name] || 0 current_value = prev_value + 1 incrementers_values[group_name] = current_value current_value.to_s.rjust(2, '0') end end end