Skip to content

Commit

Permalink
feat: create executor database functionality
Browse files Browse the repository at this point in the history
  • Loading branch information
Nolife999 committed Feb 9, 2024
1 parent 2f0473b commit 8caf4e0
Show file tree
Hide file tree
Showing 18 changed files with 581 additions and 231 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,7 @@ private Delimiters() {

public static final String SQL_TOKEN_DELIMITER = "_";
public static final String SQL_SCHEMA_DELIMITER = ".";


public static final String KUBERNETES_TOKEN_DELIMITER="-";

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package fr.insee.arc.core.service.kubernetes;

import java.util.ArrayList;
import java.util.List;

import fr.insee.arc.core.service.kubernetes.api.BuildRestQuery;
import fr.insee.arc.core.service.kubernetes.configuration.BuildJsonConfiguration;
import fr.insee.arc.core.service.kubernetes.security.BuildAccessToken;
import fr.insee.arc.utils.exception.ArcException;
import fr.insee.arc.utils.kubernetes.KubernetesService;
import fr.insee.arc.utils.kubernetes.bo.KubernetesServiceResult;

public class ApiManageExecutorDatabase {

private ApiManageExecutorDatabase() {
throw new IllegalStateException("Utility class");
}

public static List<KubernetesServiceResult> create() throws ArcException
{
List<KubernetesServiceResult> results = new ArrayList<>();

// create stateful set of executor databases
results.add(KubernetesService.execute(
BuildRestQuery.stateful().getUri(), //
BuildRestQuery.stateful().getHttpMethod(), //
BuildAccessToken.retrieve().getToken(), //
BuildJsonConfiguration.stateful()));

// create services

for (String serviceJsonConfiguration : BuildJsonConfiguration.services())
{
results.add(KubernetesService.execute(
BuildRestQuery.service().getUri(), //
BuildRestQuery.service().getHttpMethod(), //
BuildAccessToken.retrieve().getToken(), //
serviceJsonConfiguration));
}

return results;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package fr.insee.arc.core.service.kubernetes.api;

import org.springframework.http.HttpMethod;

import fr.insee.arc.core.service.kubernetes.bo.RestQuery;
import fr.insee.arc.utils.kubernetes.KubernetesService;
import fr.insee.arc.utils.ressourceUtils.PropertiesHandler;

public class BuildRestQuery {

private BuildRestQuery() {
throw new IllegalStateException("Utility class");
}

private static PropertiesHandler properties = PropertiesHandler.getInstance();

public static RestQuery stateful() {
return new RestQuery() //
.setUri(properties.getKubernetesApiUri() + "/apis/apps/v1/namespaces/"
+ properties.getKubernetesApiNamespace() + "/statefulsets")
.setHttpMethod(HttpMethod.POST);
}

public static RestQuery service() {
return new RestQuery() //
.setUri(properties.getKubernetesApiUri() + "/api/v1/namespaces/"
+ properties.getKubernetesApiNamespace() + "/services")
.setHttpMethod(HttpMethod.POST);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package fr.insee.arc.core.service.kubernetes.bo;

public class AccessToken {

public AccessToken(String token) {
super();
this.token = token;
}

private String token;

public String getToken() {
return token;
}


}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package fr.insee.arc.core.service.kubernetes.bo;

/**
* class that map the parameter placeholders found in kubernetes the json
* configuration files located at src/main/resources/kubernetes
*
* @author FY2QEQ
*
*/
public class JsonFileParameter {

private JsonFileParameter() {
throw new IllegalStateException("Utility class");
}

public static final String EXECUTOR_LABEL = "{pg-arc-executor-label}";
public static final String EXECUTOR_NUMBER = "{pg-arc-executor-number}";
public static final String EXECUTOR_PASSWORD = "{password}";

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package fr.insee.arc.core.service.kubernetes.bo;

import org.springframework.http.HttpMethod;

public class RestQuery {

private String uri;

private HttpMethod httpMethod;

public String getUri() {
return uri;
}

public HttpMethod getHttpMethod() {
return httpMethod;
}

public RestQuery setUri(String uri) {
this.uri = uri;
return this;
}

public RestQuery setHttpMethod(HttpMethod httpMethod) {
this.httpMethod = httpMethod;
return this;
}



}
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
package fr.insee.arc.core.service.kubernetes.configuration;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.io.IOUtils;

import fr.insee.arc.core.model.Delimiters;
import fr.insee.arc.core.service.kubernetes.bo.JsonFileParameter;
import fr.insee.arc.core.service.p0initialisation.ApiInitialisationService;
import fr.insee.arc.utils.exception.ArcException;
import fr.insee.arc.utils.exception.ArcExceptionMessage;
import fr.insee.arc.utils.ressourceUtils.PropertiesHandler;

public class BuildJsonConfiguration {

private BuildJsonConfiguration() {
throw new IllegalStateException("Utility class");
}

private static PropertiesHandler properties = PropertiesHandler.getInstance();


/**
* Create the json configuration to create <ExecutorNumber> replica of stateful databases
* @return
* @throws ArcException
*/
public static String stateful() throws ArcException
{
return readConfiguration("kubernetes/executorDatabaseStatefulTemplate.json"
, JsonFileParameter.EXECUTOR_LABEL, properties.getKubernetesExecutorLabel() //
, JsonFileParameter.EXECUTOR_NUMBER, String.valueOf(properties.getKubernetesExecutorNumber()) //
, JsonFileParameter.EXECUTOR_PASSWORD, properties.getDatabasePassword() //
)
;
}

/**
* Create a set of json configuration for the set of services
* One service per replica
* @return
* @throws ArcException
*/
public static List<String> services() throws ArcException
{
List<String> servicesLayers = new ArrayList<>();

for (int i=0; i< properties.getKubernetesExecutorNumber(); i++)
{
servicesLayers.add(service(i));
}
return servicesLayers;
}


/**
* Create the json configuration for the service matching the given executor replica index
* @param executorReplicaIndex
* @return
* @throws ArcException
*/
private static String service(int executorReplicaIndex) throws ArcException
{
PropertiesHandler properties = PropertiesHandler.getInstance();
return readConfiguration("kubernetes/executorDatabaseServiceTemplate.json"
, JsonFileParameter.EXECUTOR_LABEL, String.join(Delimiters.KUBERNETES_TOKEN_DELIMITER, properties.getKubernetesExecutorLabel(), String.valueOf(executorReplicaIndex)) //
)
;
}


private static String readConfiguration(String kubernetesConfigurationFileName, String...keyvalue) throws ArcException
{
String resource;
try {
resource = IOUtils.toString(
ApiInitialisationService.class.getClassLoader().getResourceAsStream(kubernetesConfigurationFileName),
StandardCharsets.UTF_8);
} catch (IOException e) {
throw new ArcException(ArcExceptionMessage.FILE_READ_FAILED, kubernetesConfigurationFileName);
}

for (int i=0;i<keyvalue.length;i=i+2)
{
resource = resource.replace(keyvalue[i], keyvalue[i+1]);
}

return resource;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package fr.insee.arc.core.service.kubernetes.security;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;

import fr.insee.arc.core.service.kubernetes.bo.AccessToken;
import fr.insee.arc.utils.exception.ArcException;
import fr.insee.arc.utils.exception.ArcExceptionMessage;
import fr.insee.arc.utils.ressourceUtils.PropertiesHandler;

public class BuildAccessToken {

private BuildAccessToken() {
throw new IllegalStateException("Utility class");
}

/**
* Retrieve token from pod. If fails, use token set in properties
* @return
* @throws ArcException
*/
public static AccessToken retrieve() throws ArcException
{
PropertiesHandler properties = PropertiesHandler.getInstance();

// token can be retrieve in pod
// kubectl exec <pod_name> -t cat /var/run/secrets/kubernetes.io/serviceaccount/token
String token;
try {
token = new String(Files.readAllBytes(Paths.get(properties.getKubernetesApiTokenPath())),
StandardCharsets.UTF_8);
} catch (IOException e) {
token = properties.getKubernetesApiTokenValue();
}

if (token==null) {
throw new ArcException(ArcExceptionMessage.ACCESS_TOKEN_NOT_EXIST);
}

return new AccessToken(token);

}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"apiVersion": "v1",
"kind": "Service",
"metadata": {
"name": "{pg-arc-executor-label}",
"labels": {
"app": "{pg-arc-executor-label}"
}
},
"spec": {
"type": "ClusterIP",
"ports": [
{
"port": 5432
}
],
"selector": {
"app": "{pg-arc-executor-label}"
}
}
}
Loading

0 comments on commit 8caf4e0

Please sign in to comment.