77import java .nio .file .Path ;
88import java .nio .file .StandardOpenOption ;
99import java .time .Instant ;
10+ import java .util .Collections ;
1011import java .util .Map ;
12+ import java .util .Map .Entry ;
1113import java .util .Objects ;
1214import java .util .Properties ;
1315import java .util .concurrent .Callable ;
@@ -29,8 +31,13 @@ public class SetPropertiesCommand implements Callable<Integer> {
2931 public static final TypeReference <Map <String , PropertyDefinition >> PROPERTY_DEFINITIONS_TYPE = new TypeReference <Map <String , PropertyDefinition >>() {
3032 };
3133
32- @ Option (names = "--definitions" , required = true , description = "JSON file of property names to PropertyDefinition mappings" )
33- Path propertyDefinitions ;
34+ @ Option (names = "--definitions" , description = "JSON file of property names to PropertyDefinition mappings" )
35+ Path propertyDefinitionsFile ;
36+
37+ @ Option (names = {"--custom-property" , "--custom-properties" , "-p" },
38+ split = "\n " , splitSynopsisLabel = "<NL>" ,
39+ description = "Key=value pairs of custom properties to set" )
40+ Map <String ,String > customProperties ;
3441
3542 @ Parameters (arity = "1" )
3643 Path propertiesFile ;
@@ -40,13 +47,23 @@ public class SetPropertiesCommand implements Callable<Integer> {
4047
4148 @ Override
4249 public Integer call () throws Exception {
43-
44- if (! Files . exists ( propertyDefinitions )) {
45- throw new InvalidParameterException ( "Property definitions file does not exist" ) ;
50+ if ( propertyDefinitionsFile == null && customProperties == null ) {
51+ System . err . println ( "Either definitions or custom properties need to be provided" );
52+ return ExitCode . USAGE ;
4653 }
4754
48- final Map <String , PropertyDefinition > propertyDefinitions = ObjectMappers .defaultMapper ()
49- .readValue (this .propertyDefinitions .toFile (), PROPERTY_DEFINITIONS_TYPE );
55+ final Map <String , PropertyDefinition > propertyDefinitions ;
56+ if (propertyDefinitionsFile != null ) {
57+ if (!Files .exists (propertyDefinitionsFile )) {
58+ throw new InvalidParameterException ("Property definitions file does not exist" );
59+ }
60+
61+ propertyDefinitions = ObjectMappers .defaultMapper ()
62+ .readValue (this .propertyDefinitionsFile .toFile (), PROPERTY_DEFINITIONS_TYPE );
63+ }
64+ else {
65+ propertyDefinitions = Collections .emptyMap ();
66+ }
5067
5168 final Properties properties = new Properties ();
5269 if (Files .exists (propertiesFile )) {
@@ -55,11 +72,11 @@ public Integer call() throws Exception {
5572 }
5673 }
5774
58- final long changes = processProperties (propertyDefinitions , properties );
75+ final long changes = processProperties (propertyDefinitions , properties , customProperties );
5976 if (changes > 0 ) {
6077 log .info ("Created/updated {} propert{} in {}" , changes , changes != 1 ? "ies" :"y" , propertiesFile );
6178
62- try (OutputStream propsOut = Files .newOutputStream (propertiesFile , StandardOpenOption .TRUNCATE_EXISTING )) {
79+ try (OutputStream propsOut = Files .newOutputStream (propertiesFile , StandardOpenOption .TRUNCATE_EXISTING , StandardOpenOption . CREATE )) {
6380 properties .store (propsOut , String .format ("Updated %s by mc-image-helper" , Instant .now ()));
6481 }
6582 }
@@ -70,40 +87,56 @@ public Integer call() throws Exception {
7087 /**
7188 * @return count of added/modified properties
7289 */
73- private long processProperties (Map <String , PropertyDefinition > propertyDefinitions , Properties properties ) {
74- return propertyDefinitions .entrySet ().stream ()
75- .map (entry -> {
76- final String name = entry .getKey ();
77- final PropertyDefinition definition = entry .getValue ();
78-
79- if (definition .isRemove ()) {
80- if (properties .containsKey (name )) {
81- log .debug ("Removing {}, which is marked for removal" , name );
82- properties .remove (name );
83- return true ;
84- }
85- else {
86- return false ;
87- }
90+ private long processProperties (Map <String , PropertyDefinition > propertyDefinitions , Properties properties ,
91+ Map <String , String > customProperties
92+ ) {
93+ long modifiedViaDefinitions = 0 ;
94+ for (final Entry <String , PropertyDefinition > entry : propertyDefinitions .entrySet ()) {
95+ final String name = entry .getKey ();
96+ final PropertyDefinition definition = entry .getValue ();
97+
98+ if (definition .isRemove ()) {
99+ if (properties .containsKey (name )) {
100+ log .debug ("Removing {}, which is marked for removal" , name );
101+ properties .remove (name );
102+ ++modifiedViaDefinitions ;
88103 }
89-
104+ }
105+ else {
90106 final String envValue = environmentVariablesProvider .get (definition .getEnv ());
91107 if (envValue != null ) {
92108 final String expectedValue = mapAndValidateValue (definition , envValue );
93109
94110 final String propValue = properties .getProperty (name );
95111
96112 if (!Objects .equals (expectedValue , propValue )) {
97- log .debug ("Setting property {} to new value '{}'" , name , expectedValue );
113+ log .debug ("Setting property {} to new value '{}'" , name , needsValueRedacted ( name ) ? "***" : expectedValue );
98114 properties .setProperty (name , expectedValue );
99- return true ;
115+ ++ modifiedViaDefinitions ;
100116 }
101117 }
118+ }
119+ }
120+
121+ long modifiedViaCustom = 0 ;
122+ if (customProperties != null ) {
123+ for (final Entry <String , String > entry : customProperties .entrySet ()) {
124+ final String name = entry .getKey ();
125+ final String targetValue = entry .getValue ();
126+ final String propValue = properties .getProperty (name );
127+ if (!Objects .equals (targetValue , propValue )) {
128+ log .debug ("Setting property {} to new value '{}'" , name , targetValue );
129+ properties .setProperty (name , targetValue );
130+ ++modifiedViaCustom ;
131+ }
132+ }
133+ }
134+
135+ return modifiedViaDefinitions + modifiedViaCustom ;
136+ }
102137
103- return false ;
104- })
105- .filter (modified -> modified )
106- .count ();
138+ private static boolean needsValueRedacted (String name ) {
139+ return name .contains ("password" );
107140 }
108141
109142 private String mapAndValidateValue (PropertyDefinition definition , String value ) {
0 commit comments