Skip to content

Commit

Permalink
Merge pull request #3751 from kalaiyarasiganeshalingam/master
Browse files Browse the repository at this point in the history
Deploy configurations
  • Loading branch information
kalaiyarasiganeshalingam authored Dec 3, 2024
2 parents d2205d7 + b7692ee commit 7671dd3
Show file tree
Hide file tree
Showing 30 changed files with 1,235 additions and 5 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ typings/
# dotenv environment variables file
.env
.env.test
!test.env

# parcel-bundler cache (https://parceljs.org/)
.cache
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -387,6 +387,21 @@ public String getMessageString() {
public void setMessageFlowTracingState(int tracingState){
}

@Override
public Object getVariable(String s) {
return null;
}

@Override
public void setVariable(String s, Object o) {
//
}

@Override
public Set getVariableKeySet() {
return null;
}

public int getMessageFlowTracingState(){
return SynapseConstants.TRACING_OFF;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
import org.wso2.micro.integrator.initializer.StartupFinalizer;
import org.wso2.micro.integrator.initializer.dashboard.HeartBeatComponent;
import org.wso2.micro.integrator.initializer.deployment.application.deployer.CappDeployer;
import org.wso2.micro.integrator.initializer.deployment.config.deployer.ConfigDeployer;
import org.wso2.micro.integrator.initializer.deployment.synapse.deployer.FileRegistryResourceDeployer;
import org.wso2.micro.integrator.initializer.deployment.synapse.deployer.SynapseAppDeployer;
import org.wso2.micro.integrator.initializer.deployment.user.store.deployer.UserStoreDeployer;
Expand Down Expand Up @@ -169,6 +170,7 @@ private void addCAppDeployer(DeploymentEngine deploymentEngine) {
cappDeployer.init(configCtx);

// Register application deployment handlers
cappDeployer.registerDeploymentHandler(new ConfigDeployer());
cappDeployer.registerDeploymentHandler(new FileRegistryResourceDeployer(
synapseEnvironmentService.getSynapseEnvironment().getSynapseConfiguration().getRegistry()));
cappDeployer.registerDeploymentHandler(new DataSourceCappDeployer());
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,259 @@
/*
* Copyright (c) 2024, WSO2 LLC. (https://www.wso2.com).
*
* WSO2 LLC. 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 org.wso2.micro.integrator.initializer.deployment.config.deployer;

import org.apache.axis2.deployment.DeploymentException;
import org.apache.axis2.engine.AxisConfiguration;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.synapse.commons.property.PropertyHolder;
import org.apache.synapse.transport.nhttp.config.SslSenderTrustStoreHolder;
import org.wso2.micro.application.deployer.CarbonApplication;
import org.wso2.micro.application.deployer.config.ApplicationConfiguration;
import org.wso2.micro.application.deployer.config.Artifact;
import org.wso2.micro.application.deployer.config.CappFile;
import org.wso2.micro.application.deployer.handler.AppDeploymentHandler;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Properties;

public class ConfigDeployer implements AppDeploymentHandler {

private static final Log log = LogFactory.getLog(ConfigDeployer.class);

private static final String PROPERTY_TYPE = "config/property";

private static final String LOCAL_CONFIG_FILE_NAME = "config.properties";
private static final String GLOBAL_CONFIG_FILE_NAME = "file.properties";
private Properties globalProperties;

public static final char URL_SEPARATOR_CHAR = '/';

public ConfigDeployer() {
}

@Override
public void deployArtifacts(CarbonApplication carbonApp, AxisConfiguration axisConfig)
throws DeploymentException {
if (log.isDebugEnabled()) {
log.debug("Deploying properties - " + carbonApp.getAppName());
}
ApplicationConfiguration appConfig = carbonApp.getAppConfig();
List<Artifact.Dependency> deps = appConfig.getApplicationArtifact().getDependencies();

List<Artifact> artifacts = new ArrayList<Artifact>();
for (Artifact.Dependency dep : deps) {
if (dep.getArtifact() != null) {
artifacts.add(dep.getArtifact());
}
}
deployConfigArtifacts(artifacts);
}

@Override
public void undeployArtifacts(CarbonApplication carbonApp, AxisConfiguration axisConfig)
throws DeploymentException {

}

private void deployConfigArtifacts(List<Artifact> artifacts) {
artifacts.stream().filter(artifact -> PROPERTY_TYPE.equals(artifact.getType())).forEach(artifact -> {
if (log.isDebugEnabled()) {
log.debug("Deploying config artifact: " + artifact.getName());
}
writePropertyToMap(artifact);
});
}

private void writePropertyToMap(Artifact artifact) {
// get the file path of the registry config file
List<CappFile> files = artifact.getFiles();
if (files.size() == 1) {
Path confFolder = Paths.get(getHome(), "conf");
Path globalPropertiesFilePath = confFolder.resolve(GLOBAL_CONFIG_FILE_NAME) ;
Path serverConfPropertyPath = confFolder.resolve(LOCAL_CONFIG_FILE_NAME);
String configFilePath = artifact.getExtractedPath() + File.separator + LOCAL_CONFIG_FILE_NAME;
processConfFile(artifact.getName(), configFilePath, globalPropertiesFilePath.toString(),
serverConfPropertyPath.toString());
} else {
log.error("config/property type must have a single file which declares " +
"config. But " + files.size() + " files found.");
}
}

private void processConfFile(String integrationName, String configFilePath, String globalPropertiesFilePath,
String serverConfPropertyPath) {
File configFile = new File(configFilePath);
// Load capp conf property file
Properties configProperties = loadPropertiesFromFile(configFile);
// Load global conf property file
this.globalProperties = loadPropertiesFromFile(new File(globalPropertiesFilePath));
// Load sever conf property file
Properties serverConfigProperties = loadPropertiesFromFile(new File(serverConfPropertyPath));

Properties newServerConfigProperties = new Properties();
if (serverConfigProperties.isEmpty() && configProperties.isEmpty() ) {
if (log.isDebugEnabled()) {
log.debug(String.format("No configuration is used in the integration[%s]", integrationName));
}
} else {
for (Map.Entry<Object, Object> entry : serverConfigProperties.entrySet()) {
String key = entry.getKey().toString();
String type = entry.getValue().toString();
if (configProperties.containsKey(key)) {
type = configProperties.getProperty(key);
configProperties.remove(key);
}
newServerConfigProperties.setProperty(key, type);
processConfigProperties(key, type);
}
for (Map.Entry<Object, Object> entry : configProperties.entrySet()) {
String key = entry.getKey().toString();
String type = entry.getValue().toString();
newServerConfigProperties.setProperty(key, type);
processConfigProperties(key, type);
}
writeServerConfFile(serverConfPropertyPath, newServerConfigProperties);
}
}

private void processConfigProperties(String key, String type) {
String value = getValueOfKey(key);
if (value != null) {
if (Objects.equals(type, "cert")) {
deployCert(key, value);
}
if (PropertyHolder.getInstance().hasKey(key)) {
String oldValue = PropertyHolder.getInstance().getPropertyValue(key);
if (!Objects.equals(oldValue, value)) {
log.info(String.format("The value of the key:[%s] has been " +
"replaced with the new value.", key));
}
}
PropertyHolder.getInstance().setProperty(key, value);
} else {
log.error(String.format("The value of the key:[%s] is not found.", key));
}
}

private void deployCert(String key, String path) {
// Load the truststore properties
char[] password = SslSenderTrustStoreHolder.getInstance().getPassword().toCharArray();
String type = SslSenderTrustStoreHolder.getInstance().getType();
Path trustStorePath = Paths.get(getHome(), SslSenderTrustStoreHolder.getInstance().getLocation());
try (FileInputStream trustStoreStream = new FileInputStream(trustStorePath.toFile())) {
KeyStore trustStore = KeyStore.getInstance(type);
trustStore.load(trustStoreStream, password);
if (!trustStore.containsAlias(key)) {
// Load the certificate file
CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
try (FileInputStream certStream = new FileInputStream(path)) {
Certificate cert = certFactory.generateCertificate(certStream);
// Add the certificate to the truststore
trustStore.setCertificateEntry(key, cert);
log.info("Certificate added with alias: " + key);
}
// Save the truststore with the new certificate
try (FileOutputStream outputStream = new FileOutputStream(trustStorePath.toFile())) {
trustStore.store(outputStream, password);
log.info("Truststore updated successfully at: " + trustStorePath);
}
} else {
log.info(String.format("The trust store already contains a certificate " +
"with the alias [%s].", key));
}
} catch (FileNotFoundException e) {
log.error(String.format("File not found for importing the certificate: %s", key));
} catch (IOException e) {
log.error(String.format("Certificate import failed: %s", key));
} catch (CertificateException e) {
log.error(String.format("An error occurred while processing the certificate: %s", key));
} catch (KeyStoreException e) {
log.error(String.format("An error occurred while processing the truststore: %s", key));
} catch (NoSuchAlgorithmException e) {
log.error(String.format("An error occurred while loading the certificate: %s", key));
}
}

private void writeServerConfFile(String file, Properties newServerConfigProperties) {
try (FileWriter writer = new FileWriter(file)) {
Enumeration<?> propertyNames = newServerConfigProperties.propertyNames();
while (propertyNames.hasMoreElements()) {
String key = (String) propertyNames.nextElement();
String value = newServerConfigProperties.getProperty(key);
writer.write(key + ":" + value + "\n");
}
} catch (IOException e) {
log.error("Failed to add the config.properties file to the server conf folder: "
+ e.getMessage());
}
}

private Properties loadPropertiesFromFile(File file) {
Properties properties = new Properties();
if (file.exists()) {
try (FileInputStream serverConfigFileReader = new FileInputStream(file)) {
properties.load(serverConfigFileReader);
} catch (IOException e) {
log.error("Error occurred while loading properties from file:" + e.getMessage());
}
}
return properties;
}

private String getValueOfKey(String key) {
String value = System.getenv(key);
if (value == null) {
value = System.getProperty(key);
if (value == null) {
value = this.globalProperties.getProperty(key);
}
}
return value;
}

private String getHome() {
String carbonHome = System.getProperty("carbon.home");
if (carbonHome == null || "".equals(carbonHome) || ".".equals(carbonHome)) {
carbonHome = getSystemDependentPath(new File(".").getAbsolutePath());
}
return carbonHome;
}

private String getSystemDependentPath(String path) {
return path.replace(URL_SEPARATOR_CHAR, File.separatorChar);
}
}
40 changes: 40 additions & 0 deletions distribution/src/scripts/micro-integrator.bat
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,12 @@ if ""%1""==""car"" goto setCar
if ""%1""==""-car"" goto setCar
if ""%1""==""--car"" goto setCar

@REM Check if the argument starts with --env-file=
set "envfile=%~1"
if "!envfile:~0,11!"=="--env-file=" (
set "file_path=!envfile:~11!"
call :export_env_file "!file_path!"
)
shift
goto setupArgs

Expand Down Expand Up @@ -133,6 +139,40 @@ echo Stopping the Micro Integrator Server
taskkill /F /PID %processId%
goto end

:export_env_file
setlocal EnableDelayedExpansion

set "file_path=%~1"

REM Check if the file exists
if not exist "!file_path!" (
echo Error: File '!file_path!' not found.
exit /b 1
)

REM Read each line in the file
for /f "usebackq tokens=1,* delims==" %%A in ("!file_path!") do (
set "line=%%A"

REM Ignore lines that start with '#' (comments) or are empty
if not "!line!"=="" (
if "!line:~0,1!" neq "#" (
set "key=%%A"
set "value=%%B"

REM Trim surrounding whitespace from key and value
for /f "tokens=* delims= " %%i in ("!key!") do set "key=%%i"
for /f "tokens=* delims= " %%i in ("!value!") do set "value=%%i"

REM Set the environment variable
setx "!key!" "!value!" >nul
set "!key!=!value!"
)
)
)
echo Environment variables loaded from !file_path!.
exit /b 0

rem ----- commandLifecycle -----------------------------------------------------
:commandLifecycle
goto findJdk
Expand Down
Loading

0 comments on commit 7671dd3

Please sign in to comment.