Skip to content
Permalink
Browse files

Fix issues with unbound variables in HTTP and HTTPS proxy envs

  • Loading branch information...
tvs committed Mar 2, 2019
1 parent 592d7ae commit 346a68729e20598c277d55283034553cfca32acb
@@ -0,0 +1,8 @@
# frozen_string_literal: true

source 'https://rubygems.org'

group :test do
gem 'bosh-template'
gem 'rspec'
end
@@ -0,0 +1,30 @@
GEM
remote: https://rubygems.org/
specs:
bosh-template (2.2.0)
semi_semantic (~> 1.2.0)
diff-lcs (1.3)
rspec (3.8.0)
rspec-core (~> 3.8.0)
rspec-expectations (~> 3.8.0)
rspec-mocks (~> 3.8.0)
rspec-core (3.8.0)
rspec-support (~> 3.8.0)
rspec-expectations (3.8.2)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.8.0)
rspec-mocks (3.8.0)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.8.0)
rspec-support (3.8.0)
semi_semantic (1.2.0)

PLATFORMS
ruby

DEPENDENCIES
bosh-template
rspec

BUNDLED WITH
2.0.1
@@ -179,12 +179,12 @@ export DOCKER_VM_MAX_MAP_COUNT=<%= p('vm.max_map_count') %>

# Proxy configuration
<% if_p('env.http_proxy') do |http_proxy| %>
export HTTP_PROXY="<%= http_proxy %>"
export http_proxy="<%= http_proxy %>"
export HTTP_PROXY='<%= http_proxy %>'
export http_proxy='<%= http_proxy %>'
<% end %>
<% if_p('env.https_proxy') do |https_proxy| %>
export HTTPS_PROXY="<%= https_proxy %>"
export https_proxy="<%= https_proxy %>"
export HTTPS_PROXY='<%= https_proxy %>'
export https_proxy='<%= https_proxy %>'
<% end %>
<% if_p('env.no_proxy') do |no_proxy| %>
export NO_PROXY="<%= no_proxy %>"
@@ -0,0 +1,47 @@
# frozen_string_literal: true

require 'rspec'
require 'spec_helper'
require 'tempfile'
require 'open3'

describe 'docker job_properties.sh' do
context "when http proxy settings have '$' in their passwords" do
let(:properties) do
{
'env' => {
'http_proxy' => "http://user:pa$word@127.0.0.1:1234",
'https_proxy' => "https://user:pa$word@127.0.0.1:1234",
}
}
end

it "does not try to interpolate it in bash" do
script = compiled_template('docker', 'bin/job_properties.sh', properties, {})
expect(script).to include("HTTP_PROXY='#{properties['env']['http_proxy']}'")
expect(script).to include("http_proxy='#{properties['env']['http_proxy']}'")
expect(script).to include("HTTPS_PROXY='#{properties['env']['https_proxy']}'")
expect(script).to include("https_proxy='#{properties['env']['https_proxy']}'")

file = Tempfile.new('job_properties.sh')
begin
# Faking a few BOSH-enforced environment vars...
file.write("JOB_DIR=/nonsense\n")
file.write("LOG_DIR=/nonsense\n")
file.write("RUN_DIR=/nonsense\n")
file.write("JOB_NAME=docker\n")
file.write("TMP_DIR=/tmp\n")

file.write(script)
file.rewind

_, stderr, status = Open3.capture3("bash -uc 'source #{file.path}'")
expect(status.success?).to be_truthy
expect(stderr).to_not include("unbound variable")
ensure
file.close
file.unlink
end
end
end
end
@@ -0,0 +1,7 @@
# frozen_string_literal: true

require 'support/template_helpers'

RSpec.configure do |config|
config.include TemplateHelpers
end
@@ -0,0 +1,65 @@
# frozen_string_literal: true

require 'bosh/template/renderer'
require 'yaml'

module TemplateHelpers
include Bosh::Template::PropertyHelper

def compiled_template(job_name, template_name, manifest_properties = {}, links = {}, network_properties = [], az = '', ip = '', id = '', instance_name: '')
manifest = emulate_bosh_director_merge(job_name, manifest_properties, links, network_properties, az, ip, id, instance_name)

renderer = Bosh::Template::Renderer.new(context: manifest)
renderer.render("jobs/#{job_name}/templates/#{template_name}.erb")
end

# Trying to emulate bosh director Bosh::Director::DeploymentPlan::Job#extract_template_properties
def emulate_bosh_director_merge(job_name, manifest_properties, links, network_properties, az, ip, id, instance_name)
job_spec = YAML.load_file("jobs/#{job_name}/spec")
spec_properties = job_spec['properties']

default_property_values = {}
spec_properties.each_pair do |name, definition|
default_value = definition['default']
copy_property(default_property_values, {}, name, default_value)
end

effective_properties = recursive_merge(default_property_values, manifest_properties)

links.each do |link_name, contents|
next unless link_name == 'cloud-provider'

link_spec = YAML.load_file("jobs/#{link_name}/spec")
link_spec_properties = link_spec['properties']

default_link_property_values = {}
link_spec_properties.each_pair do |name, definition|
default_value = definition['default']
copy_property(default_link_property_values, {}, name, default_value)
end

link_properties = recursive_merge(default_link_property_values, contents['properties'])
contents['properties'] = link_properties
end

{
'properties' => effective_properties,
'networks' => network_properties,
'links' => links,
'az' => az,
'ip' => ip,
'id' => id,
'name' => instance_name
}.to_json
end

def recursive_merge(first, other)
first.merge(other) do |_, old_value, new_value|
if old_value.class == Hash && new_value.class == Hash
recursive_merge(old_value, new_value)
else
new_value
end
end
end
end

0 comments on commit 346a687

Please sign in to comment.
You can’t perform that action at this time.