Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactored and fixed jobs without properties #3

Merged
merged 1 commit into from
May 31, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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,
},
})
}