Skip to content

Commit

Permalink
INFRA-427: Add a new deployment type to accommodate the new Ozone pac…
Browse files Browse the repository at this point in the history
…kaging (#42)

* INFRA-427: Add a new deployment type to accommodate the new Ozone packaging

* Allow cd to legacy docker compose folder

* Add legacy Spec

* Update review

* Remove debug

* Rename project type

* Update JS doc for DockerComposeFromArtifactDeployment

* Fix typo

---------

Co-authored-by: Romain Buisson <rbuisson@users.noreply.github.com>
  • Loading branch information
enyachoke and rbuisson committed Jan 25, 2024
1 parent 896ca15 commit e5534ca
Show file tree
Hide file tree
Showing 11 changed files with 583 additions and 24 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,7 @@ That is because the bulk of the logic of what OCD3 does lives here. Almost all J
This is how one would build the underlying Node JS scripts:
```bash
gradle node-scripts:build
./gradlew node-scripts:build
```
And this must be done before submitting code commits.
However note that the code base is not really built into anything since the container links directly to **/node-scripts**, but this formats the code and runs the test suite.
Expand All @@ -231,7 +231,7 @@ See [here](readme/docker/README.md).
OCD3 not only needs a Docker image for its binaries but also requires a 'Jenkins home' folder that provides a pre-configured Jenkins setup:

```bash
gradle jenkins:build
./gradlew jenkins:build
```
This will package a zip archive of the jenkins folder.

Expand Down
10 changes: 5 additions & 5 deletions docker/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,13 +1,9 @@
ARG VERSION=2.346.3
ARG VERSION=2.387.3
FROM jenkins/jenkins:$VERSION
MAINTAINER Mekom Solutions <support@mekomsolutions.com>

USER root

# Add the APP_DATA_DIR volume to keep OpenMRS CD data out of the Jenkins Home
ARG APP_DATA_DIR="/var/lib/openmrs_cd/app_data"
RUN mkdir -p $APP_DATA_DIR && chown -R jenkins:jenkins $APP_DATA_DIR

RUN apt update --fix-missing
RUN apt -y install nano jq openssh-server rsync libxml2-utils

Expand All @@ -22,6 +18,10 @@ RUN sudo apt install -y nodejs
# Jenkins needs to be a sudo to execute some build tasks (particularly Bahmni Apps)
RUN echo "jenkins ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers

# Add the APP_DATA_DIR volume to keep OpenMRS CD data out of the Jenkins Home
ARG APP_DATA_DIR="/var/lib/openmrs_cd/app_data"
RUN mkdir -p $APP_DATA_DIR && chown -R jenkins:jenkins $APP_DATA_DIR

# Provide access to the /usr/share/jenkins directory
RUN chown -R jenkins /usr/share/jenkins

Expand Down
8 changes: 7 additions & 1 deletion docker/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,13 @@ repositories {

def dockerHubRepo = "mekomsolutions/openmrscd"
def getShortCommit() {
return ['sh', '-c', 'git log -1 --format=%h'].execute().text.trim()
def stdout = new ByteArrayOutputStream()
exec {
commandLine 'git', 'rev-parse', '--short', 'HEAD'
standardOutput = stdout
}
return stdout.toString().trim()

}

task buildDockerImage(type: DockerBuildImage) {
Expand Down
4 changes: 2 additions & 2 deletions docker/config/plugins.txt
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
git:4.12.1
git:5.2.0
ansicolor:1.0.2
workflow-aggregator:590.v6a_d052e5a_a_b_5
nodejs:1.5.1
envinject:2.866.v5c0403e3d4df
conditional-buildstep:1.4.2
parameterized-trigger:2.45
build-name-setter:2.2.0
pipeline-build-step:2.18
pipeline-build-step:496.v2449a_9a_221f2
generic-webhook-trigger:1.84
matrix-auth:3.1.5
pipeline-utility-steps:2.13.0
Expand Down
2 changes: 1 addition & 1 deletion jenkins/jenkins_home/config.xml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<?xml version='1.1' encoding='UTF-8'?>
<hudson>
<disabledAdministrativeMonitors/>
<version>2.346.2</version>
<version>2.387.3</version>
<numExecutors>2</numExecutors>
<mode>NORMAL</mode>
<useSecurity>true</useSecurity>
Expand Down
138 changes: 138 additions & 0 deletions node-scripts/spec/pipeline3/impl/dockerComposeFromArtifact.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
"use strict";

describe("Docker Compose Generic Deployment implementation", function() {
// deps
const path = require("path");
const config = require(path.resolve("src/utils/config"));
const cst = require(path.resolve("src/const"));
const dockerCompose = require(path.resolve(
"src/pipeline3/impl/dockerComposeFromArtifact"
));

const scripts = require(path.resolve(
"src/" + config.getJobNameForPipeline3() + "/scripts"
));

var instanceDef = {
uuid: "336af1ee-90a1-4d1b-baaf-db12c84deec0",
name: "cambodia1",
type: "dev",
group: "tlc",
deployment: {
hostDir: "/var/docker-volumes/",
type: "dockerComposeFromArtifact",
composePlugin: true,
dockerComposeFiles: ["docker-compose.yml", "docker-compose-2.yml"],
envFiles: ["env-file-1", "env-file-2"],
value: {
projectPath: "/var/docker-volumes/artifacts/run/docker",
services: ["proxy", "openmrs", "mysql"]
},
timezone: "Europe/Amsterdam",
host: {
type: "ssh",
value: {
ip: "hsc-dev.mekomsolutions.net",
user: "mekom",
port: "22"
}
}
},
data: [
{
type: "sqlDocker",
value: {
service: "mysql",
sourceFile: "/var/instance-data/sql-script.sql"
}
}
]
};
it("should use the correct compose command if composePlugin is set to true", () => {
var expected = "docker compose";
expect(dockerCompose.composeExec(true)).toEqual(expected);
});

it("should use the correct compose command if composePlugin is set to false", () => {
var expected = "docker-compose";
expect(dockerCompose.composeExec(false)).toEqual(expected);
});

it("should generate the correct compose command given multiple docker compose files", () => {
var expected = " -f docker-compose.yml -f docker-compose-2.yml ";
expect(
dockerCompose.combineComposeFiles(
instanceDef.deployment.dockerComposeFiles
)
).toEqual(expected);
});
it("should generate Pre-Host Preparation deployment script", () => {
var expected = "";
expected += scripts.initFolder(
config.getCDDockerDirPath(instanceDef.uuid),
"jenkins",
"jenkins",
true
);

expect(
dockerCompose.preHostPreparation.getDeploymentScript(instanceDef)
).toEqual(expected);
});

it("should generate Host Preparation deployment script", () => {
var expected = "";

expected +=
scripts.remote(
instanceDef.deployment.host.value,
scripts.writeProperty(
"TIMEZONE",
instanceDef.deployment.timezone,
path
.resolve(instanceDef.deployment.value.projectPath, ".env")
.toString()
)
) + "\n";

expected +=
scripts.remote(
instanceDef.deployment.host.value,
scripts.createEnvVarFileDockerGeneric(instanceDef)
) +
"\n" +
scripts.remote(
instanceDef.deployment.host.value,
"cd " +
path.resolve(instanceDef.deployment.value.projectPath).toString() +
" && docker compose -p " +
instanceDef.name +
" -f docker-compose.yml -f docker-compose-2.yml " +
" --env-file=env-file-1 --env-file=env-file-2 --env-file=/var/docker-volumes/artifacts/run/docker/cambodia1.env" +
" build --pull proxy openmrs mysql" +
"\n"
) +
scripts.remote(
instanceDef.deployment.host.value,
"cd " +
path.resolve(instanceDef.deployment.value.projectPath).toString() +
" && docker compose -p " +
instanceDef.name +
" -f docker-compose.yml -f docker-compose-2.yml " +
" --env-file=env-file-1 --env-file=env-file-2 --env-file=/var/docker-volumes/artifacts/run/docker/cambodia1.env" +
" pull proxy openmrs mysql" +
"\n"
) +
scripts.remote(
instanceDef.deployment.host.value,
"sudo chown -R root:root " +
path
.resolve(instanceDef.deployment.hostDir, instanceDef.name)
.toString()
);
let generated = dockerCompose.hostPreparation.getDeploymentScript(
instanceDef
);
expect(generated).toEqual(expected);
});
});
20 changes: 17 additions & 3 deletions node-scripts/src/instance-event/validator.js
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,6 @@ module.exports = {
} else if (deployment.hostDir === "") {
throw new Error("The 'host dir' is not specified.");
}

// validating the actual config based on its type
module.exports
.getConfigValidatorsMap()
Expand Down Expand Up @@ -248,6 +247,18 @@ module.exports = {
);
}
},
validateDockerComposeFromArtifactDeploymentConfigValue: function(value) {
if (
JSON.stringify(Object.keys(value).sort()) >=
JSON.stringify(
Object.keys(new model.DockerComposeFromArtifactDeployment()).sort()
)
) {
throw new Error(
"The Docker compose deployment value should be provided as an instance of 'DockerComposeFromArtifactDeployment'."
);
}
},
validateFileTLSDeploymentConfigValue: function(value) {
if (
JSON.stringify(Object.keys(value).sort()) !==
Expand Down Expand Up @@ -306,8 +317,9 @@ module.exports = {
);
}
} else if (element.type === "sqlDocker") {
// Since we just check the number of keys we can loosen the check to just if the keys are more than the model
if (
JSON.stringify(Object.keys(element.value).sort()) !==
JSON.stringify(Object.keys(element.value).sort()) >=
JSON.stringify(Object.keys(new model.SqlDocker()).sort())
) {
throw new Error(
Expand Down Expand Up @@ -369,7 +381,9 @@ module.exports = {
dockerComposeMaven:
module.exports.validateDockerComposeMavenDeploymentConfigValue,
dockerComposeGenericMaven:
module.exports.validateDockerComposeGenericMavenDeploymentConfigValue
module.exports.validateDockerComposeGenericMavenDeploymentConfigValue,
dockerComposeFromArtifact:
module.exports.validateDockerComposeFromArtifactDeploymentConfigValue
};
}
};
Loading

0 comments on commit e5534ca

Please sign in to comment.