Skip to content

Commit

Permalink
Disable JVM DNS Caching
Browse files Browse the repository at this point in the history
Previously JVM DNS caching was always governed by the JVM's settings of
always/10s.  This causes issues in situations where DNS entries are being
refreshed by BOSH quite quickly.  To address this, BOSH has added a DNS server
of its own that is accessible on a link-local address.  This BOSH DNS server
implements the appropriate caching close by (and obeying ttls) removing the
need for the JVM to so.  This change notices the BOSH DNS as staging time and
if it exists, disables the default JVM DNS caching in lieu of the BOSH DNS
caching.

[resolves #505]
  • Loading branch information
nebhale committed Oct 23, 2017
1 parent 1cd01e1 commit 087010f
Show file tree
Hide file tree
Showing 14 changed files with 146 additions and 15 deletions.
1 change: 1 addition & 0 deletions .idea/dictionaries/bhale.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions .rubocop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,9 @@ Metrics/CyclomaticComplexity:
Metrics/LineLength:
Max: 120
Metrics/MethodLength:
Max: 20
Max: 25
Metrics/ParameterLists:
Max: 8
Max: 10
Metrics/PerceivedComplexity:
Max: 10
RSpec/ExampleLength:
Expand Down
2 changes: 1 addition & 1 deletion config/components.yml
Original file line number Diff line number Diff line change
Expand Up @@ -66,5 +66,5 @@ frameworks:
- "JavaBuildpack::Framework::SpringInsight"
- "JavaBuildpack::Framework::YourKitProfiler"
- "JavaBuildpack::Framework::TakipiAgent"
- "JavaBuildpack::Framework::SecurityProviders"
- "JavaBuildpack::Framework::JavaSecurity"
- "JavaBuildpack::Framework::JavaOpts"
4 changes: 3 additions & 1 deletion lib/java_buildpack/buildpack.rb
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
require 'java_buildpack/component/immutable_java_home'
require 'java_buildpack/component/java_opts'
require 'java_buildpack/component/mutable_java_home'
require 'java_buildpack/component/networking'
require 'java_buildpack/component/security_providers'
require 'java_buildpack/logging/logger_factory'
require 'java_buildpack/util/cache/application_cache'
Expand Down Expand Up @@ -131,6 +132,7 @@ def initialize(app_dir, application)
'env_vars' => Component::EnvironmentVariables.new(app_dir),
'extension_directories' => Component::ExtensionDirectories.new(app_dir),
'java_opts' => @java_opts,
'networking' => Component::Networking.new,
'security_providers' => Component::SecurityProviders.new
}

Expand Down Expand Up @@ -181,7 +183,7 @@ def instantiate(components, java_home, component_info)
droplet: Component::Droplet.new(component_info['additional_libraries'], component_id,
component_info['env_vars'], component_info['extension_directories'],
java_home, component_info['java_opts'], component_info['app_dir'],
component_info['security_providers'])
component_info['networking'], component_info['security_providers'])
}
component.constantize.new(context)
end
Expand Down
8 changes: 7 additions & 1 deletion lib/java_buildpack/component/droplet.rb
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,10 @@ class Droplet
# @return [JavaOpts] the shared +JavaOpts+ instance for all components
attr_reader :java_opts

# @!attribute [r] networking
# @return [Networking] the shared +Networking+ instance for all components
attr_reader :networking

# @!attribute [r] root
# @return [JavaBuildpack::Util::FilteringPathname] the root of the droplet's fileystem filtered so that it
# excludes files in the sandboxes of other components
Expand Down Expand Up @@ -83,10 +87,11 @@ class Droplet
# be an instance of +MutableJavaHome+. Otherwise it should
# be an instance of +ImmutableJavaHome+.
# @param [JavaOpts] java_opts the shared +JavaOpts+ instance for all components
# @param [Networking] networking the shared +Networking+ instance for all components
# @param [Pathname] root the root of the droplet
# @param [SecurityProviders] security_providers the shared +SecurityProviders+ instance for all components
def initialize(additional_libraries, component_id, env_vars, extension_directories, java_home, java_opts, root,
security_providers)
networking, security_providers)

@additional_libraries = additional_libraries
@component_id = component_id
Expand All @@ -110,6 +115,7 @@ def initialize(additional_libraries, component_id, env_vars, extension_directori
->(path) { !in?(path, buildpack_root) || in?(path, @sandbox) },
true
)
@networking = networking
@security_providers = security_providers
end

Expand Down
54 changes: 54 additions & 0 deletions lib/java_buildpack/component/networking.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# Cloud Foundry Java Buildpack
# Copyright 2013-2017 the original author or authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

require 'fileutils'
require 'java_buildpack/component'

module JavaBuildpack
module Component

# An abstraction around the networking configuration provided to a droplet by components.
#
# A new instance of this type should be created once for the application.
class Networking

# @!attribute [rw] networkaddress_cache_ttl
# @return [Integer] the number of seconds to cache the successful lookup
attr_accessor :networkaddress_cache_ttl

# @!attribute [rw] networkaddress_cache_negative_ttl
# @return [Integer] the number of seconds to cache the failure for un-successful lookups
attr_accessor :networkaddress_cache_negative_ttl

# Write the networking configuration to a destination file
#
# @param [Pathname] destination the destination to write to
# @return [Void]
def write_to(destination)
FileUtils.mkdir_p destination.parent

destination.open(File::CREAT | File::APPEND | File::WRONLY) do |f|
f.write "networkaddress.cache.ttl=#{@networkaddress_cache_ttl}\n" if @networkaddress_cache_ttl

if @networkaddress_cache_negative_ttl
f.write "networkaddress.cache.negative.ttl=#{networkaddress_cache_negative_ttl}\n"
end
end
end

end

end
end
2 changes: 1 addition & 1 deletion lib/java_buildpack/component/security_providers.rb
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ class SecurityProviders < Array
def write_to(destination)
FileUtils.mkdir_p destination.parent

destination.open(File::CREAT | File::WRONLY) do |f|
destination.open(File::CREAT | File::APPEND | File::WRONLY) do |f|
each_with_index { |security_provider, index| f.write "security.provider.#{index + 1}=#{security_provider}\n" }
end
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,16 @@ module JavaBuildpack
module Framework

# Encapsulates the functionality for contributing custom Security Providers to an application.
class SecurityProviders < JavaBuildpack::Component::BaseComponent
class JavaSecurity < JavaBuildpack::Component::BaseComponent

# (see JavaBuildpack::Component::BaseComponent#detect)
def detect
SecurityProviders.to_s.dash_case
JavaSecurity.to_s.dash_case
end

# (see JavaBuildpack::Component::BaseComponent#compile)
def compile
@droplet.networking.write_to java_security
@droplet.security_providers.write_to java_security
end

Expand Down
22 changes: 22 additions & 0 deletions lib/java_buildpack/jre/open_jdk_like_jre.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,12 @@
# See the License for the specific language governing permissions and
# limitations under the License.

require 'ipaddr'
require 'fileutils'
require 'java_buildpack/component/versioned_dependency_component'
require 'java_buildpack/jre'
require 'java_buildpack/util/tokenized_version'
require 'resolv'

module JavaBuildpack
module Jre
Expand Down Expand Up @@ -48,6 +50,7 @@ def detect
def compile
download_tar
@droplet.copy_resources
disable_dns_caching if link_local_dns?

return if @droplet.java_home.java_8_or_later?

Expand All @@ -62,6 +65,25 @@ def release
.add_system_property('java.io.tmpdir', '$TMPDIR')
end

private

LINK_LOCAL = IPAddr.new('169.254.0.0/16').freeze

private_constant :LINK_LOCAL

def disable_dns_caching
puts ' JVM DNS caching disabled in lieu of BOSH DNS caching'

@droplet.networking.networkaddress_cache_ttl = 0
@droplet.networking.networkaddress_cache_negative_ttl = 0
end

def link_local_dns?
Resolv::DNS::Config.new.lazy_initialize.nameserver_port.any? do |nameserver_port|
LINK_LOCAL.include? IPAddr.new(nameserver_port[0])
end
end

end

end
Expand Down
6 changes: 5 additions & 1 deletion spec/droplet_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
require 'java_buildpack/component/extension_directories'
require 'java_buildpack/component/immutable_java_home'
require 'java_buildpack/component/java_opts'
require 'java_buildpack/component/networking'
require 'java_buildpack/component/security_providers'
require 'java_buildpack/util/snake_case'
require 'pathname'
Expand All @@ -38,7 +39,8 @@

let(:droplet) do
JavaBuildpack::Component::Droplet.new(additional_libraries, component_id, environment_variables,
extension_directories, java_home, java_opts, app_dir, security_providers)
extension_directories, java_home, java_opts, app_dir, networking,
security_providers)
end

let(:extension_directories) { JavaBuildpack::Component::ExtensionDirectories.new app_dir }
Expand All @@ -62,6 +64,8 @@
java_opts
end

let(:networking) { JavaBuildpack::Component::Networking.new }

let(:security_providers) { JavaBuildpack::Component::SecurityProviders.new }

before do
Expand Down
4 changes: 4 additions & 0 deletions spec/fixtures/framework_java_security_networking
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
networkaddress.cache.ttl=-1
networkaddress.cache.negative.ttl=-2
security.provider.1=test-security-provider-1
security.provider.2=test-security-provider-2
2 changes: 2 additions & 0 deletions spec/fixtures/framework_java_security_security_providers
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
security.provider.1=test-security-provider-1
security.provider.2=test-security-provider-2
Original file line number Diff line number Diff line change
Expand Up @@ -16,28 +16,40 @@
require 'spec_helper'
require 'component_helper'
require 'fileutils'
require 'java_buildpack/framework/security_providers'
require 'java_buildpack/framework/java_security'

describe JavaBuildpack::Framework::SecurityProviders do
describe JavaBuildpack::Framework::JavaSecurity do
include_context 'component_helper'

it 'adds extension directories to system properties' do
component.release

expect(java_opts).to include('-Djava.ext.dirs=$PWD/.java-buildpack/security_providers/test-extension-directory-1:' \
'$PWD/.java-buildpack/security_providers/test-extension-directory-2')
expect(java_opts).to include('-Djava.ext.dirs=$PWD/.java-buildpack/java_security/test-extension-directory-1:' \
'$PWD/.java-buildpack/java_security/test-extension-directory-2')
end

it 'writes new security properties' do
it 'writes security provider security properties' do
component.compile

expect(sandbox + 'java.security').to exist
expect(File.read(sandbox + 'java.security'))
.to eq File.read('spec/fixtures/framework_java_security_security_providers')
end

it 'writes networking security properties' do
networking.networkaddress_cache_ttl = -1
networking.networkaddress_cache_negative_ttl = -2

component.compile

expect(sandbox + 'java.security').to exist
expect(File.read(sandbox + 'java.security')).to eq File.read('spec/fixtures/framework_java_security_networking')
end

it 'adds security properties to system properties' do
component.release

expect(java_opts).to include('-Djava.security.properties=$PWD/.java-buildpack/security_providers/' \
expect(java_opts).to include('-Djava.security.properties=$PWD/.java-buildpack/java_security/' \
'java.security')
end

Expand Down
23 changes: 23 additions & 0 deletions spec/java_buildpack/jre/open_jdk_like_jre_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
require 'component_helper'
require 'java_buildpack/component/mutable_java_home'
require 'java_buildpack/jre/open_jdk_like_jre'
require 'resolv'

describe JavaBuildpack::Jre::OpenJDKLikeJre do
include_context 'component_helper'
Expand Down Expand Up @@ -49,4 +50,26 @@
expect(java_opts).to include('-Djava.io.tmpdir=$TMPDIR')
end

it 'does not disable dns caching if no BOSH DNS',
cache_fixture: 'stub-java.tar.gz' do

component.detect
component.compile

expect(networking.networkaddress_cache_ttl).not_to be
expect(networking.networkaddress_cache_negative_ttl).not_to be
end

it 'disables dns caching if BOSH DNS',
cache_fixture: 'stub-java.tar.gz' do

allow_any_instance_of(Resolv::DNS::Config).to receive(:nameserver_port).and_return([['169.254.0.2', 53]])

component.detect
component.compile

expect(networking.networkaddress_cache_ttl).to eq 0
expect(networking.networkaddress_cache_negative_ttl).to eq 0
end

end

0 comments on commit 087010f

Please sign in to comment.