11package datadog .trace .bootstrap .config .provider ;
22
3- import datadog .cli .CLIHelper ;
43import datadog .trace .bootstrap .config .provider .stableconfigyaml .ConfigurationMap ;
54import datadog .trace .bootstrap .config .provider .stableconfigyaml .Rule ;
65import datadog .trace .bootstrap .config .provider .stableconfigyaml .Selector ;
76import datadog .trace .bootstrap .config .provider .stableconfigyaml .StableConfigYaml ;
87import datadog .yaml .YamlParser ;
98import java .io .IOException ;
9+ import java .nio .charset .StandardCharsets ;
10+ import java .nio .file .Files ;
11+ import java .nio .file .Paths ;
1012import java .util .Collections ;
1113import java .util .HashMap ;
12- import java .util .HashSet ;
1314import java .util .List ;
14- import java .util .Set ;
1515import java .util .function .BiPredicate ;
1616import org .slf4j .Logger ;
1717import org .slf4j .LoggerFactory ;
1818
1919public class StableConfigParser {
2020 private static final Logger log = LoggerFactory .getLogger (StableConfigParser .class );
2121
22- private static final Set <String > VM_ARGS = new HashSet <>(CLIHelper .getVmArgs ());
22+ private static final String ENVIRONMENT_VARIABLES_PREFIX = "environment_variables['" ;
23+ private static final String PROCESS_ARGUMENTS_PREFIX = "process_arguments['" ;
24+ private static final String UNDEFINED_VALUE = "UNDEFINED" ;
2325
2426 /**
2527 * Parses a configuration file and returns a stable configuration object.
@@ -37,7 +39,9 @@ public class StableConfigParser {
3739 */
3840 public static StableConfigSource .StableConfig parse (String filePath ) throws IOException {
3941 try {
40- StableConfigYaml data = YamlParser .parse (filePath , StableConfigYaml .class );
42+ String content = new String (Files .readAllBytes (Paths .get (filePath )), StandardCharsets .UTF_8 );
43+ String processedContent = processTemplate (content );
44+ StableConfigYaml data = YamlParser .parse (processedContent , StableConfigYaml .class );
4145
4246 String configId = data .getConfig_id ();
4347 ConfigurationMap configMap = data .getApm_configuration_default ();
@@ -66,7 +70,9 @@ public static StableConfigSource.StableConfig parse(String filePath) throws IOEx
6670
6771 } catch (IOException e ) {
6872 log .debug (
69- "Stable configuration file either not found or not readable at filepath {}" , filePath );
73+ "Stable configuration file either not found or not readable at filepath {}. Error: {}" ,
74+ filePath ,
75+ e .getMessage ());
7076 }
7177 return StableConfigSource .StableConfig .EMPTY ;
7278 }
@@ -166,14 +172,100 @@ static boolean selectorMatch(String origin, List<String> matches, String operato
166172 return false ;
167173 }
168174 case "process_arguments" :
169- // For now, always return true if `key` exists in the JVM Args
170175 // TODO: flesh out the meaning of each operator for process_arguments
171- return VM_ARGS .contains (key );
176+ if (!key .startsWith ("-D" )) {
177+ log .warn (
178+ "Ignoring unsupported process_arguments entry in selector match, '{}'. Only system properties specified with the '-D' prefix are supported." ,
179+ key );
180+ return false ;
181+ }
182+ // Cut the -D prefix
183+ return System .getProperty (key .substring (2 )) != null ;
172184 case "tags" :
173185 // TODO: Support this down the line (Must define the source of "tags" first)
174186 return false ;
175187 default :
176188 return false ;
177189 }
178190 }
191+
192+ static String processTemplate (String content ) throws IOException {
193+ // Do nothing if there are no variables to process
194+ int openIndex = content .indexOf ("{{" );
195+ if (openIndex == -1 ) {
196+ return content ;
197+ }
198+
199+ StringBuilder result = new StringBuilder (content .length ());
200+
201+ // Add everything before the opening braces
202+ result .append (content , 0 , openIndex );
203+
204+ while (true ) {
205+
206+ // Find the closing braces
207+ int closeIndex = content .indexOf ("}}" , openIndex );
208+ if (closeIndex == -1 ) {
209+ throw new IOException ("Unterminated template in config" );
210+ }
211+
212+ // Extract the template variable
213+ String templateVar = content .substring (openIndex + 2 , closeIndex ).trim ();
214+
215+ // Process the template variable and get its value
216+ String value = processTemplateVar (templateVar );
217+
218+ // Add the processed value
219+ result .append (value );
220+
221+ // Continue with the next template variable
222+ openIndex = content .indexOf ("{{" , closeIndex );
223+ if (openIndex == -1 ) {
224+ // Stop and add everything left after the final closing braces
225+ result .append (content , closeIndex + 2 , content .length ());
226+ break ;
227+ } else {
228+ // Add everything between the last braces and the next
229+ result .append (content , closeIndex + 2 , openIndex );
230+ }
231+ }
232+
233+ return result .toString ();
234+ }
235+
236+ private static String processTemplateVar (String templateVar ) throws IOException {
237+ if (templateVar .startsWith (ENVIRONMENT_VARIABLES_PREFIX ) && templateVar .endsWith ("']" )) {
238+ String envVar =
239+ templateVar
240+ .substring (ENVIRONMENT_VARIABLES_PREFIX .length (), templateVar .length () - 2 )
241+ .trim ();
242+ if (envVar .isEmpty ()) {
243+ throw new IOException ("Empty environment variable name in template" );
244+ }
245+ String value = System .getenv (envVar .toUpperCase ());
246+ if (value == null || value .isEmpty ()) {
247+ return UNDEFINED_VALUE ;
248+ }
249+ return value ;
250+ } else if (templateVar .startsWith (PROCESS_ARGUMENTS_PREFIX ) && templateVar .endsWith ("']" )) {
251+ String processArg =
252+ templateVar .substring (PROCESS_ARGUMENTS_PREFIX .length (), templateVar .length () - 2 ).trim ();
253+ if (processArg .isEmpty ()) {
254+ throw new IOException ("Empty process argument in template" );
255+ }
256+ if (!processArg .startsWith ("-D" )) {
257+ log .warn (
258+ "Ignoring unsupported process_arguments entry in template variable, '{}'. Only system properties specified with the '-D' prefix are supported." ,
259+ processArg );
260+ return UNDEFINED_VALUE ;
261+ }
262+ String value = System .getProperty (processArg .substring (2 ));
263+ if (value == null || value .isEmpty ()) {
264+ return UNDEFINED_VALUE ;
265+ }
266+ return value ;
267+ } else {
268+ return UNDEFINED_VALUE ;
269+ }
270+ }
179271}
0 commit comments