title: Puppet .erb template: syntax error, unexpected $end, expecting ')' (or: inserting variables declared in .erb into text after end of code)
body: <p>I'm working on an .erb in Puppet to manage an Apache Flume config file. (Flume is going to ship logs to Elasticsearch, so they can be searched and sorted in Kibana.)</p>
  
  <p>Some background: it's getting this information from a custom fact in facter called logpaths that keeps the paths of my logs in this format:</p>
  
  <pre><code>&gt;MysqlBlah;/var/logs/mysql/error.log:/var/logs/mysql/slow_query.log
  &gt;TomcatBlah;/var/logs/tomcat/catalina.out:/var/logs/tomcat/error.log
  </code></pre>
  
  <p>So each service starts with a >, the list of logs starts with a ;, and the log paths are delimited with a :.</p>
  
  <p>I want my ERB to read that, and iterate through each logfile to come out with text I can put in my flume config file. </p>
  
  <p>All that seems to be OK, but I'm getting hit with an error that I can't track down:</p>
  
  <pre><code>-:58: syntax error, unexpected $end, expecting ')'
  </code></pre>
  
  <p>I don't seem to have any unclosed parentheses anywhere, so I'm not sure how to look for what's causing this.</p>
  
  <p><strong>EDIT 1:</strong></p>
  
  <p>Per @Daiku, I added double-quotes around all the variables, and it is now passing syntax check. However, Puppet now presents this error:</p>
  
  <pre><code>Could not find value for 'sourcenamelist'
  </code></pre>
  
  <p>Is this a scope issue? Is there another way to access the variable (which I declared in this erb) after the <code>%&gt;</code>?</p>
  
  <p><strong>EDIT 2:</strong></p>
  
  <p>I should have looked at the line number. It turns out I could insert variables the way I was, the line number causing problems was the one where I was appending to a list (which makes sense, as I hadn't declared that variable before I started appending to it). I'm back on track now; will post the finished code once I work out the remaining bugs of mine.</p>
  
  <p>My code is as follows:</p>
  
  <pre><code>&lt;%
  #split on &gt; to get each service
  services = @logpaths.split("&gt;")
  services.each do |serviceline| 
  #split on semicolon
  service = serviceline.split(";")
  servicename = service[0]
  #split into logs on colon
  logs = service[1].string.split(":")
  lognumber = 0
  logs.each do |log|
  #sourcelist is a space-delimited list of names for each logfile (eg mysql3311-1)
  lognumber += 1
  sourcename = servicename + "-" + lognumber.to_s + " "
  sourcenamelist &lt;&lt; sourcename    
  #sourceconfigs assigns each source to channel, exec path
  sourceconfig = "a1.sources.#{sourcename}.type = exec\na1.sources.#{sourcename}.command = tail -F #{log}\na1.sources.#{sourcename}.channels = c1"
  sourceconfiglist &lt;&lt; sourceconfig
  #sourceinterceptors appends sourcename, path, and servicename (you know, for search)
  sourceinterceptors = "a1.sources.#{sourcename}.interceptors = i1 i2 i3 i4\na1.sources.#{sourcename}.interceptors.i1.type = timestamp"
  sourceinterceptorlist &lt;&lt; sourceinterceptors
  end
  end 
  -%&gt;
  
  # Name the components on this agent
  a1.sources = &lt;%= #{sourcenamelist} -%&gt;
  a1.sinks = k1
  a1.channels = c1
  
  # Describe/configure the source 
  &lt;%= #{sourceconfiglist} -%&gt;
  
  # Describe the sink
  a1.sinks.k1.type = elasticsearch
  a1.sinks.k1.hostNames = (my elasticsearch host):9300
  a1.sinks.k1.indexName = flume
  a1.sinks.k1.indexType = flume_logs
  a1.sinks.k1.clusterName = elasticsearch
  a1.sinks.k1.batchSize = 1000
  a1.sinks.k1.ttl = 2
  a1.sinks.k1.serializer = org.apache.flume.sink.elasticsearch.ElasticSearchLogStashEventSerializer
  
  # Use a channel which buffers events in memory
  a1.channels.c1.type = memory
  a1.channels.c1.capacity = 1000
  a1.channels.c1.transactionCapacity = 100
  
  # Bind the source and sink to the channel
  a1.sources.r1.channels = c1
  a1.sinks.k1.channel = c1
  
  #interceptor
  &lt;%= #{sourceinterceptorlist} -%&gt;
  </code></pre>