/** * Copyright 2016-2017 Sixt GmbH & Co. Autovermietung KG * 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. */ package com.sixt.service.framework; import com.jcabi.manifests.Manifests; import com.sixt.service.framework.logging.SixtLogbackContext; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.BufferedReader; import java.io.InputStreamReader; import java.util.HashMap; import java.util.Map; import java.util.UUID; public class ServiceProperties { private static final Logger logger = LoggerFactory.getLogger(ServiceProperties.class); public static final String REGISTRY_SERVER_KEY = "registryServer"; public static final String KAFKA_SERVER_KEY = "kafkaServer"; public static final String DATABASE_SERVER_KEY = "databaseServer"; public static final String DATABASE_USERNAME_KEY = "databaseUsername"; public static final String DATABASE_PASSWORD_KEY = "databasePassword"; public static final String SERVICE_PORT_KEY = "servicePort"; public static final String LOG_LEVEL_KEY = "logLevel"; public static final String SERVICE_UNKNOWN = "com.sixt.service.unknown"; private String serviceName = SERVICE_UNKNOWN; private String serviceVersion = "0.0.0-fffffff"; private String serviceInstanceId = "unknown"; private int servicePort = 0; private Map<String, String> allProperties = new HashMap<>(); protected SixtLogbackContext logbackContext = new SixtLogbackContext(); public ServiceProperties() { } /** * Parse the command-line arguments. Framework-level (standard arguments for * all Java services) are parsed, and any remaining arguments and environment * variables are set into our properties map as well. */ public void initialize(String[] args) { parseServiceProperties(); parseCommandLineArguments(args); parseEnvironmentVariables(); String logLevel = allProperties.get(LOG_LEVEL_KEY); if (! StringUtils.isBlank(logLevel)) { System.setProperty("SIXT_LOGGING", logLevel); logbackContext.updateLoggerLogLevel(logLevel); } if (allProperties.containsKey(SERVICE_PORT_KEY)) { setServicePort(Integer.parseInt(allProperties.get(SERVICE_PORT_KEY))); } } private void parseServiceProperties() { try { String name = Manifests.read("Service-Title"); setServiceName(name); } catch (Exception ex) { logger.info("Error finding Service-Title in manifests", ex); } try { serviceVersion = Manifests.read("Service-Version"); } catch (Exception ex) { logger.info("Error finding Service-Version in manifests", ex); } parseServiceInstance(); } /** * If running in docker, use that; else, generate test_service */ private void parseServiceInstance() { try { ProcessBuilder pb = new ProcessBuilder("bash", "-c", "cat /proc/self/cgroup | grep docker | sed 's/^.*\\///' | tail -n1 | cut -c 1-12"); Process p = pb.start(); BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream())); String output = reader.readLine(); if (! StringUtils.isBlank(output)) { serviceInstanceId = output.trim(); } p.waitFor(); } catch (Exception e) { logger.error("Error getting docker container id", e); } if ("unknown".equals(serviceInstanceId)) { serviceInstanceId = UUID.randomUUID().toString().replaceAll("-", "").substring(0, 12); } } private void parseCommandLineArguments(String[] args) { if (args.length % 2 == 1) { throw new IllegalArgumentException("Expecting even number of arguments"); } for (int i = 0; i < args.length; i += 2) { String key = args[i]; while (key.startsWith("-")) { key = key.substring(1); } String value = args[i + 1]; logger.debug("Setting property from cmd-line {} to {}", key, value); allProperties.put(key, value); } } private void parseEnvironmentVariables() { Map<String, String> env = System.getenv(); for (String key : env.keySet()) { if (key.startsWith("LC_") || key.startsWith("_")) { continue; } String value = env.get(key); logger.debug("Setting property from environment {} to {}", key, value); allProperties.put(key, value); } } public void ensureProperties(String[] requiredProps) { boolean fail = ! areAllPropertiesSet(requiredProps); if (fail) { throw new IllegalStateException("EnsureProperties failed"); } } public boolean areAllPropertiesSet(String[] requiredProps) { boolean fail = true; if (requiredProps != null) { for (String prop : requiredProps) { if (allProperties.get(prop) == null) { logger.info("Required property {} was not set", prop); fail = false; } } } return fail; } public String getServiceName() { return serviceName; } public String getServiceVersion() { return serviceVersion; } public String getServiceInstanceId() { return serviceInstanceId; } public void setServicePort(int servicePort) { this.servicePort = servicePort; } public int getServicePort() { return servicePort; } /** * Consul server in the form of host:port */ public String getRegistryServer() { return allProperties.get(REGISTRY_SERVER_KEY); } public String getKafkaServer() { return allProperties.get(KAFKA_SERVER_KEY); } public String getDatabaseServer() { return allProperties.get(DATABASE_SERVER_KEY); } public String getDatabaseUsername() { return allProperties.get(DATABASE_USERNAME_KEY); } public String getDatabasePassword() { return allProperties.get(DATABASE_PASSWORD_KEY); } public void addProperty(String key, String value) { allProperties.put(key, value); } public String getProperty(String key) { return allProperties.get(key); } public Map<String, String> getAllProperties() { return allProperties; } public int getIntegerProperty(String key, int defaultValue) { String value = getProperty(key); if (StringUtils.isNotBlank(value)) { try { return Integer.valueOf(value); } catch (Exception ex) { logger.info("Service property '{}' was not an integer value: '{}'", key, value); } } return defaultValue; } //Intended only for testing public void setServiceName(String name) { serviceName = name; } //Intended only for testing public void setServiceInstanceId(String id) { serviceInstanceId = id; } }