Skip to content

Commit

Permalink
Merge c464bb0 into d65b705
Browse files Browse the repository at this point in the history
  • Loading branch information
f0rmiga committed May 30, 2019
2 parents d65b705 + c464bb0 commit d3566e6
Show file tree
Hide file tree
Showing 8 changed files with 220 additions and 98 deletions.
1 change: 1 addition & 0 deletions assets/no_properties.yml.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
no_properties
10 changes: 10 additions & 0 deletions assets/no_properties_job.MF
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
name: no_properties
packages:
- foopackage
templates:
no_properties.yml.erb: no_properties.yml

consumes:
- name: barprovider
type: barprovider
109 changes: 11 additions & 98 deletions bosh_template_go.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
//go:generate rice embed-go

package boshgotemplate

import (
Expand All @@ -6,8 +8,9 @@ import (
"os/exec"
"path/filepath"

rice "github.com/GeertJohan/go.rice"
"github.com/pkg/errors"
"gopkg.in/yaml.v2"
yaml "gopkg.in/yaml.v2"
)

const (
Expand All @@ -20,103 +23,7 @@ var (
// RubyBinary is the name of the ruby binary. Can be an absolute path.
RubyBinary = "ruby"
// RubyGemBinary is the name of the ruby gem binary. Can be an absolute path.
RubyGemBinary = "gem"
templateEvaluationContextRb = []byte(`
require "erb"
require "yaml"
require "bosh/template"
require 'fileutils'
if $0 == __FILE__
context_path, spec_path, instance_path, src_path, dst_path = *ARGV
puts "Context file: #{context_path}"
puts "Instance file: #{instance_path}"
puts "Spec file: #{spec_path}"
puts "Template file: #{src_path}"
puts "Output file: #{dst_path}"
# Load the context hash
context_hash = YAML.load_file(context_path)
# Load the job spec
job_spec = YAML.load_file(spec_path)
# Load the instace info
instance_info = YAML.load_file(instance_path)
# Read the erb template
begin
perms = File.stat(src_path).mode
template = Bosh::Template::Test::Template.new(job_spec, src_path)
rescue Errno::ENOENT
raise "failed to read template file #{src_path}"
end
# Build links
links = []
if context_hash['properties'] && context_hash['properties']['bosh_containerization'] && context_hash['properties']['bosh_containerization']['consumes']
context_hash['properties']['bosh_containerization']['consumes'].each_pair do |name, link|
next if link['instances'].empty?
instances = []
link['instances'].each do |link_instance|
instances << Bosh::Template::Test::InstanceSpec.new(
address: link_instance['address'],
az: link_instance['az'],
id: link_instance['id'],
index: link_instance['index'],
name: link_instance['name'],
bootstrap: link_instance['index'] == '0',
)
end
links << Bosh::Template::Test::Link.new(name: name, instances: instances, properties: link['properties'])
end
end
# Build instance
instance = Bosh::Template::Test::InstanceSpec.new(
address: instance_info['address'],
az: instance_info['az'],
bootstrap: instance_info['index'] == '0',
deployment: instance_info['deployment'],
id: instance_info['id'],
index: instance_info['index'],
ip: instance_info['ip'],
name: instance_info['name'],
networks: {'default' => {'ip' => instance_info['ip'],
'dns_record_name' => instance_info['address'],
# TODO: Do we need more, like netmask and gateway?
# https://github.com/cloudfoundry/bosh-agent/blob/master/agent/applier/applyspec/v1_apply_spec_test.go
}},
)
# Process the Template
output = template.render(context_hash['properties'], spec: instance, consumes: links)
begin
# Open the output file
output_dir = File.dirname(dst_path)
FileUtils.mkdir_p(output_dir)
out_file = File.open(dst_path, 'w')
# Write results to the output file
out_file.write(output)
# Set the appropriate permissions on the output file
if File.basename(File.dirname(dst_path)) == 'bin'
out_file.chmod(0755)
else
out_file.chmod(perms)
end
rescue Errno::ENOENT, Errno::EACCES => e
out_file = nil
raise "failed to open output file #{dst_path}: #{e}"
ensure
out_file.close unless out_file.nil?
end
end
`)
RubyGemBinary = "gem"
)

// EvaluationContext is the context passed to the erb renderer
Expand Down Expand Up @@ -174,6 +81,12 @@ func (e *ERBRenderer) Render(inputFilePath, outputFilePath string) (returnErr er

// Write the ruby class to a file
rbClassFilePath := filepath.Join(tmpDir, rbClassFileName)
templateEvaluationContextRb, err := rice.
MustFindBox("rb").
Bytes("template_evaluation_context.rb")
if err != nil {
return errors.Wrap(err, "failed to load ruby class")
}
err = ioutil.WriteFile(rbClassFilePath, templateEvaluationContextRb, 0600)
if err != nil {
return errors.Wrap(err, "failed to write the rendering ruby class file")
Expand Down
25 changes: 25 additions & 0 deletions bosh_template_go_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -296,3 +296,28 @@ func TestRenderWithLinkProperty(t *testing.T) {
assert.NoError(err)
assert.Equal("toaster", string(output))
}

func TestWithNilContext(t *testing.T) {
// Arrange
assert := assert.New(t)
erbFile := filepath.Join(testDir(), "assets", "no_properties.yml.erb")
jobSpecFile := filepath.Join(testDir(), "assets", "no_properties_job.MF")

erbRenderer := NewERBRenderer(
&EvaluationContext{},
&InstanceInfo{},
jobSpecFile)
outDir, err := ioutil.TempDir("", "bosh-erb-render")
assert.NoError(err)
outFile := filepath.Join(outDir, "output")

// Act
err = erbRenderer.Render(erbFile, outFile)
assert.NoError(err)

output, err := ioutil.ReadFile(outFile)

// Assert
assert.NoError(err)
assert.Equal("no_properties\n", string(output))
}
10 changes: 10 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
module github.com/viovanov/bosh-template-go

go 1.12

require (
github.com/GeertJohan/go.rice v1.0.0
github.com/pkg/errors v0.8.1
github.com/stretchr/testify v1.3.0
gopkg.in/yaml.v2 v2.2.2
)
25 changes: 25 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
github.com/GeertJohan/go.incremental v1.0.0/go.mod h1:6fAjUhbVuX1KcMD3c8TEgVUqmo4seqhv0i0kdATSkM0=
github.com/GeertJohan/go.rice v1.0.0 h1:KkI6O9uMaQU3VEKaj01ulavtF7o1fWT7+pk/4voiMLQ=
github.com/GeertJohan/go.rice v1.0.0/go.mod h1:eH6gbSOAUv07dQuZVnBmoDP8mgsM1rtixis4Tib9if0=
github.com/akavel/rsrc v0.8.0/go.mod h1:uLoCtb9J+EyAqh+26kdrTgmzRBFPGOolLWKpdxkKq+c=
github.com/daaku/go.zipexe v1.0.0 h1:VSOgZtH418pH9L16hC/JrgSNJbbAL26pj7lmD1+CGdY=
github.com/daaku/go.zipexe v1.0.0/go.mod h1:z8IiR6TsVLEYKwXAoE/I+8ys/sDkgTzSL0CLnGVd57E=
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
github.com/nkovacs/streamquote v0.0.0-20170412213628-49af9bddb229/go.mod h1:0aYXnNPJ8l7uZxf45rWW1a/uME32OF0rhiYGNQ2oF2E=
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
95 changes: 95 additions & 0 deletions rb/template_evaluation_context.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
require "erb"
require "yaml"
require "bosh/template"
require "fileutils"

if $0 == __FILE__
context_path, spec_path, instance_path, src_path, dst_path = *ARGV

puts "Context file: #{context_path}"
puts "Instance file: #{instance_path}"
puts "Spec file: #{spec_path}"
puts "Template file: #{src_path}"
puts "Output file: #{dst_path}"

# Load the context hash
context_hash = YAML.load_file(context_path)

# Load the job spec
job_spec = YAML.load_file(spec_path)
job_spec['properties'] = {} if job_spec['properties'].nil?

# Load the instace info
instance_info = YAML.load_file(instance_path)

# Read the erb template
begin
perms = File.stat(src_path).mode
template = Bosh::Template::Test::Template.new(job_spec, src_path)
rescue Errno::ENOENT
raise "failed to read template file #{src_path}"
end

# Build links
links = []
if context_hash['properties'] && context_hash['properties']['bosh_containerization'] && context_hash['properties']['bosh_containerization']['consumes']
context_hash['properties']['bosh_containerization']['consumes'].each_pair do |name, link|
next if link['instances'].empty?

instances = []
link['instances'].each do |link_instance|
instances << Bosh::Template::Test::InstanceSpec.new(
address: link_instance['address'],
az: link_instance['az'],
id: link_instance['id'],
index: link_instance['index'],
name: link_instance['name'],
bootstrap: link_instance['index'] == '0',
)
end
links << Bosh::Template::Test::Link.new(name: name, instances: instances, properties: link['properties'])
end
end

# Build instance
instance = Bosh::Template::Test::InstanceSpec.new(
address: instance_info['address'],
az: instance_info['az'],
bootstrap: instance_info['index'] == '0',
deployment: instance_info['deployment'],
id: instance_info['id'],
index: instance_info['index'],
ip: instance_info['ip'],
name: instance_info['name'],
networks: {'default' => {'ip' => instance_info['ip'],
'dns_record_name' => instance_info['address'],
# TODO: Do we need more, like netmask and gateway?
# https://github.com/cloudfoundry/bosh-agent/blob/master/agent/applier/applyspec/v1_apply_spec_test.go
}},
)

# Process the Template
output = template.render(context_hash['properties'], spec: instance, consumes: links)

begin
# Open the output file
output_dir = File.dirname(dst_path)
FileUtils.mkdir_p(output_dir)
out_file = File.open(dst_path, 'w')

# Write results to the output file
out_file.write(output)

# Set the appropriate permissions on the output file
if File.basename(File.dirname(dst_path)) == 'bin'
out_file.chmod(0755)
else
out_file.chmod(perms)
end
rescue Errno::ENOENT, Errno::EACCES => e
out_file = nil
raise "failed to open output file #{dst_path}: #{e}"
ensure
out_file.close unless out_file.nil?
end
end
43 changes: 43 additions & 0 deletions rice-box.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package boshgotemplate

import (
"time"

"github.com/GeertJohan/go.rice/embedded"
)

func init() {

// define files
file2 := &embedded.EmbeddedFile{
Filename: "template_evaluation_context.rb",
FileModTime: time.Unix(1559256632, 0),

Content: string("require \"erb\"\nrequire \"yaml\"\nrequire \"bosh/template\"\nrequire \"fileutils\"\n\nif $0 == __FILE__\n context_path, spec_path, instance_path, src_path, dst_path = *ARGV\n\n puts \"Context file: #{context_path}\"\n puts \"Instance file: #{instance_path}\"\n puts \"Spec file: #{spec_path}\"\n puts \"Template file: #{src_path}\"\n puts \"Output file: #{dst_path}\"\n\n # Load the context hash\n context_hash = YAML.load_file(context_path)\n\n # Load the job spec\n job_spec = YAML.load_file(spec_path)\n job_spec['properties'] = {} if job_spec['properties'].nil?\n\n # Load the instace info\n instance_info = YAML.load_file(instance_path)\n\n # Read the erb template\n begin\n perms = File.stat(src_path).mode\n template = Bosh::Template::Test::Template.new(job_spec, src_path)\n rescue Errno::ENOENT\n raise \"failed to read template file #{src_path}\"\n end\n\n # Build links\n links = []\n if context_hash['properties'] && context_hash['properties']['bosh_containerization'] && context_hash['properties']['bosh_containerization']['consumes']\n context_hash['properties']['bosh_containerization']['consumes'].each_pair do |name, link|\n next if link['instances'].empty?\n\n instances = []\n link['instances'].each do |link_instance|\n instances << Bosh::Template::Test::InstanceSpec.new(\n address: link_instance['address'],\n az: link_instance['az'],\n id: link_instance['id'],\n index: link_instance['index'],\n name: link_instance['name'],\n bootstrap: link_instance['index'] == '0',\n )\n end\n links << Bosh::Template::Test::Link.new(name: name, instances: instances, properties: link['properties'])\n end\n end\n\n # Build instance\n instance = Bosh::Template::Test::InstanceSpec.new(\n address: instance_info['address'],\n az: instance_info['az'],\n bootstrap: instance_info['index'] == '0',\n deployment: instance_info['deployment'],\n id: instance_info['id'],\n index: instance_info['index'],\n ip: instance_info['ip'],\n name: instance_info['name'],\n networks: {'default' => {'ip' => instance_info['ip'],\n 'dns_record_name' => instance_info['address'],\n # TODO: Do we need more, like netmask and gateway?\n # https://github.com/cloudfoundry/bosh-agent/blob/master/agent/applier/applyspec/v1_apply_spec_test.go\n }},\n )\n\n # Process the Template\n output = template.render(context_hash['properties'], spec: instance, consumes: links)\n\n begin\n # Open the output file\n output_dir = File.dirname(dst_path)\n FileUtils.mkdir_p(output_dir)\n out_file = File.open(dst_path, 'w')\n\n # Write results to the output file\n out_file.write(output)\n\n # Set the appropriate permissions on the output file\n if File.basename(File.dirname(dst_path)) == 'bin'\n out_file.chmod(0755)\n else\n out_file.chmod(perms)\n end\n rescue Errno::ENOENT, Errno::EACCES => e\n out_file = nil\n raise \"failed to open output file #{dst_path}: #{e}\"\n ensure\n out_file.close unless out_file.nil?\n end\nend\n"),
}

// define dirs
dir1 := &embedded.EmbeddedDir{
Filename: "",
DirModTime: time.Unix(1559254477, 0),
ChildFiles: []*embedded.EmbeddedFile{
file2, // "template_evaluation_context.rb"

},
}

// link ChildDirs
dir1.ChildDirs = []*embedded.EmbeddedDir{}

// register embeddedBox
embedded.RegisterEmbeddedBox(`rb`, &embedded.EmbeddedBox{
Name: `rb`,
Time: time.Unix(1559254477, 0),
Dirs: map[string]*embedded.EmbeddedDir{
"": dir1,
},
Files: map[string]*embedded.EmbeddedFile{
"template_evaluation_context.rb": file2,
},
})
}

0 comments on commit d3566e6

Please sign in to comment.