Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(agama): add support for autoconfiguration #6210

Merged
merged 2 commits into from
Oct 9, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions docs/admin/developer/agama/projects-deployment.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@ Deployment occurs through a REST API. Here is a typical workflow once a `.gama`
1. Poll (via GET) the status of the deployment. When the archive has been effectively deployed a status of 200 should be obtained. It may take up to 30 seconds for the process to complete once the archive is sent. This time may extend if there is another deployment in course
1. Optionally supply configuration properties for flows if needed. This is done via PUT to the `/configs` endpoint. The response of the previous step may contain descriptive/sample configurations that can be used as a guide
1. Test the deployed flows and adjust the archive for any changes required
1. Go to point 1 if needed
1. Go to point 1 if needed. If configuration properties were previously set and no changes are required in this regard, step 3 can be skipped
1. If desired, a request can be sent to undeploy the flows (via DELETE)

The following tables summarize the available endpoints. All URLs are relative to `/jans-config-api/api/v1`. An OpenAPI document is also available [here](https://github.com/JanssenProject/jans/blob/main/jans-config-api/docs/jans-config-api-swagger.yaml#L110-L254).
The following tables summarize the available endpoints. All URLs are relative to `/jans-config-api/api/v1`. An OpenAPI document is also available [here](https://github.com/JanssenProject/jans/blob/main/jans-config-api/docs/jans-config-api-swagger.yaml#L177).


|Endpoint -> |`/agama-deployment`|
Expand Down Expand Up @@ -66,6 +66,7 @@ The following tables summarize the available endpoints. All URLs are relative to
|Method|POST|
|Path params|`name` (the project's name)|
|Body|The binary contents of a `.gama` file; example [here](#sample-file). Ensure to use header `Content-Type: application/zip`|
|Query params|`autoconfigure` - passing `true` will make this project be configured with the sample configurations found in the provided binary archive (`configs` section of [project.json](../../../agama/gama-format.md#metadata)). This param should rarely be passed: use only in controlled environments where the archive is not shared with third parties|
|Output|Textual explanation, e.g. `A deployment task for project XXX has been queued. Use the GET endpoint to poll status`|
|Status|202 (the task was created and scheduled for deployment), 409 (there is a task already for this project and it hasn't finished yet), 400 (a param is missing)|

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@
import java.io.IOException;
import java.nio.file.*;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.ArrayList;
import java.util.*;
import java.util.Base64.Decoder;
import java.util.Base64.Encoder;
Expand Down Expand Up @@ -100,10 +99,10 @@ public void process() throws IOException {
new String[]{ "jansId", "jansStartDate", "jansEndDate", "adsPrjDeplDetails" });

//Find the oldest, non-active entry without finish timestamp. Pick that one
Deployment deployment = depls.stream().filter(d -> d.getFinishedAt() == null)
Deployment dep = depls.stream().filter(d -> d.getFinishedAt() == null)
.min((d1, d2) -> d1.getCreatedAt().compareTo(d2.getCreatedAt())).orElse(null);

if (deployment == null) {
if (dep == null) {
updateFlowsAndAssets(depls);

//find deployments in course
Expand All @@ -113,13 +112,13 @@ public void process() throws IOException {
removeStaleDeployments(entryManager.findEntries(BASE_DN, Deployment.class, filter,
new String[]{ "jansId", "jansStartDate" }), System.currentTimeMillis());
} else {
deployProject(deployment.getDn(), deployment.getId(),
deployment.getDetails().getProjectMetadata().getProjectName());
deployProject(dep.getDn(), dep.getId(), dep.getDetails().isAutoconfigure(),
dep.getDetails().getProjectMetadata().getProjectName());
}

}

private void deployProject(String dn, String prjId, String name) throws IOException {
private void deployProject(String dn, String prjId, boolean autoconf, String name) throws IOException {

logger.info("Deploying project {}", name);
DeploymentDetails dd = new DeploymentDetails();
Expand Down Expand Up @@ -148,7 +147,7 @@ private void deployProject(String dn, String prjId, String name) throws IOExcept
try {
//craft a path so assets of different projects do not collide, see jans#4501
String prjBasepath = makeShortSafePath(prjId);
Set<String> flowIds = createFlows(pcode, dd, prjBasepath);
Set<String> flowIds = createFlows(pcode, dd, prjBasepath, autoconf);
if (dd.getError() == null) {
projectsFlows.put(prjId, flowIds);

Expand Down Expand Up @@ -203,7 +202,8 @@ private void deployProject(String dn, String prjId, String name) throws IOExcept

}

private Set<String> createFlows(Path dir, DeploymentDetails dd, String prjBasepath) throws IOException {
private Set<String> createFlows(Path dir, DeploymentDetails dd,
String prjBasepath, boolean autoconfigure) throws IOException {

BiPredicate<Path, BasicFileAttributes> matcher =
(path, attrs) -> attrs.isRegularFile() && path.getFileName().toString().endsWith("." + FLOW_EXT);
Expand All @@ -230,6 +230,8 @@ private Set<String> createFlows(Path dir, DeploymentDetails dd, String prjBasepa
ProjectMetadata prjMetadata = dd.getProjectMetadata();
List<String> noDirectLaunch = Optional.ofNullable(
prjMetadata.getNoDirectLaunchFlows()).orElse(Collections.emptyList());
Map<String, Map<String, Object>> configHints = Optional.ofNullable(
prjMetadata.getConfigHints()).orElse(Collections.emptyMap());

for (Path p: flowsPaths) {
String error = null;
Expand Down Expand Up @@ -271,7 +273,12 @@ private Set<String> createFlows(Path dir, DeploymentDetails dd, String prjBasepa
meta.setDescription(prvMeta.getDescription());
meta.setProperties(prvMeta.getProperties());
}


if (autoconfigure) {
logger.warn("Setting flow configuration as provided in project archive");
meta.setProperties(configHints.get(qname));
}

String compiled = tresult.getCode();
fl.setMetadata(meta);
fl.setSource(source);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,11 @@ public class DeploymentDetails {
private List<String> folders;
private List<String> libs;
private String error;
private boolean autoconfigure;
private ProjectMetadata metadata = new ProjectMetadata();

@JsonInclude(JsonInclude.Include.ALWAYS)
private Map<String, String> flowsError;

public ProjectMetadata getProjectMetadata() {
return metadata;
}

public void setProjectMetadata(ProjectMetadata metadata) {
this.metadata = metadata;
}

public List<String> getFolders() {
return folders;
Expand Down Expand Up @@ -57,4 +50,20 @@ public void setFlowsError(Map<String, String> flowsError) {
this.flowsError = flowsError;
}

public boolean isAutoconfigure() {
return autoconfigure;
}

public void setAutoconfigure(boolean autoconfigure) {
this.autoconfigure = autoconfigure;
}

public ProjectMetadata getProjectMetadata() {
return metadata;
}

public void setProjectMetadata(ProjectMetadata metadata) {
this.metadata = metadata;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ public class ProjectMetadata {

@JsonProperty("configs")
@JsonInclude(JsonInclude.Include.ALWAYS)
private Map<String, Object> configHints;
private Map<String, Map<String, Object>> configHints;

@JsonProperty("noDirectLaunch")
private List<String> noDirectLaunchFlows;
Expand Down Expand Up @@ -63,11 +63,11 @@ public void setVersion(String version) {
this.version = version;
}

public Map<String, Object> getConfigHints() {
public Map<String, Map<String, Object>> getConfigHints() {
return configHints;
}

public void setConfigHints(Map<String, Object> configHints) {
public void setConfigHints(Map<String, Map<String, Object>> configHints) {
this.configHints = configHints;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,13 +101,13 @@ public Response getDeployment(@Parameter(description = "Agama project name") @Pa
superScopes = { ApiAccessConstants.SUPER_ADMIN_WRITE_ACCESS })
@Path(ApiConstants.NAME_PARAM_PATH)
public Response deploy(@Parameter(description = "Agama project name") @PathParam(ApiConstants.NAME)
String projectName, byte[] gamaBinary) {
String projectName, @QueryParam("autoconfigure") String autoconfigure, byte[] gamaBinary) {

if (gamaBinary == null)
return Response.status(Response.Status.BAD_REQUEST)
.entity("Project name or binary data missing").build();
if (ads.createDeploymentTask(projectName, gamaBinary))

if (ads.createDeploymentTask(projectName, gamaBinary, Boolean.parseBoolean(autoconfigure)))
return Response.accepted().entity("A deployment task for project " + projectName +
" has been queued. Use the GET endpoint to poll status").build();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ public Deployment getDeployment(String name) {

}

public boolean createDeploymentTask(String name, byte[] gamaBinary) {
public boolean createDeploymentTask(String name, byte[] gamaBinary, boolean autoconfigure) {

Deployment d = null;
String id = idFromName(name);
Expand All @@ -75,7 +75,8 @@ public boolean createDeploymentTask(String name, byte[] gamaBinary) {
return false;
}

DeploymentDetails dd = new DeploymentDetails();
DeploymentDetails dd = new DeploymentDetails();
dd.setAutoconfigure(autoconfigure);
dd.getProjectMetadata().setProjectName(name);

if (!existing) {
Expand Down