blob: dd3a4e7b7d58b14868016e410cbfd772cee4163e [file] [log] [blame]
package com.epam.datalab.properties;
import com.epam.datalab.auth.UserInfo;
import com.epam.datalab.constants.ServiceConsts;
import com.epam.datalab.exceptions.DynamicChangePropertiesException;
import com.epam.datalab.rest.client.RESTService;
import com.google.inject.name.Named;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import sun.reflect.generics.reflectiveObjects.NotImplementedException;
import javax.inject.Inject;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@Slf4j
public class DynamicChangeProperties implements ChangePropertiesConst {
private final RESTService externalSelfService;
@Inject
public DynamicChangeProperties(@Named(ServiceConsts.PROVISIONING_SERVICE_NAME) RESTService externalSelfService) {
this.externalSelfService = externalSelfService;
}
public String getProperties(String path, String name) {
return readFileAsString(path, name);
}
public void overwriteProperties(String path, String name, String ymlString) {
writeFileFromString(ymlString, name, path);
}
public Map<String, String> getPropertiesWithExternal(String endpoint, UserInfo userInfo, String url) {
Map<String, String> properties = new HashMap<>();
if (endpoint.equals(ChangePropertiesConst.LOCAL_ENDPOINT_NAME)) {
properties.put(ChangePropertiesConst.SELF_SERVICE, getProperties(ChangePropertiesConst.SELF_SERVICE_PROP_PATH, ChangePropertiesConst.SELF_SERVICE));
properties.put(ChangePropertiesConst.PROVISIONING_SERVICE, getProperties(ChangePropertiesConst.PROVISIONING_SERVICE_PROP_PATH, ChangePropertiesConst.PROVISIONING_SERVICE));
properties.put(ChangePropertiesConst.BILLING_SERVICE, getProperties(ChangePropertiesConst.BILLING_SERVICE_PROP_PATH, ChangePropertiesConst.BILLING_SERVICE));
} else {
log.info("Trying to read properties, for external endpoint : {} , for user: {}",
endpoint, userInfo.getSimpleName());
properties.put(ChangePropertiesConst.PROVISIONING_SERVICE,
externalSelfService.get(url + "/provisioning-service", userInfo.getAccessToken(), String.class));
properties.put(ChangePropertiesConst.BILLING_SERVICE,
externalSelfService.get(url + "/billing", userInfo.getAccessToken(), String.class));
}
return properties;
}
public void overwritePropertiesWithExternal(String path, String name, YmlDTO ymlDTO, UserInfo userInfo,
String url) {
log.info("Trying to write {}, for external endpoint : {} , for user: {}",
name, ymlDTO.getEndpointName(), userInfo.getSimpleName());
if (ymlDTO.getEndpointName().equals(ChangePropertiesConst.LOCAL_ENDPOINT_NAME)
|| name.equals(SELF_SERVICE)
|| name.equals(GKE_SELF_SERVICE)) {
writeFileFromString(ymlDTO.getYmlString(), name, path);
} else {
url += findMethodName(name);
externalSelfService.post(url, ymlDTO.getYmlString(), userInfo.getAccessToken(), String.class);
}
}
public void restart(RestartForm restartForm) {
try {
boolean billing = restartForm.isBilling();
boolean provserv = restartForm.isProvserv();
boolean ui = restartForm.isUi();
String shCommand = buildSHRestartCommand(billing, provserv, ui);
log.info("Tying to restart ui: {}, provserv: {}, billing: {}, with command: {}", ui,
provserv, billing, shCommand);
Runtime.getRuntime().exec(shCommand).waitFor();
} catch (IOException | InterruptedException e) {
log.error(e.getMessage());
}
}
public void restartForExternal(RestartForm restartForm, UserInfo userInfo, String url) {
if (restartForm.getEndpoint().equals(LOCAL_ENDPOINT_NAME)) {
restart(restartForm);
} else {
log.info("External request for endpoint {}, for user {}", restartForm.getEndpoint(), userInfo.getSimpleName());
externalSelfService.post(url, userInfo.getAccessToken(), restartForm, Void.class);
}
}
private String findMethodName(String name) {
switch (name) {
case "provisioning.yml": {
return "/provisioning-service";
}
case "billing.yml": {
return "/billing";
}
default:
return "";
}
}
private String buildSHRestartCommand(boolean billing, boolean provserv, boolean ui) {
StringBuilder stringBuilder = new StringBuilder(ChangePropertiesConst.SUPERVISORCTL_RESTART_SH_COMMAND);
if (billing) stringBuilder.append(ChangePropertiesConst.BILLING_SERVICE_SUPERVISORCTL_RUN_NAME);
if (provserv) stringBuilder.append(ChangePropertiesConst.PROVISIONING_SERVICE_SUPERVISORCTL_RUN_NAME);
if (ui) stringBuilder.append(ChangePropertiesConst.SELF_SERVICE_SUPERVISORCTL_RUN_NAME);
return stringBuilder.toString();
}
private String readFileAsString(String selfServicePropPath, String serviceName) {
try {
log.info("Trying to read self-service.yml, file from path {} :", selfServicePropPath);
String currentConf = FileUtils.readFileToString(new File(selfServicePropPath), Charset.defaultCharset());
return hideSecretsAndRemoveLicence(currentConf);
} catch (IOException e) {
log.error(e.getMessage());
throw new DynamicChangePropertiesException(String.format("Failed while read file %s", serviceName));
}
}
private String hideSecretsAndRemoveLicence(String currentConf) {
Matcher m = Pattern.compile(ChangePropertiesConst.SECRET_REGEX).matcher(currentConf);
List<String> secrets = new ArrayList<>();
String confWithReplacedSecretConf = removeLicence(currentConf);
while (m.find()) {
String secret = m.group().split(":")[ChangePropertiesConst.DEFAULT_VALUE_PLACE];
if (!(secret.isEmpty() || secret.trim().isEmpty()))
secrets.add(secret);
}
for (String secret : secrets) {
confWithReplacedSecretConf = confWithReplacedSecretConf.replace(secret, ChangePropertiesConst.SECRET_REPLACEMENT_FORMAT);
}
return confWithReplacedSecretConf;
}
private String removeLicence(String conf) {
return conf.split(ChangePropertiesConst.LICENCE_REGEX)[conf.split(ChangePropertiesConst.LICENCE_REGEX).length - 1];
}
private void writeFileFromString(String newPropFile, String serviceName, String servicePath) {
try {
String oldFile = FileUtils.readFileToString(new File(servicePath), Charset.defaultCharset());
changeCHMODE(serviceName, servicePath, ChangePropertiesConst.DEFAULT_CHMOD, ChangePropertiesConst.WRITE_CHMOD);
BufferedWriter writer = new BufferedWriter(new FileWriter(servicePath));
log.info("Trying to overwrite {}, file for path {} :", serviceName, servicePath);
writer.write(addLicence());
writer.write(checkAndReplaceSecretIfEmpty(newPropFile, oldFile));
log.info("{} overwritten successfully", serviceName);
writer.close();
changeCHMODE(serviceName, servicePath, ChangePropertiesConst.WRITE_CHMOD, ChangePropertiesConst.DEFAULT_CHMOD);
} catch (IOException e) {
log.error("Failed during overwriting {}", serviceName);
throw new DynamicChangePropertiesException(String.format("Failed during overwriting %s", serviceName));
}
}
private void changeCHMODE(String serviceName, String path, String fromMode, String toMode) throws IOException {
try {
String command = String.format(ChangePropertiesConst.CHANGE_CHMOD_SH_COMMAND_FORMAT, toMode, path);
log.info("Trying to change chmod for file {} {}->{}", serviceName, fromMode, toMode);
log.info("Execute command: {}", command);
Runtime.getRuntime().exec(command).waitFor();
} catch (InterruptedException e) {
log.error("Failed change chmod for file {} {}->{}", serviceName, fromMode, toMode);
}
}
private String addLicence() {
return ChangePropertiesConst.LICENCE;
}
private String checkAndReplaceSecretIfEmpty(String newPropFile, String oldProf) {
Map<String, String> emptySecrets = findEmptySecret(newPropFile);
return emptySecrets.isEmpty() ? newPropFile : replaceEmptySecret(newPropFile, oldProf, emptySecrets);
}
private String replaceEmptySecret(String newPropFile, String oldProf, Map<String, String> emptySecrets) {
String fileWithReplacedEmptySecrets = newPropFile;
Matcher oldProfMatcher = Pattern.compile(ChangePropertiesConst.SECRET_REGEX).matcher(oldProf);
while (oldProfMatcher.find()) {
String[] s = oldProfMatcher.group().split(":");
if (emptySecrets.containsKey(s[ChangePropertiesConst.DEFAULT_NAME_PLACE])) {
fileWithReplacedEmptySecrets = fileWithReplacedEmptySecrets.replace(emptySecrets.get(s[ChangePropertiesConst.DEFAULT_NAME_PLACE]), oldProfMatcher.group());
}
}
return fileWithReplacedEmptySecrets;
}
private Map<String, String> findEmptySecret(String newPropFile) {
Matcher newPropFileMatcher = Pattern.compile(ChangePropertiesConst.SECRET_REGEX).matcher(newPropFile);
Map<String, String> emptySecrets = new HashMap<>();
while (newPropFileMatcher.find()) {
String[] s = newPropFileMatcher.group().split(":");
if (s[ChangePropertiesConst.DEFAULT_VALUE_PLACE].equals(ChangePropertiesConst.SECRET_REPLACEMENT_FORMAT)) {
emptySecrets.put(s[ChangePropertiesConst.DEFAULT_NAME_PLACE], newPropFileMatcher.group());
}
}
return emptySecrets;
}
public void restartForExternalForGKE(UserInfo userInfo, RestartForm restartForm) {
throw new NotImplementedException();
}
}