blob: 67f75b44a00bea7ee19c9365dcdf9a8244d6b67a [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.epam.datalab.properties;
import com.epam.datalab.exceptions.DynamicChangePropertiesException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
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 ChangePropertiesService {
public String readFileAsString(String selfServicePropPath, String serviceName) {
try {
log.info("Trying to read {}, file from path {} :", serviceName, 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));
}
}
public void writeFileFromString(String newPropFile, String serviceName, String servicePath) {
String oldFile = readFile(serviceName, servicePath);
try (BufferedWriter writer = new BufferedWriter(new FileWriter(servicePath))) {
try {
changeCHMODE(serviceName, servicePath, ChangePropertiesConst.DEFAULT_CHMOD, ChangePropertiesConst.WRITE_CHMOD);
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 (Exception e) {
log.error("Failed during overwriting {}", serviceName);
writer.write(oldFile);
throw new DynamicChangePropertiesException(String.format("Failed during overwriting %s", serviceName));
}
} catch (IOException e) {
log.error("Failed to create writer with path {}", servicePath);
throw new DynamicChangePropertiesException(String.format("Failed during overwriting %s", serviceName));
}
}
private String readFile(String serviceName, String servicePath) {
String oldFile;
try {
oldFile = FileUtils.readFileToString(new File(servicePath), Charset.defaultCharset());
} catch (IOException e) {
log.error("Failed to read with path {}", servicePath);
throw new DynamicChangePropertiesException(String.format("Failed during overwriting %s", serviceName));
}
return oldFile;
}
public RestartAnswer 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();
return RestartAnswer.builder()
.billingSuccess(billing)
.provservSuccess(provserv)
.endpoint(restartForm.getEndpoint())
.build();
} catch (IOException | InterruptedException e) {
log.error(e.getMessage());
return RestartAnswer.builder()
.billingSuccess(false)
.provservSuccess(false)
.endpoint(restartForm.getEndpoint())
.build();
}
}
private String hideSecretsAndRemoveLicence(String currentConf) {
Matcher passMatcher = Pattern.compile(ChangePropertiesConst.SECRET_REGEX).matcher(currentConf);
Matcher userMatcher = Pattern.compile(ChangePropertiesConst.USER_REGEX).matcher(currentConf);
List<String> secretsAndUsers = new ArrayList<>();
String confWithReplacedSecretConf = removeLicence(currentConf);
while (passMatcher.find()) {
String secret = passMatcher.group().split(":")[ChangePropertiesConst.DEFAULT_VALUE_PLACE];
if (!(secret.isEmpty() || secret.trim().isEmpty()))
secretsAndUsers.add(secret);
}
while (userMatcher.find()) {
String user = userMatcher.group().split(":")[ChangePropertiesConst.DEFAULT_VALUE_PLACE];
if (!(user.isEmpty() || user.trim().isEmpty()))
secretsAndUsers.add(user);
}
for (String secretOrUser : secretsAndUsers) {
int start = confWithReplacedSecretConf.indexOf(secretOrUser);
int end = confWithReplacedSecretConf.indexOf("\n", start) - 1;
boolean isTure;
try {
String s = confWithReplacedSecretConf.substring(start, end);
isTure = s.equals(secretOrUser);
} catch (StringIndexOutOfBoundsException e) {
isTure = true;
}
if (isTure)
confWithReplacedSecretConf = confWithReplacedSecretConf.replace(secretOrUser, 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 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> emptySecretsAndUserNames = findEmptySecretAndNames(newPropFile);
return emptySecretsAndUserNames.isEmpty() ? newPropFile : replaceEmptySecret(newPropFile, oldProf, emptySecretsAndUserNames);
}
private String replaceEmptySecret(String newPropFile, String oldProf, Map<String, String> emptySecrets) {
String fileWithReplacedEmptySecrets = newPropFile;
Matcher oldPassMatcher = Pattern.compile(ChangePropertiesConst.SECRET_REGEX).matcher(oldProf);
Matcher oldUserMatcher = Pattern.compile(ChangePropertiesConst.USER_REGEX).matcher(oldProf);
while (oldPassMatcher.find()) {
String[] s = oldPassMatcher.group().split(":");
if (emptySecrets.containsKey(s[ChangePropertiesConst.DEFAULT_NAME_PLACE])) {
fileWithReplacedEmptySecrets = fileWithReplacedEmptySecrets.replace(emptySecrets.get(s[ChangePropertiesConst.DEFAULT_NAME_PLACE]), oldPassMatcher.group());
}
}
while (oldUserMatcher.find()) {
String[] s = oldUserMatcher.group().split(":");
if (emptySecrets.containsKey(s[ChangePropertiesConst.DEFAULT_NAME_PLACE])) {
fileWithReplacedEmptySecrets = fileWithReplacedEmptySecrets.replace(emptySecrets.get(s[ChangePropertiesConst.DEFAULT_NAME_PLACE]), oldUserMatcher.group());
}
}
return fileWithReplacedEmptySecrets;
}
private Map<String, String> findEmptySecretAndNames(String newPropFile) {
Matcher passMatcher = Pattern.compile(ChangePropertiesConst.SECRET_REGEX).matcher(newPropFile);
Matcher userNameMatcher = Pattern.compile(ChangePropertiesConst.USER_REGEX).matcher(newPropFile);
Map<String, String> emptySecrets = new HashMap<>();
while (passMatcher.find()) {
String[] s = passMatcher.group().split(":");
if (s[ChangePropertiesConst.DEFAULT_VALUE_PLACE].equals(ChangePropertiesConst.SECRET_REPLACEMENT_FORMAT)) {
emptySecrets.put(s[ChangePropertiesConst.DEFAULT_NAME_PLACE], passMatcher.group());
}
}
while (userNameMatcher.find()) {
String[] s = userNameMatcher.group().split(":");
if (s[ChangePropertiesConst.DEFAULT_VALUE_PLACE].equals(ChangePropertiesConst.SECRET_REPLACEMENT_FORMAT)) {
emptySecrets.put(s[ChangePropertiesConst.DEFAULT_NAME_PLACE], userNameMatcher.group());
}
}
return emptySecrets;
}
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();
}
}