Skip to content

Commit 00fc4bb

Browse files
committed
JAVA_OPTS from environment variables
Previously, the JAVA_OPTS environment variable was ignored in all cases. This change adds support for integrating the contents of the JAVA_OPTS environment variable when configured to do so. By default, the contents will be used, but a change to the config/java_opts.yml file by a buildpack admin can disable this behavior. [#64162734]
1 parent 55c3847 commit 00fc4bb

5 files changed

Lines changed: 107 additions & 26 deletions

File tree

config/java_opts.yml

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# Cloud Foundry Java Buildpack
2+
# Copyright (c) 2014 the original author or authors.
3+
#
4+
# Licensed under the Apache License, Version 2.0 (the "License");
5+
# you may not use this file except in compliance with the License.
6+
# You may obtain a copy of the License at
7+
#
8+
# http://www.apache.org/licenses/LICENSE-2.0
9+
#
10+
# Unless required by applicable law or agreed to in writing, software
11+
# distributed under the License is distributed on an "AS IS" BASIS,
12+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
# See the License for the specific language governing permissions and
14+
# limitations under the License.
15+
16+
# JAVA_OPTS configuration
17+
---
18+
from_environment: true
19+
# java_opts:

docs/framework-java_opts.md

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
11
# Java Options Framework
22
The Java Options Framework contributes arbitrary Java options to the application at runtime.
33

4-
Note: passing Java options using a `JAVA_OPTS` environment variable is not supported and will not work.
54

65
<table>
76
<tr>
8-
<td><strong>Detection Criterion</strong></td><td><tt>java_opts</tt> set in the <tt>config/java_opts.yml</tt> file</td>
7+
<td><strong>Detection Criterion</strong></td>
8+
<td><tt>java_opts</tt> set in the <tt>config/java_opts.yml</tt> file or the <tt>JAVA_OPTS</tt> environment variable set</td>
99
</tr>
1010
<tr>
11-
<td><strong>Tags</strong></td><td><tt>java-opts</tt></td>
11+
<td><strong>Tags</strong></td>
12+
<td><tt>java-opts</tt></td>
1213
</tr>
1314
</table>
1415
Tags are printed to standard output by the buildpack detect script
@@ -17,10 +18,12 @@ Tags are printed to standard output by the buildpack detect script
1718
## Configuration
1819
For general information on configuring the buildpack, refer to [Configuration and Extension][].
1920

20-
The framework can be configured by creating or modifying the `config/java_opts.yml` file in the buildpack fork.
21+
The framework can be configured by creating or modifying the [`config/java_opts.yml`][] file in the buildpack fork.
2122

2223
| Name | Description
2324
| ---- | -----------
25+
| `from_environment` | Whether to append the value of the `JAVA_OPTS` environment variable to the collection of Java options
2426
| `java_opts` | The Java options to use when running the application. All values are used without modification when invoking the JVM. The options are specified as a single YAML scalar in plain style or enclosed in single or double quotes.
2527

2628
[Configuration and Extension]: ../README.md#configuration-and-extension
29+
[`config/java_opts.yml`]: ../config/java_opts.yml

lib/java_buildpack/framework/java_opts.rb

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ class JavaOpts < JavaBuildpack::Component::BaseComponent
2727

2828
# (see JavaBuildpack::Component::BaseComponent#detect)
2929
def detect
30-
@configuration.key?(CONFIGURATION_PROPERTY) ? JavaOpts.to_s.dash_case : nil
30+
(supports_configuration? || supports_environment?) ? JavaOpts.to_s.dash_case : nil
3131
end
3232

3333
# (see JavaBuildpack::Component::BaseComponent#compile)
@@ -46,15 +46,30 @@ def release
4646

4747
CONFIGURATION_PROPERTY = 'java_opts'.freeze
4848

49+
ENVIRONMENT_PROPERTY = 'from_environment'.freeze
50+
51+
ENVIRONMENT_VARIABLE = 'JAVA_OPTS'.freeze
52+
4953
def memory_option?(option)
5054
option =~ /-Xms/ || option =~ /-Xmx/ || option =~ /-XX:MaxMetaspaceSize/ || option =~ /-XX:MaxPermSize/ ||
5155
option =~ /-Xss/ || option =~ /-XX:MetaspaceSize/ || option =~ /-XX:PermSize/
5256
end
5357

5458
def parsed_java_opts
55-
@configuration[CONFIGURATION_PROPERTY].shellsplit.map do |java_opt|
56-
java_opt.gsub(/([\s])/, '\\\\\1')
57-
end
59+
parsed_java_opts = []
60+
61+
parsed_java_opts.concat @configuration[CONFIGURATION_PROPERTY].shellsplit if supports_configuration?
62+
parsed_java_opts.concat ENV[ENVIRONMENT_VARIABLE].shellsplit if supports_environment?
63+
64+
parsed_java_opts.map { |java_opt| java_opt.gsub(/([\s])/, '\\\\\1') }
65+
end
66+
67+
def supports_configuration?
68+
@configuration.key? CONFIGURATION_PROPERTY
69+
end
70+
71+
def supports_environment?
72+
@configuration[ENVIRONMENT_PROPERTY] && ENV.key?(ENVIRONMENT_VARIABLE)
5873
end
5974

6075
end

spec/application_helper.rb

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,19 +23,27 @@
2323

2424
let(:app_dir) { Pathname.new Dir.mktmpdir }
2525

26-
let(:application) do
27-
allow(ENV).to receive(:to_hash).and_return(environment)
28-
29-
JavaBuildpack::Component::Application.new app_dir
30-
end
31-
32-
let(:details) { application.details }
26+
previous_environment = ENV
3327

3428
let(:environment) do
3529
{ 'test-key' => 'test-value', 'VCAP_APPLICATION' => vcap_application.to_yaml,
3630
'VCAP_SERVICES' => vcap_services.to_yaml }
3731
end
3832

33+
before do
34+
ENV.replace environment
35+
end
36+
37+
after do
38+
ENV.replace previous_environment
39+
end
40+
41+
let(:application) do
42+
JavaBuildpack::Component::Application.new app_dir
43+
end
44+
45+
let(:details) { application.details }
46+
3947
let(:services) { application.services }
4048

4149
let(:vcap_application) { { 'application_name' => 'test-application-name' } }

spec/java_buildpack/framework/java_opts_spec.rb

Lines changed: 47 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -18,25 +18,42 @@
1818
require 'component_helper'
1919
require 'java_buildpack/framework/java_opts'
2020

21-
describe JavaBuildpack::Framework::JavaOpts do
21+
describe JavaBuildpack::Framework::JavaOpts, :focus do
2222
include_context 'component_helper'
2323

2424
context do
25-
let(:configuration) { super().merge('java_opts' => '-Xmx1024M') }
25+
let(:configuration) { { 'java_opts' => '-Xmx1024M' } }
2626

2727
it 'should detect with java.opts configuration' do
2828
expect(component.detect).to eq('java-opts')
2929
end
3030
end
3131

32+
context do
33+
let(:configuration) { { 'from_environment' => true } }
34+
let(:environment) { { 'JAVA_OPTS' => '-Dalpha=bravo' } }
35+
36+
it 'should detect with ENV and with from_environment configuration' do
37+
expect(component.detect).to eq('java-opts')
38+
end
39+
end
40+
41+
context do
42+
let(:environment) { { 'JAVA_OPTS' => '-Dalpha=bravo' } }
43+
44+
it 'should not detect with ENV and without from_environment configuration' do
45+
expect(component.detect).to be_nil
46+
end
47+
end
48+
3249
it 'should not detect without java_opts configuration' do
3350
expect(component.detect).to be_nil
3451
end
3552

3653
context do
3754
let(:configuration) do
38-
super().merge('java_opts' => '-Xdebug -Xnoagent -Xrunjdwp:transport=dt_socket,server=y,address=8000,suspend=y ' \
39-
"-XX:OnOutOfMemoryError='kill -9 %p'")
55+
{ 'java_opts' => '-Xdebug -Xnoagent -Xrunjdwp:transport=dt_socket,server=y,address=8000,suspend=y ' \
56+
"-XX:OnOutOfMemoryError='kill -9 %p'" }
4057
end
4158

4259
it 'should add split java_opts to context' do
@@ -50,59 +67,78 @@
5067
end
5168

5269
context do
53-
let(:configuration) { super().merge('java_opts' => '-Xms1024M') }
70+
let(:configuration) { { 'java_opts' => '-Xms1024M' } }
5471

5572
it 'should raise an error if a -Xms is configured' do
5673
expect { component.compile }.to raise_error(/-Xms/)
5774
end
5875
end
5976

6077
context do
61-
let(:configuration) { super().merge('java_opts' => '-Xmx1024M') }
78+
let(:configuration) { { 'java_opts' => '-Xmx1024M' } }
6279

6380
it 'should raise an error if a -Xmx is configured' do
6481
expect { component.compile }.to raise_error(/-Xmx/)
6582
end
6683
end
6784

6885
context do
69-
let(:configuration) { super().merge('java_opts' => '-XX:MaxMetaspaceSize=128M') }
86+
let(:configuration) { { 'java_opts' => '-XX:MaxMetaspaceSize=128M' } }
7087

7188
it 'should raise an error if a -XX:MaxMetaspaceSize is configured' do
7289
expect { component.compile }.to raise_error(/-XX:MaxMetaspaceSize/)
7390
end
7491
end
7592

7693
context do
77-
let(:configuration) { super().merge('java_opts' => '-XX:MetaspaceSize=128M') }
94+
let(:configuration) { { 'java_opts' => '-XX:MetaspaceSize=128M' } }
7895

7996
it 'should raise an error if a -XX:MetaspaceSize is configured' do
8097
expect { component.compile }.to raise_error(/-XX:MetaspaceSize/)
8198
end
8299
end
83100

84101
context do
85-
let(:configuration) { super().merge('java_opts' => '-XX:MaxPermSize=128M') }
102+
let(:configuration) { { 'java_opts' => '-XX:MaxPermSize=128M' } }
86103

87104
it 'should raise an error if a -XX:MaxPermSize is configured' do
88105
expect { component.compile }.to raise_error(/-XX:MaxPermSize/)
89106
end
90107
end
91108

92109
context do
93-
let(:configuration) { super().merge('java_opts' => '-XX:PermSize=128M') }
110+
let(:configuration) { { 'java_opts' => '-XX:PermSize=128M' } }
94111

95112
it 'should raise an error if a -XX:PermSize is configured' do
96113
expect { component.compile }.to raise_error(/-XX:PermSize/)
97114
end
98115
end
99116

100117
context do
101-
let(:configuration) { super().merge('java_opts' => '-Xss1M') }
118+
let(:configuration) { { 'java_opts' => '-Xss1M' } }
102119

103120
it 'should raise an error if a -Xss is configured' do
104121
expect { component.compile }.to raise_error(/-Xss/)
105122
end
106123
end
107124

125+
context do
126+
let(:configuration) { { 'from_environment' => true } }
127+
let(:environment) { { 'JAVA_OPTS' => '-Dalpha=bravo' } }
128+
129+
it 'should include values specified in ENV[JAVA_OPTS]' do
130+
component.release
131+
expect(java_opts).to include('-Dalpha=bravo')
132+
end
133+
end
134+
135+
context do
136+
let(:environment) { { 'JAVA_OPTS' => '-Dalpha=bravo' } }
137+
138+
it 'should not include values specified in ENV[JAVA_OPTS] without from_environment' do
139+
component.release
140+
expect(java_opts).not_to include('-Dalpha=bravo')
141+
end
142+
end
143+
108144
end

0 commit comments

Comments
 (0)