diff --git a/jdl/jhipster/deployment-options.js b/jdl/jhipster/deployment-options.js index b73eb74515c..67f680547bf 100644 --- a/jdl/jhipster/deployment-options.js +++ b/jdl/jhipster/deployment-options.js @@ -16,8 +16,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -const _ = require('lodash'); - const DeploymentTypes = { DOCKERCOMPOSE: 'docker-compose', KUBERNETES: 'kubernetes', @@ -25,73 +23,118 @@ const DeploymentTypes = { exists: deploymentType => !!deploymentType && !!DeploymentTypes[deploymentType.toUpperCase().replace('-', '')], }; -const Options = { - deploymentType: { - dockerCompose: DeploymentTypes.DOCKERCOMPOSE, - rancherCompose: DeploymentTypes.RANCHERCOMPOSE, - kubernetes: DeploymentTypes.KUBERNETES, - openshift: DeploymentTypes.OPENSHIFT, - }, - gatewayType: { - springCloudGateway: 'SpringCloudGateway', - }, - monitoring: { - no: 'no', - prometheus: 'prometheus', - }, - directoryPath: '../', - appsFolders: [], - clusteredDbApps: [], - // adminPassword: 'admin', - serviceDiscoveryType: { - eureka: 'eureka', - consul: 'consul', - no: 'no', - }, - dockerRepositoryName: '', - dockerPushCommand: 'docker push', - // Kubernetes specific +const kubernetesRelatedOptions = { kubernetesNamespace: 'default', kubernetesServiceType: { loadBalancer: 'LoadBalancer', nodePort: 'NodePort', ingress: 'Ingress', }, + kubernetesStorageClassName: '', + kubernetesUseDynamicStorage: { + false: false, + true: true, + }, ingressDomain: '', + ingressType: { + nginx: 'nginx', + gke: 'gke', + }, istio: { false: false, true: true, }, - // openshift specific +}; + +const openshiftRelatedOptions = { openshiftNamespace: 'default', + registryReplicas: { + two: 2, + }, storageType: { ephemeral: 'ephemeral', persistent: 'persistent', }, }; -Options.defaults = (deploymentType = Options.deploymentType.dockerCompose) => - _.omitBy( - { - deploymentType, - gatewayType: Options.gatewayType.springCloudGateway, - monitoring: Options.monitoring.no, - directoryPath: Options.directoryPath, +const dockerComposeRelatedOptions = { + gatewayType: { + springCloudGateway: 'SpringCloudGateway', + }, +}; + +const baseOptions = { + appsFolders: [], + clusteredDbApps: [], + directoryPath: '../', + monitoring: { + no: 'no', + prometheus: 'prometheus', + }, + serviceDiscoveryType: { + eureka: 'eureka', + consul: 'consul', + no: 'no', + }, +}; + +const Options = { + ...baseOptions, + deploymentType: { + dockerCompose: DeploymentTypes.DOCKERCOMPOSE, + kubernetes: DeploymentTypes.KUBERNETES, + openshift: DeploymentTypes.OPENSHIFT, + }, + dockerPushCommand: 'docker push', + dockerRepositoryName: '', + ...dockerComposeRelatedOptions, + ...kubernetesRelatedOptions, + ...openshiftRelatedOptions, +}; + +Options.defaults = (deploymentType = Options.deploymentType.dockerCompose) => { + if (deploymentType === Options.deploymentType.kubernetes) { + return { appsFolders: new Set(), + directoryPath: Options.directoryPath, clusteredDbApps: new Set(), - adminPassword: Options.adminPassword, serviceDiscoveryType: Options.serviceDiscoveryType.eureka, dockerRepositoryName: Options.dockerRepositoryName, dockerPushCommand: Options.dockerPushCommand, - kubernetesNamespace: deploymentType === Options.deploymentType.kubernetes ? Options.kubernetesNamespace : undefined, - kubernetesServiceType: deploymentType === Options.deploymentType.kubernetes ? Options.kubernetesServiceType.loadBalancer : undefined, - ingressDomain: deploymentType === Options.deploymentType.kubernetes ? Options.ingressDomain : undefined, - istio: deploymentType === Options.deploymentType.kubernetes ? Options.istio.false : undefined, - openshiftNamespace: deploymentType === Options.deploymentType.openshift ? Options.openshiftNamespace : undefined, - storageType: deploymentType === Options.deploymentType.openshift ? Options.storageType.ephemeral : undefined, - }, - _.isUndefined - ); + kubernetesNamespace: Options.kubernetesNamespace, + kubernetesServiceType: Options.kubernetesServiceType.loadBalancer, + kubernetesUseDynamicStorage: Options.kubernetesUseDynamicStorage.false, + kubernetesStorageClassName: Options.kubernetesStorageClassName, + ingressDomain: Options.ingressDomain, + monitoring: Options.monitoring.no, + istio: Options.istio.false, + }; + } + + if (deploymentType === Options.deploymentType.dockerCompose) { + return { + appsFolders: new Set(), + directoryPath: Options.directoryPath, + gatewayType: Options.gatewayType.springCloudGateway, + clusteredDbApps: new Set(), + monitoring: Options.monitoring.no, + serviceDiscoveryType: Options.serviceDiscoveryType.eureka, + }; + } + + return { + appsFolders: new Set(), + directoryPath: Options.directoryPath, + clusteredDbApps: new Set(), + serviceDiscoveryType: Options.serviceDiscoveryType.eureka, + monitoring: Options.monitoring.no, + dockerRepositoryName: Options.dockerRepositoryName, + dockerPushCommand: Options.dockerPushCommand, + openshiftNamespace: Options.openshiftNamespace, + storageType: Options.storageType.ephemeral, + registryReplicas: Options.registryReplicas.two, + }; +}; module.exports = { Options, diff --git a/jdl/parsing/lexer/deployment-tokens.js b/jdl/parsing/lexer/deployment-tokens.js index 7b75cb56fed..2dea8e8a6e2 100644 --- a/jdl/parsing/lexer/deployment-tokens.js +++ b/jdl/parsing/lexer/deployment-tokens.js @@ -26,19 +26,23 @@ const deploymentCategoryToken = createTokenFromConfig({ }); const deploymentTokens = [ - { name: 'DEPLOYMENT_TYPE', pattern: 'deploymentType' }, - { name: 'GATEWAY_TYPE', pattern: 'gatewayType' }, - { name: 'MONITORING', pattern: 'monitoring' }, - { name: 'DIRECTORY_PATH', pattern: 'directoryPath' }, { name: 'APPS_FOLDERS', pattern: 'appsFolders' }, { name: 'CLUSTERED_DB_APPS', pattern: 'clusteredDbApps' }, - { name: 'DOCKER_REPOSITORY_NAME', pattern: 'dockerRepositoryName' }, + { name: 'DEPLOYMENT_TYPE', pattern: 'deploymentType' }, + { name: 'DIRECTORY_PATH', pattern: 'directoryPath' }, { name: 'DOCKER_PUSH_COMMAND', pattern: 'dockerPushCommand' }, - { name: 'KUBERNETES_NAMESPACE', pattern: 'kubernetesNamespace' }, - { name: 'KUBERNETES_SERVICE_TYPE', pattern: 'kubernetesServiceType' }, + { name: 'DOCKER_REPOSITORY_NAME', pattern: 'dockerRepositoryName' }, + { name: 'GATEWAY_TYPE', pattern: 'gatewayType' }, { name: 'INGRESS_DOMAIN', pattern: 'ingressDomain' }, + { name: 'INGRESS_TYPE', pattern: 'ingressType' }, { name: 'ISTIO', pattern: 'istio' }, + { name: 'KUBERNETES_NAMESPACE', pattern: 'kubernetesNamespace' }, + { name: 'KUBERNETES_SERVICE_TYPE', pattern: 'kubernetesServiceType' }, + { name: 'KUBERNETES_STORAGE_CLASS_NAME', pattern: 'kubernetesStorageClassName' }, + { name: 'KUBERNETES_USE_DYNAMIC_STORAGE', pattern: 'kubernetesUseDynamicStorage' }, + { name: 'MONITORING', pattern: 'monitoring' }, { name: 'OPENSHIFT_NAMESPACE', pattern: 'openshiftNamespace' }, + { name: 'REGISTRY_REPLICAS', pattern: 'registryReplicas' }, { name: 'STORAGE_TYPE', pattern: 'storageType' }, ].map(tokenConfig => { tokenConfig.categories = [deploymentCategoryToken]; diff --git a/jdl/parsing/validator.js b/jdl/parsing/validator.js index 9307893f718..5472f476bab 100644 --- a/jdl/parsing/validator.js +++ b/jdl/parsing/validator.js @@ -44,6 +44,7 @@ const LANGUAGE_PATTERN = /^[a-z]+(-[A-Za-z0-9]+)*$/; const PATH_PATTERN = /^"([^\/]+).*"$/; // const PASSWORD_PATTERN = /^(.+)$/; const REPONAME_PATTERN = /^"((?:http(s)?:\/\/)?[\w.-]+(?:\.[\w.-]+)+[\w\-._~:\/?#[\]@!$&'()*+,;=]+|[a-zA-Z0-9]+)"$/; +const KUBERNETES_STORAGE_CLASS_NAME = /^"[A-Za-z]*"$/; const JWT_SECRET_KEY_PATTERN = /^\S+$/; const REMEMBER_ME_KEY_PATTERN = /^\S+$/; const NUMERIC = /^\d$/; @@ -275,11 +276,22 @@ const deploymentConfigPropsValidations = { pattern: ALPHABETIC, msg: 'kubernetesServiceType property', }, + KUBERNETES_STORAGE_CLASS_NAME: { + type: 'STRING', + pattern: KUBERNETES_STORAGE_CLASS_NAME, + msg: 'kubernetesStorageClassName property', + }, + KUBERNETES_USE_DYNAMIC_STORAGE: { type: 'BOOLEAN' }, INGRESS_DOMAIN: { type: 'STRING', pattern: REPONAME_PATTERN, msg: 'ingressDomain property', }, + INGRESS_TYPE: { + type: 'STRING', + pattern: ALPHABETIC, + msg: 'ingressType property', + }, ISTIO: { type: 'BOOLEAN', msg: 'istio property', @@ -289,6 +301,7 @@ const deploymentConfigPropsValidations = { pattern: ALPHANUMERIC_DASH, msg: 'openshiftNamespace property', }, + REGISTRY_REPLICAS: { type: 'INTEGER' }, STORAGE_TYPE: { type: 'NAME', pattern: ALPHABETIC_LOWER, diff --git a/jdl/validators/deployment-validator.js b/jdl/validators/deployment-validator.js index 7997b38cdb6..4d9e4bdb8b8 100644 --- a/jdl/validators/deployment-validator.js +++ b/jdl/validators/deployment-validator.js @@ -17,16 +17,68 @@ * limitations under the License. */ +const { MICROSERVICE } = require('../jhipster/application-types'); +const { NO } = require('../jhipster/database-types'); +const { ELASTICSEARCH } = require('../jhipster/search-engine-types'); +const { Options } = require('../jhipster/deployment-options'); const Validator = require('./validator'); -class DeploymentValidator extends Validator { +module.exports = class DeploymentValidator extends Validator { constructor() { - super('deployment', ['deploymentType', 'appsFolders', 'dockerRepositoryName']); + super('deployment', ['deploymentType', 'appsFolders', 'directoryPath']); } - validate(jdlDeployment) { + validate(jdlDeployment, options = {}) { super.validate(jdlDeployment); + + switch (jdlDeployment.deploymentType) { + case Options.deploymentType.dockerCompose: + validateDockerComposeRelatedDeployment(jdlDeployment, options); + break; + case Options.deploymentType.kubernetes: + validateKubernetesRelatedDeployment(jdlDeployment); + break; + case Options.deploymentType.openshift: + validateOpenshiftRelatedDeployment(jdlDeployment, options); + break; + default: + throw new Error(`The deployment type ${jdlDeployment.deploymentType} isn't supported.`); + } + } +}; + +function validateDockerComposeRelatedDeployment(jdlDeployment, options = {}) { + if (jdlDeployment.gatewayType !== Options.gatewayType.springCloudGateway && options.applicationType === MICROSERVICE) { + throw new Error('A gateway type must be provided when dealing with microservices and the deployment type is docker-compose.'); + } +} + +function validateKubernetesRelatedDeployment(jdlDeployment) { + if (!jdlDeployment.kubernetesServiceType) { + throw new Error('A kubernetes service type must be provided when dealing with kubernetes-related deployments.'); + } + if (jdlDeployment.istio && !jdlDeployment.ingressDomain) { + throw new Error( + 'An ingress domain must be provided when dealing with kubernetes-related deployments, with istio and when the service type is ingress.' + ); + } + if (jdlDeployment.kubernetesServiceType === Options.kubernetesServiceType.ingress && !jdlDeployment.ingressType) { + throw new Error('An ingress type is required when dealing with kubernetes-related deployments and when the service type is ingress.'); } } -module.exports = DeploymentValidator; +function validateOpenshiftRelatedDeployment(jdlDeployment, options) { + if (jdlDeployment.storageType) { + if (options.prodDatabaseType === NO) { + throw new Error("Can't have the storageType option set when there is no prodDatabaseType."); + } + + if (options.searchEngine === ELASTICSEARCH) { + throw new Error("Can't have the storageType option set when elasticsearch is the search engine."); + } + + if (jdlDeployment.monitoring === Options.monitoring.prometheus) { + throw new Error("Can't have the storageType option set when the monitoring is done with prometheus."); + } + } +} diff --git a/test/jdl/converters/parsedJDLToJDLObject/parsed-jdl-to-jdl-object-converter.spec.js b/test/jdl/converters/parsedJDLToJDLObject/parsed-jdl-to-jdl-object-converter.spec.js index 48b3b12f32a..b91b7ffc070 100644 --- a/test/jdl/converters/parsedJDLToJDLObject/parsed-jdl-to-jdl-object-converter.spec.js +++ b/test/jdl/converters/parsedJDLToJDLObject/parsed-jdl-to-jdl-object-converter.spec.js @@ -544,7 +544,6 @@ describe('ParsedJDLToJDLObjectConverter', () => { expect(deployment).to.deep.equal({ deploymentType: 'docker-compose', directoryPath: '../', - dockerPushCommand: 'docker push', dockerRepositoryName: 'test', gatewayType: 'SpringCloudGateway', monitoring: 'no', diff --git a/test/jdl/exporters/jhipster-deployment-exporter.spec.js b/test/jdl/exporters/jhipster-deployment-exporter.spec.js index cda04591a25..4f38e427b7e 100644 --- a/test/jdl/exporters/jhipster-deployment-exporter.spec.js +++ b/test/jdl/exporters/jhipster-deployment-exporter.spec.js @@ -88,7 +88,6 @@ describe('JHipsterDeploymentExporter', () => { appsFolders: ['tata', 'titi'], clusteredDbApps: [], directoryPath: '../', - dockerPushCommand: 'docker push', dockerRepositoryName: 'test', gatewayType: 'SpringCloudGateway', monitoring: 'no', @@ -128,12 +127,13 @@ describe('JHipsterDeploymentExporter', () => { directoryPath: '../', dockerPushCommand: 'docker push', dockerRepositoryName: 'test', - gatewayType: 'SpringCloudGateway', ingressDomain: '', istio: false, kubernetesNamespace: 'default', kubernetesServiceType: 'LoadBalancer', monitoring: 'no', + kubernetesUseDynamicStorage: false, + kubernetesStorageClassName: '', serviceDiscoveryType: 'eureka', }); }); diff --git a/test/jdl/grammar/grammar.spec.js b/test/jdl/grammar/grammar.spec.js index d9c2b42c941..15d0d5088ee 100644 --- a/test/jdl/grammar/grammar.spec.js +++ b/test/jdl/grammar/grammar.spec.js @@ -1721,4 +1721,46 @@ entity A { }); }); }); + context('when parsing deployments', () => { + context('with kubernetesStorageClassName', () => { + context('being empty', () => { + let parsedDeployment; + + before(() => { + const content = parseFromContent( + `deployment { + kubernetesStorageClassName "" +} +` + ); + parsedDeployment = content.deployments[0]; + }); + + it('should parse it', () => { + expect(parsedDeployment).to.deep.equal({ + kubernetesStorageClassName: '', + }); + }); + }); + context('being set', () => { + let parsedDeployment; + + before(() => { + const content = parseFromContent( + `deployment { + kubernetesStorageClassName "SetValue" +} +` + ); + parsedDeployment = content.deployments[0]; + }); + + it('should parse it', () => { + expect(parsedDeployment).to.deep.equal({ + kubernetesStorageClassName: 'SetValue', + }); + }); + }); + }); + }); }); diff --git a/test/jdl/jdl-importer.spec.js b/test/jdl/jdl-importer.spec.js index 83cc10032b4..b389066e5d8 100644 --- a/test/jdl/jdl-importer.spec.js +++ b/test/jdl/jdl-importer.spec.js @@ -1361,7 +1361,6 @@ relationship OneToOne { clusteredDbApps: [], deploymentType: 'docker-compose', serviceDiscoveryType: 'eureka', - dockerPushCommand: 'docker push', dockerRepositoryName: 'test', monitoring: 'no', }, @@ -1410,7 +1409,6 @@ relationship OneToOne { clusteredDbApps: [], deploymentType: 'docker-compose', serviceDiscoveryType: 'eureka', - dockerPushCommand: 'docker push', dockerRepositoryName: 'test', monitoring: 'no', }, @@ -1423,8 +1421,9 @@ relationship OneToOne { deploymentType: 'kubernetes', dockerPushCommand: 'docker push', dockerRepositoryName: 'test', - gatewayType: 'SpringCloudGateway', ingressDomain: '', + kubernetesUseDynamicStorage: false, + kubernetesStorageClassName: 'KubernetesStorageClassName', istio: false, kubernetesNamespace: 'default', kubernetesServiceType: 'LoadBalancer', @@ -1440,8 +1439,8 @@ relationship OneToOne { deploymentType: 'openshift', dockerPushCommand: 'docker push', dockerRepositoryName: 'test', - gatewayType: 'SpringCloudGateway', monitoring: 'no', + registryReplicas: 2, openshiftNamespace: 'default', serviceDiscoveryType: 'eureka', storageType: 'ephemeral', @@ -1620,13 +1619,11 @@ relationship OneToOne { clusteredDbApps: [], serviceDiscoveryType: false, dockerRepositoryName: 'deepu105', - dockerPushCommand: 'docker push', }, }, { 'generator-jhipster': { deploymentType: 'kubernetes', - gatewayType: 'SpringCloudGateway', monitoring: 'no', directoryPath: '../', appsFolders: ['store', 'invoice', 'notification', 'product'], @@ -1636,8 +1633,10 @@ relationship OneToOne { dockerPushCommand: 'docker push', kubernetesNamespace: 'default', kubernetesServiceType: 'LoadBalancer', + kubernetesStorageClassName: '', ingressDomain: '', istio: false, + kubernetesUseDynamicStorage: false, }, }, ]; diff --git a/test/jdl/jhipster/deployment-options.spec.js b/test/jdl/jhipster/deployment-options.spec.js index 718a09259d8..8c1cd333864 100644 --- a/test/jdl/jhipster/deployment-options.spec.js +++ b/test/jdl/jhipster/deployment-options.spec.js @@ -50,12 +50,9 @@ describe('DeploymentOptions', () => { context('when passing no args', () => { it('should return docker deployment config', () => { expect(Options.defaults()).to.eql({ - deploymentType: 'docker-compose', appsFolders: new Set(), clusteredDbApps: new Set(), directoryPath: '../', - dockerPushCommand: 'docker push', - dockerRepositoryName: '', gatewayType: 'SpringCloudGateway', monitoring: 'no', serviceDiscoveryType: 'eureka', @@ -65,13 +62,13 @@ describe('DeploymentOptions', () => { context('when passing kubernetes as arg', () => { it('should return kubernetes deployment config', () => { expect(Options.defaults('kubernetes')).to.eql({ - deploymentType: 'kubernetes', appsFolders: new Set(), clusteredDbApps: new Set(), directoryPath: '../', dockerPushCommand: 'docker push', dockerRepositoryName: '', - gatewayType: 'SpringCloudGateway', + kubernetesUseDynamicStorage: false, + kubernetesStorageClassName: '', monitoring: 'no', serviceDiscoveryType: 'eureka', ingressDomain: '', @@ -84,17 +81,16 @@ describe('DeploymentOptions', () => { context('when passing openshift as arg', () => { it('should return openshift deployment config', () => { expect(Options.defaults('openshift')).to.eql({ - deploymentType: 'openshift', appsFolders: new Set(), clusteredDbApps: new Set(), directoryPath: '../', dockerPushCommand: 'docker push', dockerRepositoryName: '', - gatewayType: 'SpringCloudGateway', monitoring: 'no', serviceDiscoveryType: 'eureka', openshiftNamespace: 'default', storageType: 'ephemeral', + registryReplicas: 2, }); }); }); diff --git a/test/jdl/models/jdl-deployment.spec.js b/test/jdl/models/jdl-deployment.spec.js index 14b14a1df44..ce5ec313411 100644 --- a/test/jdl/models/jdl-deployment.spec.js +++ b/test/jdl/models/jdl-deployment.spec.js @@ -75,8 +75,8 @@ describe('JDLDeployment', () => { it('should stringify its content without default values', () => { expect(deployment.toString()).to.eql(`deployment { - deploymentType ${args.deploymentType} appsFolders [${args.appsFolders.join(', ').replace(/'/g, '')}] + deploymentType ${args.deploymentType} dockerRepositoryName ${args.dockerRepositoryName} }`); }); @@ -98,9 +98,9 @@ describe('JDLDeployment', () => { it('should stringify it', () => { expect(deployment.toString()).to.eql(`deployment { - deploymentType ${args.deploymentType} - directoryPath ${args.directoryPath} appsFolders [${args.appsFolders.join(', ').replace(/'/g, '')}] + directoryPath ${args.directoryPath} + deploymentType ${args.deploymentType} dockerRepositoryName ${args.dockerRepositoryName} }`); }); diff --git a/test/jdl/test-files/deployments.jdl b/test/jdl/test-files/deployments.jdl index b5ba8e97a9f..37bb9401b5e 100644 --- a/test/jdl/test-files/deployments.jdl +++ b/test/jdl/test-files/deployments.jdl @@ -7,6 +7,7 @@ deployment { deploymentType kubernetes, appsFolders [tata, titi], dockerRepositoryName "test" + kubernetesStorageClassName "KubernetesStorageClassName" } deployment { deploymentType openshift, diff --git a/test/jdl/validators/deployment-validator.spec.js b/test/jdl/validators/deployment-validator.spec.js index 3113a73fb57..910d7103515 100644 --- a/test/jdl/validators/deployment-validator.spec.js +++ b/test/jdl/validators/deployment-validator.spec.js @@ -18,6 +18,10 @@ */ const { expect } = require('chai'); +const { Options } = require('../../../jdl/jhipster/deployment-options'); +const { MICROSERVICE } = require('../../../jdl/jhipster/application-types'); +const { MONGODB, NO } = require('../../../jdl/jhipster/database-types'); +const SearchEngineTypes = require('../../../jdl/jhipster/search-engine-types'); const DeploymentValidator = require('../../../jdl/validators/deployment-validator'); describe('DeploymentValidator', () => { @@ -34,23 +38,286 @@ describe('DeploymentValidator', () => { }); }); context('when a deployment is passed', () => { - context('when not missing any attribute', () => { - it('should not fail', () => { - expect(() => { - validator.validate({ - deploymentType: 'kubernetes', - appsFolders: ['invoices'], - dockerRepositoryName: 'test', + context('when having a docker-compose-related deployment', () => { + context('without appFolders', () => { + it('should fail', () => { + expect(() => + validator.validate({ + deploymentType: Options.deploymentType.dockerCompose, + directoryPath: '../', + gatewayType: Options.gatewayType.springCloudGateway, + monitoring: 'no', + serviceDiscoveryType: Options.serviceDiscoveryType.eureka, + }) + ).to.throw(/^The deployment attribute appsFolders was not found.$/); + }); + }); + context('without directoryPath', () => { + it('should fail', () => { + expect(() => + validator.validate({ + deploymentType: Options.deploymentType.dockerCompose, + appsFolders: ['beers', 'burgers'], + gatewayType: Options.gatewayType.springCloudGateway, + monitoring: 'no', + serviceDiscoveryType: Options.serviceDiscoveryType.eureka, + }) + ).to.throw(/^The deployment attribute directoryPath was not found.$/); + }); + }); + context('without monitoring', () => { + it('should not fail', () => { + expect(() => + validator.validate({ + deploymentType: Options.deploymentType.dockerCompose, + appsFolders: ['beers', 'burgers'], + directoryPath: '../', + gatewayType: Options.gatewayType.springCloudGateway, + serviceDiscoveryType: Options.serviceDiscoveryType.eureka, + }) + ).not.to.throw(); + }); + }); + context('with microservices', () => { + context('without gatewayType', () => { + it('should fail', () => { + expect(() => + validator.validate( + { + deploymentType: Options.deploymentType.dockerCompose, + appsFolders: ['beers', 'burgers'], + directoryPath: '../', + monitoring: 'no', + serviceDiscoveryType: Options.serviceDiscoveryType.eureka, + }, + { + applicationType: MICROSERVICE, + } + ) + ).to.throw(/^A gateway type must be provided when dealing with microservices and the deployment type is docker-compose.$/); }); - }).not.to.throw(); + }); + }); + context('without serviceDiscoveryType', () => { + it('should not fail', () => { + expect(() => + validator.validate({ + deploymentType: Options.deploymentType.dockerCompose, + appsFolders: ['beers', 'burgers'], + directoryPath: '../', + monitoring: 'no', + }) + ).not.to.throw(); + }); }); }); - context('when missing attributes', () => { - it('should fail', () => { - expect(() => validator.validate({})).to.throw( - /^The deployment attributes deploymentType, appsFolders, dockerRepositoryName were not found.$/ - ); + context('when having a kubernetes-related deployment', () => { + context('without appFolders', () => { + it('should fail', () => { + expect(() => + validator.validate({ + deploymentType: Options.deploymentType.kubernetes, + directoryPath: '../', + kubernetesServiceType: Options.kubernetesServiceType.loadBalancer, + monitoring: 'no', + serviceDiscoveryType: Options.serviceDiscoveryType.eureka, + }) + ).to.throw(/^The deployment attribute appsFolders was not found.$/); + }); + }); + context('without directoryPath', () => { + it('should fail', () => { + expect(() => + validator.validate({ + deploymentType: Options.deploymentType.kubernetes, + appsFolders: ['beers', 'burgers'], + kubernetesServiceType: Options.kubernetesServiceType.loadBalancer, + monitoring: 'no', + serviceDiscoveryType: Options.serviceDiscoveryType.eureka, + }) + ).to.throw(/^The deployment attribute directoryPath was not found.$/); + }); + }); + context( + 'without monitoring, dockerPushCommand, dockerRepositoryName, kubernetesNamespace, kubernetesUseDynamicStorage, kubernetesStorageClassName or istio and an ingressDomain', + () => { + it('should not fail', () => { + expect(() => + validator.validate({ + deploymentType: Options.deploymentType.kubernetes, + appsFolders: ['beers', 'burgers'], + directoryPath: '../', + kubernetesServiceType: Options.kubernetesServiceType.loadBalancer, + serviceDiscoveryType: Options.serviceDiscoveryType.eureka, + }) + ).not.to.throw(); + }); + } + ); + context('without kubernetesServiceType', () => { + it('should fail', () => { + expect(() => + validator.validate({ + deploymentType: Options.deploymentType.kubernetes, + appsFolders: ['beers', 'burgers'], + directoryPath: '../', + serviceDiscoveryType: Options.serviceDiscoveryType.eureka, + }) + ).to.throw(/^A kubernetes service type must be provided when dealing with kubernetes-related deployments.$/); + }); + }); + context('with istio', () => { + context('without an ingressDomain', () => { + it('should fail', () => { + expect(() => + validator.validate({ + deploymentType: Options.deploymentType.kubernetes, + appsFolders: ['beers', 'burgers'], + directoryPath: '../', + serviceDiscoveryType: Options.serviceDiscoveryType.eureka, + kubernetesServiceType: Options.kubernetesServiceType.loadBalancer, + istio: true, + }) + ).to.throw( + /^An ingress domain must be provided when dealing with kubernetes-related deployments, with istio and when the service type is ingress.$/ + ); + }); + }); }); + context('with the kubernetesServiceType being Ingress', () => { + context('without an ingressType', () => { + it('should fail', () => { + expect(() => + validator.validate({ + deploymentType: Options.deploymentType.kubernetes, + appsFolders: ['beers', 'burgers'], + directoryPath: '../', + kubernetesServiceType: Options.kubernetesServiceType.ingress, + serviceDiscoveryType: Options.serviceDiscoveryType.eureka, + }) + ).to.throw( + /^An ingress type is required when dealing with kubernetes-related deployments and when the service type is ingress.$/ + ); + }); + }); + }); + }); + context('when having an openshift-related deployment', () => { + context('without appFolders', () => { + it('should fail', () => { + expect(() => + validator.validate({ + deploymentType: Options.deploymentType.openshift, + directoryPath: '../', + gatewayType: Options.gatewayType.springCloudGateway, + openshiftNamespace: 'default', + }) + ).to.throw(/^The deployment attribute appsFolders was not found.$/); + }); + }); + context('without directoryPath', () => { + it('should fail', () => { + expect(() => + validator.validate({ + deploymentType: Options.deploymentType.openshift, + appsFolders: ['beers', 'burgers'], + monitoring: 'no', + openshiftNamespace: 'default', + }) + ).to.throw(/^The deployment attribute directoryPath was not found.$/); + }); + }); + context('without monitoring', () => { + it('should not fail', () => { + expect(() => + validator.validate({ + deploymentType: Options.deploymentType.openshift, + appsFolders: ['beers', 'burgers'], + directoryPath: '../', + openshiftNamespace: 'default', + }) + ).not.to.throw(); + }); + }); + context('without openshiftNamespace', () => { + it('should not fail', () => { + expect(() => + validator.validate({ + deploymentType: Options.deploymentType.openshift, + appsFolders: ['beers', 'burgers'], + directoryPath: '../', + }) + ).not.to.throw(); + }); + }); + context('when there is no prodDatabaseType', () => { + it('should fail if there is a storageType', () => { + expect(() => + validator.validate( + { + deploymentType: Options.deploymentType.openshift, + appsFolders: ['beers', 'burgers'], + directoryPath: '../', + storageType: Options.storageType.ephemeral, + }, + { prodDatabaseType: NO } + ) + ).to.throw(/^Can't have the storageType option set when there is no prodDatabaseType.$/); + }); + }); + context('when the search engine is elasticsearch', () => { + it('should fail if there is a storageType', () => { + expect(() => + validator.validate( + { + deploymentType: Options.deploymentType.openshift, + appsFolders: ['beers', 'burgers'], + directoryPath: '../', + storageType: Options.storageType.ephemeral, + }, + { searchEngine: SearchEngineTypes.ELASTICSEARCH } + ) + ).to.throw(/^Can't have the storageType option set when elasticsearch is the search engine.$/); + }); + }); + context('when the monitoring is done with prometheus', () => { + it('should fail if there is a storageType', () => { + expect(() => + validator.validate({ + deploymentType: Options.deploymentType.openshift, + appsFolders: ['beers', 'burgers'], + directoryPath: '../', + storageType: Options.storageType.ephemeral, + monitoring: Options.monitoring.prometheus, + }) + ).to.throw(/^Can't have the storageType option set when the monitoring is done with prometheus.$/); + }); + }); + context('when the prodDatabaseType is set and the storageType is not set', () => { + it('should not fail', () => { + expect(() => + validator.validate( + { + deploymentType: Options.deploymentType.openshift, + appsFolders: ['beers', 'burgers'], + directoryPath: '../', + }, + { prodDatabaseType: MONGODB } + ) + ).not.to.throw(); + }); + }); + }); + }); + context('when passing an unknown deployment type', () => { + it('should fail', () => { + expect(() => + validator.validate({ + deploymentType: 'whatever', + appsFolders: ['beers', 'burgers'], + directoryPath: '../', + }) + ).to.throw(/^The deployment type whatever isn't supported.$/); }); }); });