diff --git a/node-scripts/spec/pipeline3/impl/dockerComposeGeneric.spec.js b/node-scripts/spec/pipeline3/impl/dockerComposeGeneric.spec.js index 55de229..707974a 100644 --- a/node-scripts/spec/pipeline3/impl/dockerComposeGeneric.spec.js +++ b/node-scripts/spec/pipeline3/impl/dockerComposeGeneric.spec.js @@ -125,13 +125,7 @@ describe("Docker Compose Generic Deployment implementation", function() { scripts.remote( instanceDef.deployment.host.value, "cd " + - path - .resolve( - instanceDef.deployment.hostDir, - instanceDef.name, - "docker_compose" - ) - .toString() + + path.resolve(instanceDef.deployment.workDir).toString() + " && docker compose -p " + instanceDef.name + " -f docker-compose.yml -f docker-compose-2.yml " + @@ -146,9 +140,9 @@ describe("Docker Compose Generic Deployment implementation", function() { .resolve(instanceDef.deployment.hostDir, instanceDef.name) .toString() ); - - // expect( - // dockerCompose.hostPreparation.getDeploymentScript(instanceDef) - // ).toEqual(expected); + let generated = dockerCompose.hostPreparation.getDeploymentScript( + instanceDef + ); + expect(generated).toEqual(expected); }); }); diff --git a/node-scripts/spec/pipeline3/impl/dockerComposeGenericRegacy.spec.js b/node-scripts/spec/pipeline3/impl/dockerComposeGenericRegacy.spec.js new file mode 100644 index 0000000..695ac4f --- /dev/null +++ b/node-scripts/spec/pipeline3/impl/dockerComposeGenericRegacy.spec.js @@ -0,0 +1,192 @@ +"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/dockerComposeGeneric" + )); + + 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: "dockerComposeGenericMaven", + composePlugin: true, + dockerComposeFiles: ["docker-compose.yml", "docker-compose-2.yml"], + envFiles: ["env-file-1", "env-file-2"], + value: { + mavenProject: { + version: "1.0.0-SNAPSHOT", + artifactId: "bahmni-docker-compose", + groupId: "net.mekomsolutions", + packaging: "zip" + }, + 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 + ); + expected += scripts.fetchArtifact( + instanceDef.deployment.value.mavenProject, + "maven", + config.getCDDockerDirPath(instanceDef.uuid), + null + ); + let generated = dockerCompose.preHostPreparation.getDeploymentScript( + instanceDef + ); + expect(generated).toEqual(expected); + }); + + it("should generate Host Preparation deployment script", () => { + var expected = ""; + expected += scripts.rsync( + { ...instanceDef.deployment.host.value, ...{ remoteDst: true } }, + config.getCDDockerDirPath(instanceDef.uuid), + path.resolve( + instanceDef.deployment.hostDir, + instanceDef.name, + "docker_compose" + ), + true, + null, + "-avzz --delete" + ); + + expected += + scripts.remote( + instanceDef.deployment.host.value, + scripts.writeProperty( + "TIMEZONE", + instanceDef.deployment.timezone, + path + .resolve( + instanceDef.deployment.hostDir, + instanceDef.name, + "docker_compose", + ".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.hostDir, + instanceDef.name, + "docker_compose" + ) + .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=" + + path + .resolve( + instanceDef.deployment.hostDir, + instanceDef.name, + instanceDef.name + ".env" + ) + .toString() + + " build --pull proxy openmrs mysql" + + "\n" + ) + + scripts.remote( + instanceDef.deployment.host.value, + "cd " + + path + .resolve( + instanceDef.deployment.hostDir, + instanceDef.name, + "docker_compose" + ) + .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=" + + path + .resolve( + instanceDef.deployment.hostDir, + instanceDef.name, + instanceDef.name + ".env" + ) + .toString() + + " 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); + }); +}); diff --git a/node-scripts/src/instance-event/validator.js b/node-scripts/src/instance-event/validator.js index 5d90062..fe86b15 100644 --- a/node-scripts/src/instance-event/validator.js +++ b/node-scripts/src/instance-event/validator.js @@ -250,7 +250,7 @@ module.exports = { }, validateDockerComposeGenericDeploymentConfigValue: function(value) { if ( - JSON.stringify(Object.keys(value).sort()) !== + JSON.stringify(Object.keys(value).sort()) >= JSON.stringify( Object.keys(new model.DockerComposeGenericDeployment()).sort() ) diff --git a/node-scripts/src/pipeline3/impl/dockerComposeGeneric.js b/node-scripts/src/pipeline3/impl/dockerComposeGeneric.js index e69a55f..691a7a2 100644 --- a/node-scripts/src/pipeline3/impl/dockerComposeGeneric.js +++ b/node-scripts/src/pipeline3/impl/dockerComposeGeneric.js @@ -8,7 +8,7 @@ const scripts = require("../scripts"); const config = require(cst.CONFIGPATH); const heredoc_2 = cst.HEREDOC_2; -const cdScript = function (instanceDef, sudo) { +const cdScript = function(instanceDef, sudo) { let path = require("path"); let workDir = path .resolve(instanceDef.deployment.hostDir, instanceDef.name, "docker_compose") @@ -25,7 +25,7 @@ const cdScript = function (instanceDef, sudo) { return script; }; -const composeExec = function (composePlugin) { +const composeExec = function(composePlugin) { let exec = "docker-compose"; if (composePlugin) { exec = "docker compose"; @@ -33,7 +33,7 @@ const composeExec = function (composePlugin) { return exec; }; -const combineComposeFiles = function (composeFiles = []) { +const combineComposeFiles = function(composeFiles = []) { let dockerComposeFiles = " "; for (const composeFile of composeFiles) { dockerComposeFiles = dockerComposeFiles + `-f ${composeFile} `; @@ -41,7 +41,19 @@ const combineComposeFiles = function (composeFiles = []) { return dockerComposeFiles; }; -const combineEnvFiles = function (instanceDef = {}) { +const combineEnvFiles = function(instanceDef = {}) { + let defaultEnvDir = path + .resolve( + instanceDef.deployment.hostDir, + instanceDef.name, + instanceDef.name + ".env" + ) + .toString(); + if (instanceDef.deployment.workDir) { + defaultEnvDir = path + .resolve(instanceDef.deployment.workDir, instanceDef.name + ".env") + .toString(); + } let files = " "; if ( instanceDef && @@ -52,15 +64,7 @@ const combineEnvFiles = function (instanceDef = {}) { files = files + `--env-file=${envFile} `; } } - files + - "--env-file=" + - path - .resolve( - instanceDef.deployment.workDir, - instanceDef.name, - instanceDef.name + ".env" - ) - .toString(); + files = files + "--env-file=" + defaultEnvDir; return files; }; @@ -70,7 +74,7 @@ const combineEnvFiles = function (instanceDef = {}) { */ module.exports = { preHostPreparation: { - getDeploymentScript: function (instanceDef) { + getDeploymentScript: function(instanceDef) { // Retrieve the Docker Compose project const mavenProject = instanceDef.deployment.value.mavenProject; const dockerDirPath = path.resolve( @@ -88,17 +92,17 @@ module.exports = { } return script; }, - getDataScript: function (instanceDef) { + getDataScript: function(instanceDef) { let script = ""; return script; }, - getArtifactsScript: function (instanceDef) { + getArtifactsScript: function(instanceDef) { return ""; } }, hostPreparation: { - getDeploymentScript: function (instanceDef) { + getDeploymentScript: function(instanceDef) { const scripts = require("../scripts"); let script = ""; @@ -119,8 +123,10 @@ module.exports = { if (instanceDef.deployment.workDir) { workDir = instanceDef.deployment.workDir; } - - if (instanceDef.deployment.mavenProject) { + if ( + instanceDef.deployment.value && + instanceDef.deployment.value.mavenProject + ) { script += scripts.rsync( { ...ssh, ...{ remoteDst: true } }, config.getCDDockerDirPath(instanceDef.uuid), @@ -137,7 +143,7 @@ module.exports = { scripts.writeProperty( "TIMEZONE", instanceDef.deployment.timezone, - path.resolve(instanceDef.deployment.workDir, ".env").toString() + path.resolve(workDir, ".env").toString() ) ); } @@ -153,49 +159,49 @@ module.exports = { script += scripts.remote( instanceDef.deployment.host.value, "cd " + - workDir + - " && " + - composeExec(instanceDef.deployment.composePlugin) + - " -p " + - instanceDef.name + - combineComposeFiles(instanceDef.deployment.dockerComposeFiles) + - combineEnvFiles(instanceDef) + - " build --pull" + - require("./dockerCompose").getInstanceServicesAsStringList( - instanceDef - ) + - "\n" + workDir + + " && " + + composeExec(instanceDef.deployment.composePlugin) + + " -p " + + instanceDef.name + + combineComposeFiles(instanceDef.deployment.dockerComposeFiles) + + combineEnvFiles(instanceDef) + + " build --pull" + + require("./dockerCompose").getInstanceServicesAsStringList( + instanceDef + ) + + "\n" ); // docker-compose pull script += scripts.remote( instanceDef.deployment.host.value, "cd " + - workDir + - " && " + - composeExec(instanceDef.deployment.composePlugin) + - " -p " + - instanceDef.name + - combineComposeFiles(instanceDef.deployment.dockerComposeFiles) + - combineEnvFiles(instanceDef) + - " pull" + - require("./dockerCompose").getInstanceServicesAsStringList( - instanceDef - ) + - "\n" + workDir + + " && " + + composeExec(instanceDef.deployment.composePlugin) + + " -p " + + instanceDef.name + + combineComposeFiles(instanceDef.deployment.dockerComposeFiles) + + combineEnvFiles(instanceDef) + + " pull" + + require("./dockerCompose").getInstanceServicesAsStringList( + instanceDef + ) + + "\n" ); script += scripts.remote( instanceDef.deployment.host.value, "sudo chown -R root:root " + - path - .resolve(instanceDef.deployment.hostDir, instanceDef.name) - .toString() + path + .resolve(instanceDef.deployment.hostDir, instanceDef.name) + .toString() ); return script; }, - getDataScript: function (instanceDef) { + getDataScript: function(instanceDef) { var script = ""; var ssh = instanceDef.deployment.host.value; let workDir = path @@ -208,13 +214,13 @@ module.exports = { if (instanceDef.deployment.workDir) { workDir = instanceDef.deployment.workDir; } - instanceDef.data.forEach(function (data) { + instanceDef.data.forEach(function(data) { var applyData = { - instance: function () { + instance: function() { // 'instance' type must be handled differently as it requires access to the 'db'. // therefore, the script is provided in the 'stage' script (host-prepation.js, start-instance.js...) }, - sqlDocker: function () { + sqlDocker: function() { let sql = data.value; let destFolder = path.resolve( instanceDef.deployment.hostDir, @@ -232,23 +238,23 @@ module.exports = { script += scripts.remote( ssh, "cd " + - workDir + - " && " + - composeExec(instanceDef.deployment.composePlugin) + - " -p " + - instanceDef.name + - combineComposeFiles(instanceDef.deployment.dockerComposeFiles) + - combineEnvFiles(instanceDef) + - " rm -vsf " + - sql.service + - " && " + - composeExec(instanceDef.deployment.composePlugin) + - " -p " + - instanceDef.name + - combineComposeFiles(instanceDef.deployment.dockerComposeFiles) + - combineEnvFiles(instanceDef) + - " up -d " + - sql.service + workDir + + " && " + + composeExec(instanceDef.deployment.composePlugin) + + " -p " + + instanceDef.name + + combineComposeFiles(instanceDef.deployment.dockerComposeFiles) + + combineEnvFiles(instanceDef) + + " rm -vsf " + + sql.service + + " && " + + composeExec(instanceDef.deployment.composePlugin) + + " -p " + + instanceDef.name + + combineComposeFiles(instanceDef.deployment.dockerComposeFiles) + + combineEnvFiles(instanceDef) + + " up -d " + + sql.service ); } }; @@ -256,12 +262,12 @@ module.exports = { }); return script; }, - getArtifactsScript: function (instanceDef) { + getArtifactsScript: function(instanceDef) { return ""; } }, startInstance: { - getDeploymentScript: function (instanceDef) { + getDeploymentScript: function(instanceDef) { let script = ""; let workDir = path .resolve( @@ -276,30 +282,30 @@ module.exports = { script += scripts.remote( instanceDef.deployment.host.value, "cd " + - workDir + - " && " + - composeExec(instanceDef.deployment.composePlugin) + - " -p " + - instanceDef.name + - combineComposeFiles(instanceDef.deployment.dockerComposeFiles) + - combineEnvFiles(instanceDef) + - " up -d" + - require("./dockerCompose").getInstanceServicesAsStringList( - instanceDef - ) + - "\n" + workDir + + " && " + + composeExec(instanceDef.deployment.composePlugin) + + " -p " + + instanceDef.name + + combineComposeFiles(instanceDef.deployment.dockerComposeFiles) + + combineEnvFiles(instanceDef) + + " up -d" + + require("./dockerCompose").getInstanceServicesAsStringList( + instanceDef + ) + + "\n" ); return script; }, - getDataScript: function (instanceDef) { + getDataScript: function(instanceDef) { return ""; }, - getArtifactsScript: function (instanceDef) { + getArtifactsScript: function(instanceDef) { return ""; } }, - ifExists: function () { }, - restart: function (instanceDef, sudo) { + ifExists: function() {}, + restart: function(instanceDef, sudo) { let script = ""; script += cdScript(instanceDef); script += @@ -312,7 +318,7 @@ module.exports = { return script + "\n"; }, - remove: function (instanceDef, sudo) { + remove: function(instanceDef, sudo) { let script = ""; script += cdScript(instanceDef); script += @@ -325,7 +331,7 @@ module.exports = { script += " down" + rmVolumes; return script + "\n"; }, - down: function (instanceDef, sudo) { + down: function(instanceDef, sudo) { let script = ""; script += cdScript(instanceDef, sudo); script += @@ -336,7 +342,7 @@ module.exports = { script += " down"; return script + "\n"; }, - pull: function () { }, + pull: function() {}, exec: (instanceDef, command, service) => { let script = ""; script += cdScript(instanceDef); @@ -356,7 +362,7 @@ module.exports = { return script + "\n"; }, - setProperties: function (instanceDef, property, output) { + setProperties: function(instanceDef, property, output) { let script = ""; let path = require("path"); let propPath = path @@ -371,33 +377,33 @@ module.exports = { script += require("../scripts").remote( instanceDef.deployment.host.value, "\n" + - "if [[ ! -e " + - propFilePath + - " ]]; then\n" + - "sudo mkdir -p " + - propPath + - "\n" + - "sudo touch " + - propFilePath + - "\n" + - "fi\n" + - "sudo bash -c 'cat > " + - propFilePath + - " < " + + propFilePath + + " < { script += " " + service.toString(); }); return script; }, - stop: function (instanceDef, sudo) { + stop: function(instanceDef, sudo) { let script = ""; script += cdScript(instanceDef); script += diff --git a/node-scripts/src/utils/model.js b/node-scripts/src/utils/model.js index 901817f..2768456 100644 --- a/node-scripts/src/utils/model.js +++ b/node-scripts/src/utils/model.js @@ -68,7 +68,7 @@ class DockerComposeMavenDeployment { } } class DockerComposeGenericMavenDeployment { - constructor(mavenProject, services) { + constructor(mavenProject, services, mavenUrl) { this.mavenProject = mavenProject; this.services = services; this.mavenUrl = this.mavenUrl;