diff --git a/bin/cap-op-plugin.js b/bin/cap-op-plugin.js index ab5719b..ef765f1 100755 --- a/bin/cap-op-plugin.js +++ b/bin/cap-op-plugin.js @@ -11,7 +11,18 @@ const yaml = require('@sap/cds-foss').yaml const Mustache = require('mustache') const { spawn } = require('child_process') -const { ask, mergeObj, isCAPOperatorChart, isConfigurableTemplateChart, transformValuesAndFillCapOpCroYaml, isServiceOnlyChart } = require('../lib/util') +const { + ask, + mergeObj, + isCAPOperatorChart, + isConfigurableTemplateChart, + transformValuesAndFillCapOpCroYaml, + isServiceOnlyChart, + getServiceInstanceKeyName, + getConfigurableCapOpCroYaml, + getDomainCroYaml, + getHelperTpl +} = require('../lib/util') const SUPPORTED = { 'generate-runtime-values': ['--with-input-yaml'], 'convert-to-configurable-template-chart': ['--with-runtime-yaml'] } @@ -25,7 +36,7 @@ async function capOperatorPlugin(cmd, option, yamlPath) { if (option === '--with-input-yaml' && !yamlPath) return _usage(`Input yaml path is missing.`) - if (option === '--with-input-yaml' && !yamlPath && cds.utils.exists(cds.utils.path.join(cds.root,yamlPath))) + if (option === '--with-input-yaml' && !yamlPath && cds.utils.exists(cds.utils.path.join(cds.root, yamlPath))) return _usage(`Input yaml path ${yamlPath} does not exist.`) await generateRuntimeValues(option, yamlPath) @@ -35,7 +46,7 @@ async function capOperatorPlugin(cmd, option, yamlPath) { if (option === '--with-runtime-yaml' && !yamlPath) return _usage(`Input runtime yaml path is missing.`) - if (option === '--with-runtime-yaml' && !yamlPath && cds.utils.exists(cds.utils.path.join(cds.root,yamlPath))) + if (option === '--with-runtime-yaml' && !yamlPath && cds.utils.exists(cds.utils.path.join(cds.root, yamlPath))) return _usage(`Input runtime yaml path ${yamlPath} does not exist.`) await convertToconfigurableTemplateChart(option, yamlPath) @@ -81,13 +92,13 @@ EXAMPLES } async function transformRuntimeValues(runtimeYamlPath) { - console.log('Transforming runtime values file '+ cds.utils.path.join(cds.root,runtimeYamlPath) + ' to the configurable template chart format.') + console.log('Transforming runtime values file ' + cds.utils.path.join(cds.root, runtimeYamlPath) + ' to the configurable template chart format.') let runtimeYaml = yaml.parse(await cds.utils.read(cds.utils.path.join(cds.root, runtimeYamlPath))) if (runtimeYaml?.workloads?.server?.deploymentDefinition?.env) { const index = runtimeYaml.workloads.server.deploymentDefinition.env.findIndex(e => e.name === 'CDS_CONFIG') if (index > -1) { const cdsConfigValueJson = JSON.parse(runtimeYaml.workloads.server.deploymentDefinition.env[index].value) - if (cdsConfigValueJson?.requires?.['cds.xt.DeploymentService']?.hdi?.create?.database_id){ + if (cdsConfigValueJson?.requires?.['cds.xt.DeploymentService']?.hdi?.create?.database_id) { runtimeYaml['hanaInstanceId'] = cdsConfigValueJson.requires['cds.xt.DeploymentService'].hdi.create.database_id delete runtimeYaml['workloads'] await cds.utils.write(yaml.stringify(runtimeYaml)).to(cds.utils.path.join(cds.root, runtimeYamlPath)) @@ -102,36 +113,55 @@ async function isRuntimeValueAlreadyTransformed(runtimeYamlPath) { } async function convertToconfigurableTemplateChart(option, runtimeYamlPath) { - if (!((cds.utils.exists('chart') && isCAPOperatorChart(cds.utils.path.join(cds.root,'chart'))))) + if (!((cds.utils.exists('chart') && isCAPOperatorChart(cds.utils.path.join(cds.root, 'chart'))))) throw new Error("No CAP Operator chart found in the project. Please run 'cds add cap-operator --force' to add the CAP Operator chart folder.") - if (isConfigurableTemplateChart(cds.utils.path.join(cds.root,'chart'))){ + if (isConfigurableTemplateChart(cds.utils.path.join(cds.root, 'chart'))) { console.log("Exisiting chart is already a configurable template chart. No need for conversion.") if (option === '--with-runtime-yaml' && runtimeYamlPath && !(await isRuntimeValueAlreadyTransformed(runtimeYamlPath))) await transformRuntimeValues(runtimeYamlPath) else - console.log('Runtime values file '+ cds.utils.path.join(cds.root,runtimeYamlPath) + ' already in the configurable template chart format.') + console.log('Runtime values file ' + cds.utils.path.join(cds.root, runtimeYamlPath) + ' already in the configurable template chart format.') return } - console.log('Converting chart '+cds.utils.path.join(cds.root,'chart')+' to configurable template chart.') + console.log('Converting chart ' + cds.utils.path.join(cds.root, 'chart') + ' to configurable template chart.') // Copy templates - await cds.utils.copy(cds.utils.path.join(__dirname, '../files/configurableTemplatesChart/templates/_helpers.tpl')).to(cds.utils.path.join(cds.root,'chart/templates/_helpers.tpl')) - await cds.utils.copy(cds.utils.path.join(__dirname, '../files/commonTemplates/')).to(cds.utils.path.join(cds.root,'chart/templates/')) + await cds.utils.copy(cds.utils.path.join(__dirname, '../files/commonTemplates/')).to(cds.utils.path.join(cds.root, 'chart/templates/')) - isServiceOnlyChart(cds.utils.path.join(cds.root,'chart')) ? await cds.utils.copy(cds.utils.path.join(__dirname, '../files/configurableTemplatesChart/templates/cap-operator-cros-svc.yaml')).to(cds.utils.path.join(cds.root,'chart/templates/cap-operator-cros.yaml')) : - await cds.utils.copy(cds.utils.path.join(__dirname, '../files/configurableTemplatesChart/templates/cap-operator-cros.yaml')).to(cds.utils.path.join(cds.root,'chart/templates/cap-operator-cros.yaml')) + const valuesYaml = yaml.parse(await cds.utils.read(cds.utils.path.join(cds.root, 'chart/values.yaml'))) + const hasIas = getServiceInstanceKeyName(valuesYaml['serviceInstances'], 'identity') != null + const hasXsuaa = getServiceInstanceKeyName(valuesYaml['serviceInstances'], 'xsuaa') != null + + // Create _helpers.tpl + await cds.utils.write(getHelperTpl({ + hasXsuaa: hasXsuaa + }, false)).to(cds.utils.path.join(cds.root, 'chart/templates/_helpers.tpl')) + + // Create domain.yaml + await cds.utils.write(getDomainCroYaml({ + hasIas: hasIas + })).to(cds.utils.path.join(cds.root, 'chart/templates/domain.yaml')) + + // Create cap-operator-cros.yaml + // Only filling those fields in the project input struct that are required to create CAPApplication CR + // Workloads will be filled during transformValuesAndFillCapOpCroYaml function call + await cds.utils.write(getConfigurableCapOpCroYaml({ + hasXsuaa: hasXsuaa, + hasIas: hasIas, + isService: isServiceOnlyChart(cds.utils.path.join(cds.root, 'chart')) + })).to(cds.utils.path.join(cds.root, 'chart/templates/cap-operator-cros.yaml')) // Copy values.schema.json - await cds.utils.copy(cds.utils.path.join(__dirname, '../files/configurableTemplatesChart/values.schema.json')).to(cds.utils.path.join(cds.root,'chart', 'values.schema.json')) + await cds.utils.copy(cds.utils.path.join(__dirname, '../files/configurableTemplatesChart/values.schema.json')).to(cds.utils.path.join(cds.root, 'chart', 'values.schema.json')) // Add annotation to chart.yaml const chartYaml = yaml.parse(await cds.utils.read(cds.utils.path.join(cds.root, 'chart/Chart.yaml'))) chartYaml['annotations']['app.kubernetes.io/part-of'] = 'cap-operator-configurable-templates' await cds.utils.write(yaml.stringify(chartYaml)).to(cds.utils.path.join(cds.root, 'chart/Chart.yaml')) - // Transform + // Transform CAPApplicationVersion CR from values.yaml await transformValuesAndFillCapOpCroYaml() if (option === '--with-runtime-yaml' && runtimeYamlPath) { @@ -140,14 +170,14 @@ async function convertToconfigurableTemplateChart(option, runtimeYamlPath) { } async function generateRuntimeValues(option, inputYamlPath) { - if (!((cds.utils.exists('chart') && isCAPOperatorChart(cds.utils.path.join(cds.root,'chart'))))) { + if (!((cds.utils.exists('chart') && isCAPOperatorChart(cds.utils.path.join(cds.root, 'chart'))))) { throw new Error("No CAP Operator chart found in the project. Please run 'cds add cap-operator --force' to add the CAP Operator chart folder.") } let answerStruct = {} const { appName, appDescription } = getAppDetails() - const isConfigurableTempChart = isConfigurableTemplateChart(cds.utils.path.join(cds.root,'chart')) - const isServiceOnly = isServiceOnlyChart(cds.utils.path.join(cds.root,'chart')) + const isConfigurableTempChart = isConfigurableTemplateChart(cds.utils.path.join(cds.root, 'chart')) + const isServiceOnly = isServiceOnlyChart(cds.utils.path.join(cds.root, 'chart')) if (option === '--with-input-yaml' && inputYamlPath) { @@ -190,8 +220,16 @@ async function generateRuntimeValues(option, inputYamlPath) { const valuesYaml = yaml.parse(await cds.utils.read(cds.utils.path.join(cds.root, 'chart/values.yaml'))) //get saas-registry and xsuaa service keys - answerStruct['saasRegistryKeyName'] = getServiceInstanceKeyName(valuesYaml['serviceInstances'], 'saas-registry') || 'saas-registry' - answerStruct['xsuaaKeyName'] = getServiceInstanceKeyName(valuesYaml['serviceInstances'], 'xsuaa') || 'xsuaa' + const xsuaaServiceInstanceKey = getServiceInstanceKeyName(valuesYaml['serviceInstances'], 'xsuaa') + if (xsuaaServiceInstanceKey == null) { + answerStruct['hasXsuaa'] = false + answerStruct['subscriptionManagerKeyName'] = getServiceInstanceKeyName(valuesYaml['serviceInstances'], 'subscription-manager') || 'subscription-manager' + answerStruct['identityKeyName'] = getServiceInstanceKeyName(valuesYaml['serviceInstances'], 'identity') || 'identity' + } else { + answerStruct['hasXsuaa'] = true + answerStruct['saasRegistryKeyName'] = getServiceInstanceKeyName(valuesYaml['serviceInstances'], 'saas-registry') || 'saas-registry' + answerStruct['xsuaaKeyName'] = getServiceInstanceKeyName(valuesYaml['serviceInstances'], 'xsuaa') || 'xsuaa' + } answerStruct['isApp'] = !isServiceOnly answerStruct['isService'] = isServiceOnly @@ -220,7 +258,7 @@ function updateWorkloadEnv(runtimeValuesYaml, valuesYaml, answerStruct) { const cdsConfigHana = Mustache.render('{"requires":{"cds.xt.DeploymentService":{"hdi":{"create":{"database_id":"{{hanaInstanceId}}"}}}}}', answerStruct) - if ((workloadDetails?.deploymentDefinition?.type === 'CAP' || workloadDetails?.deploymentDefinition?.type === 'service') && answerStruct['hanaInstanceId']) { + if ((workloadDetails?.deploymentDefinition?.type === 'CAP' || workloadDetails?.deploymentDefinition?.type === 'Service') && answerStruct['hanaInstanceId']) { updateCdsConfigEnv(runtimeValuesYaml, workloadKey, 'deploymentDefinition', cdsConfigHana) } @@ -242,14 +280,6 @@ function updateWorkloadEnv(runtimeValuesYaml, valuesYaml, answerStruct) { } } -function getServiceInstanceKeyName(serviceInstances, offeringName) { - for (const key in serviceInstances) { - if (serviceInstances[key].serviceOfferingName === offeringName) - return key - } - return null -} - function updateCdsConfigEnv(runtimeValuesYaml, workloadKey, workloadDefintion, cdsConfigHana) { const index = runtimeValuesYaml['workloads'][workloadKey][workloadDefintion]['env'].findIndex(e => e.name === 'CDS_CONFIG') if (index > -1) { @@ -285,7 +315,7 @@ async function getShootDomain() { kubectl.on('close', () => { resolve() }) }) - } catch (error) {} + } catch (error) { } return domain } diff --git a/files/approuter.yaml.hbs b/files/approuter.yaml.hbs index be76069..ecbcefa 100644 --- a/files/approuter.yaml.hbs +++ b/files/approuter.yaml.hbs @@ -6,16 +6,22 @@ workloads: consumedBTPServices: {{#hasXsuaa}} - {{appName}}-uaa-bind + {{#isApp}} + - {{appName}}-saas-registry-bind + {{/isApp}} {{/hasXsuaa}} + {{#hasIas}} + - {{appName}}-identity-bind + {{#isApp}} + - {{appName}}-subscription-manager-bind + {{/isApp}} + {{/hasIas}} {{#hasDestination}} - {{appName}}-destination-bind {{/hasDestination}} {{#hasHTML5Repo}} - {{appName}}-html5-repo-runtime-bind {{/hasHTML5Repo}} - {{#hasMultitenancy}} - - {{appName}}-saas-registry-bind - {{/hasMultitenancy}} deploymentDefinition: type: Router image: diff --git a/files/commonTemplates/service-instance.yaml b/files/commonTemplates/service-instance.yaml index 2120bf9..ba40a56 100644 --- a/files/commonTemplates/service-instance.yaml +++ b/files/commonTemplates/service-instance.yaml @@ -38,12 +38,20 @@ spec: {{- if or $serviceSpec.parameters $serviceSpec.jsonParameters }} {{- $parameters := $serviceSpec.parameters | default (dict) }} - {{- if and (eq $serviceSpec.serviceOfferingName "xsuaa") (or (not (get (get $parameters "oauth2-configuration" | default (dict)) "redirect-uris")) (eq (len (get (get $parameters "oauth2-configuration" | default (dict)) "redirect-uris")) 0)) }} - {{- $redirectUris := include "redirectUris" $ | fromJson }} - {{- $oauth2Cfg := merge ($redirectUris) (get $parameters "oauth2-configuration" | default (dict)) }} - {{- $_ := set $parameters "oauth2-configuration" $oauth2Cfg }} - {{- end }} {{- $jsonParameters := $serviceSpec.jsonParameters | default "{}" }} + + {{- if or (eq $serviceSpec.serviceOfferingName "xsuaa") (eq $serviceSpec.serviceOfferingName "identity") }} + {{- $missingRedirects := or + (not (get (get $parameters "oauth2-configuration" | default (dict)) "redirect-uris")) + (eq (len (get (get $parameters "oauth2-configuration" | default (dict)) "redirect-uris")) 0) + -}} + + {{- if $missingRedirects }} + {{- $redirectUris := include "redirectUris" (dict "serviceOfferingName" $serviceSpec.serviceOfferingName "context" $) | fromJson }} + {{- $oauth2Cfg := merge $redirectUris (get $parameters "oauth2-configuration" | default (dict)) }} + {{- $_ := set $parameters "oauth2-configuration" $oauth2Cfg }} + {{- end }} + {{- end }} parameters: {{- $jsonParameters | fromJson | merge $parameters | toYaml | nindent 4 }} {{- end }} diff --git a/files/configurableTemplatesChart/values.yaml.hbs b/files/configurableTemplatesChart/values.yaml.hbs index b9fc022..e64b136 100644 --- a/files/configurableTemplatesChart/values.yaml.hbs +++ b/files/configurableTemplatesChart/values.yaml.hbs @@ -41,3 +41,7 @@ workloads: {{/isApp}} contentDeploy: image: + {{#hasAms}} + amsDeployer: + image: + {{/hasAms}} diff --git a/files/ias.yaml.hbs b/files/ias.yaml.hbs new file mode 100644 index 0000000..8dd6096 --- /dev/null +++ b/files/ias.yaml.hbs @@ -0,0 +1,27 @@ +serviceInstances: + identity: + name: {{appName}}-identity + serviceOfferingName: identity + servicePlanName: application + parameters: + display-name: {{appName}} + multi-tenant: true + xsuaa-cross-consumption: true + {{#hasAms}} + authorization: + enabled: true + {{/hasAms}} + oauth2-configuration: + redirect-uris: [] + post-logout-redirect-uris: [] + home-url: "" + +serviceBindings: + identity: + name: {{appName}}-identity-bind + serviceInstanceName: {{appName}}-identity + secretName: {{appName}}-identity-bind-secret + secretKey: credentials + parameters: + credential-type: X509_GENERATED + app-identifier: {{appName}} diff --git a/files/runtime-values.yaml.hbs b/files/runtime-values.yaml.hbs index cebc5d6..05f91f8 100644 --- a/files/runtime-values.yaml.hbs +++ b/files/runtime-values.yaml.hbs @@ -1,4 +1,6 @@ serviceInstances: + {{#hasXsuaa}} + {{#isApp}} {{saasRegistryKeyName}}: parameters: xsappname: {{appName}} @@ -13,10 +15,37 @@ serviceInstances: getDependencies: "https://{{appName}}.{{clusterDomain}}/callback/v1.0/dependencies" {{/isService}} onSubscription: "https://{{capOperatorSubdomain}}.{{clusterDomain}}/provision/tenants/{tenantId}" + {{/isApp}} {{xsuaaKeyName}}: parameters: xsappname: {{appName}} - + {{/hasXsuaa}} + {{^hasXsuaa}} + {{#isApp}} + {{subscriptionManagerKeyName}}: + parameters: + appName: {{appName}} + commercialAppName: {{appName}} + displayName: ({{appName}}) + description: ({{appDescription}}) + category: CAP + appCallbacks: + dependenciesCallbacks: + url: "https://{{providerSubdomain}}.{{appName}}.{{clusterDomain}}/v1.0/callback/tenants/{app_tid}/dependencies" + subscriptionCallbacks: + url: "https://{{capOperatorSubdomain}}.{{clusterDomain}}/sms/provision/tenants/{app_tid}" + {{/isApp}} + {{identityKeyName}}: + parameters: + display-name: {{appName}} + home-url: "https://$BTP_SUBDOMAIN.{{appName}}.{{clusterDomain}}" + {{/hasXsuaa}} +{{^hasXsuaa}} +serviceBindings: + {{identityKeyName}}: + parameters: + app-identifier: {{appName}} +{{/hasXsuaa}} app: domains: primary: {{appName}}.{{clusterDomain}} diff --git a/files/saas-registry.yaml.hbs b/files/saas-registry.yaml.hbs index 32e43f3..c39638c 100644 --- a/files/saas-registry.yaml.hbs +++ b/files/saas-registry.yaml.hbs @@ -10,10 +10,12 @@ serviceInstances: displayName: ({{appName}}) description: ({{appDescription}}) appUrls: + getDependencies: "" + onSubscription: "" callbackTimeoutMillis: 300000 onSubscriptionAsync: true onUnSubscriptionAsync: true - category: "CAP" + category: CAP serviceBindings: saasRegistry: diff --git a/files/subscription-manager.yaml.hbs b/files/subscription-manager.yaml.hbs new file mode 100644 index 0000000..c979703 --- /dev/null +++ b/files/subscription-manager.yaml.hbs @@ -0,0 +1,30 @@ +serviceInstances: + subscriptionManager: + name: {{appName}}-subscription-manager + serviceOfferingName: subscription-manager + servicePlanName: provider + parameters: + iasServiceInstanceName: {{appName}}-identity + applicationType: application + appName: {{appName}} + commercialAppName: {{appName}} + displayName: ({{appName}}) + description: ({{appDescription}}) + category: CAP + appCallbacks: + dependenciesCallbacks: + url: "" + subscriptionCallbacks: + url: "" + async: + subscribeEnable: true + unSubscribeEnable: true + timeoutInMillis: 300000 + +serviceBindings: + subscriptionManager: + name: {{appName}}-subscription-manager-bind + serviceInstanceName: {{appName}}-subscription-manager + secretName: {{appName}}-subscription-manager-bind-secret + secretKey: credentials + parameters: {} diff --git a/files/workloads.yaml.hbs b/files/workloads.yaml.hbs index 8b5a719..9e1337c 100644 --- a/files/workloads.yaml.hbs +++ b/files/workloads.yaml.hbs @@ -6,23 +6,39 @@ workloads: consumedBTPServices: {{#hasXsuaa}} - {{appName}}-uaa-bind - {{/hasXsuaa}} - {{#hasMultitenancy}} + {{#isApp}} - {{appName}}-saas-registry-bind + {{/isApp}} + {{/hasXsuaa}} + {{#hasIas}} + - {{appName}}-identity-bind + {{#isApp}} + - {{appName}}-subscription-manager-bind + {{/isApp}} + {{/hasIas}} + {{#isApp}} - {{appName}}-service-manager-bind - {{/hasMultitenancy}} + {{/isApp}} deploymentDefinition: {{#isApp}} type: CAP {{/isApp}} {{#isService}} - type: service + type: Service ports: - name: server-port port: 4004 appProtocol: http {{/isService}} image: + {{#hasAms}} + env: + - name: AMS_DCL_ROOT + value: ams/dcl + securityContext: + runAsUser: 1000 + runAsGroup: 1000 + {{/hasAms}} contentDeploy: name: content-deploy @@ -32,9 +48,9 @@ workloads: {{#hasXsuaa}} - {{appName}}-uaa-bind {{/hasXsuaa}} - {{#hasMultitenancy}} - - {{appName}}-saas-registry-bind - {{/hasMultitenancy}} + {{#hasIas}} + - {{appName}}-identity-bind + {{/hasIas}} {{#hasHtml5Repo}} - {{appName}}-html5-repo-host-bind {{/hasHtml5Repo}} @@ -50,15 +66,32 @@ workloads: consumedBTPServices: {{#hasXsuaa}} - {{appName}}-uaa-bind - {{/hasXsuaa}} - {{#hasMultitenancy}} - {{appName}}-saas-registry-bind + {{/hasXsuaa}} + {{#hasIas}} + - {{appName}}-identity-bind + - {{appName}}-subscription-manager-bind + {{/hasIas}} - {{appName}}-service-manager-bind - {{/hasMultitenancy}} jobDefinition: type: TenantOperation image: {{/isApp}} + + {{#hasAms}} + amsDeployer: + name: ams-deployer + labels: + sme.sap.com/app-type: {{appName}} + consumedBTPServices: + {{#hasIas}} + - {{appName}}-identity-bind + {{/hasIas}} + jobDefinition: + type: Content + image: + {{/hasAms}} + {{#isService}} serviceExposures: - subDomain: {{appName}} @@ -66,3 +99,9 @@ serviceExposures: - workloadName: server port: 4004 {{/isService}} + +{{#hasAms}} +contentJobs: +- content-deploy +- ams-deployer +{{/hasAms}} diff --git a/lib/add.js b/lib/add.js index b0a3a5e..3e5bb48 100644 --- a/lib/add.js +++ b/lib/add.js @@ -8,11 +8,19 @@ const { copy, rimraf, exists, path, read, write } = cds.utils const { join } = path const yaml = require('@sap/cds-foss').yaml const md5 = data => require('crypto').createHash('md5').update(data).digest('hex') +const Mustache = require('mustache') const MtaTransformer = require('./mta-transformer') -const { isCAPOperatorChart, isConfigurableTemplateChart, injectTemplateFunction, transformValuesAndFillCapOpCroYaml, isServiceOnlyChart } = require('./util') - -const Mustache = require('mustache') +const { + isCAPOperatorChart, + isConfigurableTemplateChart, + transformValuesAndFillCapOpCroYaml, + isServiceOnlyChart, + getConfigurableCapOpCroYaml, + getCAPOpCroYaml, + getDomainCroYaml, + getHelperTpl +} = require('./util') module.exports = class CapOperatorAddPlugin extends cds.add.Plugin { @@ -41,18 +49,26 @@ module.exports = class CapOperatorAddPlugin extends cds.add.Plugin { } } + async canRun() { - const { hasMultitenancy, hasApprouter, hasXsuaa } = cds.add.readProject() - if (!hasXsuaa) { - console.log(`❌ xsuaa is not added to this project. Run 'cds add xsuaa'.`) + const { hasMultitenancy, hasApprouter, hasXsuaa, hasIas } = cds.add.readProject() + const isServiceOnly = cds.cli.options['with-service-only'] || isServiceOnlyChart('chart') + + if (!hasXsuaa && !hasIas) { + console.log(`❌ Neither xsuaa nor ias is added to this project. Run 'cds add xsuaa' or 'cds add ias'.`) return false - } else if (!hasApprouter && !exists('approuter') && !cds.cli.options['with-service-only']) { + } + + if (!hasApprouter && !exists('approuter') && !isServiceOnly) { console.log(`❌ approuter is not added to this project. Run 'cds add approuter'.`) return false - } else if (!hasMultitenancy && !cds.cli.options['with-service-only']) { + } + + if (!hasMultitenancy && !isServiceOnly) { console.log(`❌ multitenancy is not added to this project. Run 'cds add multitenancy'.`) return false } + return true } @@ -61,150 +77,82 @@ module.exports = class CapOperatorAddPlugin extends cds.add.Plugin { } async run() { - if (cds.cli.options['with-configurable-templates'] && cds.cli.options['with-templates']) { - throw new Error(`Option '--with-templates' cannot be used with '--with-configurable-templates' option.`) - } else if (!cds.cli.options['with-mta'] && cds.cli.options['with-mta-extensions']) { - throw new Error(`mta YAML not provided. Please pass the mta YAML via option '--with-mta'.`) - } else if (cds.cli.options['with-service-only'] && (cds.cli.options['with-mta'] || cds.cli.options['with-mta-extensions'])) { - throw new Error(`Option '--with-service-only' cannot be used with '--with-mta' or '--with-mta-extensions' options.`) - } + const opts = cds.cli.options + const isConfigurable = opts['with-configurable-templates'] + const isServiceOnly = opts['with-service-only'] + const withTemplates = opts['with-templates'] - if (cds.cli.options.force) - await rimraf('chart') + this.validateOptions(opts) - if (exists('chart')) { - const isConfigurableTempChart = isConfigurableTemplateChart('chart') - let loggingDone = false - if (!isCAPOperatorChart('chart')) { - throw new Error(`Existing 'chart' folder is not a CAP Operator helm chart. Run 'cds add cap-operator --force' to overwrite.`) - } - - if (!exists('chart/templates') && cds.cli.options['with-templates']) { - await this.copySimpleChartTemplates(isServiceOnlyChart('chart')) - console.log("Added 'templates' folder to the 'chart' folder.") - loggingDone = true - } - - if (!isConfigurableTempChart && cds.cli.options['with-configurable-templates']) { - console.log("CAP Operator chart already present. If you want to convert the existing chart to a configurable template chart, run 'npx cap-op-plugin convert-to-configurable-template-chart'") - } + if (opts.force) await rimraf('chart') - const valuesSchemaPath = isConfigurableTempChart ? '../files/configurableTemplatesChart/values.schema.json' : '../files/chart/values.schema.json' - if (md5(JSON.stringify(await read('chart/values.schema.json'))) !== md5(JSON.stringify(await read(join(__dirname, valuesSchemaPath))))) { - console.log("⚠️ 'values.schema.json' file is outdated. Run with '--force' to overwrite the file and accept the new changes.") - loggingDone = true - } - - if (!loggingDone) { - console.log("CAP Operator chart already present. If you want to overwrite the chart, use `--force' flag.") - } + // If chart folder exists, read the chart.yaml to determine if it's a service only chart + const project = this.readProject(isServiceOnly || isServiceOnlyChart('chart')) + if (exists('chart')) { + await this.handleExistingChart(project) return } - const project = this.readProject(cds.cli.options['with-service-only']) - - if (cds.cli.options['with-configurable-templates']) { - await copy(join(__dirname, '../files/configurableTemplatesChart/templates/_helpers.tpl')).to('chart/templates/_helpers.tpl') - await copy(join(__dirname, '../files/commonTemplates/')).to('chart/templates/') - cds.cli.options['with-service-only'] ? await copy(join(__dirname, '../files/configurableTemplatesChart/templates/cap-operator-cros-svc.yaml')).to('chart/templates/cap-operator-cros.yaml') : - await copy(join(__dirname, '../files/configurableTemplatesChart/templates/cap-operator-cros.yaml')).to('chart/templates/cap-operator-cros.yaml') - - await cds.add.merge(__dirname, '../files/configurableTemplatesChart/Chart.yaml.hbs').into('chart/Chart.yaml', { project }) - await cds.add.merge(__dirname, '../files/configurableTemplatesChart/values.yaml.hbs').into('chart/values.yaml', { project }) - await copy(join(__dirname, '../files/configurableTemplatesChart/values.schema.json')).to('chart/values.schema.json') - - const originalAppNameFunCode = `{{- define "originalAppName" -}}\n{{ print "` + project['appName'] + `" }}\n{{- end -}}` - injectTemplateFunction(join(cds.root, 'chart/templates/_helpers.tpl'), originalAppNameFunCode) + if (isConfigurable) { + await this.createConfigurableChart(project) } else { - await cds.add.merge(__dirname, '../files/chart/Chart.yaml.hbs').into('chart/Chart.yaml', { project }) - await cds.add.merge(__dirname, '../files/chart/values.yaml.hbs').into('chart/values.yaml', { project }) - await copy(join(__dirname, '../files/chart/values.schema.json')).to('chart/values.schema.json') - - if (cds.cli.options['with-templates']) - await this.copySimpleChartTemplates(cds.cli.options['with-service-only']) + await this.createSimpleChart(project, withTemplates) } console.log("`chart` folder generated.") - if (cds.cli.options['with-mta']) { - const { hasMta } = project - if (!hasMta) throw new Error(`mta is not added to this project. Run 'cds add mta'.`) - - const mtaTransformer = new MtaTransformer(cds.cli.options['with-mta'], cds.cli.options['with-mta-extensions'] ? cds.cli.options['with-mta-extensions'].split(',') : []) - - let updateValuesMap = new Map() - updateValuesMap.set('serviceInstances', await mtaTransformer.getServiceInstances()) - updateValuesMap.set('serviceBindings', await mtaTransformer.getServiceBindings()) - updateValuesMap.set('workloads', await mtaTransformer.getWorkloads()) - await this.updateValuesYaml(updateValuesMap) - - console.log("⚠️ Deriving values.yaml from mta.yaml cannot be done one to one. It's a best guess, so some information might be missing and needs to be reviewed and corrected by the application developer.") - - if (isConfigurableTemplateChart('chart')) { - await transformValuesAndFillCapOpCroYaml() - } + if (opts['with-mta']) { + await this.handleMtaIntegration(project) } else { console.log("Review and update the values.yaml file in the 'chart' folder as per your project's requirements.") } - // Update xs-security.json - const { hasXsuaa } = project - if (hasXsuaa) { - await cds.add.merge(__dirname, '../files/xs-security.json.hbs').into('xs-security.json', { - project, - additions: [{ in: 'scopes', where: { name: '$XSAPPNAME.Callback' } }, - { in: 'scopes', where: { name: '$XSAPPNAME.mtcallback' } }] - }) - } - + await this.updateXsSecurity(project) console.log("Once values.yaml is updated, run 'cds build' to generate the helm chart. You can find the generated chart in the 'gen' folder within your project directory.") } async combine() { - // In case of 'cds add cap-operator --with-mta', service instances, service bindings and workloads are derived from mta.yaml. No need to add them again. if (cds.cli.options['with-mta']) return const isServiceOnly = isServiceOnlyChart('chart') const project = this.readProject(isServiceOnly) - const { hasDestination, hasHtml5Repo, hasXsuaa, hasApprouter, hasMultitenancy } = project - const valuesYaml = yaml.parse(await read(join(cds.root, 'chart/values.yaml'))) - - if (hasDestination) { - const destinationYaml = yaml.parse(Mustache.render(await read(join(__dirname, '../files/destination.yaml.hbs')), project)) - await cds.add.merge(destinationYaml).into(valuesYaml) - } - - if (hasHtml5Repo) { - const html5RepoYaml = yaml.parse(Mustache.render(await read(join(__dirname, '../files/html5Repo.yaml.hbs')), project)) - await cds.add.merge(html5RepoYaml).into(valuesYaml) - } - - if (hasXsuaa) { - const xsuaaaYaml = yaml.parse(Mustache.render(await read(join(__dirname, '../files/xsuaa.yaml.hbs')), project)) - await cds.add.merge(xsuaaaYaml).into(valuesYaml) + const { + hasDestination, hasHtml5Repo, hasXsuaa, hasApprouter, + hasMultitenancy, hasIas + } = project + + const valuesPath = join(cds.root, 'chart/values.yaml') + const valuesYaml = yaml.parse(await read(valuesPath)) + + const addIf = async (condition, file) => { + if (condition) { + const rendered = Mustache.render(await read(join(__dirname, file)), project) + await cds.add.merge(yaml.parse(rendered)).into(valuesYaml) + } } - if (hasMultitenancy || isServiceOnly) { - const saasRegistryYaml = yaml.parse(Mustache.render(await read(join(__dirname, '../files/saas-registry.yaml.hbs')), project)) - await cds.add.merge(saasRegistryYaml).into(valuesYaml) + await addIf(hasDestination, '../files/destination.yaml.hbs') + await addIf(hasHtml5Repo, '../files/html5Repo.yaml.hbs') + await addIf(hasIas, '../files/ias.yaml.hbs') + await addIf(!hasIas && hasXsuaa, '../files/xsuaa.yaml.hbs') - const serviceManagerYaml = yaml.parse(Mustache.render(await read(join(__dirname, '../files/service-manager.yaml.hbs')), project)) - await cds.add.merge(serviceManagerYaml).into(valuesYaml) + if (hasMultitenancy) { + await addIf(hasIas, '../files/subscription-manager.yaml.hbs') + await addIf(!hasIas && hasXsuaa, '../files/saas-registry.yaml.hbs') + await addIf(true, '../files/service-manager.yaml.hbs') } if (!isConfigurableTemplateChart('chart')) { - if ((hasApprouter || exists('approuter')) && !isServiceOnly) { - const approuterYaml = yaml.parse(Mustache.render(await read(join(__dirname, '../files/approuter.yaml.hbs')), project)) - await cds.add.merge(approuterYaml).into(valuesYaml) - } - - const workloadsYaml = yaml.parse(Mustache.render(await read(join(__dirname, '../files/workloads.yaml.hbs')), project)) - await cds.add.merge(workloadsYaml).into(valuesYaml) + await addIf( + (hasApprouter || exists('approuter')) && !isServiceOnly, + '../files/approuter.yaml.hbs' + ) + await addIf(true, '../files/workloads.yaml.hbs') } - await write(yaml.stringify(valuesYaml)).to(join(cds.root, 'chart/values.yaml')) + await write(yaml.stringify(valuesYaml)).to(valuesPath) } async updateValuesYaml(updatedValues) { @@ -215,28 +163,119 @@ module.exports = class CapOperatorAddPlugin extends cds.add.Plugin { await write(yaml.stringify(valuesYaml)).to(join(cds.root, 'chart/values.yaml')) } - async copySimpleChartTemplates(isServiceOnly) { - await copy(join(__dirname, '../files/chart/templates/_helpers.tpl')).to('chart/templates/_helpers.tpl') - await copy(join(__dirname, '../files/commonTemplates/')).to('chart/templates/') - - isServiceOnly ? await copy(join(__dirname, '../files/chart/templates/cap-operator-cros-svc.yaml')).to('chart/templates/cap-operator-cros.yaml') : - await copy(join(__dirname, '../files/chart/templates/cap-operator-cros.yaml')).to('chart/templates/cap-operator-cros.yaml') - } - readProject(isServiceOnly) { return new Proxy(cds.add.readProject(), { get(target, prop) { - if (prop === 'isService') { - return isServiceOnly - } - if (prop === 'isApp') { - return !isServiceOnly - } + if (prop === 'isService') return isServiceOnly + if (prop === 'isApp') return !isServiceOnly return target[prop] }, has(target, prop) { - return prop === 'isService' || prop === 'isApp' || prop in target; + return ['isService', 'isApp'].includes(prop) || prop in target } }) } + + validateOptions(opts) { + if (opts['with-configurable-templates'] && opts['with-templates']) + throw new Error(`Option '--with-templates' cannot be used with '--with-configurable-templates'`) + + if (!opts['with-mta'] && opts['with-mta-extensions']) + throw new Error(`Missing mta YAML. Use '--with-mta' option`) + + if (opts['with-service-only'] && (opts['with-mta'] || opts['with-mta-extensions'])) + throw new Error(`Option '--with-service-only' cannot be used with '--with-mta' or '--with-mta-extensions'`) + } + + async handleExistingChart(project) { + const isConfigurable = isConfigurableTemplateChart('chart') + let loggingDone = false + + if (!isCAPOperatorChart('chart')) + throw new Error(`Existing 'chart' folder is not a CAP Operator helm chart. Run 'cds add cap-operator --force' to overwrite.`) + + if (!exists('chart/templates') && cds.cli.options['with-templates']) { + await this.copySimpleChartTemplates(project) + console.log("Added 'templates' folder to the 'chart' folder.") + loggingDone = true + } + + if (!isConfigurable && cds.cli.options['with-configurable-templates']) + console.log("CAP Operator chart already present. If you want to convert the existing chart to a configurable template chart, run 'npx cap-op-plugin convert-to-configurable-template-chart'") + + const valuesSchemaPath = isConfigurable + ? '../files/configurableTemplatesChart/values.schema.json' + : '../files/chart/values.schema.json' + + const existingSchema = await read('chart/values.schema.json') + const referenceSchema = await read(join(__dirname, valuesSchemaPath)) + + if (md5(JSON.stringify(existingSchema)) !== md5(JSON.stringify(referenceSchema))) { + console.log("⚠️ 'values.schema.json' file is outdated. Run with '--force' to overwrite the file and accept the new changes.") + loggingDone = true + } + + if (!loggingDone) + console.log("CAP Operator chart already present. If you want to overwrite the chart, use `--force' flag.") + } + + async createConfigurableChart(project) { + await copy(join(__dirname, '../files/commonTemplates/')).to('chart/templates/') + await write(getHelperTpl(project, true)).to('chart/templates/_helpers.tpl') + await write(getDomainCroYaml(project)).to('chart/templates/domain.yaml') + await write(getConfigurableCapOpCroYaml(project)).to('chart/templates/cap-operator-cros.yaml') + + await cds.add.merge(__dirname, '../files/configurableTemplatesChart/Chart.yaml.hbs').into('chart/Chart.yaml', { project }) + await cds.add.merge(__dirname, '../files/configurableTemplatesChart/values.yaml.hbs').into('chart/values.yaml', { project }) + await copy(join(__dirname, '../files/configurableTemplatesChart/values.schema.json')).to('chart/values.schema.json') + } + + async createSimpleChart(project, withTemplates) { + await cds.add.merge(__dirname, '../files/chart/Chart.yaml.hbs').into('chart/Chart.yaml', { project }) + await cds.add.merge(__dirname, '../files/chart/values.yaml.hbs').into('chart/values.yaml', { project }) + await copy(join(__dirname, '../files/chart/values.schema.json')).to('chart/values.schema.json') + + if (withTemplates) + await this.copySimpleChartTemplates(project) + } + + async copySimpleChartTemplates(project) { + await copy(join(__dirname, '../files/commonTemplates/')).to('chart/templates/') + await write(getHelperTpl(project, false)).to('chart/templates/_helpers.tpl') + await write(getDomainCroYaml(project)).to('chart/templates/domain.yaml') + await write(getCAPOpCroYaml(project)).to('chart/templates/cap-operator-cros.yaml') + } + + async handleMtaIntegration(project) { + if (!project.hasMta) + throw new Error(`mta is not added to this project. Run 'cds add mta'.`) + + const { ['with-mta']: mtaPath, ['with-mta-extensions']: mtaExt } = cds.cli.options + const mtaTransformer = new MtaTransformer(mtaPath, mtaExt ? mtaExt.split(',') : []) + + const updateValuesMap = new Map([ + ['serviceInstances', await mtaTransformer.getServiceInstances()], + ['serviceBindings', await mtaTransformer.getServiceBindings()], + ['workloads', await mtaTransformer.getWorkloads()] + ]) + + await this.updateValuesYaml(updateValuesMap) + + console.log("⚠️ Deriving values.yaml from mta.yaml cannot be done one to one. It's a best guess, so some information might be missing and needs to be reviewed and corrected by the application developer.") + + if (isConfigurableTemplateChart('chart')) + await transformValuesAndFillCapOpCroYaml() + } + + async updateXsSecurity(project) { + if (!project.hasXsuaa) return + await cds.add.merge(__dirname, '../files/xs-security.json.hbs').into('xs-security.json', { + project, + additions: [ + { in: 'scopes', where: { name: '$XSAPPNAME.Callback' } }, + { in: 'scopes', where: { name: '$XSAPPNAME.mtcallback' } } + ] + }) + } + } diff --git a/lib/build.js b/lib/build.js index 6fe1a10..4643af3 100644 --- a/lib/build.js +++ b/lib/build.js @@ -4,8 +4,15 @@ SPDX-License-Identifier: Apache-2.0 */ const cds = require('@sap/cds-dk') +const yaml = require('@sap/cds-foss').yaml const { exists, path } = cds.utils -const { isServiceOnlyChart } = require('./util') +const { + isServiceOnlyChart, + getCAPOpCroYaml, + getServiceInstanceKeyName, + getDomainCroYaml, + getHelperTpl +} = require('./util') module.exports = class CapOperatorBuildPlugin extends cds.build.Plugin { static hasTask() { @@ -30,11 +37,28 @@ module.exports = class CapOperatorBuildPlugin extends cds.build.Plugin { return await this.copy(path.join(this.task.src, 'chart/templates')).to(path.join(this.task.dest, 'templates')) } - await this.copy(path.join(__dirname, '../files/chart/templates/_helpers.tpl')).to(path.join(this.task.dest, 'templates/_helpers.tpl')) await this.copy(path.join(__dirname, '../files/commonTemplates/')).to(path.join(this.task.dest, 'templates/')) - isServiceOnlyChart('chart') ? await this.copy(path.join(__dirname, '../files/chart/templates/cap-operator-cros-svc.yaml')).to(path.join(this.task.dest, 'templates/cap-operator-cros.yaml')) : - await this.copy(path.join(__dirname, '../files/chart/templates/cap-operator-cros.yaml')).to(path.join(this.task.dest, 'templates/cap-operator-cros.yaml')) + const valuesYaml = yaml.parse(await cds.utils.read(path.join(this.task.src, 'chart/values.yaml'))) + + // Create _helpers.tpl + await cds.utils.write(getHelperTpl({ + hasXsuaa: getServiceInstanceKeyName(valuesYaml['serviceInstances'], 'xsuaa') != null + })).to(path.join(this.task.dest, 'templates/_helpers.tpl')) + + const hasIas = getServiceInstanceKeyName(valuesYaml['serviceInstances'], 'identity') != null + + // Create domain.yaml + await cds.utils.write(getDomainCroYaml({ + hasIas: hasIas + })).to(path.join(this.task.dest, 'templates/domain.yaml')) + + // Create cap-operator-cros.yaml + // Only filling those fields in the project input struct that are required to create CAPApplication + await cds.utils.write(getCAPOpCroYaml({ + hasIas: hasIas, + isService: isServiceOnlyChart('chart') + })).to(path.join(this.task.dest, 'templates/cap-operator-cros.yaml')) } async copyChartYaml() { diff --git a/lib/util.js b/lib/util.js index 2e98b9b..84b67ef 100644 --- a/lib/util.js +++ b/lib/util.js @@ -9,225 +9,781 @@ const readline = require('readline') const fs = require('fs') function replacePlaceholders(obj, replacements) { - if (typeof obj === "object") { - if (Array.isArray(obj)) { - // If it's an array, recursively process each element - for (let i = 0; i < obj.length; i++) { - obj[i] = replacePlaceholders(obj[i], replacements) - } - } else { - // If it's an object, recursively process each property - for (const prop in obj) { - if (obj.hasOwnProperty(prop)) { - obj[prop] = replacePlaceholders(obj[prop], replacements) - } - } + if (typeof obj === "object") { + if (Array.isArray(obj)) { + // If it's an array, recursively process each element + for (let i = 0; i < obj.length; i++) { + obj[i] = replacePlaceholders(obj[i], replacements) + } + } else { + // If it's an object, recursively process each property + for (const prop in obj) { + if (obj.hasOwnProperty(prop)) { + obj[prop] = replacePlaceholders(obj[prop], replacements) } - } else if (typeof obj === "string") { - // If it's a string, replace placeholders - Object.entries(replacements).forEach(([placeholder, value]) => { - const regex = new RegExp("\\${" + placeholder + "}", "g") - obj = obj.replace(regex, value) - }) + } } - return obj + } else if (typeof obj === "string") { + // If it's a string, replace placeholders + Object.entries(replacements).forEach(([placeholder, value]) => { + const regex = new RegExp("\\${" + placeholder + "}", "g") + obj = obj.replace(regex, value) + }) + } + return obj } function _isObject(item) { - return item && typeof item === 'object' && !Array.isArray(item) + return item && typeof item === 'object' && !Array.isArray(item) } function mergeObj(source, target) { - const unique = array => [...new Set(array.map(JSON.stringify))].map(JSON.parse) - if (_isObject(target) && _isObject(source)) { - for (const key in source) { - if (_isObject(source[key])) { - if (!target[key]) Object.assign(target, { [key]: source[key] }) - else mergeObj(source[key], target[key]) - } else if (Array.isArray(source[key]) && Array.isArray(target[key])) { - target[key] = unique([...source[key], ...target[key]]) - } else { - Object.assign(target, { [key]: target[key] || source[key] }) - } - } - } else if (Array.isArray(target) && Array.isArray(source)) { - target = unique([...source, ...target]) + const unique = array => [...new Set(array.map(JSON.stringify))].map(JSON.parse) + if (_isObject(target) && _isObject(source)) { + for (const key in source) { + if (_isObject(source[key])) { + if (!target[key]) Object.assign(target, { [key]: source[key] }) + else mergeObj(source[key], target[key]) + } else if (Array.isArray(source[key]) && Array.isArray(target[key])) { + target[key] = unique([...source[key], ...target[key]]) + } else { + Object.assign(target, { [key]: target[key] || source[key] }) + } } - return target ?? source + } else if (Array.isArray(target) && Array.isArray(source)) { + target = unique([...source, ...target]) + } + return target ?? source } function isCAPOperatorChart(chartFolderPath) { - try { - const chartYaml = cds.parse.yaml(cds.utils.fs.readFileSync(chartFolderPath + "/Chart.yaml").toString()) - return chartYaml.annotations?.["app.kubernetes.io/managed-by"] === 'cap-operator-plugin' || false - } catch (err) { - return false - } + try { + const chartYaml = cds.parse.yaml(cds.utils.fs.readFileSync(chartFolderPath + "/Chart.yaml").toString()) + return chartYaml.annotations?.["app.kubernetes.io/managed-by"] === 'cap-operator-plugin' || false + } catch (err) { + return false + } } function isConfigurableTemplateChart(chartFolderPath) { - try { - const chartYaml = cds.parse.yaml(cds.utils.fs.readFileSync(chartFolderPath + "/Chart.yaml").toString()) - return chartYaml.annotations?.["app.kubernetes.io/part-of"] === 'cap-operator-configurable-templates' || false - } catch (err) { - return false - } + try { + const chartYaml = cds.parse.yaml(cds.utils.fs.readFileSync(chartFolderPath + "/Chart.yaml").toString()) + return chartYaml.annotations?.["app.kubernetes.io/part-of"] === 'cap-operator-configurable-templates' || false + } catch (err) { + return false + } } function isServiceOnlyChart(chartFolderPath) { - try { - const chartYaml = cds.parse.yaml(cds.utils.fs.readFileSync(chartFolderPath + "/Chart.yaml").toString()) - return chartYaml.annotations?.["app.kubernetes.io/component"] === 'service-only' || false - } catch (err) { - return false - } + try { + const chartYaml = cds.parse.yaml(cds.utils.fs.readFileSync(chartFolderPath + "/Chart.yaml").toString()) + return chartYaml.annotations?.["app.kubernetes.io/component"] === 'service-only' || false + } catch (err) { + return false + } } async function ask(...args) { - const answers = [] - const rl = readline.createInterface({ - input: process.stdin, - output: process.stdout + const answers = [] + const rl = readline.createInterface({ + input: process.stdin, + output: process.stdout + }) + + function askQuestion(question, suggestion, mandatory) { + return new Promise((resolve) => { + const prompt = suggestion ? `${question} [${suggestion}] ` : `${question} ` + console.log() + rl.question(prompt, (answer) => { + const trimmedAnswer = answer.trim() + if (mandatory && !trimmedAnswer && !suggestion) { + // If the question is mandatory and no answer is provided, re-ask the question + console.error('\nThis question is mandatory. Please provide an answer.') + resolve(askQuestion(question, suggestion, mandatory)) + } else { + answers.push(trimmedAnswer || suggestion || '') + resolve() + } + }) }) + } - function askQuestion(question, suggestion, mandatory) { - return new Promise((resolve) => { - const prompt = suggestion ? `${question} [${suggestion}] ` : `${question} ` - console.log() - rl.question(prompt, (answer) => { - const trimmedAnswer = answer.trim() - if (mandatory && !trimmedAnswer && !suggestion) { - // If the question is mandatory and no answer is provided, re-ask the question - console.error('\nThis question is mandatory. Please provide an answer.') - resolve(askQuestion(question, suggestion, mandatory)) - } else { - answers.push(trimmedAnswer || suggestion || '') - resolve() - } - }) - }) + for (const [question, suggestion, mandatory] of args) { + await askQuestion(question, suggestion, mandatory) + } + + rl.close() + return answers +} + +async function transformValuesAndFillCapOpCroYaml() { + let valuesYaml = yaml.parse(await cds.utils.read(cds.utils.path.join(cds.root, 'chart/values.yaml'))) + const capOpCROYaml = cds.utils.fs.readFileSync(cds.utils.path.join(cds.root, 'chart/templates/cap-operator-cros.yaml'), 'utf8') + + // Update cap-operator-cro.yaml with existing values + let workloadArray = [] + let newWorkloadObj = {} + let tenantHostPattern = { name: 'TENANT_HOST_PATTERN', value: '{{ include "tenantHostPattern" . }}' } + for (const [workloadKey, workloadDetails] of Object.entries(valuesYaml.workloads)) { + if (workloadDetails?.deploymentDefinition?.type === 'Router') { + if (!workloadDetails.deploymentDefinition.env) { + workloadDetails.deploymentDefinition.env = [tenantHostPattern] + } else if (!workloadDetails.deploymentDefinition.env.some(e => e.name === tenantHostPattern.name)) { + workloadDetails.deploymentDefinition.env.push(tenantHostPattern) + } + } else if ((workloadDetails?.deploymentDefinition?.type === 'CAP' || workloadDetails?.deploymentDefinition?.type === 'Service') && workloadDetails.deploymentDefinition.env) { + const index = workloadDetails.deploymentDefinition.env.findIndex(e => e.name === 'CDS_CONFIG') + if (index > -1) { + const cdsConfigValueJson = JSON.parse(workloadDetails.deploymentDefinition.env[index].value) + if (cdsConfigValueJson?.requires?.['cds.xt.DeploymentService']?.hdi?.create?.database_id) { + valuesYaml['hanaInstanceId'] = cdsConfigValueJson.requires['cds.xt.DeploymentService'].hdi.create.database_id + cdsConfigValueJson.requires['cds.xt.DeploymentService'].hdi.create.database_id = '{{.Values.hanaInstanceId}}' + workloadDetails.deploymentDefinition.env[index].value = JSON.stringify(cdsConfigValueJson) + } + } + } else if (workloadDetails?.jobDefinition?.type === 'TenantOperation' && workloadDetails.jobDefinition.env) { + const index = workloadDetails.jobDefinition.env.findIndex(e => e.name === 'CDS_CONFIG') + if (index > -1) { + const cdsConfigValueJson = JSON.parse(workloadDetails.jobDefinition.env[index].value) + if (cdsConfigValueJson?.requires?.['cds.xt.DeploymentService']?.hdi?.create?.database_id) { + valuesYaml['hanaInstanceId'] = cdsConfigValueJson.requires['cds.xt.DeploymentService'].hdi.create.database_id + cdsConfigValueJson.requires['cds.xt.DeploymentService'].hdi.create.database_id = '{{.Values.hanaInstanceId}}' + workloadDetails.jobDefinition.env[index].value = JSON.stringify(cdsConfigValueJson) + } + } } - for (const [question, suggestion, mandatory] of args) { - await askQuestion(question, suggestion, mandatory) + let workloadKeyCamelCase = convertHypenNameToCamelcase(workloadKey) + if (workloadDetails.deploymentDefinition) { + newWorkloadObj[workloadKeyCamelCase] = { "image": workloadDetails.deploymentDefinition.image } + workloadDetails.deploymentDefinition.image = '{{.Values.workloads.' + workloadKeyCamelCase + '.image}}' + } else { + newWorkloadObj[workloadKeyCamelCase] = { "image": workloadDetails.jobDefinition.image } + workloadDetails.jobDefinition.image = '{{.Values.workloads.' + workloadKeyCamelCase + '.image}}' } - rl.close() - return answers + workloadArray.push(workloadDetails) + } + + let updatedCapOpCROYaml = capOpCROYaml.replace( + /workloads:(?:\s*\[\])?(?:\n(.*\n)*?)?(?=\n\s{2,}- name|spec:|$)/gm, + yaml.stringify({ 'workloads': workloadArray }, { indent: 2 }) + ) + + if (valuesYaml['tenantOperations']) { + updatedCapOpCROYaml = updatedCapOpCROYaml.replace( + /spec:\n((?:.*\n)*?)(\n[^ ]|$)/gm, + (match, p1, p2) => `spec:\n${p1} ${yaml.stringify({ 'tenantOperations': valuesYaml['tenantOperations'] }, { indent: 4 })}${p2}` + ) + delete valuesYaml['tenantOperations'] + } + + if (valuesYaml['contentJobs']) { + updatedCapOpCROYaml = updatedCapOpCROYaml.replace( + /spec:\n((?:.*\n)*?)(\n[^ ]|$)/gm, + (match, p1, p2) => `spec:\n${p1} ${yaml.stringify({ 'contentJobs': valuesYaml['contentJobs'] }, { indent: 2 })}${p2}` + ) + delete valuesYaml['contentJobs'] + } + + if (valuesYaml['serviceExposures']) { + updatedCapOpCROYaml = updatedCapOpCROYaml.replace( + /spec:\n((?:.*\n)*?)(\n[^ ]|$)/gm, + (match, p1, p2) => `spec:\n${p1} ${yaml.stringify({ 'serviceExposures': valuesYaml['serviceExposures'] }, { indent: 2 })}${p2}` + ) + delete valuesYaml['serviceExposures'] + } + + await cds.utils.write(updatedCapOpCROYaml).to(cds.utils.path.join(cds.root, 'chart/templates/cap-operator-cros.yaml')) + + valuesYaml['workloads'] = newWorkloadObj + await cds.utils.write(yaml.stringify(valuesYaml)).to(cds.utils.path.join(cds.root, 'chart/values.yaml')) +} + +function convertHypenNameToCamelcase(str) { + if (!str.includes('-')) { + return str + } + return str + .split('-') // Split the string into an array by the hyphen + .map((word, index) => { + // Capitalize the first letter of each word except the first word + if (index === 0) { + return word // Keep the first word in lowercase + } + return word.charAt(0).toUpperCase() + word.slice(1) + }).join('') // Join the words back together without spaces } -function injectTemplateFunction(templateFilePath, newFunctionCode) { - fs.readFile(templateFilePath, 'utf8', (err, data) => { - if (err) - throw new Error(`Error reading the file: ${err}; _helper.tpl modification failed`) +function getServiceInstanceKeyName(serviceInstances, offeringName) { + for (const key in serviceInstances) { + if (serviceInstances[key].serviceOfferingName === offeringName) + return key + } + return null +} - // Append the new function to the content - const updatedContent = data + '\n' + newFunctionCode + '\n' +function yamlBuilder() { + const lines = [] + let indent = 0 - fs.writeFile(templateFilePath, updatedContent, 'utf8', (err) => { - if (err) - throw new Error(`Error writing to the file: ${err}; _helper.tpl modification failed`) - }) + const push = (line = '') => { + if (Array.isArray(line)) { + lines.push(...line.map(l => l === '\n' ? '' : ' '.repeat(indent) + l)) + } else { + lines.push(line === '\n' ? '' : ' '.repeat(indent) + line) + } + } + + const inc = (n = 2) => (indent += n) + const dec = (n = 2) => (indent = Math.max(0, indent - n)) + + const block = (headerLines = [], fn) => { + if (headerLines.length) push(headerLines) + inc() + fn() + dec() + } + + return { push, block, inc, dec, toString: () => lines.join('\n') + '\n' } +} + +function writeCAPApplicationCRO(yaml, hasIas, isService) { + yaml.push([ + '---', + 'apiVersion: sme.sap.com/v1alpha1', + 'kind: CAPApplication' + ]) + + yaml.block(['metadata:'], () => { + yaml.push('name: {{ include "appName" $ }}') + if (hasIas) { + yaml.block(['annotations:'], () => { + yaml.push('sme.sap.com/vs-route-request-header-set: |') + yaml.push(' {') + yaml.push(' "x-forwarded-client-cert": "%DOWNSTREAM_PEER_CERT%"') + yaml.push(' }') + }) + } + }) + + yaml.block(['spec:'], () => { + yaml.push('domainRefs:') + yaml.push('- kind: Domain') + yaml.push(' name: {{ include "domainName" $ }}') + yaml.push('{{- range .Values.app.domains.additionalDomainRefs }}') + yaml.push('- kind: {{ .kind }}') + yaml.push(' name: {{ .name }}') + yaml.push('{{- end }}') + + yaml.push('btpAppName: {{ include "appName" $ }}') + yaml.push('globalAccountId: {{ .Values.btp.globalAccountId }}') + + if (!isService) { + yaml.block(['provider:'], () => { + yaml.push('subDomain: {{ .Values.btp.provider.subdomain }}') + yaml.push('tenantId: {{ .Values.btp.provider.tenantId }}') + }) + } + + yaml.block(['btp:'], () => { + yaml.push('services:') + yaml.push([ + '{{- $serviceInstances := .Values.serviceInstances }}', + '{{- range $k, $v := .Values.serviceBindings }}', + '{{- $serviceInstance := dict }}', + '{{- range $sik, $siv := $serviceInstances }}', + ' {{- if eq $siv.name $v.serviceInstanceName }}', + ' {{- $serviceInstance = $siv }}', + ' {{- end }}', + '{{- end }}', + '{{- if hasKey $serviceInstance "serviceOfferingName" }}', + '- class: {{ get $serviceInstance "serviceOfferingName" | default "invalidValue" }}', + ' {{- if $v.externalName }}', + ' name: {{ $v.externalName | default "invalidValue" }}', + ' {{- else }}', + ' name: {{ $v.name | default "invalidValue" }}', + ' {{- end }}', + ' secret: {{ $v.secretName | default "invalidValue" }}', + '{{- end }}', + '{{- end }}' + ]) }) + }) } -async function transformValuesAndFillCapOpCroYaml() { - let valuesYaml = yaml.parse(await cds.utils.read(cds.utils.path.join(cds.root, 'chart/values.yaml'))) - const capOpCROYaml = cds.utils.fs.readFileSync(cds.utils.path.join(cds.root, 'chart/templates/cap-operator-cros.yaml'), 'utf8') - - // Update cap-operator-cro.yaml with existing values - let workloadArray = [] - let newWorkloadObj = {} - let tenantHostPattern = { name: 'TENANT_HOST_PATTERN', value: '{{ include "tenantHostPattern" . }}' } - for (const [workloadKey, workloadDetails] of Object.entries(valuesYaml.workloads)) { - if (workloadDetails?.deploymentDefinition?.type === 'Router') { - if (!workloadDetails.deploymentDefinition.env) { - workloadDetails.deploymentDefinition.env = [tenantHostPattern] - } else if (!workloadDetails.deploymentDefinition.env.some(e => e.name === tenantHostPattern.name)) { - workloadDetails.deploymentDefinition.env.push(tenantHostPattern) - } - } else if ((workloadDetails?.deploymentDefinition?.type === 'CAP' || workloadDetails?.deploymentDefinition?.type === 'service') && workloadDetails.deploymentDefinition.env) { - const index = workloadDetails.deploymentDefinition.env.findIndex(e => e.name === 'CDS_CONFIG') - if (index > -1) { - const cdsConfigValueJson = JSON.parse(workloadDetails.deploymentDefinition.env[index].value) - if (cdsConfigValueJson?.requires?.['cds.xt.DeploymentService']?.hdi?.create?.database_id) { - valuesYaml['hanaInstanceId'] = cdsConfigValueJson.requires['cds.xt.DeploymentService'].hdi.create.database_id - cdsConfigValueJson.requires['cds.xt.DeploymentService'].hdi.create.database_id = '{{.Values.hanaInstanceId}}' - workloadDetails.deploymentDefinition.env[index].value = JSON.stringify(cdsConfigValueJson) - } - } - } else if (workloadDetails?.jobDefinition?.type === 'TenantOperation' && workloadDetails.jobDefinition.env) { - const index = workloadDetails.jobDefinition.env.findIndex(e => e.name === 'CDS_CONFIG') - if (index > -1) { - const cdsConfigValueJson = JSON.parse(workloadDetails.jobDefinition.env[index].value) - if (cdsConfigValueJson?.requires?.['cds.xt.DeploymentService']?.hdi?.create?.database_id) { - valuesYaml['hanaInstanceId'] = cdsConfigValueJson.requires['cds.xt.DeploymentService'].hdi.create.database_id - cdsConfigValueJson.requires['cds.xt.DeploymentService'].hdi.create.database_id = '{{.Values.hanaInstanceId}}' - workloadDetails.jobDefinition.env[index].value = JSON.stringify(cdsConfigValueJson) - } - } +function writeCAPApplicationVersionCommonCRO(yaml) { + // Common part of CAPApplicationVersion can be added here if needed in the future + yaml.push([ + '---', + 'apiVersion: sme.sap.com/v1alpha1', + 'kind: CAPApplicationVersion', + 'metadata:', + ' annotations:', + ' helm.sh/hook: post-install,post-upgrade', + ' helm.sh/resource-policy: keep', + ' name: {{ include "capApplicationVersionName" $ }}', + 'spec:', + ' capApplicationInstance: {{ include "appName" $ }}', + ' version: "{{ .Release.Revision }}"', + ' registrySecrets:', + ' {{- range .Values.imagePullSecrets }}', + ' - {{ . }}', + ' {{- end }}' + ]) +} + +function getConfigurableCapOpCroYaml(project) { + const yaml = yamlBuilder() + const { hasDestination, hasHtml5Repo, hasXsuaa, hasApprouter, hasMultitenancy, hasIas, isService, hasAms } = project + + // === CAPApplicationCRO === + writeCAPApplicationCRO(yaml, hasIas, isService) + + // === CAPApplicationVersion Common=== + writeCAPApplicationVersionCommonCRO(yaml) + + // === Workloads === + yaml.push(' workloads:') + yaml.inc() // indent workloads items + + // --- Server Workload --- + yaml.block([ + '- name: server', + ' labels:', + ' sme.sap.com/app-type: {{ include "appName" $ }}', + ' consumedBTPServices:'], () => { + if (hasXsuaa) yaml.push('- {{ include "originalAppName" $ }}-uaa-bind') + if (hasIas) yaml.push('- {{ include "originalAppName" $ }}-identity-bind') + if (hasMultitenancy && hasXsuaa) { + yaml.push([ + '- {{ include "originalAppName" $ }}-saas-registry-bind', + '- {{ include "originalAppName" $ }}-service-manager-bind' + ]) + } + if (hasMultitenancy && hasIas) { + yaml.push([ + '- {{ include "originalAppName" $ }}-subscription-manager-bind', + '- {{ include "originalAppName" $ }}-service-manager-bind' + ]) + } + + yaml.block(['deploymentDefinition:'], () => { + if (isService) { + yaml.push([ + 'type: Service', + 'ports:', + '- name: server-port', + ' port: 4004', + ' appProtocol: http' + ]) + } else { + yaml.push('type: CAP') } + yaml.push([ + 'image: {{ .Values.workloads.server.image }}', + ]) - let workloadKeyCamelCase = convertHypenNameToCamelcase(workloadKey) - if (workloadDetails.deploymentDefinition) { - newWorkloadObj[workloadKeyCamelCase] = { "image": workloadDetails.deploymentDefinition.image } - workloadDetails.deploymentDefinition.image = '{{.Values.workloads.' + workloadKeyCamelCase + '.image}}' + if (hasAms) { + yaml.push([ + `env:`, + `- name: AMS_DCL_ROOT`, + ` value: ams/dcl`, + '{{- if .Values.hanaInstanceId }}', + '- name: CDS_CONFIG', + ' value: \'{"requires":{"cds.xt.DeploymentService":{"hdi":{"create":{"database_id":"{{ .Values.hanaInstanceId }}"}}}}}\'', + '{{- end }}', + `securityContext:`, + ` runAsUser: 1000`, + ` runAsGroup: 1000` + ]) } else { - newWorkloadObj[workloadKeyCamelCase] = { "image": workloadDetails.jobDefinition.image } - workloadDetails.jobDefinition.image = '{{.Values.workloads.' + workloadKeyCamelCase + '.image}}' + yaml.push([ + '{{- if .Values.hanaInstanceId }}', + 'env:', + '- name: CDS_CONFIG', + ' value: \'{"requires":{"cds.xt.DeploymentService":{"hdi":{"create":{"database_id":"{{ .Values.hanaInstanceId }}"}}}}}\'', + '{{- end }}' + ]) } + }) + }) - workloadArray.push(workloadDetails) - } + // --- App Router Workload --- + if (hasApprouter) { + yaml.block([ + '- name: app-router', + ' labels:', + ' sme.sap.com/app-type: {{ include "appName" $ }}', + ' consumedBTPServices:'], () => { + if (hasXsuaa) yaml.push('- {{ include "originalAppName" $ }}-uaa-bind') + if (hasIas) yaml.push('- {{ include "originalAppName" $ }}-identity-bind') + if (hasMultitenancy && hasXsuaa) yaml.push('- {{ include "originalAppName" $ }}-saas-registry-bind') + if (hasMultitenancy && hasIas) yaml.push('- {{ include "originalAppName" $ }}-subscription-manager-bind') + if (hasDestination) yaml.push('- {{ include "originalAppName" $ }}-destination-bind') + if (hasHtml5Repo) yaml.push('- {{ include "originalAppName" $ }}-html5-repo-runtime-bind') - let updatedCapOpCROYaml = capOpCROYaml.replace( - /workloads:\n(.*\n)*?(?=\n\s{2,}- name|spec:|$)/gm, - yaml.stringify({ 'workloads': workloadArray }, { indent: 2 }) - ) + yaml.block(['deploymentDefinition:'], () => { + yaml.push([ + 'type: Router', + 'image: {{ .Values.workloads.appRouter.image }}', + 'env:', + '- name: TENANT_HOST_PATTERN', + ' value: {{ include "tenantHostPattern" . }}', + 'ports:', + '- name: router-port', + ' port: 5000' + ]) + }) + }) + } - if (valuesYaml['tenantOperations']) { - updatedCapOpCROYaml = updatedCapOpCROYaml.replace( - /spec:\n((?:.*\n)*?)(\n[^ ]|$)/gm, - (match, p1, p2) => `spec:\n${p1} ${yaml.stringify({ 'tenantOperations': valuesYaml['tenantOperations'] }, { indent: 4 })}${p2}` - ) - delete valuesYaml['tenantOperations'] - } + // --- Tenant Job Workload --- + if (!isService) { + yaml.block([ + '- name: tenant-job', + ' labels:', + ' sme.sap.com/app-type: {{ include "appName" $ }}', + ' consumedBTPServices:'], () => { + if (hasXsuaa) yaml.push('- {{ include "originalAppName" $ }}-uaa-bind') + if (hasIas) yaml.push('- {{ include "originalAppName" $ }}-identity-bind') + if (hasMultitenancy && hasXsuaa) { + yaml.push([ + '- {{ include "originalAppName" $ }}-saas-registry-bind', + '- {{ include "originalAppName" $ }}-service-manager-bind' + ]) + } + if (hasMultitenancy && hasIas) { + yaml.push([ + '- {{ include "originalAppName" $ }}-subscription-manager-bind', + '- {{ include "originalAppName" $ }}-service-manager-bind' + ]) + } - if (valuesYaml['contentJobs']) { - updatedCapOpCROYaml = updatedCapOpCROYaml.replace( - /spec:\n((?:.*\n)*?)(\n[^ ]|$)/gm, - (match, p1, p2) => `spec:\n${p1} ${yaml.stringify({ 'contentJobs': valuesYaml['contentJobs'] }, { indent: 2 })}${p2}` - ) - delete valuesYaml['contentJobs'] - } + yaml.block(['jobDefinition:'], () => { + yaml.push([ + 'type: TenantOperation', + 'image: {{ .Values.workloads.tenantJob.image }}', + '{{- if .Values.hanaInstanceId }}', + 'env:', + '- name: CDS_CONFIG', + ' value: \'{"requires":{"cds.xt.DeploymentService":{"hdi":{"create":{"database_id":"{{ .Values.hanaInstanceId }}"}}}}}\'', + '{{- end }}' + ]) + }) + }) + } - if (valuesYaml['serviceExposures']) { - updatedCapOpCROYaml = updatedCapOpCROYaml.replace( - /spec:\n((?:.*\n)*?)(\n[^ ]|$)/gm, - (match, p1, p2) => `spec:\n${p1} ${yaml.stringify({ 'serviceExposures': valuesYaml['serviceExposures'] }, { indent: 2 })}${p2}` - ) - delete valuesYaml['serviceExposures'] - } + // --- Content Deploy Job --- + yaml.block([ + '- name: content-deploy', + ' labels:', + ' sme.sap.com/app-type: {{ include "appName" $ }}', + ' consumedBTPServices:'], () => { + if (hasXsuaa) yaml.push('- {{ include "originalAppName" $ }}-uaa-bind') + if (hasIas) yaml.push('- {{ include "originalAppName" $ }}-identity-bind') + if (hasHtml5Repo) yaml.push('- {{ include "originalAppName" $ }}-html5-repo-host-bind') + + yaml.block(['jobDefinition:'], () => { + yaml.push('type: Content') + yaml.push('image: {{ .Values.workloads.contentDeploy.image }}') + }) + }) + + // -- AMS Deployer Content Job --- + if (hasAms) { + yaml.block([ + '- name: ams-deployer', + ' labels:', + ' sme.sap.com/app-type: {{ include "appName" $ }}', + ' consumedBTPServices:'], () => { + if (hasIas) yaml.push('- {{ include "originalAppName" $ }}-identity-bind') + + yaml.block(['jobDefinition:'], () => { + yaml.push('type: Content') + yaml.push('image: {{ .Values.workloads.amsDeployer.image }}') + }) + }) + } + + yaml.dec() // unindent workloads + + // --- Service Exposure --- + if (isService) { + yaml.block([' serviceExposures:'], () => { + yaml.block([ + '- subDomain: {{ include "appName" $ }}', + ' routes:'], () => { + yaml.push([ + '- workloadName: server', + ' port: 4004' + ]) + }) + }) + } - cds.utils.fs.writeFileSync(cds.utils.path.join(cds.root, 'chart/templates/cap-operator-cros.yaml'), updatedCapOpCROYaml) + // -- Content Jobs --- + if (hasAms) { + yaml.block([' contentJobs:'], () => { + yaml.push([ + '- content-deploy', + '- ams-deployer' + ]) + }) + } - valuesYaml['workloads'] = newWorkloadObj - await cds.utils.write(yaml.stringify(valuesYaml)).to(cds.utils.path.join(cds.root, 'chart/values.yaml')) + return yaml.toString() } -function convertHypenNameToCamelcase(str) { - if (!str.includes('-')) { - return str +function getCAPOpCroYaml(project) { + const yaml = yamlBuilder() + const { hasIas, isService } = project + + // === CAPApplicationCRO === + writeCAPApplicationCRO(yaml, hasIas, isService) + + // === CAPApplicationVersion Common=== + writeCAPApplicationVersionCommonCRO(yaml) + + // === Workloads === + yaml.block([' workloads:'], () => { + yaml.push([ + '{{- range $k, $v := .Values.workloads }}', + '- name: {{ $v.name }}', + '\n', + ' {{- if $v.labels }}', + ' labels: {{- toYaml $v.labels | trim | nindent 6 }}', + ' {{- end }}', + '\n', + ' {{- if $v.annotations }}', + ' annotations: {{- toYaml $v.annotations | trim | nindent 6 }}', + ' {{- end }}', + '\n', + ' {{- if $v.consumedBTPServices }}', + ' consumedBTPServices: {{- toYaml $v.consumedBTPServices | trim | nindent 4 }}', + ' {{- end }}', + '\n', + ' {{- if and $v.deploymentDefinition (eq $v.deploymentDefinition.type "Router") }}', + ' {{- $thp := include "tenantHostPattern" $ }}', + ' {{- $tphEnv := list (dict "name" "TENANT_HOST_PATTERN" "value" $thp) }}', + ' {{- $baseEnv := get $v.deploymentDefinition "env" | default (list) }}', + ' {{- $exists := false }}', + ' {{- range $baseVar := $baseEnv }}', + ' {{- if eq $baseVar.name "TENANT_HOST_PATTERN" }}', + ' {{- $exists = true }}', + ' {{- end }}', + ' {{- end }}', + ' {{- if not $exists }}', + ' {{- $baseEnv = concat $baseEnv $tphEnv }}', + ' {{- end }}', + ' {{- $modified := merge (dict "env" $baseEnv) $v.deploymentDefinition }}', + ' deploymentDefinition: {{- toYaml $modified | trim | nindent 6 }}', + ' {{- else if $v.deploymentDefinition }}', + ' deploymentDefinition: {{- toYaml $v.deploymentDefinition | trim | nindent 6 }}', + ' {{- end }}', + '\n', + ' {{- if $v.jobDefinition }}', + ' jobDefinition: {{- toYaml $v.jobDefinition | trim | nindent 6 }}', + ' {{- end }}', + '{{- end }}' + ]) + }) + + if (!isService) { + yaml.push([ + '\n', + ' {{- if .Values.tenantOperations }}', + ' tenantOperations: {{- toYaml .Values.tenantOperations | trim | nindent 4 }}', + ' {{- end }}' + ]) + } + + yaml.push([ + '\n', + ' {{- if .Values.contentJobs }}', + ' contentJobs: {{- toYaml .Values.contentJobs | trim | nindent 4 }}', + ' {{- end }}' + ]) + + // --- Service Exposure --- + if (isService) { + yaml.push([ + '\n', + ' {{- if .Values.serviceExposures }}', + ' serviceExposures: {{- toYaml .Values.serviceExposures | trim | nindent 4 }}', + ' {{- end }}' + ]) + } + + return yaml.toString() +} + +function getDomainCroYaml(project) { + const yaml = yamlBuilder() + const { hasIas } = project + + yaml.push([ + 'apiVersion: sme.sap.com/v1alpha1', + 'kind: Domain' + ]) + + yaml.block(['metadata:'], () => { + yaml.push('name: {{ include "domainName" $ }}') + }) + + yaml.block(['spec:'], () => { + yaml.push([ + 'dnsMode: Wildcard', + 'domain: {{ .Values.app.domains.primary }}', + 'ingressSelector:', + '{{- range $k, $v := $.Values.app.istioIngressGatewayLabels }}', + ' {{ $k }}: {{ $v | default "invalidValue" }}', + '{{- end }}', + ]) + + if (hasIas) { + yaml.push([ + 'certConfig:', + ' additionalCACertificate: |', + ' -----BEGIN CERTIFICATE-----', + ' MIIFZjCCA06gAwIBAgIQGHcPvmUGa79M6pM42bGFYjANBgkqhkiG9w0BAQsFADBN', + ' MQswCQYDVQQGEwJERTERMA8GA1UEBwwIV2FsbGRvcmYxDzANBgNVBAoMBlNBUCBT', + ' RTEaMBgGA1UEAwwRU0FQIENsb3VkIFJvb3QgQ0EwHhcNMTkwMjEzMTExOTM2WhcN', + ' MzkwMjEzMTEyNjMyWjBNMQswCQYDVQQGEwJERTERMA8GA1UEBwwIV2FsbGRvcmYx', + ' DzANBgNVBAoMBlNBUCBTRTEaMBgGA1UEAwwRU0FQIENsb3VkIFJvb3QgQ0EwggIi', + ' MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQChbHLXJoe/zFag6fB3IcN3d3HT', + ' Y14nSkEZIuUzYs7B96GFxQi0T/2s971JFiLfB4KaCG+UcG3dLXf1H/wewq8ahArh', + ' FTsu4UR71ePUQiYlk/G68EFSy2zWYAJliXJS5k0DFMIWHD1lbSjCF3gPVJSUKf+v', + ' HmWD5e9vcuiPBlSCaEnSeimYRhg0ITmi3RJ4Wu7H0Xp7tDd5z4HUKuyi9XRinfvG', + ' kPALiBaX01QRC51cixmo0rhVe7qsNh7WDnLNBZeA0kkxNhLKDl8J6fQHKDdDEzmZ', + ' KhK5KxL5p5YIZWZ8eEdNRoYRMXR0PxmHvRanzRvSVlXSbfqxaKlORfJJ1ah1bRNt', + ' o0ngAQchTghsrRuf3Qh/2Kn29IuBy4bjKR9CdNLxGrClvX/q26rUUlz6A3lbXbwJ', + ' EHSRnendRfEiia+xfZD+NG2oZW0IdTXSqkCbnBnign+uxGH5ECjuLEtvtUx6i9Ae', + ' xAvK2FqIuud+AchqiZBKzmQAhUjKUoACzNP2Bx2zgJOeB0BqGvf6aldG0n2hYxJF', + ' 8Xssc8TBlwvAqtiubP/UxJJPs+IHqU+zjm7KdP6dM2sbE+J9O3n8DzOP0SDyEmWU', + ' UCwnmoPOQlq1z6fH9ghcp9bDdbh6adXM8I+SUYUcfvupOzBU7rWHxDCXld/24tpI', + ' FA7FRzHwKXqMSjwtBQIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/', + ' BAUwAwEB/zAdBgNVHQ4EFgQUHLxmKw7KjUufjZNxqQ/KZ0ZpEyIwDQYJKoZIhvcN', + ' AQELBQADggIBABdSKQsh3EfVoqplSIx6X43y2Pp+kHZLtEsRWMzgO5LhYy2/Fvel', + ' eRBw/XEiB5iKuEGhxHz/Gqe0gZixw3SsHB1Q464EbGT4tPQ2UiMhiiDho9hVe6tX', + ' qX1FhrhycAD1xHIxMxQP/buX9s9arFZauZrpw/Jj4tGp7aEj4hypWpO9tzjdBthy', + ' 5vXSviU8L2HyiQpVND/Rp+dNJmVYTiFLuULRY28QbikgFO2xp9s4RNkDBnbDeTrT', + ' CKWcVsmlZLPJJQZm0n2p8CvoeAsKzIULT9YSbEEBwmeqRlmbUaoT/rUGoobSFcrP', + ' jrBg66y5hA2w7S3tDH0GjMpRu16b2u0hYQocUDuMlyhrkhsO+Qtqkz1ubwHCJ8PA', + ' RJw6zYl9VeBtgI5F69AEJdkAgYfvPw5DJipgVuQDSv7ezi6ZcI75939ENGjSyLVy', + ' 4SuP99G7DuItG008T8AYFUHAM2h/yskVyvoZ8+gZx54TC9aY9gPIKyX++4bHv5BC', + ' qbEdU46N05R+AIBW2KvWozQkjhSQCbzcp6DHXLoZINI6y0WOImzXrvLUSIm4CBaj', + ' 6MTXInIkmitdURnmpxTxLva5Kbng/u20u5ylIQKqpcD8HWX97lLVbmbnPkbpKxo+', + ' LvHPhNDM3rMsLu06agF4JTbO8ANYtWQTx0PVrZKJu+8fcIaUp7MVBIVZ', + ' -----END CERTIFICATE-----', + 'tlsMode: OptionalMutual' + ]) + } else { + yaml.push('tlsMode: Simple') } - return str - .split('-') // Split the string into an array by the hyphen - .map((word, index) => { - // Capitalize the first letter of each word except the first word - if (index === 0) { - return word // Keep the first word in lowercase - } - return word.charAt(0).toUpperCase() + word.slice(1) - }).join('') // Join the words back together without spaces + }) + + return yaml.toString() } -module.exports = { replacePlaceholders, mergeObj, isCAPOperatorChart, isConfigurableTemplateChart, isServiceOnlyChart, ask, injectTemplateFunction, transformValuesAndFillCapOpCroYaml, convertHypenNameToCamelcase } +function getHelperTpl(project, isConfigurableTemplateChart) { + const yaml = yamlBuilder() + const { hasXsuaa } = project + + yaml.push([ + '{{- define "capApplicationVersionName" -}}', + '{{ printf "%s-%d" (include "appName" $) (.Release.Revision) }}', + '{{- end -}}', + '\n', + '{{- define "domainName" -}}', + '{{ printf "%s-primary" (include "appName" $)}}', + '{{- end -}}', + '\n' + ]) + if (hasXsuaa) { + yaml.push([ + '{{- define "appName" -}}', + '{{- range $sik, $siv := .Values.serviceInstances }}', + ' {{- if and (eq (get $siv "serviceOfferingName") "xsuaa") (eq (get $siv "servicePlanName") "broker") -}}', + ' {{ printf "%s" $siv.parameters.xsappname }}', + ' {{- break -}}', + ' {{- end -}}', + '{{- end -}}', + '{{- end -}}', + '\n' + ]) + } else { + yaml.push([ + '{{- define "appName" -}}', + '{{- range $sik, $siv := .Values.serviceInstances }}', + ' {{- if and (eq (get $siv "serviceOfferingName") "subscription-manager") (eq (get $siv "servicePlanName") "provider") -}}', + ' {{ printf "%s" $siv.parameters.appName }}', + ' {{- break -}}', + ' {{- end -}}', + '{{- end -}}', + '{{- end -}}', + '\n' + ]) + } + yaml.push([ + '{{- define "domainHostMap" -}}', + ' {{- $domains := list .Values.app.domains.primary -}}', + ' {{- range .Values.app.domains.additionalDomainRefs }}', + ' {{- $apiVersion := "sme.sap.com/v1alpha1" -}}', + ' {{- $namespace := (eq .kind "Domain" | ternary $.Release.Namespace "") -}}', + ' {{- $resource := (lookup $apiVersion .kind $namespace .name) -}}', + ' {{- if and $resource (kindIs "map" $resource) (hasKey $resource "spec") (hasKey $resource.spec "domain") -}}', + ' {{- $domains = append $domains $resource.spec.domain -}}', + ' {{- end -}}', + ' {{- end -}}', + ' {{- toJson (dict "domains" $domains) -}}', + '{{- end }}', + '\n', + '{{- define "redirectUris" -}}', + ' {{- $ctx := .context -}}', + ' {{- $svc := .serviceOfferingName -}}', + ' {{- $domains := (include "domainHostMap" $ctx | fromJson).domains -}}', + ' {{- $redirectUris := list -}}', + ' {{- range $domains }}', + ' {{- $redirectUris = append $redirectUris (printf "https://*.%s/**" .) -}}', + ' {{- end -}}', + ' {{- if eq $svc "identity" }}', + ' {{- toJson (dict "redirect-uris" $redirectUris "post-logout-redirect-uris" $redirectUris) -}}', + ' {{- else }}', + ' {{- toJson (dict "redirect-uris" $redirectUris) -}}', + ' {{- end -}}', + '{{- end }}', + '\n', + '{{- define "tenantHostPattern" -}}', + ' {{- $domains := (include "domainHostMap" . | fromJson).domains -}}', + ' {{- printf "^(.*)\\\\.(%s)" (join "|" $domains | replace "." "\\\\.") -}}', + '{{- end }}' + ]) + + if (isConfigurableTemplateChart) { + yaml.push([ + '\n', + '{{- define "originalAppName" -}}', + `{{ print "` + project.appName + `" }}`, + '{{- end -}}' + ]) + } + + return yaml.toString() +} + +module.exports = { + replacePlaceholders, + mergeObj, + isCAPOperatorChart, + isConfigurableTemplateChart, + isServiceOnlyChart, + ask, + transformValuesAndFillCapOpCroYaml, + convertHypenNameToCamelcase, + getServiceInstanceKeyName, + getConfigurableCapOpCroYaml, + getCAPOpCroYaml, + getDomainCroYaml, + getHelperTpl +} diff --git a/package-lock.json b/package-lock.json index f5bdbed..f0e31b2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -42,9 +42,9 @@ } }, "node_modules/@babel/compat-data": { - "version": "7.28.4", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.28.4.tgz", - "integrity": "sha512-YsmSKC29MJwf0gF8Rjjrg5LQCmyh+j/nD8/eP7f+BeoQTKYqs9RoWbjGOdy0+1Ekr68RJZMUOPVQaQisnIo4Rw==", + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.28.5.tgz", + "integrity": "sha512-6uFXyCayocRbqhZOB+6XcuZbkMNimwfVGFji8CTZnCzOHVGvDqzvitu1re2AU5LROliz7eQPhB8CpAMvnx9EjA==", "dev": true, "license": "MIT", "engines": { @@ -52,21 +52,21 @@ } }, "node_modules/@babel/core": { - "version": "7.28.4", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.4.tgz", - "integrity": "sha512-2BCOP7TN8M+gVDj7/ht3hsaO/B/n5oDbiAyyvnRlNOs+u1o+JWNYTQrmpuNp1/Wq2gcFrI01JAW+paEKDMx/CA==", + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.5.tgz", + "integrity": "sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw==", "dev": true, "license": "MIT", "dependencies": { "@babel/code-frame": "^7.27.1", - "@babel/generator": "^7.28.3", + "@babel/generator": "^7.28.5", "@babel/helper-compilation-targets": "^7.27.2", "@babel/helper-module-transforms": "^7.28.3", "@babel/helpers": "^7.28.4", - "@babel/parser": "^7.28.4", + "@babel/parser": "^7.28.5", "@babel/template": "^7.27.2", - "@babel/traverse": "^7.28.4", - "@babel/types": "^7.28.4", + "@babel/traverse": "^7.28.5", + "@babel/types": "^7.28.5", "@jridgewell/remapping": "^2.3.5", "convert-source-map": "^2.0.0", "debug": "^4.1.0", @@ -90,9 +90,9 @@ "license": "MIT" }, "node_modules/@babel/core/node_modules/debug": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", - "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", "dev": true, "license": "MIT", "dependencies": { @@ -125,14 +125,14 @@ } }, "node_modules/@babel/generator": { - "version": "7.28.3", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.3.tgz", - "integrity": "sha512-3lSpxGgvnmZznmBkCRnVREPUFJv2wrv9iAoFDvADJc0ypmdOxdUtcLeBgBJ6zE0PMeTKnxeQzyk0xTBq4Ep7zw==", + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.5.tgz", + "integrity": "sha512-3EwLFhZ38J4VyIP6WNtt2kUdW9dokXA9Cr4IVIFHuCpZ3H8/YFOl5JjZHisrn1fATPBmKKqXzDFvh9fUwHz6CQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/parser": "^7.28.3", - "@babel/types": "^7.28.2", + "@babel/parser": "^7.28.5", + "@babel/types": "^7.28.5", "@jridgewell/gen-mapping": "^0.3.12", "@jridgewell/trace-mapping": "^0.3.28", "jsesc": "^3.0.2" @@ -221,9 +221,9 @@ } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz", - "integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==", + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", + "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", "dev": true, "license": "MIT", "engines": { @@ -255,13 +255,13 @@ } }, "node_modules/@babel/parser": { - "version": "7.28.4", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.4.tgz", - "integrity": "sha512-yZbBqeM6TkpP9du/I2pUZnJsRMGGvOuIrhjzC1AwHwW+6he4mni6Bp/m8ijn0iOuZuPI2BfkCoSRunpyjnrQKg==", + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.5.tgz", + "integrity": "sha512-KKBU1VGYR7ORr3At5HAtUQ+TV3SzRCXmA/8OdDZiLDBIZxVyzXuztPjfLd3BV1PRAQGCMWWSHYhL0F8d5uHBDQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/types": "^7.28.4" + "@babel/types": "^7.28.5" }, "bin": { "parser": "bin/babel-parser.js" @@ -286,18 +286,18 @@ } }, "node_modules/@babel/traverse": { - "version": "7.28.4", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.4.tgz", - "integrity": "sha512-YEzuboP2qvQavAcjgQNVgsvHIDv6ZpwXvcvjmyySP2DIMuByS/6ioU5G9pYrWHM6T2YDfc7xga9iNzYOs12CFQ==", + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.5.tgz", + "integrity": "sha512-TCCj4t55U90khlYkVV/0TfkJkAkUg3jZFA3Neb7unZT8CPok7iiRfaX0F+WnqWqt7OxhOn0uBKXCw4lbL8W0aQ==", "dev": true, "license": "MIT", "dependencies": { "@babel/code-frame": "^7.27.1", - "@babel/generator": "^7.28.3", + "@babel/generator": "^7.28.5", "@babel/helper-globals": "^7.28.0", - "@babel/parser": "^7.28.4", + "@babel/parser": "^7.28.5", "@babel/template": "^7.27.2", - "@babel/types": "^7.28.4", + "@babel/types": "^7.28.5", "debug": "^4.3.1" }, "engines": { @@ -305,9 +305,9 @@ } }, "node_modules/@babel/traverse/node_modules/debug": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", - "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", "dev": true, "license": "MIT", "dependencies": { @@ -330,23 +330,23 @@ "license": "MIT" }, "node_modules/@babel/types": { - "version": "7.28.4", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.4.tgz", - "integrity": "sha512-bkFqkLhh3pMBUQQkpVgWDWq/lqzc2678eUyDlTBhRqhCHFguYYGM0Efga7tYk4TogG/3x0EEl66/OQ+WGbWB/Q==", + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.5.tgz", + "integrity": "sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA==", "dev": true, "license": "MIT", "dependencies": { "@babel/helper-string-parser": "^7.27.1", - "@babel/helper-validator-identifier": "^7.27.1" + "@babel/helper-validator-identifier": "^7.28.5" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@eslint/js": { - "version": "9.35.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.35.0.tgz", - "integrity": "sha512-30iXE9whjlILfWobBkNerJo+TXYsgVM5ERQwMcMKCHckHflCmf7wXDAHlARoWnh0s1U72WqlbeyE7iAcCzuCPw==", + "version": "9.38.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.38.0.tgz", + "integrity": "sha512-UZ1VpFvXf9J06YG9xQBdnzU+kthors6KjhMAl6f4gH4usHyh31rUf2DLGInT8RFYIReYXNSydgPY0V2LuWgl7A==", "license": "MIT", "peer": true, "engines": { @@ -521,9 +521,9 @@ "license": "MIT" }, "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.30", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.30.tgz", - "integrity": "sha512-GQ7Nw5G2lTu/BtHTKfXhKHok2WGetd4XYcVKGx00SjAk8GMwgJM3zr6zORiPGuOE+/vkc90KtTosSSvaCjKb2Q==", + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", "dev": true, "license": "MIT", "dependencies": { @@ -543,13 +543,13 @@ } }, "node_modules/@sap/cds": { - "version": "9.3.1", - "resolved": "https://registry.npmjs.org/@sap/cds/-/cds-9.3.1.tgz", - "integrity": "sha512-xA9EN29X8HKaz83Aod1e3Bs6LRvqcCVoaTvCtyOup5rMYDQumcoZ7UOKH6NIUTeO0zOtafUiMHucMG+dBnq5XQ==", + "version": "9.4.4", + "resolved": "https://registry.npmjs.org/@sap/cds/-/cds-9.4.4.tgz", + "integrity": "sha512-JJCHeEJF4xzFyZSf2ToocvVE9dyHfNLTRXOauOxlmpfyaLg97G7Qp+L4bD132eB0onBG9bQj3eH8DzBm0hVvIw==", "license": "SEE LICENSE IN LICENSE", "peer": true, "dependencies": { - "@sap/cds-compiler": "^6.1", + "@sap/cds-compiler": "^6.3", "@sap/cds-fiori": "^2", "js-yaml": "^4.1.0" }, @@ -575,9 +575,9 @@ } }, "node_modules/@sap/cds-compiler": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/@sap/cds-compiler/-/cds-compiler-6.3.0.tgz", - "integrity": "sha512-4HhZuiKa8SztqtjfM9Iey7yb2U6xQGzUbjib3JXcSSP6AJ6Bz0gViliTwf8dASPTLRtv7HU82277m4uqxU2qjw==", + "version": "6.4.2", + "resolved": "https://registry.npmjs.org/@sap/cds-compiler/-/cds-compiler-6.4.2.tgz", + "integrity": "sha512-kjhq8GxzCLIfsM4aln9saxkifPC26MYuAqT82QB7RGZDVFM5Pw09Dp6TcKCSp65hut0YgHkvHlVGWMZWWBJNdA==", "license": "SEE LICENSE IN LICENSE", "peer": true, "bin": { @@ -590,9 +590,9 @@ } }, "node_modules/@sap/cds-dk": { - "version": "9.3.0", - "resolved": "https://registry.npmjs.org/@sap/cds-dk/-/cds-dk-9.3.0.tgz", - "integrity": "sha512-p2cjXJSjiH9xoQsduje6Ku3xKDLTNSs8OEJ0cwjYyHc3GRVwe3UsMnmlHTX3HtR9XTKvr7XVQXipDgKee+EAdA==", + "version": "9.4.2", + "resolved": "https://registry.npmjs.org/@sap/cds-dk/-/cds-dk-9.4.2.tgz", + "integrity": "sha512-umNz4D30a/Oh3cFQU1wK8rxoIOBQrBiUs/k6OfG2ibQaF/rGOXz8N8lGzkY7pC535RJbtJ31OwNjKAcLGrchVQ==", "hasShrinkwrap": true, "license": "SEE LICENSE IN LICENSE", "peer": true, @@ -631,8 +631,8 @@ } }, "node_modules/@sap/cds-dk/node_modules/@cap-js/db-service": { - "version": "2.4.0", - "integrity": "sha512-tWZUkgAPgZQIVu3xownD9cA9joXPI84KDstx3ZezOxXJuRsapgM2QEs0TXwQK5XLG43FUAsGO7wVJPoZ29ZH2Q==", + "version": "2.5.1", + "integrity": "sha512-dpz9lvOepcXOgE8uTs9abCotLcCt1odpwlrUT4AW2pnSrMB0EVMRbHKVIlufmrm8Kh/Y5c2d6ODald8eahsEDw==", "license": "Apache-2.0", "optional": true, "peer": true, @@ -656,8 +656,8 @@ } }, "node_modules/@sap/cds-dk/node_modules/@cap-js/sqlite": { - "version": "2.0.2", - "integrity": "sha512-oNg2f56sfELshyp0eSmYYwG1lt4Zmc135sLIzS8iykHdRVxxJpTrPj0jx0Y4Hc6sfC9u25LRXVu/ZKqjm9Yu+Q==", + "version": "2.0.3", + "integrity": "sha512-Zm2JLpPuddFkeqM47TX7V7IC6x3WOfn5lTRbaiVOMvRQoshCNXTkjv083ssfiwF/jF/46/PSVox+fTElozg6XA==", "license": "Apache-2.0", "optional": true, "peer": true, @@ -670,8 +670,8 @@ } }, "node_modules/@sap/cds-dk/node_modules/@eslint/js": { - "version": "9.34.0", - "integrity": "sha512-EoyvqQnBNsV1CWaEJ559rxXL4c8V92gxirbawSmVUOWXlsRxxQXl6LmCpdUblgxgSkDIqKnhzba2SjRTI/A5Rw==", + "version": "9.38.0", + "integrity": "sha512-UZ1VpFvXf9J06YG9xQBdnzU+kthors6KjhMAl6f4gH4usHyh31rUf2DLGInT8RFYIReYXNSydgPY0V2LuWgl7A==", "license": "MIT", "peer": true, "engines": { @@ -682,12 +682,12 @@ } }, "node_modules/@sap/cds-dk/node_modules/@sap/cds": { - "version": "9.3.0", - "integrity": "sha512-2JaY4AlYvDP88DpZj5vo7B+9+r2ICmY5ktcCxHpnPoC9cmauYmXQtSn6gfuDwuBAWnFMSQEMu6qXz+7Yt8o7mQ==", + "version": "9.4.4", + "integrity": "sha512-JJCHeEJF4xzFyZSf2ToocvVE9dyHfNLTRXOauOxlmpfyaLg97G7Qp+L4bD132eB0onBG9bQj3eH8DzBm0hVvIw==", "license": "SEE LICENSE IN LICENSE", "peer": true, "dependencies": { - "@sap/cds-compiler": "^6.1", + "@sap/cds-compiler": "^6.3", "@sap/cds-fiori": "^2", "js-yaml": "^4.1.0" }, @@ -713,8 +713,8 @@ } }, "node_modules/@sap/cds-dk/node_modules/@sap/cds-compiler": { - "version": "6.3.0", - "integrity": "sha512-4HhZuiKa8SztqtjfM9Iey7yb2U6xQGzUbjib3JXcSSP6AJ6Bz0gViliTwf8dASPTLRtv7HU82277m4uqxU2qjw==", + "version": "6.4.2", + "integrity": "sha512-kjhq8GxzCLIfsM4aln9saxkifPC26MYuAqT82QB7RGZDVFM5Pw09Dp6TcKCSp65hut0YgHkvHlVGWMZWWBJNdA==", "license": "SEE LICENSE IN LICENSE", "peer": true, "bin": { @@ -727,18 +727,18 @@ } }, "node_modules/@sap/cds-dk/node_modules/@sap/cds-fiori": { - "version": "2.0.1", - "integrity": "sha512-KZVLWXndydgqdlao8OL1gtgd/XMgBdiKBmmgwGpBL1y4S21FOXglnWh6d3bnSZL/qwR3z50D+0PoGghjhayF0Q==", + "version": "2.1.0", + "integrity": "sha512-EoNtPT5aVurxwsqHQfW2FgnXA3Ysu9GvihR0jTQNUZ4pVlHHFkfFehH6G2DIHKyfTROWaahegJsMpiwpE8clkg==", "license": "SEE LICENSE IN LICENSE", "peer": true, "peerDependencies": { "@sap/cds": ">=8", - "express": ">=4" + "express": "^4" } }, "node_modules/@sap/cds-dk/node_modules/@sap/cds-mtxs": { - "version": "3.3.0", - "integrity": "sha512-udIzKk+qUoYWLJKbGUJm0csuZP5r54msnTNy11bFDsuESio07ppgDkCIk+oGXCjsJLeoLZULCGgFvifLRi0ATg==", + "version": "3.4.2", + "integrity": "sha512-bpKHKbehDSZpe9IoY1Vn2LQ5kgQns6RdlMsTOE9rw9zP//Yq5hFtl7SKFEM0A0/+WL3E+Rp/7Y2tc76erKYqdA==", "license": "SEE LICENSE IN LICENSE", "peer": true, "dependencies": { @@ -777,8 +777,8 @@ } }, "node_modules/@sap/cds-dk/node_modules/@sap/hdi-deploy": { - "version": "5.5.0", - "integrity": "sha512-nxamWIBz+D/4wcvgYgxGSJLsyJ1KNtU9X6gfMHiyi/IjozGN/3WdeT11++jy5qeZNkdinuND55RRlRcnsu3W5g==", + "version": "5.5.1", + "integrity": "sha512-5r9SIkXX7cO+MwRFF32O566sMx6LP1mLin0eT9F+Adqy+0SrdwkWv4JslQzYetiWLuNsfqQljcao62alaxts8A==", "license": "See LICENSE file", "peer": true, "dependencies": { @@ -866,8 +866,8 @@ "peer": true }, "node_modules/@sap/cds-dk/node_modules/axios": { - "version": "1.11.0", - "integrity": "sha512-1Lx3WLFQWm3ooKDYZD1eXmoGO9fxYQjrycfHFC8P0sCfQVXyROp0p9PFWBehewBOdCwHc+f/b8I0fMto5eSfwA==", + "version": "1.12.2", + "integrity": "sha512-vMJzPewAlRyOgxV2dU0Cuz2O8zzzx9VYtbJOaBgXFeLc4IV/Eg50n4LowmehOOR61S8ZMpc2K5Sa7g6A4jfkUw==", "license": "MIT", "peer": true, "dependencies": { @@ -898,8 +898,8 @@ "peer": true }, "node_modules/@sap/cds-dk/node_modules/better-sqlite3": { - "version": "12.2.0", - "integrity": "sha512-eGbYq2CT+tos1fBwLQ/tkBt9J5M3JEHjku4hbvQUePCckkvVf14xWj+1m7dGoK81M/fOjFT7yM9UMeKT/+vFLQ==", + "version": "12.4.1", + "integrity": "sha512-3yVdyZhklTiNrtg+4WqHpJpFDd+WHTg2oM7UcR80GqL05AOV0xEJzc6qNvFYoEtE+hRp1n9MpN6/+4yhlGkDXQ==", "hasInstallScript": true, "license": "MIT", "optional": true, @@ -1190,8 +1190,8 @@ } }, "node_modules/@sap/cds-dk/node_modules/detect-libc": { - "version": "2.0.4", - "integrity": "sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA==", + "version": "2.1.2", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", "license": "Apache-2.0", "optional": true, "peer": true, @@ -1909,8 +1909,8 @@ "peer": true }, "node_modules/@sap/cds-dk/node_modules/node-abi": { - "version": "3.75.0", - "integrity": "sha512-OhYaY5sDsIka7H7AtijtI9jwGYLyl29eQn/W623DiN/MIv5sUqc4g7BIDThX+gb7di9f6xK02nkp8sdfFWZLTg==", + "version": "3.78.0", + "integrity": "sha512-E2wEyrgX/CqvicaQYU3Ze1PFGjc4QYPGsjUrlYkqAE0WjHEZwgOsGMPMzkMse4LjJbDmaEuDX3CM036j5K2DSQ==", "license": "MIT", "optional": true, "peer": true, @@ -2160,8 +2160,8 @@ "peer": true }, "node_modules/@sap/cds-dk/node_modules/semver": { - "version": "7.7.2", - "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "version": "7.7.3", + "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", "license": "ISC", "optional": true, "peer": true, @@ -2399,8 +2399,8 @@ } }, "node_modules/@sap/cds-dk/node_modules/tar-fs": { - "version": "2.1.3", - "integrity": "sha512-090nwYJDmlhwFwEW3QQl+vaNnxsO2yVsd45eTKRBzSzu+hlb1w2K9inVq5b0ngXuLVqQ4ApvsUHHnu/zQNkWAg==", + "version": "2.1.4", + "integrity": "sha512-mDAjwmZdh7LTT6pNleZ05Yt65HC3E+NiQzl672vQG38jIrehtJk/J3mNwIg+vShQPcLF/LV7CMnDW6vjj6sfYQ==", "license": "MIT", "optional": true, "peer": true, @@ -2595,14 +2595,14 @@ } }, "node_modules/@sap/cds-fiori": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@sap/cds-fiori/-/cds-fiori-2.0.1.tgz", - "integrity": "sha512-KZVLWXndydgqdlao8OL1gtgd/XMgBdiKBmmgwGpBL1y4S21FOXglnWh6d3bnSZL/qwR3z50D+0PoGghjhayF0Q==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@sap/cds-fiori/-/cds-fiori-2.1.0.tgz", + "integrity": "sha512-EoNtPT5aVurxwsqHQfW2FgnXA3Ysu9GvihR0jTQNUZ4pVlHHFkfFehH6G2DIHKyfTROWaahegJsMpiwpE8clkg==", "license": "SEE LICENSE IN LICENSE", "peer": true, "peerDependencies": { "@sap/cds": ">=8", - "express": ">=4" + "express": "^4" } }, "node_modules/@sap/cds-foss": { @@ -2691,9 +2691,9 @@ } }, "node_modules/ansi-regex": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.0.tgz", - "integrity": "sha512-TKY5pyBkHyADOPYlRT9Lx6F544mPl0vS5Ew7BJ45hA08Q+t3GjbueLliBWN3sMICk6+y7HdyxSzC4bWS8baBdg==", + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", "dev": true, "license": "MIT", "engines": { @@ -2769,6 +2769,16 @@ "dev": true, "license": "MIT" }, + "node_modules/baseline-browser-mapping": { + "version": "2.8.20", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.8.20.tgz", + "integrity": "sha512-JMWsdF+O8Orq3EMukbUN1QfbLK9mX2CkUmQBcW2T0s8OmdAUL5LLM/6wFwSrqXzlXB13yhyK9gTKS1rIizOduQ==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "baseline-browser-mapping": "dist/cli.js" + } + }, "node_modules/big.js": { "version": "6.2.2", "resolved": "https://registry.npmjs.org/big.js/-/big.js-6.2.2.tgz", @@ -2826,9 +2836,9 @@ "license": "ISC" }, "node_modules/browserslist": { - "version": "4.25.4", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.25.4.tgz", - "integrity": "sha512-4jYpcjabC606xJ3kw2QwGEZKX0Aw7sgQdZCvIK9dhVSPh76BKo+C+btT1RRofH7B+8iNpEbgGNVWiLki5q93yg==", + "version": "4.27.0", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.27.0.tgz", + "integrity": "sha512-AXVQwdhot1eqLihwasPElhX2tAZiBjWdJ9i/Zcj2S6QYIjkx62OKSfnobkriB81C3l4w0rVy3Nt4jaTBltYEpw==", "dev": true, "funding": [ { @@ -2846,10 +2856,11 @@ ], "license": "MIT", "dependencies": { - "caniuse-lite": "^1.0.30001737", - "electron-to-chromium": "^1.5.211", - "node-releases": "^2.0.19", - "update-browserslist-db": "^1.1.3" + "baseline-browser-mapping": "^2.8.19", + "caniuse-lite": "^1.0.30001751", + "electron-to-chromium": "^1.5.238", + "node-releases": "^2.0.26", + "update-browserslist-db": "^1.1.4" }, "bin": { "browserslist": "cli.js" @@ -2926,9 +2937,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001741", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001741.tgz", - "integrity": "sha512-QGUGitqsc8ARjLdgAfxETDhRbJ0REsP6O3I96TAth/mVjh2cYzN2u+3AzPP3aVSm2FehEItaJw1xd+IGBXWeSw==", + "version": "1.0.30001751", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001751.tgz", + "integrity": "sha512-A0QJhug0Ly64Ii3eIqHu5X51ebln3k4yTUkY1j8drqpWHVreg/VLijN48cZ1bYPiqOQuqpkIKnzr/Ul8V+p6Cw==", "dev": true, "funding": [ { @@ -3310,9 +3321,9 @@ "peer": true }, "node_modules/electron-to-chromium": { - "version": "1.5.214", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.214.tgz", - "integrity": "sha512-TpvUNdha+X3ybfU78NoQatKvQEm1oq3lf2QbnmCEdw+Bd9RuIAY+hJTvq1avzHM0f7EJfnH3vbCnbzKzisc/9Q==", + "version": "1.5.240", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.240.tgz", + "integrity": "sha512-OBwbZjWgrCOH+g6uJsA2/7Twpas2OlepS9uvByJjR2datRDuKGYeD+nP8lBBks2qnB7bGJNHDUx7c/YLaT3QMQ==", "dev": true, "license": "ISC" }, @@ -3891,6 +3902,16 @@ "node": ">=8" } }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/is-plain-obj": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", @@ -4069,9 +4090,9 @@ } }, "node_modules/istanbul-lib-source-maps/node_modules/debug": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", - "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", "dev": true, "license": "MIT", "dependencies": { @@ -4354,9 +4375,9 @@ } }, "node_modules/mocha": { - "version": "11.7.2", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-11.7.2.tgz", - "integrity": "sha512-lkqVJPmqqG/w5jmmFtiRvtA2jkDyNVUcefFJKb2uyX4dekk8Okgqop3cgbFiaIvj8uCRJVTP5x9dfxGyXm2jvQ==", + "version": "11.7.4", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-11.7.4.tgz", + "integrity": "sha512-1jYAaY8x0kAZ0XszLWu14pzsf4KV740Gld4HXkhNTXwcHx4AUEDkPzgEHg9CM5dVcW+zv036tjpsEbLraPJj4w==", "dev": true, "license": "MIT", "dependencies": { @@ -4368,6 +4389,7 @@ "find-up": "^5.0.0", "glob": "^10.4.5", "he": "^1.2.0", + "is-path-inside": "^3.0.3", "js-yaml": "^4.1.0", "log-symbols": "^4.1.0", "minimatch": "^9.0.5", @@ -4390,9 +4412,9 @@ } }, "node_modules/mocha/node_modules/debug": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", - "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", "dev": true, "license": "MIT", "dependencies": { @@ -4454,9 +4476,9 @@ } }, "node_modules/node-releases": { - "version": "2.0.20", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.20.tgz", - "integrity": "sha512-7gK6zSXEH6neM212JgfYFXe+GmZQM+fia5SsusuBIUgnPheLFBmIPhtFoAQRj8/7wASYQnbDlHPVwY0BefoFgA==", + "version": "2.0.26", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.26.tgz", + "integrity": "sha512-S2M9YimhSjBSvYnlr5/+umAnPHE++ODwt5e2Ij6FoX45HA/s4vHdkDx1eax2pAPeAOqu4s9b7ppahsyEFdVqQA==", "dev": true, "license": "MIT" }, @@ -5222,9 +5244,9 @@ "peer": true }, "node_modules/semver": { - "version": "7.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", - "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "version": "7.7.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", + "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", "dev": true, "license": "ISC", "bin": { @@ -5590,9 +5612,9 @@ } }, "node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz", + "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==", "dev": true, "license": "MIT", "dependencies": { @@ -5794,9 +5816,9 @@ } }, "node_modules/update-browserslist-db": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz", - "integrity": "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.4.tgz", + "integrity": "sha512-q0SPT4xyU84saUX+tomz1WLkxUbuaJnR1xWt17M7fJtEJigJeWUNGUqrauFXsHnqev9y9JTRGwk13tFBuKby4A==", "dev": true, "funding": [ { @@ -5878,9 +5900,9 @@ "license": "ISC" }, "node_modules/workerpool": { - "version": "9.3.3", - "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-9.3.3.tgz", - "integrity": "sha512-slxCaKbYjEdFT/o2rH9xS1hf4uRDch1w7Uo+apxhZ+sf/1d9e0ZVkn42kPNGP2dgjIx6YFvSevj0zHvbWe2jdw==", + "version": "9.3.4", + "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-9.3.4.tgz", + "integrity": "sha512-TmPRQYYSAnnDiEB0P/Ytip7bFGvqnSU6I2BcuSw7Hx+JSg/DsUi5ebYfc8GYaSdpuvOcEs6dXxPurOYpe9QFwg==", "dev": true, "license": "Apache-2.0" }, @@ -5967,9 +5989,9 @@ } }, "node_modules/wrap-ansi/node_modules/ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", "dev": true, "license": "MIT", "engines": { diff --git a/test/addCheck.test.js b/test/add-check.test.js similarity index 100% rename from test/addCheck.test.js rename to test/add-check.test.js diff --git a/test/add-services.test.js b/test/add-services.test.js new file mode 100644 index 0000000..ff948d9 --- /dev/null +++ b/test/add-services.test.js @@ -0,0 +1,102 @@ +const { join } = require('path') +const { execSync } = require('child_process') +const { expect } = require("chai") +const fs = require('fs') + +const TempUtil = require('./tempUtil') +const tempUtil = new TempUtil(__filename, { local: true }) + +const { getFileHash, updateDependency, setupHack, undoSetupHack } = require('./util') + +describe('cds add cap-operator', () => { + let temp, bookshop, orignalXsSecurityJson + + before(async () => { + await tempUtil.cleanUp() + temp = await tempUtil.mkTempFolder() + bookshop = join(temp, 'bookshop') + execSync(`cds init bookshop --add xsuaa,html5-repo,destination`, { cwd: temp }) + updateDependency(bookshop) + execSync(`npm install`, { cwd: bookshop }) + setupHack(bookshop) + orignalXsSecurityJson = fs.readFileSync(bookshop+"/xs-security.json", 'utf8') + }) + + afterEach(async () => { + if (cds.utils.exists(join(bookshop, 'chart'))) execSync(`rm -r chart`, { cwd: bookshop }) + }) + + after(async () => { + undoSetupHack(bookshop) + await tempUtil.cleanUp() + }) + + it('Add cap-operator chart with service only', async () => { + execSync(`cds add cap-operator --with-service-only`, { cwd: bookshop }) + + expect(getFileHash(join(__dirname,'files/expectedChart/Chart-svc.yaml'))).to.equal(getFileHash(join(bookshop, 'chart/Chart.yaml'))) + expect(getFileHash(join(__dirname,'../files/chart/values.schema.json'))).to.equal(getFileHash(join(bookshop, 'chart/values.schema.json'))) + expect(getFileHash(join(__dirname,'files/expectedChart/values-svc.yaml'))).to.equal(getFileHash(join(bookshop, 'chart/values.yaml'))) + }) + + it('Add cap-operator chart with service only and mta', async () => { + expect(() => execSync(`cds add cap-operator --with-service-only --with-mta mta.yaml`, { cwd: bookshop })).to.throw('Option \'--with-service-only\' cannot be used with \'--with-mta\' or \'--with-mta-extensions\'') + }) + + it('Add templates to an existing cap-operator service only chart', async () => { + execSync(`cds add cap-operator --with-service-only`, { cwd: bookshop }) + execSync(`cds add cap-operator --with-templates`, { cwd: bookshop }) + + expect(getFileHash(join(__dirname,'files/expectedChart/Chart-svc.yaml'))).to.equal(getFileHash(join(bookshop, 'chart/Chart.yaml'))) + expect(getFileHash(join(__dirname,'files/expectedChart/values-svc.yaml'))).to.equal(getFileHash(join(bookshop, 'chart/values.yaml'))) + expect(getFileHash(join(__dirname,'files/expectedChart/templates/_helpers.tpl'))).to.equal(getFileHash(join(bookshop, 'chart/templates/_helpers.tpl'))) + expect(getFileHash(join(__dirname,'files/expectedChart/templates/cap-operator-cros-svc.yaml'))).to.equal(getFileHash(join(bookshop, 'chart/templates/cap-operator-cros.yaml'))) + expect(getFileHash(join(__dirname,'files/domain.yaml'))).to.equal(getFileHash(join(bookshop, 'chart/templates/domain.yaml'))) + + expect(getFileHash(join(__dirname,'../files/chart/values.schema.json'))).to.equal(getFileHash(join(bookshop, 'chart/values.schema.json'))) + expect(getFileHash(join(__dirname,'../files/commonTemplates/service-binding.yaml'))).to.equal(getFileHash(join(bookshop, 'chart/templates/service-binding.yaml'))) + expect(getFileHash(join(__dirname,'../files/commonTemplates/service-instance.yaml'))).to.equal(getFileHash(join(bookshop, 'chart/templates/service-instance.yaml'))) + }) + + it('Add cap-operator configurable template chart with service only', async () => { + + execSync(`cds add cap-operator --with-service-only --with-configurable-templates`, { cwd: bookshop }) + + expect(getFileHash(join(__dirname,'files/expectedConfigurableTemplatesChart/Chart-svc.yaml'))).to.equal(getFileHash(join(bookshop, 'chart/Chart.yaml'))) + expect(getFileHash(join(__dirname,'files/expectedConfigurableTemplatesChart/values-svc.yaml'))).to.equal(getFileHash(join(bookshop, 'chart/values.yaml'))) + expect(getFileHash(join(__dirname,'files/expectedConfigurableTemplatesChart/templates/_helpers.tpl'))).to.equal(getFileHash(join(bookshop, 'chart/templates/_helpers.tpl'))) + expect(getFileHash(join(__dirname,'files/expectedConfigurableTemplatesChart/templates/cap-operator-cros-svc.yaml'))).to.equal(getFileHash(join(bookshop, 'chart/templates/cap-operator-cros.yaml'))) + expect(getFileHash(join(__dirname,'files/domain.yaml'))).to.equal(getFileHash(join(bookshop, 'chart/templates/domain.yaml'))) + + expect(getFileHash(join(__dirname,'../files/configurableTemplatesChart/values.schema.json'))).to.equal(getFileHash(join(bookshop, 'chart/values.schema.json'))) + expect(getFileHash(join(__dirname,'../files/commonTemplates/service-binding.yaml'))).to.equal(getFileHash(join(bookshop, 'chart/templates/service-binding.yaml'))) + expect(getFileHash(join(__dirname,'../files/commonTemplates/service-instance.yaml'))).to.equal(getFileHash(join(bookshop, 'chart/templates/service-instance.yaml'))) + }) + + it('Add cap-operator service only chart with IAS & AMS', async () => { + execSync(`cds add ias,ams`, { cwd: bookshop }) + execSync(`cds add cap-operator --with-service-only --with-templates`, { cwd: bookshop }) + + expect(getFileHash(join(__dirname,'files/expectedChart/Chart-svc.yaml'))).to.equal(getFileHash(join(bookshop, 'chart/Chart.yaml'))) + expect(getFileHash(join(__dirname,'files/expectedChart/values-svc-ias.yaml'))).to.equal(getFileHash(join(bookshop, 'chart/values.yaml'))) + expect(getFileHash(join(__dirname,'files/expectedChart/templates/_helpers-ias.tpl'))).to.equal(getFileHash(join(bookshop, 'chart/templates/_helpers.tpl'))) + expect(getFileHash(join(__dirname,'files/expectedChart/templates/cap-operator-cros-svc-ias.yaml'))).to.equal(getFileHash(join(bookshop, 'chart/templates/cap-operator-cros.yaml'))) + + expect(getFileHash(join(__dirname,'../files/chart/values.schema.json'))).to.equal(getFileHash(join(bookshop, 'chart/values.schema.json'))) + }) + + it('Add cap-operator configurable template service only chart with IAS & AMS', async () => { + execSync(`cds add ias,ams`, { cwd: bookshop }) + execSync(`cds add cap-operator --with-service-only --with-configurable-templates`, { cwd: bookshop }) + + expect(getFileHash(join(__dirname,'files/expectedConfigurableTemplatesChart/Chart-svc.yaml'))).to.equal(getFileHash(join(bookshop, 'chart/Chart.yaml'))) + expect(getFileHash(join(__dirname,'files/expectedConfigurableTemplatesChart/values-svc-ias.yaml'))).to.equal(getFileHash(join(bookshop, 'chart/values.yaml'))) + expect(getFileHash(join(__dirname,'files/expectedConfigurableTemplatesChart/templates/_helpers-ias.tpl'))).to.equal(getFileHash(join(bookshop, 'chart/templates/_helpers.tpl'))) + expect(getFileHash(join(__dirname,'files/expectedConfigurableTemplatesChart/templates/cap-operator-cros-svc-ias.yaml'))).to.equal(getFileHash(join(bookshop, 'chart/templates/cap-operator-cros.yaml'))) + expect(getFileHash(join(__dirname,'files/domain-ias.yaml'))).to.equal(getFileHash(join(bookshop, 'chart/templates/domain.yaml'))) + + expect(getFileHash(join(__dirname,'../files/configurableTemplatesChart/values.schema.json'))).to.equal(getFileHash(join(bookshop, 'chart/values.schema.json'))) + expect(getFileHash(join(__dirname,'../files/commonTemplates/service-binding.yaml'))).to.equal(getFileHash(join(bookshop, 'chart/templates/service-binding.yaml'))) + expect(getFileHash(join(__dirname,'../files/commonTemplates/service-instance.yaml'))).to.equal(getFileHash(join(bookshop, 'chart/templates/service-instance.yaml'))) + }) +}) diff --git a/test/add.test.js b/test/add.test.js index 19b96cc..b2695e9 100644 --- a/test/add.test.js +++ b/test/add.test.js @@ -19,7 +19,7 @@ describe('cds add cap-operator', () => { updateDependency(bookshop) execSync(`npm install`, { cwd: bookshop }) setupHack(bookshop) - orignalXsSecurityJson = fs.readFileSync(bookshop+"/xs-security.json", 'utf8') + orignalXsSecurityJson = fs.readFileSync(bookshop + "/xs-security.json", 'utf8') }) afterEach(async () => { @@ -34,34 +34,35 @@ describe('cds add cap-operator', () => { it('Add cap-operator chart', async () => { execSync(`cds add cap-operator`, { cwd: bookshop }) - expect(getFileHash(join(__dirname,'files/expectedChart/Chart.yaml'))).to.equal(getFileHash(join(bookshop, 'chart/Chart.yaml'))) - expect(getFileHash(join(__dirname,'../files/chart/values.schema.json'))).to.equal(getFileHash(join(bookshop, 'chart/values.schema.json'))) - expect(getFileHash(join(__dirname,'files/expectedChart/values.yaml'))).to.equal(getFileHash(join(bookshop, 'chart/values.yaml'))) + expect(getFileHash(join(__dirname, 'files/expectedChart/Chart.yaml'))).to.equal(getFileHash(join(bookshop, 'chart/Chart.yaml'))) + expect(getFileHash(join(__dirname, '../files/chart/values.schema.json'))).to.equal(getFileHash(join(bookshop, 'chart/values.schema.json'))) + expect(getFileHash(join(__dirname, 'files/expectedChart/values.yaml'))).to.equal(getFileHash(join(bookshop, 'chart/values.yaml'))) // Check changes to xs-security.json - expect(getFileHash(join(__dirname,'files/xs-security.json'))).to.equal(getFileHash(join(bookshop, 'xs-security.json'))) + expect(getFileHash(join(__dirname, 'files/xs-security.json'))).to.equal(getFileHash(join(bookshop, 'xs-security.json'))) }) it('Add cap-operator chart with force', async () => { execSync(`cds add cap-operator --force`, { cwd: bookshop }) - expect(getFileHash(join(__dirname,'files/expectedChart/Chart.yaml'))).to.equal(getFileHash(join(bookshop, 'chart/Chart.yaml'))) - expect(getFileHash(join(__dirname,'../files/chart/values.schema.json'))).to.equal(getFileHash(join(bookshop, 'chart/values.schema.json'))) - expect(getFileHash(join(__dirname,'files/expectedChart/values.yaml'))).to.equal(getFileHash(join(bookshop, 'chart/values.yaml'))) + expect(getFileHash(join(__dirname, 'files/expectedChart/Chart.yaml'))).to.equal(getFileHash(join(bookshop, 'chart/Chart.yaml'))) + expect(getFileHash(join(__dirname, '../files/chart/values.schema.json'))).to.equal(getFileHash(join(bookshop, 'chart/values.schema.json'))) + expect(getFileHash(join(__dirname, 'files/expectedChart/values.yaml'))).to.equal(getFileHash(join(bookshop, 'chart/values.yaml'))) }) it('Add templates to an existing cap-operator chart', async () => { execSync(`cds add cap-operator --force`, { cwd: bookshop }) execSync(`cds add cap-operator --with-templates`, { cwd: bookshop }) - expect(getFileHash(join(__dirname,'files/expectedChart/Chart.yaml'))).to.equal(getFileHash(join(bookshop, 'chart/Chart.yaml'))) - expect(getFileHash(join(__dirname,'files/expectedChart/values.yaml'))).to.equal(getFileHash(join(bookshop, 'chart/values.yaml'))) - expect(getFileHash(join(__dirname,'../files/chart/values.schema.json'))).to.equal(getFileHash(join(bookshop, 'chart/values.schema.json'))) - expect(getFileHash(join(__dirname,'../files/chart/templates/_helpers.tpl'))).to.equal(getFileHash(join(bookshop, 'chart/templates/_helpers.tpl'))) - expect(getFileHash(join(__dirname,'../files/commonTemplates/service-binding.yaml'))).to.equal(getFileHash(join(bookshop, 'chart/templates/service-binding.yaml'))) - expect(getFileHash(join(__dirname,'../files/commonTemplates/service-instance.yaml'))).to.equal(getFileHash(join(bookshop, 'chart/templates/service-instance.yaml'))) - expect(getFileHash(join(__dirname,'../files/commonTemplates/domain.yaml'))).to.equal(getFileHash(join(bookshop, 'chart/templates/domain.yaml'))) - expect(getFileHash(join(__dirname,'../files/chart/templates/cap-operator-cros.yaml'))).to.equal(getFileHash(join(bookshop, 'chart/templates/cap-operator-cros.yaml'))) + expect(getFileHash(join(__dirname, 'files/expectedChart/Chart.yaml'))).to.equal(getFileHash(join(bookshop, 'chart/Chart.yaml'))) + expect(getFileHash(join(__dirname, 'files/expectedChart/values.yaml'))).to.equal(getFileHash(join(bookshop, 'chart/values.yaml'))) + expect(getFileHash(join(__dirname, 'files/expectedChart/templates/_helpers.tpl'))).to.equal(getFileHash(join(bookshop, 'chart/templates/_helpers.tpl'))) + expect(getFileHash(join(__dirname, 'files/expectedChart/templates/cap-operator-cros.yaml'))).to.equal(getFileHash(join(bookshop, 'chart/templates/cap-operator-cros.yaml'))) + expect(getFileHash(join(__dirname, 'files/domain.yaml'))).to.equal(getFileHash(join(bookshop, 'chart/templates/domain.yaml'))) + + expect(getFileHash(join(__dirname, '../files/chart/values.schema.json'))).to.equal(getFileHash(join(bookshop, 'chart/values.schema.json'))) + expect(getFileHash(join(__dirname, '../files/commonTemplates/service-binding.yaml'))).to.equal(getFileHash(join(bookshop, 'chart/templates/service-binding.yaml'))) + expect(getFileHash(join(__dirname, '../files/commonTemplates/service-instance.yaml'))).to.equal(getFileHash(join(bookshop, 'chart/templates/service-instance.yaml'))) }) it('Chart folder already added by `cds add helm` ', async () => { @@ -83,65 +84,69 @@ describe('cds add cap-operator', () => { it('Add cap-operator chart with templates', async () => { execSync(`cds add cap-operator --with-templates`, { cwd: bookshop }) - expect(getFileHash(join(__dirname,'files/expectedChart/Chart.yaml'))).to.equal(getFileHash(join(bookshop, 'chart/Chart.yaml'))) - expect(getFileHash(join(__dirname,'files/expectedChart/values.yaml'))).to.equal(getFileHash(join(bookshop, 'chart/values.yaml'))) - expect(getFileHash(join(__dirname,'../files/chart/values.schema.json'))).to.equal(getFileHash(join(bookshop, 'chart/values.schema.json'))) - expect(getFileHash(join(__dirname,'../files/chart/templates/_helpers.tpl'))).to.equal(getFileHash(join(bookshop, 'chart/templates/_helpers.tpl'))) - expect(getFileHash(join(__dirname,'../files/commonTemplates/service-binding.yaml'))).to.equal(getFileHash(join(bookshop, 'chart/templates/service-binding.yaml'))) - expect(getFileHash(join(__dirname,'../files/commonTemplates/service-instance.yaml'))).to.equal(getFileHash(join(bookshop, 'chart/templates/service-instance.yaml'))) - expect(getFileHash(join(__dirname,'../files/commonTemplates/domain.yaml'))).to.equal(getFileHash(join(bookshop, 'chart/templates/domain.yaml'))) - expect(getFileHash(join(__dirname,'../files/chart/templates/cap-operator-cros.yaml'))).to.equal(getFileHash(join(bookshop, 'chart/templates/cap-operator-cros.yaml'))) + expect(getFileHash(join(__dirname, 'files/expectedChart/Chart.yaml'))).to.equal(getFileHash(join(bookshop, 'chart/Chart.yaml'))) + expect(getFileHash(join(__dirname, 'files/expectedChart/values.yaml'))).to.equal(getFileHash(join(bookshop, 'chart/values.yaml'))) + expect(getFileHash(join(__dirname, 'files/expectedChart/templates/_helpers.tpl'))).to.equal(getFileHash(join(bookshop, 'chart/templates/_helpers.tpl'))) + expect(getFileHash(join(__dirname, 'files/expectedChart/templates/cap-operator-cros.yaml'))).to.equal(getFileHash(join(bookshop, 'chart/templates/cap-operator-cros.yaml'))) + expect(getFileHash(join(__dirname, 'files/domain.yaml'))).to.equal(getFileHash(join(bookshop, 'chart/templates/domain.yaml'))) + + expect(getFileHash(join(__dirname, '../files/chart/values.schema.json'))).to.equal(getFileHash(join(bookshop, 'chart/values.schema.json'))) + expect(getFileHash(join(__dirname, '../files/commonTemplates/service-binding.yaml'))).to.equal(getFileHash(join(bookshop, 'chart/templates/service-binding.yaml'))) + expect(getFileHash(join(__dirname, '../files/commonTemplates/service-instance.yaml'))).to.equal(getFileHash(join(bookshop, 'chart/templates/service-instance.yaml'))) + }) it('Add cap-operator chart with mta but mta.yaml is not present', async () => { + // remove mta.yaml if present + if (cds.utils.exists(join(bookshop, 'mta.yaml'))) fs.unlinkSync(join(bookshop, 'mta.yaml')) expect(() => execSync(`cds add cap-operator --with-mta mta.yaml`, { cwd: bookshop })).to.throw('mta is not added to this project. Run \'cds add mta\'.') }) it('Add cap-operator chart without mta.yaml but with mta extensions', async () => { - expect(() => execSync(`cds add cap-operator --with-mta-extensions corrected_xsappname.mtaext`, { cwd: bookshop })).to.throw('mta YAML not provided. Please pass the mta YAML via option \'--with-mta\'.') + expect(() => execSync(`cds add cap-operator --with-mta-extensions corrected_xsappname.mtaext`, { cwd: bookshop })).to.throw('Missing mta YAML. Use \'--with-mta\' option') }) it('Add cap-operator chart with mta and mtaExtensions', async () => { await cds.utils.copy(join('test/files', 'mta.yaml'), join(bookshop, 'mta.yaml')) await cds.utils.copy(join('test/files', 'corrected_xsappname.mtaext'), join(bookshop, 'corrected_xsappname.mtaext')) // revert xs-security to original value - fs.writeFileSync(bookshop+"/xs-security.json", orignalXsSecurityJson) + fs.writeFileSync(bookshop + "/xs-security.json", orignalXsSecurityJson) execSync(`cds add cap-operator --with-mta mta.yaml --with-mta-extensions corrected_xsappname.mtaext`, { cwd: bookshop }) - expect(getFileHash(join(__dirname,'files/expectedChart/Chart.yaml'))).to.equal(getFileHash(join(bookshop, 'chart/Chart.yaml'))) - expect(getFileHash(join(__dirname,'../files/chart/values.schema.json'))).to.equal(getFileHash(join(bookshop, 'chart/values.schema.json'))) - expect(getFileHash(join(__dirname,'files/expectedChart/valuesWithMTA.yaml'))).to.equal(getFileHash(join(bookshop, 'chart/values.yaml'))) - expect(getFileHash(join(__dirname,'files/xs-security.json'))).to.equal(getFileHash(join(bookshop, 'xs-security.json'))) + expect(getFileHash(join(__dirname, 'files/expectedChart/Chart.yaml'))).to.equal(getFileHash(join(bookshop, 'chart/Chart.yaml'))) + expect(getFileHash(join(__dirname, '../files/chart/values.schema.json'))).to.equal(getFileHash(join(bookshop, 'chart/values.schema.json'))) + expect(getFileHash(join(__dirname, 'files/expectedChart/valuesWithMTA.yaml'))).to.equal(getFileHash(join(bookshop, 'chart/values.yaml'))) + expect(getFileHash(join(__dirname, 'files/xs-security.json'))).to.equal(getFileHash(join(bookshop, 'xs-security.json'))) }) it('Add cap-operator chart and add destination', async () => { execSync(`cds add cap-operator --force`, { cwd: bookshop }) execSync(`cds add destination`, { cwd: bookshop }) - expect(getFileHash(join(__dirname,'files/expectedChart/Chart.yaml'))).to.equal(getFileHash(join(bookshop, 'chart/Chart.yaml'))) - expect(getFileHash(join(__dirname,'../files/chart/values.schema.json'))).to.equal(getFileHash(join(bookshop, 'chart/values.schema.json'))) - expect(getFileHash(join(__dirname,'files/expectedChart/valuesWithDestination.yaml'))).to.equal(getFileHash(join(bookshop, 'chart/values.yaml'))) + expect(getFileHash(join(__dirname, 'files/expectedChart/Chart.yaml'))).to.equal(getFileHash(join(bookshop, 'chart/Chart.yaml'))) + expect(getFileHash(join(__dirname, '../files/chart/values.schema.json'))).to.equal(getFileHash(join(bookshop, 'chart/values.schema.json'))) + expect(getFileHash(join(__dirname, 'files/expectedChart/valuesWithDestination.yaml'))).to.equal(getFileHash(join(bookshop, 'chart/values.yaml'))) }) it('Add cap-operator configurable template chart', async () => { // revert xs-security to original value - fs.writeFileSync(bookshop+"/xs-security.json", orignalXsSecurityJson) + fs.writeFileSync(bookshop + "/xs-security.json", orignalXsSecurityJson) execSync(`cds add cap-operator --with-configurable-templates`, { cwd: bookshop }) - expect(getFileHash(join(__dirname,'files/expectedConfigurableTemplatesChart/Chart.yaml'))).to.equal(getFileHash(join(bookshop, 'chart/Chart.yaml'))) - expect(getFileHash(join(__dirname,'files/expectedConfigurableTemplatesChart/values.yaml'))).to.equal(getFileHash(join(bookshop, 'chart/values.yaml'))) - expect(getFileHash(join(__dirname,'files/expectedConfigurableTemplatesChart/templates/_helpers.tpl'))).to.equal(getFileHash(join(bookshop, 'chart/templates/_helpers.tpl'))) + expect(getFileHash(join(__dirname, 'files/expectedConfigurableTemplatesChart/Chart.yaml'))).to.equal(getFileHash(join(bookshop, 'chart/Chart.yaml'))) + expect(getFileHash(join(__dirname, 'files/expectedConfigurableTemplatesChart/values.yaml'))).to.equal(getFileHash(join(bookshop, 'chart/values.yaml'))) + expect(getFileHash(join(__dirname, 'files/expectedConfigurableTemplatesChart/templates/_helpers.tpl'))).to.equal(getFileHash(join(bookshop, 'chart/templates/_helpers.tpl'))) + expect(getFileHash(join(__dirname, 'files/expectedConfigurableTemplatesChart/templates/cap-operator-cros.yaml'))).to.equal(getFileHash(join(bookshop, 'chart/templates/cap-operator-cros.yaml'))) + expect(getFileHash(join(__dirname, 'files/domain.yaml'))).to.equal(getFileHash(join(bookshop, 'chart/templates/domain.yaml'))) - expect(getFileHash(join(__dirname,'../files/configurableTemplatesChart/values.schema.json'))).to.equal(getFileHash(join(bookshop, 'chart/values.schema.json'))) - expect(getFileHash(join(__dirname,'../files/configurableTemplatesChart/templates/cap-operator-cros.yaml'))).to.equal(getFileHash(join(bookshop, 'chart/templates/cap-operator-cros.yaml'))) - expect(getFileHash(join(__dirname,'../files/commonTemplates/service-binding.yaml'))).to.equal(getFileHash(join(bookshop, 'chart/templates/service-binding.yaml'))) - expect(getFileHash(join(__dirname,'../files/commonTemplates/service-instance.yaml'))).to.equal(getFileHash(join(bookshop, 'chart/templates/service-instance.yaml'))) - expect(getFileHash(join(__dirname,'../files/commonTemplates/domain.yaml'))).to.equal(getFileHash(join(bookshop, 'chart/templates/domain.yaml'))) + expect(getFileHash(join(__dirname, '../files/configurableTemplatesChart/values.schema.json'))).to.equal(getFileHash(join(bookshop, 'chart/values.schema.json'))) + expect(getFileHash(join(__dirname, '../files/commonTemplates/service-binding.yaml'))).to.equal(getFileHash(join(bookshop, 'chart/templates/service-binding.yaml'))) + expect(getFileHash(join(__dirname, '../files/commonTemplates/service-instance.yaml'))).to.equal(getFileHash(join(bookshop, 'chart/templates/service-instance.yaml'))) // Check changes to xs-security.json - expect(getFileHash(join(__dirname,'files/xs-security.json'))).to.equal(getFileHash(join(bookshop, 'xs-security.json'))) + expect(getFileHash(join(__dirname, 'files/xs-security.json'))).to.equal(getFileHash(join(bookshop, 'xs-security.json'))) }) it('Add cap-operator configurable template chart with cap-operator chart already present', async () => { @@ -167,55 +172,41 @@ describe('cds add cap-operator', () => { await cds.utils.copy(join('test/files', 'mta.yaml'), join(bookshop, 'mta.yaml')) await cds.utils.copy(join('test/files', 'corrected_xsappname.mtaext'), join(bookshop, 'corrected_xsappname.mtaext')) // revert xs-security to original value - fs.writeFileSync(bookshop+"/xs-security.json", orignalXsSecurityJson) + fs.writeFileSync(bookshop + "/xs-security.json", orignalXsSecurityJson) execSync(`cds add cap-operator --with-mta mta.yaml --with-mta-extensions corrected_xsappname.mtaext --with-configurable-templates`, { cwd: bookshop }) - expect(getFileHash(join(__dirname,'files/expectedConfigurableTemplatesChart/Chart.yaml'))).to.equal(getFileHash(join(bookshop, 'chart/Chart.yaml'))) - expect(getFileHash(join(__dirname,'files/expectedConfigurableTemplatesChart/valuesWithMTA.yaml'))).to.equal(getFileHash(join(bookshop, 'chart/values.yaml'))) - expect(getFileHash(join(__dirname,'files/expectedConfigurableTemplatesChart/templates/cap-operator-cros-mta.yaml'))).to.equal(getFileHash(join(bookshop, 'chart/templates/cap-operator-cros.yaml'))) - expect(getFileHash(join(__dirname,'files/expectedConfigurableTemplatesChart/templates/_helpers.tpl'))).to.equal(getFileHash(join(bookshop, 'chart/templates/_helpers.tpl'))) - expect(getFileHash(join(__dirname,'files/xs-security.json'))).to.equal(getFileHash(join(bookshop, 'xs-security.json'))) - }) - - it('Add cap-operator chart with service only', async () => { - execSync(`cds add cap-operator --with-service-only`, { cwd: bookshop }) - - expect(getFileHash(join(__dirname,'files/expectedChart/Chart-svc.yaml'))).to.equal(getFileHash(join(bookshop, 'chart/Chart.yaml'))) - expect(getFileHash(join(__dirname,'../files/chart/values.schema.json'))).to.equal(getFileHash(join(bookshop, 'chart/values.schema.json'))) - expect(getFileHash(join(__dirname,'files/expectedChart/values-svc.yaml'))).to.equal(getFileHash(join(bookshop, 'chart/values.yaml'))) + expect(getFileHash(join(__dirname, 'files/expectedConfigurableTemplatesChart/Chart.yaml'))).to.equal(getFileHash(join(bookshop, 'chart/Chart.yaml'))) + expect(getFileHash(join(__dirname, 'files/expectedConfigurableTemplatesChart/valuesWithMTA.yaml'))).to.equal(getFileHash(join(bookshop, 'chart/values.yaml'))) + expect(getFileHash(join(__dirname, 'files/expectedConfigurableTemplatesChart/templates/cap-operator-cros-mta.yaml'))).to.equal(getFileHash(join(bookshop, 'chart/templates/cap-operator-cros.yaml'))) + expect(getFileHash(join(__dirname, 'files/expectedConfigurableTemplatesChart/templates/_helpers.tpl'))).to.equal(getFileHash(join(bookshop, 'chart/templates/_helpers.tpl'))) + expect(getFileHash(join(__dirname, 'files/xs-security.json'))).to.equal(getFileHash(join(bookshop, 'xs-security.json'))) }) - it('Add cap-operator chart with service only and mta', async () => { - expect(() => execSync(`cds add cap-operator --with-service-only --with-mta mta.yaml`, { cwd: bookshop })).to.throw('Option \'--with-service-only\' cannot be used with \'--with-mta\' or \'--with-mta-extensions\' options.') - }) - - it('Add templates to an existing cap-operator service only chart', async () => { - execSync(`cds add cap-operator --with-service-only`, { cwd: bookshop }) + it('Add cap-operator chart with IAS & AMS', async () => { + execSync(`cds add ias,ams`, { cwd: bookshop }) execSync(`cds add cap-operator --with-templates`, { cwd: bookshop }) - expect(getFileHash(join(__dirname,'files/expectedChart/Chart-svc.yaml'))).to.equal(getFileHash(join(bookshop, 'chart/Chart.yaml'))) - expect(getFileHash(join(__dirname,'files/expectedChart/values-svc.yaml'))).to.equal(getFileHash(join(bookshop, 'chart/values.yaml'))) - expect(getFileHash(join(__dirname,'../files/chart/values.schema.json'))).to.equal(getFileHash(join(bookshop, 'chart/values.schema.json'))) - expect(getFileHash(join(__dirname,'../files/chart/templates/_helpers.tpl'))).to.equal(getFileHash(join(bookshop, 'chart/templates/_helpers.tpl'))) - expect(getFileHash(join(__dirname,'../files/commonTemplates/service-binding.yaml'))).to.equal(getFileHash(join(bookshop, 'chart/templates/service-binding.yaml'))) - expect(getFileHash(join(__dirname,'../files/commonTemplates/service-instance.yaml'))).to.equal(getFileHash(join(bookshop, 'chart/templates/service-instance.yaml'))) - expect(getFileHash(join(__dirname,'../files/commonTemplates/domain.yaml'))).to.equal(getFileHash(join(bookshop, 'chart/templates/domain.yaml'))) - expect(getFileHash(join(__dirname,'../files/chart/templates/cap-operator-cros-svc.yaml'))).to.equal(getFileHash(join(bookshop, 'chart/templates/cap-operator-cros.yaml'))) - }) + expect(getFileHash(join(__dirname, 'files/expectedChart/Chart.yaml'))).to.equal(getFileHash(join(bookshop, 'chart/Chart.yaml'))) + expect(getFileHash(join(__dirname, 'files/expectedChart/values-ias.yaml'))).to.equal(getFileHash(join(bookshop, 'chart/values.yaml'))) + expect(getFileHash(join(__dirname, 'files/expectedChart/templates/_helpers-ias.tpl'))).to.equal(getFileHash(join(bookshop, 'chart/templates/_helpers.tpl'))) + expect(getFileHash(join(__dirname,'files/expectedChart/templates/cap-operator-cros-ias.yaml'))).to.equal(getFileHash(join(bookshop, 'chart/templates/cap-operator-cros.yaml'))) - it('Add cap-operator configurable template chart with service only', async () => { + expect(getFileHash(join(__dirname, '../files/chart/values.schema.json'))).to.equal(getFileHash(join(bookshop, 'chart/values.schema.json'))) + }) - execSync(`cds add cap-operator --with-service-only --with-configurable-templates`, { cwd: bookshop }) + it('Add cap-operator configurable template chart with IAS & AMS', async () => { + execSync(`cds add ias,ams`, { cwd: bookshop }) + execSync(`cds add cap-operator --with-configurable-templates`, { cwd: bookshop }) - expect(getFileHash(join(__dirname,'files/expectedConfigurableTemplatesChart/Chart-svc.yaml'))).to.equal(getFileHash(join(bookshop, 'chart/Chart.yaml'))) - expect(getFileHash(join(__dirname,'files/expectedConfigurableTemplatesChart/values-svc.yaml'))).to.equal(getFileHash(join(bookshop, 'chart/values.yaml'))) - expect(getFileHash(join(__dirname,'files/expectedConfigurableTemplatesChart/templates/_helpers.tpl'))).to.equal(getFileHash(join(bookshop, 'chart/templates/_helpers.tpl'))) + expect(getFileHash(join(__dirname, 'files/expectedConfigurableTemplatesChart/Chart.yaml'))).to.equal(getFileHash(join(bookshop, 'chart/Chart.yaml'))) + expect(getFileHash(join(__dirname, 'files/expectedConfigurableTemplatesChart/values-ias.yaml'))).to.equal(getFileHash(join(bookshop, 'chart/values.yaml'))) + expect(getFileHash(join(__dirname, 'files/expectedConfigurableTemplatesChart/templates/_helpers-ias.tpl'))).to.equal(getFileHash(join(bookshop, 'chart/templates/_helpers.tpl'))) + expect(getFileHash(join(__dirname, 'files/expectedConfigurableTemplatesChart/templates/cap-operator-cros-ias.yaml'))).to.equal(getFileHash(join(bookshop, 'chart/templates/cap-operator-cros.yaml'))) + expect(getFileHash(join(__dirname, 'files/domain-ias.yaml'))).to.equal(getFileHash(join(bookshop, 'chart/templates/domain.yaml'))) - expect(getFileHash(join(__dirname,'../files/configurableTemplatesChart/values.schema.json'))).to.equal(getFileHash(join(bookshop, 'chart/values.schema.json'))) - expect(getFileHash(join(__dirname,'../files/configurableTemplatesChart/templates/cap-operator-cros-svc.yaml'))).to.equal(getFileHash(join(bookshop, 'chart/templates/cap-operator-cros.yaml'))) - expect(getFileHash(join(__dirname,'../files/commonTemplates/service-binding.yaml'))).to.equal(getFileHash(join(bookshop, 'chart/templates/service-binding.yaml'))) - expect(getFileHash(join(__dirname,'../files/commonTemplates/service-instance.yaml'))).to.equal(getFileHash(join(bookshop, 'chart/templates/service-instance.yaml'))) - expect(getFileHash(join(__dirname,'../files/commonTemplates/domain.yaml'))).to.equal(getFileHash(join(bookshop, 'chart/templates/domain.yaml'))) + expect(getFileHash(join(__dirname, '../files/configurableTemplatesChart/values.schema.json'))).to.equal(getFileHash(join(bookshop, 'chart/values.schema.json'))) + expect(getFileHash(join(__dirname, '../files/commonTemplates/service-binding.yaml'))).to.equal(getFileHash(join(bookshop, 'chart/templates/service-binding.yaml'))) + expect(getFileHash(join(__dirname, '../files/commonTemplates/service-instance.yaml'))).to.equal(getFileHash(join(bookshop, 'chart/templates/service-instance.yaml'))) }) }) diff --git a/test/build-services.test.js b/test/build-services.test.js new file mode 100644 index 0000000..89311ef --- /dev/null +++ b/test/build-services.test.js @@ -0,0 +1,48 @@ +const fs = require('fs') +const { join } = require('path') +const { execSync } = require('child_process') +const { expect } = require("chai") + +const TempUtil = require('./tempUtil') +const tempUtil = new TempUtil(__filename, { local: true }) + +const { getFileHash, updateDependency, setupHack, undoSetupHack } = require('./util') + +describe('cds build', () => { + + let temp, bookshop + + before(async () => { + await tempUtil.cleanUp() + temp = await tempUtil.mkTempFolder() + bookshop = join(temp, 'bookshop') + execSync(`cds init bookshop --add xsuaa,html5-repo,destination`, { cwd: temp }) + updateDependency(bookshop) + execSync(`npm install`, { cwd: bookshop }) + setupHack(bookshop) + }) + + afterEach(async () => { + execSync(`rm -r chart`, { cwd: bookshop }) + }) + + after(async () => { + undoSetupHack(bookshop) + await tempUtil.cleanUp() + }) + + it('Build cap-operator service only chart', async () => { + execSync(`cds add cap-operator --force --with-service-only`, { cwd: bookshop }) + execSync(`cds build`, { cwd: bookshop }) + + expect(getFileHash(join(__dirname,'files/expectedChart/Chart-svc.yaml'))).to.equal(getFileHash(join(bookshop, 'gen/chart/Chart.yaml'))) + expect(getFileHash(join(__dirname,'files/expectedChart/values-svc.yaml'))).to.equal(getFileHash(join(bookshop, 'gen/chart/values.yaml'))) + expect(getFileHash(join(__dirname,'files/expectedChart/templates/_helpers.tpl'))).to.equal(getFileHash(join(bookshop, 'gen/chart/templates/_helpers.tpl'))) + expect(getFileHash(join(__dirname,'files/expectedChart/templates/cap-operator-cros-svc.yaml'))).to.equal(getFileHash(join(bookshop, 'gen/chart/templates/cap-operator-cros.yaml'))) + expect(getFileHash(join(__dirname,'files/domain.yaml'))).to.equal(getFileHash(join(bookshop, 'gen/chart/templates/domain.yaml'))) + + expect(getFileHash(join(__dirname,'../files/chart/values.schema.json'))).to.equal(getFileHash(join(bookshop, 'gen/chart/values.schema.json'))) + expect(getFileHash(join(__dirname,'../files/commonTemplates/service-binding.yaml'))).to.equal(getFileHash(join(bookshop, 'gen/chart/templates/service-binding.yaml'))) + expect(getFileHash(join(__dirname,'../files/commonTemplates/service-instance.yaml'))).to.equal(getFileHash(join(bookshop, 'gen/chart/templates/service-instance.yaml'))) + }) +}) diff --git a/test/build.test.js b/test/build.test.js index a674dda..f072080 100644 --- a/test/build.test.js +++ b/test/build.test.js @@ -37,13 +37,14 @@ describe('cds build', () => { expect(getFileHash(join(__dirname,'files/expectedChart/Chart.yaml'))).to.equal(getFileHash(join(bookshop, 'gen/chart/Chart.yaml'))) expect(getFileHash(join(__dirname,'files/expectedChart/values.yaml'))).to.equal(getFileHash(join(bookshop, 'gen/chart/values.yaml'))) + expect(getFileHash(join(__dirname,'files/expectedChart/templates/_helpers.tpl'))).to.equal(getFileHash(join(bookshop, 'gen/chart/templates/_helpers.tpl'))) + expect(getFileHash(join(__dirname,'files/domain.yaml'))).to.equal(getFileHash(join(bookshop, 'gen/chart/templates/domain.yaml'))) + expect(getFileHash(join(__dirname,'files/expectedChart/templates/cap-operator-cros.yaml'))).to.equal(getFileHash(join(bookshop, 'gen/chart/templates/cap-operator-cros.yaml'))) + expect(getFileHash(join(__dirname,'../files/chart/values.schema.json'))).to.equal(getFileHash(join(bookshop, 'gen/chart/values.schema.json'))) - expect(getFileHash(join(__dirname,'../files/chart/templates/_helpers.tpl'))).to.equal(getFileHash(join(bookshop, 'gen/chart/templates/_helpers.tpl'))) expect(getFileHash(join(__dirname,'../files/commonTemplates/service-binding.yaml'))).to.equal(getFileHash(join(bookshop, 'gen/chart/templates/service-binding.yaml'))) expect(getFileHash(join(__dirname,'../files/commonTemplates/service-instance.yaml'))).to.equal(getFileHash(join(bookshop, 'gen/chart/templates/service-instance.yaml'))) - expect(getFileHash(join(__dirname,'../files/commonTemplates/domain.yaml'))).to.equal(getFileHash(join(bookshop, 'gen/chart/templates/domain.yaml'))) - expect(getFileHash(join(__dirname,'../files/chart/templates/cap-operator-cros.yaml'))).to.equal(getFileHash(join(bookshop, 'gen/chart/templates/cap-operator-cros.yaml'))) }) it('Build cap-operator chart with modified templates', async () => { @@ -56,27 +57,13 @@ describe('cds build', () => { expect(getFileHash(join(__dirname,'files/expectedChart/Chart.yaml'))).to.equal(getFileHash(join(bookshop, 'gen/chart/Chart.yaml'))) expect(getFileHash(join(__dirname,'files/expectedChart/values.yaml'))).to.equal(getFileHash(join(bookshop, 'gen/chart/values.yaml'))) - expect(getFileHash(join(__dirname,'../files/chart/values.schema.json'))).to.equal(getFileHash(join(bookshop, 'gen/chart/values.schema.json'))) - expect(getFileHash(join(__dirname,'../files/commonTemplates/service-binding.yaml'))).to.equal(getFileHash(join(bookshop, 'gen/chart/templates/service-binding.yaml'))) - expect(getFileHash(join(__dirname,'../files/commonTemplates/service-instance.yaml'))).to.equal(getFileHash(join(bookshop, 'gen/chart/templates/service-instance.yaml'))) - expect(getFileHash(join(__dirname,'../files/commonTemplates/domain.yaml'))).to.equal(getFileHash(join(bookshop, 'gen/chart/templates/domain.yaml'))) - expect(getFileHash(join(__dirname,'../files/chart/templates/cap-operator-cros.yaml'))).to.equal(getFileHash(join(bookshop, 'gen/chart/templates/cap-operator-cros.yaml'))) - - expect(fs.existsSync(join(bookshop, 'gen/chart/templates/_helpers.tpl'))).to.equal(false) - }) + expect(getFileHash(join(__dirname,'files/expectedChart/templates/cap-operator-cros.yaml'))).to.equal(getFileHash(join(bookshop, 'gen/chart/templates/cap-operator-cros.yaml'))) - it('Build cap-operator service only chart', async () => { - execSync(`cds add cap-operator --force --with-service-only`, { cwd: bookshop }) - execSync(`cds build`, { cwd: bookshop }) - - expect(getFileHash(join(__dirname,'files/expectedChart/Chart-svc.yaml'))).to.equal(getFileHash(join(bookshop, 'gen/chart/Chart.yaml'))) - expect(getFileHash(join(__dirname,'files/expectedChart/values-svc.yaml'))).to.equal(getFileHash(join(bookshop, 'gen/chart/values.yaml'))) expect(getFileHash(join(__dirname,'../files/chart/values.schema.json'))).to.equal(getFileHash(join(bookshop, 'gen/chart/values.schema.json'))) - expect(getFileHash(join(__dirname,'../files/chart/templates/_helpers.tpl'))).to.equal(getFileHash(join(bookshop, 'gen/chart/templates/_helpers.tpl'))) expect(getFileHash(join(__dirname,'../files/commonTemplates/service-binding.yaml'))).to.equal(getFileHash(join(bookshop, 'gen/chart/templates/service-binding.yaml'))) expect(getFileHash(join(__dirname,'../files/commonTemplates/service-instance.yaml'))).to.equal(getFileHash(join(bookshop, 'gen/chart/templates/service-instance.yaml'))) - expect(getFileHash(join(__dirname,'../files/commonTemplates/domain.yaml'))).to.equal(getFileHash(join(bookshop, 'gen/chart/templates/domain.yaml'))) + expect(getFileHash(join(__dirname,'files/domain.yaml'))).to.equal(getFileHash(join(bookshop, 'gen/chart/templates/domain.yaml'))) - expect(getFileHash(join(__dirname,'../files/chart/templates/cap-operator-cros-svc.yaml'))).to.equal(getFileHash(join(bookshop, 'gen/chart/templates/cap-operator-cros.yaml'))) + expect(fs.existsSync(join(bookshop, 'gen/chart/templates/_helpers.tpl'))).to.equal(false) }) }) diff --git a/test/cap-op-plugin.test.js b/test/cap-op-plugin.test.js index f642d36..32d9940 100644 --- a/test/cap-op-plugin.test.js +++ b/test/cap-op-plugin.test.js @@ -227,4 +227,86 @@ EXAMPLES expect(log).to.include('Exisiting chart is already a configurable template chart. No need for conversion.') expect(log).to.include('Transforming runtime values file') }) + + //------------------------------------------------ + // IAS test cases + //------------------------------------------------ + it('Generate runtime-values via prompts - IAS', async () => { + execSync(`cds add ias`, { cwd: bookshop }) + execSync(`cds add cap-operator`, { cwd: bookshop }) + + rlQuestion = sinon.stub() + rlInterface = { + question: rlQuestion, + close: sinon.stub() + } + sinon.stub(readline, 'createInterface').returns(rlInterface) + + rlQuestion.onFirstCall().callsArgWith(1, 'bkshop') + rlQuestion.onSecondCall().callsArgWith(1, '') + rlQuestion.onThirdCall().callsArgWith(1, 'c-abc.kyma.ondemand.com') + rlQuestion.onCall(3).callsArgWith(1, 'dc94db56-asda-adssa-dada-123456789012') + rlQuestion.onCall(4).callsArgWith(1, 'bem-aad-sadad-123456789012') + rlQuestion.onCall(5).callsArgWith(1, 'dasdsd-1234-1234-1234-123456789012') + rlQuestion.onCall(6).callsArgWith(1, 'sdasd-4c4d-4d4d-4d4d-123456789012') + rlQuestion.onCall(7).callsArgWith(1, 'regcred') + + cds.root = bookshop + await capOperatorPlugin('generate-runtime-values') + sinon.restore() + + expect(getFileHash(join(__dirname, 'files/expectedChart/runtime-values-ias.yaml'))).to.equal(getFileHash(join(bookshop, 'chart/runtime-values.yaml'))) + }) + + it('Generate runtime-values via prompts for configurable template chart - IAS', async () => { + execSync(`cds add ias`, { cwd: bookshop }) + execSync(`cds add cap-operator --with-configurable-templates`, { cwd: bookshop }) + + rlQuestion = sinon.stub() + rlInterface = { + question: rlQuestion, + close: sinon.stub() + } + sinon.stub(readline, 'createInterface').returns(rlInterface) + + rlQuestion.onFirstCall().callsArgWith(1, 'bkshop') + rlQuestion.onSecondCall().callsArgWith(1, '') + rlQuestion.onThirdCall().callsArgWith(1, 'c-abc.kyma.ondemand.com') + rlQuestion.onCall(3).callsArgWith(1, 'dc94db56-asda-adssa-dada-123456789012') + rlQuestion.onCall(4).callsArgWith(1, 'bem-aad-sadad-123456789012') + rlQuestion.onCall(5).callsArgWith(1, 'dasdsd-1234-1234-1234-123456789012') + rlQuestion.onCall(6).callsArgWith(1, 'sdasd-4c4d-4d4d-4d4d-123456789012') + rlQuestion.onCall(7).callsArgWith(1, 'regcred') + + cds.root = bookshop + await capOperatorPlugin('generate-runtime-values') + sinon.restore() + + expect(getFileHash(join(__dirname, 'files/expectedConfigurableTemplatesChart/runtime-values-ias.yaml'))).to.equal(getFileHash(join(bookshop, 'chart/runtime-values.yaml'))) + }) + + it('Generate runtime-values via prompts for service only chart - IAS', async () => { + execSync(`cds add ias`, { cwd: bookshop }) + execSync(`cds add cap-operator --with-service-only`, { cwd: bookshop }) + + rlQuestion = sinon.stub() + rlInterface = { + question: rlQuestion, + close: sinon.stub() + } + sinon.stub(readline, 'createInterface').returns(rlInterface) + + rlQuestion.onFirstCall().callsArgWith(1, 'bkshop') + rlQuestion.onSecondCall().callsArgWith(1, '') + rlQuestion.onThirdCall().callsArgWith(1, 'c-abc.kyma.ondemand.com') + rlQuestion.onCall(3).callsArgWith(1, 'dc94db56-asda-adssa-dada-123456789012') + rlQuestion.onCall(4).callsArgWith(1, 'sdasd-4c4d-4d4d-4d4d-123456789012') + rlQuestion.onCall(5).callsArgWith(1, 'regcred') + + cds.root = bookshop + await capOperatorPlugin('generate-runtime-values') + sinon.restore() + + expect(getFileHash(join(__dirname, 'files/expectedChart/runtime-values-svc-ias.yaml'))).to.equal(getFileHash(join(bookshop, 'chart/runtime-values.yaml'))) + }) }) diff --git a/test/files/domain-ias.yaml b/test/files/domain-ias.yaml new file mode 100644 index 0000000..7f55c2f --- /dev/null +++ b/test/files/domain-ias.yaml @@ -0,0 +1,45 @@ +apiVersion: sme.sap.com/v1alpha1 +kind: Domain +metadata: + name: {{ include "domainName" $ }} +spec: + dnsMode: Wildcard + domain: {{ .Values.app.domains.primary }} + ingressSelector: + {{- range $k, $v := $.Values.app.istioIngressGatewayLabels }} + {{ $k }}: {{ $v | default "invalidValue" }} + {{- end }} + certConfig: + additionalCACertificate: | + -----BEGIN CERTIFICATE----- + MIIFZjCCA06gAwIBAgIQGHcPvmUGa79M6pM42bGFYjANBgkqhkiG9w0BAQsFADBN + MQswCQYDVQQGEwJERTERMA8GA1UEBwwIV2FsbGRvcmYxDzANBgNVBAoMBlNBUCBT + RTEaMBgGA1UEAwwRU0FQIENsb3VkIFJvb3QgQ0EwHhcNMTkwMjEzMTExOTM2WhcN + MzkwMjEzMTEyNjMyWjBNMQswCQYDVQQGEwJERTERMA8GA1UEBwwIV2FsbGRvcmYx + DzANBgNVBAoMBlNBUCBTRTEaMBgGA1UEAwwRU0FQIENsb3VkIFJvb3QgQ0EwggIi + MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQChbHLXJoe/zFag6fB3IcN3d3HT + Y14nSkEZIuUzYs7B96GFxQi0T/2s971JFiLfB4KaCG+UcG3dLXf1H/wewq8ahArh + FTsu4UR71ePUQiYlk/G68EFSy2zWYAJliXJS5k0DFMIWHD1lbSjCF3gPVJSUKf+v + HmWD5e9vcuiPBlSCaEnSeimYRhg0ITmi3RJ4Wu7H0Xp7tDd5z4HUKuyi9XRinfvG + kPALiBaX01QRC51cixmo0rhVe7qsNh7WDnLNBZeA0kkxNhLKDl8J6fQHKDdDEzmZ + KhK5KxL5p5YIZWZ8eEdNRoYRMXR0PxmHvRanzRvSVlXSbfqxaKlORfJJ1ah1bRNt + o0ngAQchTghsrRuf3Qh/2Kn29IuBy4bjKR9CdNLxGrClvX/q26rUUlz6A3lbXbwJ + EHSRnendRfEiia+xfZD+NG2oZW0IdTXSqkCbnBnign+uxGH5ECjuLEtvtUx6i9Ae + xAvK2FqIuud+AchqiZBKzmQAhUjKUoACzNP2Bx2zgJOeB0BqGvf6aldG0n2hYxJF + 8Xssc8TBlwvAqtiubP/UxJJPs+IHqU+zjm7KdP6dM2sbE+J9O3n8DzOP0SDyEmWU + UCwnmoPOQlq1z6fH9ghcp9bDdbh6adXM8I+SUYUcfvupOzBU7rWHxDCXld/24tpI + FA7FRzHwKXqMSjwtBQIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/ + BAUwAwEB/zAdBgNVHQ4EFgQUHLxmKw7KjUufjZNxqQ/KZ0ZpEyIwDQYJKoZIhvcN + AQELBQADggIBABdSKQsh3EfVoqplSIx6X43y2Pp+kHZLtEsRWMzgO5LhYy2/Fvel + eRBw/XEiB5iKuEGhxHz/Gqe0gZixw3SsHB1Q464EbGT4tPQ2UiMhiiDho9hVe6tX + qX1FhrhycAD1xHIxMxQP/buX9s9arFZauZrpw/Jj4tGp7aEj4hypWpO9tzjdBthy + 5vXSviU8L2HyiQpVND/Rp+dNJmVYTiFLuULRY28QbikgFO2xp9s4RNkDBnbDeTrT + CKWcVsmlZLPJJQZm0n2p8CvoeAsKzIULT9YSbEEBwmeqRlmbUaoT/rUGoobSFcrP + jrBg66y5hA2w7S3tDH0GjMpRu16b2u0hYQocUDuMlyhrkhsO+Qtqkz1ubwHCJ8PA + RJw6zYl9VeBtgI5F69AEJdkAgYfvPw5DJipgVuQDSv7ezi6ZcI75939ENGjSyLVy + 4SuP99G7DuItG008T8AYFUHAM2h/yskVyvoZ8+gZx54TC9aY9gPIKyX++4bHv5BC + qbEdU46N05R+AIBW2KvWozQkjhSQCbzcp6DHXLoZINI6y0WOImzXrvLUSIm4CBaj + 6MTXInIkmitdURnmpxTxLva5Kbng/u20u5ylIQKqpcD8HWX97lLVbmbnPkbpKxo+ + LvHPhNDM3rMsLu06agF4JTbO8ANYtWQTx0PVrZKJu+8fcIaUp7MVBIVZ + -----END CERTIFICATE----- + tlsMode: OptionalMutual diff --git a/files/commonTemplates/domain.yaml b/test/files/domain.yaml similarity index 71% rename from files/commonTemplates/domain.yaml rename to test/files/domain.yaml index db9bc1e..e40a1fa 100644 --- a/files/commonTemplates/domain.yaml +++ b/test/files/domain.yaml @@ -4,9 +4,9 @@ metadata: name: {{ include "domainName" $ }} spec: dnsMode: Wildcard - domain: {{.Values.app.domains.primary}} + domain: {{ .Values.app.domains.primary }} ingressSelector: {{- range $k, $v := $.Values.app.istioIngressGatewayLabels }} - {{ $k }}: {{ $v | default "invalidValue"}} + {{ $k }}: {{ $v | default "invalidValue" }} {{- end }} tlsMode: Simple diff --git a/test/files/expectedChart/runtime-values-ias.yaml b/test/files/expectedChart/runtime-values-ias.yaml new file mode 100644 index 0000000..63c2a5a --- /dev/null +++ b/test/files/expectedChart/runtime-values-ias.yaml @@ -0,0 +1,46 @@ +serviceInstances: + subscriptionManager: + parameters: + appName: bkshop + commercialAppName: bkshop + displayName: (bkshop) + description: (A simple CAP project.) + category: CAP + appCallbacks: + dependenciesCallbacks: + url: https://bem-aad-sadad-123456789012.bkshop.c-abc.kyma.ondemand.com/v1.0/callback/tenants/{app_tid}/dependencies + subscriptionCallbacks: + url: https://cap-op.c-abc.kyma.ondemand.com/sms/provision/tenants/{app_tid} + identity: + parameters: + display-name: bkshop + home-url: https://$BTP_SUBDOMAIN.bkshop.c-abc.kyma.ondemand.com +serviceBindings: + identity: + parameters: + app-identifier: bkshop +app: + domains: + primary: bkshop.c-abc.kyma.ondemand.com + additionalDomainRefs: [] + istioIngressGatewayLabels: + istio: ingressgateway + app: istio-ingressgateway +btp: + globalAccountId: dc94db56-asda-adssa-dada-123456789012 + provider: + subdomain: bem-aad-sadad-123456789012 + tenantId: dasdsd-1234-1234-1234-123456789012 +imagePullSecrets: + - regcred +workloads: + server: + deploymentDefinition: + env: + - name: CDS_CONFIG + value: '{"requires":{"cds.xt.DeploymentService":{"hdi":{"create":{"database_id":"sdasd-4c4d-4d4d-4d4d-123456789012"}}}}}' + tenantJob: + jobDefinition: + env: + - name: CDS_CONFIG + value: '{"requires":{"cds.xt.DeploymentService":{"hdi":{"create":{"database_id":"sdasd-4c4d-4d4d-4d4d-123456789012"}}}}}' diff --git a/test/files/expectedChart/runtime-values-svc-ias.yaml b/test/files/expectedChart/runtime-values-svc-ias.yaml new file mode 100644 index 0000000..9561c60 --- /dev/null +++ b/test/files/expectedChart/runtime-values-svc-ias.yaml @@ -0,0 +1,26 @@ +serviceInstances: + identity: + parameters: + display-name: bkshop + home-url: https://$BTP_SUBDOMAIN.bkshop.c-abc.kyma.ondemand.com +serviceBindings: + identity: + parameters: + app-identifier: bkshop +app: + domains: + primary: bkshop.c-abc.kyma.ondemand.com + additionalDomainRefs: [] + istioIngressGatewayLabels: + istio: ingressgateway + app: istio-ingressgateway +btp: + globalAccountId: dc94db56-asda-adssa-dada-123456789012 +imagePullSecrets: + - regcred +workloads: + server: + deploymentDefinition: + env: + - name: CDS_CONFIG + value: '{"requires":{"cds.xt.DeploymentService":{"hdi":{"create":{"database_id":"sdasd-4c4d-4d4d-4d4d-123456789012"}}}}}' diff --git a/test/files/expectedChart/runtime-values-svc.yaml b/test/files/expectedChart/runtime-values-svc.yaml index 857b122..e6c8290 100644 --- a/test/files/expectedChart/runtime-values-svc.yaml +++ b/test/files/expectedChart/runtime-values-svc.yaml @@ -1,13 +1,4 @@ serviceInstances: - saasRegistry: - parameters: - xsappname: bkshop - appName: bkshop - displayName: bkshop - description: A simple CAP project. - appUrls: - getDependencies: https://bkshop.c-abc.kyma.ondemand.com/callback/v1.0/dependencies - onSubscription: https://cap-op.c-abc.kyma.ondemand.com/provision/tenants/{tenantId} xsuaa: parameters: xsappname: bkshop diff --git a/test/files/expectedChart/templates/_helpers-ias.tpl b/test/files/expectedChart/templates/_helpers-ias.tpl new file mode 100644 index 0000000..3150d35 --- /dev/null +++ b/test/files/expectedChart/templates/_helpers-ias.tpl @@ -0,0 +1,49 @@ +{{- define "capApplicationVersionName" -}} +{{ printf "%s-%d" (include "appName" $) (.Release.Revision) }} +{{- end -}} + +{{- define "domainName" -}} +{{ printf "%s-primary" (include "appName" $)}} +{{- end -}} + +{{- define "appName" -}} +{{- range $sik, $siv := .Values.serviceInstances }} + {{- if and (eq (get $siv "serviceOfferingName") "subscription-manager") (eq (get $siv "servicePlanName") "provider") -}} + {{ printf "%s" $siv.parameters.appName }} + {{- break -}} + {{- end -}} +{{- end -}} +{{- end -}} + +{{- define "domainHostMap" -}} + {{- $domains := list .Values.app.domains.primary -}} + {{- range .Values.app.domains.additionalDomainRefs }} + {{- $apiVersion := "sme.sap.com/v1alpha1" -}} + {{- $namespace := (eq .kind "Domain" | ternary $.Release.Namespace "") -}} + {{- $resource := (lookup $apiVersion .kind $namespace .name) -}} + {{- if and $resource (kindIs "map" $resource) (hasKey $resource "spec") (hasKey $resource.spec "domain") -}} + {{- $domains = append $domains $resource.spec.domain -}} + {{- end -}} + {{- end -}} + {{- toJson (dict "domains" $domains) -}} +{{- end }} + +{{- define "redirectUris" -}} + {{- $ctx := .context -}} + {{- $svc := .serviceOfferingName -}} + {{- $domains := (include "domainHostMap" $ctx | fromJson).domains -}} + {{- $redirectUris := list -}} + {{- range $domains }} + {{- $redirectUris = append $redirectUris (printf "https://*.%s/**" .) -}} + {{- end -}} + {{- if eq $svc "identity" }} + {{- toJson (dict "redirect-uris" $redirectUris "post-logout-redirect-uris" $redirectUris) -}} + {{- else }} + {{- toJson (dict "redirect-uris" $redirectUris) -}} + {{- end -}} +{{- end }} + +{{- define "tenantHostPattern" -}} + {{- $domains := (include "domainHostMap" . | fromJson).domains -}} + {{- printf "^(.*)\\.(%s)" (join "|" $domains | replace "." "\\.") -}} +{{- end }} diff --git a/files/chart/templates/_helpers.tpl b/test/files/expectedChart/templates/_helpers.tpl similarity index 70% rename from files/chart/templates/_helpers.tpl rename to test/files/expectedChart/templates/_helpers.tpl index 72468e8..38fd357 100644 --- a/files/chart/templates/_helpers.tpl +++ b/test/files/expectedChart/templates/_helpers.tpl @@ -8,10 +8,10 @@ {{- define "appName" -}} {{- range $sik, $siv := .Values.serviceInstances }} - {{- if and (eq (get $siv "serviceOfferingName") "xsuaa") (eq (get $siv "servicePlanName") "broker") -}} - {{ printf "%s" $siv.parameters.xsappname }} - {{- break -}} - {{- end -}} + {{- if and (eq (get $siv "serviceOfferingName") "xsuaa") (eq (get $siv "servicePlanName") "broker") -}} + {{ printf "%s" $siv.parameters.xsappname }} + {{- break -}} + {{- end -}} {{- end -}} {{- end -}} @@ -29,12 +29,18 @@ {{- end }} {{- define "redirectUris" -}} - {{- $domains := (include "domainHostMap" . | fromJson).domains -}} + {{- $ctx := .context -}} + {{- $svc := .serviceOfferingName -}} + {{- $domains := (include "domainHostMap" $ctx | fromJson).domains -}} {{- $redirectUris := list -}} {{- range $domains }} {{- $redirectUris = append $redirectUris (printf "https://*.%s/**" .) -}} {{- end -}} - {{- toJson (dict "redirect-uris" $redirectUris) -}} + {{- if eq $svc "identity" }} + {{- toJson (dict "redirect-uris" $redirectUris "post-logout-redirect-uris" $redirectUris) -}} + {{- else }} + {{- toJson (dict "redirect-uris" $redirectUris) -}} + {{- end -}} {{- end }} {{- define "tenantHostPattern" -}} diff --git a/test/files/expectedChart/templates/cap-operator-cros-ias.yaml b/test/files/expectedChart/templates/cap-operator-cros-ias.yaml new file mode 100644 index 0000000..0b786c6 --- /dev/null +++ b/test/files/expectedChart/templates/cap-operator-cros-ias.yaml @@ -0,0 +1,105 @@ +--- +apiVersion: sme.sap.com/v1alpha1 +kind: CAPApplication +metadata: + name: {{ include "appName" $ }} + annotations: + sme.sap.com/vs-route-request-header-set: | + { + "x-forwarded-client-cert": "%DOWNSTREAM_PEER_CERT%" + } +spec: + domainRefs: + - kind: Domain + name: {{ include "domainName" $ }} + {{- range .Values.app.domains.additionalDomainRefs }} + - kind: {{ .kind }} + name: {{ .name }} + {{- end }} + btpAppName: {{ include "appName" $ }} + globalAccountId: {{ .Values.btp.globalAccountId }} + provider: + subDomain: {{ .Values.btp.provider.subdomain }} + tenantId: {{ .Values.btp.provider.tenantId }} + btp: + services: + {{- $serviceInstances := .Values.serviceInstances }} + {{- range $k, $v := .Values.serviceBindings }} + {{- $serviceInstance := dict }} + {{- range $sik, $siv := $serviceInstances }} + {{- if eq $siv.name $v.serviceInstanceName }} + {{- $serviceInstance = $siv }} + {{- end }} + {{- end }} + {{- if hasKey $serviceInstance "serviceOfferingName" }} + - class: {{ get $serviceInstance "serviceOfferingName" | default "invalidValue" }} + {{- if $v.externalName }} + name: {{ $v.externalName | default "invalidValue" }} + {{- else }} + name: {{ $v.name | default "invalidValue" }} + {{- end }} + secret: {{ $v.secretName | default "invalidValue" }} + {{- end }} + {{- end }} +--- +apiVersion: sme.sap.com/v1alpha1 +kind: CAPApplicationVersion +metadata: + annotations: + helm.sh/hook: post-install,post-upgrade + helm.sh/resource-policy: keep + name: {{ include "capApplicationVersionName" $ }} +spec: + capApplicationInstance: {{ include "appName" $ }} + version: "{{ .Release.Revision }}" + registrySecrets: + {{- range .Values.imagePullSecrets }} + - {{ . }} + {{- end }} + workloads: + {{- range $k, $v := .Values.workloads }} + - name: {{ $v.name }} + + {{- if $v.labels }} + labels: {{- toYaml $v.labels | trim | nindent 6 }} + {{- end }} + + {{- if $v.annotations }} + annotations: {{- toYaml $v.annotations | trim | nindent 6 }} + {{- end }} + + {{- if $v.consumedBTPServices }} + consumedBTPServices: {{- toYaml $v.consumedBTPServices | trim | nindent 4 }} + {{- end }} + + {{- if and $v.deploymentDefinition (eq $v.deploymentDefinition.type "Router") }} + {{- $thp := include "tenantHostPattern" $ }} + {{- $tphEnv := list (dict "name" "TENANT_HOST_PATTERN" "value" $thp) }} + {{- $baseEnv := get $v.deploymentDefinition "env" | default (list) }} + {{- $exists := false }} + {{- range $baseVar := $baseEnv }} + {{- if eq $baseVar.name "TENANT_HOST_PATTERN" }} + {{- $exists = true }} + {{- end }} + {{- end }} + {{- if not $exists }} + {{- $baseEnv = concat $baseEnv $tphEnv }} + {{- end }} + {{- $modified := merge (dict "env" $baseEnv) $v.deploymentDefinition }} + deploymentDefinition: {{- toYaml $modified | trim | nindent 6 }} + {{- else if $v.deploymentDefinition }} + deploymentDefinition: {{- toYaml $v.deploymentDefinition | trim | nindent 6 }} + {{- end }} + + {{- if $v.jobDefinition }} + jobDefinition: {{- toYaml $v.jobDefinition | trim | nindent 6 }} + {{- end }} + {{- end }} + + {{- if .Values.tenantOperations }} + tenantOperations: {{- toYaml .Values.tenantOperations | trim | nindent 4 }} + {{- end }} + + {{- if .Values.contentJobs }} + contentJobs: {{- toYaml .Values.contentJobs | trim | nindent 4 }} + {{- end }} diff --git a/test/files/expectedChart/templates/cap-operator-cros-svc-ias.yaml b/test/files/expectedChart/templates/cap-operator-cros-svc-ias.yaml new file mode 100644 index 0000000..fbfec8f --- /dev/null +++ b/test/files/expectedChart/templates/cap-operator-cros-svc-ias.yaml @@ -0,0 +1,102 @@ +--- +apiVersion: sme.sap.com/v1alpha1 +kind: CAPApplication +metadata: + name: {{ include "appName" $ }} + annotations: + sme.sap.com/vs-route-request-header-set: | + { + "x-forwarded-client-cert": "%DOWNSTREAM_PEER_CERT%" + } +spec: + domainRefs: + - kind: Domain + name: {{ include "domainName" $ }} + {{- range .Values.app.domains.additionalDomainRefs }} + - kind: {{ .kind }} + name: {{ .name }} + {{- end }} + btpAppName: {{ include "appName" $ }} + globalAccountId: {{ .Values.btp.globalAccountId }} + btp: + services: + {{- $serviceInstances := .Values.serviceInstances }} + {{- range $k, $v := .Values.serviceBindings }} + {{- $serviceInstance := dict }} + {{- range $sik, $siv := $serviceInstances }} + {{- if eq $siv.name $v.serviceInstanceName }} + {{- $serviceInstance = $siv }} + {{- end }} + {{- end }} + {{- if hasKey $serviceInstance "serviceOfferingName" }} + - class: {{ get $serviceInstance "serviceOfferingName" | default "invalidValue" }} + {{- if $v.externalName }} + name: {{ $v.externalName | default "invalidValue" }} + {{- else }} + name: {{ $v.name | default "invalidValue" }} + {{- end }} + secret: {{ $v.secretName | default "invalidValue" }} + {{- end }} + {{- end }} +--- +apiVersion: sme.sap.com/v1alpha1 +kind: CAPApplicationVersion +metadata: + annotations: + helm.sh/hook: post-install,post-upgrade + helm.sh/resource-policy: keep + name: {{ include "capApplicationVersionName" $ }} +spec: + capApplicationInstance: {{ include "appName" $ }} + version: "{{ .Release.Revision }}" + registrySecrets: + {{- range .Values.imagePullSecrets }} + - {{ . }} + {{- end }} + workloads: + {{- range $k, $v := .Values.workloads }} + - name: {{ $v.name }} + + {{- if $v.labels }} + labels: {{- toYaml $v.labels | trim | nindent 6 }} + {{- end }} + + {{- if $v.annotations }} + annotations: {{- toYaml $v.annotations | trim | nindent 6 }} + {{- end }} + + {{- if $v.consumedBTPServices }} + consumedBTPServices: {{- toYaml $v.consumedBTPServices | trim | nindent 4 }} + {{- end }} + + {{- if and $v.deploymentDefinition (eq $v.deploymentDefinition.type "Router") }} + {{- $thp := include "tenantHostPattern" $ }} + {{- $tphEnv := list (dict "name" "TENANT_HOST_PATTERN" "value" $thp) }} + {{- $baseEnv := get $v.deploymentDefinition "env" | default (list) }} + {{- $exists := false }} + {{- range $baseVar := $baseEnv }} + {{- if eq $baseVar.name "TENANT_HOST_PATTERN" }} + {{- $exists = true }} + {{- end }} + {{- end }} + {{- if not $exists }} + {{- $baseEnv = concat $baseEnv $tphEnv }} + {{- end }} + {{- $modified := merge (dict "env" $baseEnv) $v.deploymentDefinition }} + deploymentDefinition: {{- toYaml $modified | trim | nindent 6 }} + {{- else if $v.deploymentDefinition }} + deploymentDefinition: {{- toYaml $v.deploymentDefinition | trim | nindent 6 }} + {{- end }} + + {{- if $v.jobDefinition }} + jobDefinition: {{- toYaml $v.jobDefinition | trim | nindent 6 }} + {{- end }} + {{- end }} + + {{- if .Values.contentJobs }} + contentJobs: {{- toYaml .Values.contentJobs | trim | nindent 4 }} + {{- end }} + + {{- if .Values.serviceExposures }} + serviceExposures: {{- toYaml .Values.serviceExposures | trim | nindent 4 }} + {{- end }} diff --git a/files/chart/templates/cap-operator-cros-svc.yaml b/test/files/expectedChart/templates/cap-operator-cros-svc.yaml similarity index 96% rename from files/chart/templates/cap-operator-cros-svc.yaml rename to test/files/expectedChart/templates/cap-operator-cros-svc.yaml index e0ec382..da4c8ee 100644 --- a/files/chart/templates/cap-operator-cros-svc.yaml +++ b/test/files/expectedChart/templates/cap-operator-cros-svc.yaml @@ -12,7 +12,7 @@ spec: name: {{ .name }} {{- end }} btpAppName: {{ include "appName" $ }} - globalAccountId: {{.Values.btp.globalAccountId}} + globalAccountId: {{ .Values.btp.globalAccountId }} btp: services: {{- $serviceInstances := .Values.serviceInstances }} @@ -45,9 +45,9 @@ spec: capApplicationInstance: {{ include "appName" $ }} version: "{{ .Release.Revision }}" registrySecrets: - {{- range .Values.imagePullSecrets }} - - {{.}} - {{- end }} + {{- range .Values.imagePullSecrets }} + - {{ . }} + {{- end }} workloads: {{- range $k, $v := .Values.workloads }} - name: {{ $v.name }} @@ -68,18 +68,15 @@ spec: {{- $thp := include "tenantHostPattern" $ }} {{- $tphEnv := list (dict "name" "TENANT_HOST_PATTERN" "value" $thp) }} {{- $baseEnv := get $v.deploymentDefinition "env" | default (list) }} - {{- $exists := false }} {{- range $baseVar := $baseEnv }} {{- if eq $baseVar.name "TENANT_HOST_PATTERN" }} {{- $exists = true }} {{- end }} {{- end }} - {{- if not $exists }} {{- $baseEnv = concat $baseEnv $tphEnv }} {{- end }} - {{- $modified := merge (dict "env" $baseEnv) $v.deploymentDefinition }} deploymentDefinition: {{- toYaml $modified | trim | nindent 6 }} {{- else if $v.deploymentDefinition }} diff --git a/files/chart/templates/cap-operator-cros.yaml b/test/files/expectedChart/templates/cap-operator-cros.yaml similarity index 93% rename from files/chart/templates/cap-operator-cros.yaml rename to test/files/expectedChart/templates/cap-operator-cros.yaml index 210707f..679ca82 100644 --- a/files/chart/templates/cap-operator-cros.yaml +++ b/test/files/expectedChart/templates/cap-operator-cros.yaml @@ -12,10 +12,10 @@ spec: name: {{ .name }} {{- end }} btpAppName: {{ include "appName" $ }} - globalAccountId: {{.Values.btp.globalAccountId}} + globalAccountId: {{ .Values.btp.globalAccountId }} provider: - subDomain: {{.Values.btp.provider.subdomain}} - tenantId: {{.Values.btp.provider.tenantId}} + subDomain: {{ .Values.btp.provider.subdomain }} + tenantId: {{ .Values.btp.provider.tenantId }} btp: services: {{- $serviceInstances := .Values.serviceInstances }} @@ -48,9 +48,9 @@ spec: capApplicationInstance: {{ include "appName" $ }} version: "{{ .Release.Revision }}" registrySecrets: - {{- range .Values.imagePullSecrets }} - - {{.}} - {{- end }} + {{- range .Values.imagePullSecrets }} + - {{ . }} + {{- end }} workloads: {{- range $k, $v := .Values.workloads }} - name: {{ $v.name }} @@ -71,18 +71,15 @@ spec: {{- $thp := include "tenantHostPattern" $ }} {{- $tphEnv := list (dict "name" "TENANT_HOST_PATTERN" "value" $thp) }} {{- $baseEnv := get $v.deploymentDefinition "env" | default (list) }} - {{- $exists := false }} {{- range $baseVar := $baseEnv }} {{- if eq $baseVar.name "TENANT_HOST_PATTERN" }} {{- $exists = true }} {{- end }} {{- end }} - {{- if not $exists }} {{- $baseEnv = concat $baseEnv $tphEnv }} {{- end }} - {{- $modified := merge (dict "env" $baseEnv) $v.deploymentDefinition }} deploymentDefinition: {{- toYaml $modified | trim | nindent 6 }} {{- else if $v.deploymentDefinition }} diff --git a/test/files/expectedChart/values-ias.yaml b/test/files/expectedChart/values-ias.yaml new file mode 100644 index 0000000..b9ee4dd --- /dev/null +++ b/test/files/expectedChart/values-ias.yaml @@ -0,0 +1,175 @@ +serviceInstances: + destination: + name: bookshop-destination + serviceOfferingName: destination + servicePlanName: lite + parameters: + HTML5Runtime_enabled: true + html5RepoRuntime: + name: bookshop-html5-repo-runtime + serviceOfferingName: html5-apps-repo + servicePlanName: app-runtime + parameters: {} + html5RepoHost: + name: bookshop-html5-repo-host + serviceOfferingName: html5-apps-repo + servicePlanName: app-host + parameters: {} + identity: + name: bookshop-identity + serviceOfferingName: identity + servicePlanName: application + parameters: + display-name: bookshop + multi-tenant: true + xsuaa-cross-consumption: true + authorization: + enabled: true + oauth2-configuration: + redirect-uris: [] + post-logout-redirect-uris: [] + home-url: "" + subscriptionManager: + name: bookshop-subscription-manager + serviceOfferingName: subscription-manager + servicePlanName: provider + parameters: + iasServiceInstanceName: bookshop-identity + applicationType: application + appName: bookshop + commercialAppName: bookshop + displayName: (bookshop) + description: (A simple CAP project.) + category: CAP + appCallbacks: + dependenciesCallbacks: + url: "" + subscriptionCallbacks: + url: "" + async: + subscribeEnable: true + unSubscribeEnable: true + timeoutInMillis: 300000 + serviceManager: + name: bookshop-service-manager + serviceOfferingName: service-manager + servicePlanName: container + parameters: {} +serviceBindings: + destination: + name: bookshop-destination-bind + serviceInstanceName: bookshop-destination + secretName: bookshop-destination-bind-secret + secretKey: credentials + parameters: {} + html5RepoRuntime: + name: bookshop-html5-repo-runtime-bind + serviceInstanceName: bookshop-html5-repo-runtime + secretName: bookshop-html5-repo-runtime-bind-secret + secretKey: credentials + parameters: {} + html5RepoHost: + name: bookshop-html5-repo-host-bind + serviceInstanceName: bookshop-html5-repo-host + secretName: bookshop-html5-repo-host-bind-secret + secretKey: credentials + parameters: {} + identity: + name: bookshop-identity-bind + serviceInstanceName: bookshop-identity + secretName: bookshop-identity-bind-secret + secretKey: credentials + parameters: + credential-type: X509_GENERATED + app-identifier: bookshop + subscriptionManager: + name: bookshop-subscription-manager-bind + serviceInstanceName: bookshop-subscription-manager + secretName: bookshop-subscription-manager-bind-secret + secretKey: credentials + parameters: {} + serviceManager: + name: bookshop-service-manager-bind + serviceInstanceName: bookshop-service-manager + secretName: bookshop-service-manager-bind-secret + secretKey: credentials + parameters: {} +app: + domains: + primary: null + additionalDomainRefs: [] + istioIngressGatewayLabels: + istio: ingressgateway + app: istio-ingressgateway +btp: + globalAccountId: null + provider: + subdomain: null + tenantId: null +imagePullSecrets: [] +workloads: + appRouter: + name: app-router + labels: + sme.sap.com/app-type: bookshop + consumedBTPServices: + - bookshop-identity-bind + - bookshop-subscription-manager-bind + - bookshop-destination-bind + - bookshop-html5-repo-runtime-bind + deploymentDefinition: + type: Router + image: null + ports: + - name: router-port + port: 5000 + server: + name: server + labels: + sme.sap.com/app-type: bookshop + consumedBTPServices: + - bookshop-identity-bind + - bookshop-subscription-manager-bind + - bookshop-service-manager-bind + deploymentDefinition: + type: CAP + image: null + env: + - name: AMS_DCL_ROOT + value: ams/dcl + securityContext: + runAsUser: 1000 + runAsGroup: 1000 + contentDeploy: + name: content-deploy + labels: + sme.sap.com/app-type: bookshop + consumedBTPServices: + - bookshop-identity-bind + - bookshop-html5-repo-host-bind + jobDefinition: + type: Content + image: null + tenantJob: + name: tenant-job + labels: + sme.sap.com/app-type: bookshop + consumedBTPServices: + - bookshop-identity-bind + - bookshop-subscription-manager-bind + - bookshop-service-manager-bind + jobDefinition: + type: TenantOperation + image: null + amsDeployer: + name: ams-deployer + labels: + sme.sap.com/app-type: bookshop + consumedBTPServices: + - bookshop-identity-bind + jobDefinition: + type: Content + image: null +contentJobs: + - content-deploy + - ams-deployer diff --git a/test/files/expectedChart/values-svc-ias.yaml b/test/files/expectedChart/values-svc-ias.yaml new file mode 100644 index 0000000..4294176 --- /dev/null +++ b/test/files/expectedChart/values-svc-ias.yaml @@ -0,0 +1,115 @@ +serviceInstances: + destination: + name: bookshop-destination + serviceOfferingName: destination + servicePlanName: lite + parameters: + HTML5Runtime_enabled: true + html5RepoRuntime: + name: bookshop-html5-repo-runtime + serviceOfferingName: html5-apps-repo + servicePlanName: app-runtime + parameters: {} + html5RepoHost: + name: bookshop-html5-repo-host + serviceOfferingName: html5-apps-repo + servicePlanName: app-host + parameters: {} + identity: + name: bookshop-identity + serviceOfferingName: identity + servicePlanName: application + parameters: + display-name: bookshop + multi-tenant: true + xsuaa-cross-consumption: true + authorization: + enabled: true + oauth2-configuration: + redirect-uris: [] + post-logout-redirect-uris: [] + home-url: "" +serviceBindings: + destination: + name: bookshop-destination-bind + serviceInstanceName: bookshop-destination + secretName: bookshop-destination-bind-secret + secretKey: credentials + parameters: {} + html5RepoRuntime: + name: bookshop-html5-repo-runtime-bind + serviceInstanceName: bookshop-html5-repo-runtime + secretName: bookshop-html5-repo-runtime-bind-secret + secretKey: credentials + parameters: {} + html5RepoHost: + name: bookshop-html5-repo-host-bind + serviceInstanceName: bookshop-html5-repo-host + secretName: bookshop-html5-repo-host-bind-secret + secretKey: credentials + parameters: {} + identity: + name: bookshop-identity-bind + serviceInstanceName: bookshop-identity + secretName: bookshop-identity-bind-secret + secretKey: credentials + parameters: + credential-type: X509_GENERATED + app-identifier: bookshop +app: + domains: + primary: null + additionalDomainRefs: [] + istioIngressGatewayLabels: + istio: ingressgateway + app: istio-ingressgateway +btp: + globalAccountId: null +imagePullSecrets: [] +workloads: + server: + name: server + labels: + sme.sap.com/app-type: bookshop + consumedBTPServices: + - bookshop-identity-bind + deploymentDefinition: + type: Service + ports: + - name: server-port + port: 4004 + appProtocol: http + image: null + env: + - name: AMS_DCL_ROOT + value: ams/dcl + securityContext: + runAsUser: 1000 + runAsGroup: 1000 + contentDeploy: + name: content-deploy + labels: + sme.sap.com/app-type: bookshop + consumedBTPServices: + - bookshop-identity-bind + - bookshop-html5-repo-host-bind + jobDefinition: + type: Content + image: null + amsDeployer: + name: ams-deployer + labels: + sme.sap.com/app-type: bookshop + consumedBTPServices: + - bookshop-identity-bind + jobDefinition: + type: Content + image: null +serviceExposures: + - subDomain: bookshop + routes: + - workloadName: server + port: 4004 +contentJobs: + - content-deploy + - ams-deployer diff --git a/test/files/expectedChart/values-svc.yaml b/test/files/expectedChart/values-svc.yaml index b588597..9e0a926 100644 --- a/test/files/expectedChart/values-svc.yaml +++ b/test/files/expectedChart/values-svc.yaml @@ -26,26 +26,6 @@ serviceInstances: credential-types: - binding-secret redirect-uris: [] - saasRegistry: - name: bookshop-saas-registry - serviceOfferingName: saas-registry - servicePlanName: application - parameters: - plan: general - xsappname: bookshop - appName: bookshop - displayName: (bookshop) - description: (A simple CAP project.) - appUrls: - callbackTimeoutMillis: 300000 - onSubscriptionAsync: true - onUnSubscriptionAsync: true - category: CAP - serviceManager: - name: bookshop-service-manager - serviceOfferingName: service-manager - servicePlanName: container - parameters: {} serviceBindings: destination: name: bookshop-destination-bind @@ -71,18 +51,6 @@ serviceBindings: secretName: bookshop-uaa-bind-secret secretKey: credentials parameters: {} - saasRegistry: - name: bookshop-saas-registry-bind - serviceInstanceName: bookshop-saas-registry - secretName: bookshop-saas-registry-bind-secret - secretKey: credentials - parameters: {} - serviceManager: - name: bookshop-service-manager-bind - serviceInstanceName: bookshop-service-manager - secretName: bookshop-service-manager-bind-secret - secretKey: credentials - parameters: {} app: domains: primary: null @@ -100,10 +68,8 @@ workloads: sme.sap.com/app-type: bookshop consumedBTPServices: - bookshop-uaa-bind - - bookshop-saas-registry-bind - - bookshop-service-manager-bind deploymentDefinition: - type: service + type: Service ports: - name: server-port port: 4004 @@ -115,7 +81,6 @@ workloads: sme.sap.com/app-type: bookshop consumedBTPServices: - bookshop-uaa-bind - - bookshop-saas-registry-bind - bookshop-html5-repo-host-bind jobDefinition: type: Content diff --git a/test/files/expectedChart/values.yaml b/test/files/expectedChart/values.yaml index defe01f..614b165 100644 --- a/test/files/expectedChart/values.yaml +++ b/test/files/expectedChart/values.yaml @@ -37,6 +37,8 @@ serviceInstances: displayName: (bookshop) description: (A simple CAP project.) appUrls: + getDependencies: "" + onSubscription: "" callbackTimeoutMillis: 300000 onSubscriptionAsync: true onUnSubscriptionAsync: true @@ -103,9 +105,9 @@ workloads: sme.sap.com/app-type: bookshop consumedBTPServices: - bookshop-uaa-bind + - bookshop-saas-registry-bind - bookshop-destination-bind - bookshop-html5-repo-runtime-bind - - bookshop-saas-registry-bind deploymentDefinition: type: Router image: null @@ -129,7 +131,6 @@ workloads: sme.sap.com/app-type: bookshop consumedBTPServices: - bookshop-uaa-bind - - bookshop-saas-registry-bind - bookshop-html5-repo-host-bind jobDefinition: type: Content diff --git a/test/files/expectedChart/valuesWithDestination.yaml b/test/files/expectedChart/valuesWithDestination.yaml index defe01f..614b165 100644 --- a/test/files/expectedChart/valuesWithDestination.yaml +++ b/test/files/expectedChart/valuesWithDestination.yaml @@ -37,6 +37,8 @@ serviceInstances: displayName: (bookshop) description: (A simple CAP project.) appUrls: + getDependencies: "" + onSubscription: "" callbackTimeoutMillis: 300000 onSubscriptionAsync: true onUnSubscriptionAsync: true @@ -103,9 +105,9 @@ workloads: sme.sap.com/app-type: bookshop consumedBTPServices: - bookshop-uaa-bind + - bookshop-saas-registry-bind - bookshop-destination-bind - bookshop-html5-repo-runtime-bind - - bookshop-saas-registry-bind deploymentDefinition: type: Router image: null @@ -129,7 +131,6 @@ workloads: sme.sap.com/app-type: bookshop consumedBTPServices: - bookshop-uaa-bind - - bookshop-saas-registry-bind - bookshop-html5-repo-host-bind jobDefinition: type: Content diff --git a/test/files/expectedConfigurableTemplatesChart/runtime-values-ias.yaml b/test/files/expectedConfigurableTemplatesChart/runtime-values-ias.yaml new file mode 100644 index 0000000..5404471 --- /dev/null +++ b/test/files/expectedConfigurableTemplatesChart/runtime-values-ias.yaml @@ -0,0 +1,36 @@ +serviceInstances: + subscriptionManager: + parameters: + appName: bkshop + commercialAppName: bkshop + displayName: (bkshop) + description: (A simple CAP project.) + category: CAP + appCallbacks: + dependenciesCallbacks: + url: https://bem-aad-sadad-123456789012.bkshop.c-abc.kyma.ondemand.com/v1.0/callback/tenants/{app_tid}/dependencies + subscriptionCallbacks: + url: https://cap-op.c-abc.kyma.ondemand.com/sms/provision/tenants/{app_tid} + identity: + parameters: + display-name: bkshop + home-url: https://$BTP_SUBDOMAIN.bkshop.c-abc.kyma.ondemand.com +serviceBindings: + identity: + parameters: + app-identifier: bkshop +app: + domains: + primary: bkshop.c-abc.kyma.ondemand.com + additionalDomainRefs: [] + istioIngressGatewayLabels: + istio: ingressgateway + app: istio-ingressgateway +btp: + globalAccountId: dc94db56-asda-adssa-dada-123456789012 + provider: + subdomain: bem-aad-sadad-123456789012 + tenantId: dasdsd-1234-1234-1234-123456789012 +imagePullSecrets: + - regcred +hanaInstanceId: sdasd-4c4d-4d4d-4d4d-123456789012 diff --git a/test/files/expectedConfigurableTemplatesChart/runtime-values-svc.yaml b/test/files/expectedConfigurableTemplatesChart/runtime-values-svc.yaml index a71538a..123db5e 100644 --- a/test/files/expectedConfigurableTemplatesChart/runtime-values-svc.yaml +++ b/test/files/expectedConfigurableTemplatesChart/runtime-values-svc.yaml @@ -1,19 +1,7 @@ serviceInstances: - saasRegistry: - parameters: - xsappname: bkshop - appName: bkshop - displayName: bkshop - description: A simple CAP project. - appUrls: - getDependencies: https://bem-aad-sadad-123456789012.bkshop.c-abc.kyma.ondemand.com/callback/v1.0/dependencies - onSubscription: https://cap-op.c-abc.kyma.ondemand.com/provision/tenants/{tenantId} xsuaa: parameters: xsappname: bkshop - oauth2-configuration: - redirect-uris: - - https://*bkshop.c-abc.kyma.ondemand.com/** app: domains: primary: bkshop.c-abc.kyma.ondemand.com diff --git a/files/configurableTemplatesChart/templates/_helpers.tpl b/test/files/expectedConfigurableTemplatesChart/templates/_helpers-ias.tpl similarity index 62% rename from files/configurableTemplatesChart/templates/_helpers.tpl rename to test/files/expectedConfigurableTemplatesChart/templates/_helpers-ias.tpl index e641020..9d60db4 100644 --- a/files/configurableTemplatesChart/templates/_helpers.tpl +++ b/test/files/expectedConfigurableTemplatesChart/templates/_helpers-ias.tpl @@ -2,30 +2,17 @@ {{ printf "%s-%d" (include "appName" $) (.Release.Revision) }} {{- end -}} -{{- define "appName" -}} -{{- range $sik, $siv := .Values.serviceInstances}} - {{- if and (eq (get $siv "serviceOfferingName") "xsuaa") (eq (get $siv "servicePlanName") "broker") -}} - {{ printf "%s" $siv.parameters.xsappname }} - {{- break -}} - {{- end -}} -{{- end -}} -{{- end -}} - {{- define "domainName" -}} {{ printf "%s-primary" (include "appName" $)}} {{- end -}} -{{- define "hasService" -}} -{{- $found := "false" -}} -{{- $offeringName := .offeringName -}} -{{- $planName := .planName -}} -{{- $si := .si -}} -{{- range $sik, $siv := $si}} - {{- if and (eq (get $siv "serviceOfferingName") $offeringName) (eq (get $siv "servicePlanName") $planName) -}} - {{- $found = "true" -}} - {{- end -}} +{{- define "appName" -}} +{{- range $sik, $siv := .Values.serviceInstances }} + {{- if and (eq (get $siv "serviceOfferingName") "subscription-manager") (eq (get $siv "servicePlanName") "provider") -}} + {{ printf "%s" $siv.parameters.appName }} + {{- break -}} + {{- end -}} {{- end -}} -{{- $found -}} {{- end -}} {{- define "domainHostMap" -}} @@ -42,15 +29,25 @@ {{- end }} {{- define "redirectUris" -}} - {{- $domains := (include "domainHostMap" . | fromJson).domains -}} + {{- $ctx := .context -}} + {{- $svc := .serviceOfferingName -}} + {{- $domains := (include "domainHostMap" $ctx | fromJson).domains -}} {{- $redirectUris := list -}} {{- range $domains }} {{- $redirectUris = append $redirectUris (printf "https://*.%s/**" .) -}} {{- end -}} - {{- toJson (dict "redirect-uris" $redirectUris) -}} + {{- if eq $svc "identity" }} + {{- toJson (dict "redirect-uris" $redirectUris "post-logout-redirect-uris" $redirectUris) -}} + {{- else }} + {{- toJson (dict "redirect-uris" $redirectUris) -}} + {{- end -}} {{- end }} {{- define "tenantHostPattern" -}} {{- $domains := (include "domainHostMap" . | fromJson).domains -}} {{- printf "^(.*)\\.(%s)" (join "|" $domains | replace "." "\\.") -}} {{- end }} + +{{- define "originalAppName" -}} +{{ print "bookshop" }} +{{- end -}} diff --git a/test/files/expectedConfigurableTemplatesChart/templates/_helpers.tpl b/test/files/expectedConfigurableTemplatesChart/templates/_helpers.tpl index 0091f9c..51d898b 100644 --- a/test/files/expectedConfigurableTemplatesChart/templates/_helpers.tpl +++ b/test/files/expectedConfigurableTemplatesChart/templates/_helpers.tpl @@ -2,30 +2,17 @@ {{ printf "%s-%d" (include "appName" $) (.Release.Revision) }} {{- end -}} -{{- define "appName" -}} -{{- range $sik, $siv := .Values.serviceInstances}} - {{- if and (eq (get $siv "serviceOfferingName") "xsuaa") (eq (get $siv "servicePlanName") "broker") -}} - {{ printf "%s" $siv.parameters.xsappname }} - {{- break -}} - {{- end -}} -{{- end -}} -{{- end -}} - {{- define "domainName" -}} {{ printf "%s-primary" (include "appName" $)}} {{- end -}} -{{- define "hasService" -}} -{{- $found := "false" -}} -{{- $offeringName := .offeringName -}} -{{- $planName := .planName -}} -{{- $si := .si -}} -{{- range $sik, $siv := $si}} - {{- if and (eq (get $siv "serviceOfferingName") $offeringName) (eq (get $siv "servicePlanName") $planName) -}} - {{- $found = "true" -}} - {{- end -}} +{{- define "appName" -}} +{{- range $sik, $siv := .Values.serviceInstances }} + {{- if and (eq (get $siv "serviceOfferingName") "xsuaa") (eq (get $siv "servicePlanName") "broker") -}} + {{ printf "%s" $siv.parameters.xsappname }} + {{- break -}} + {{- end -}} {{- end -}} -{{- $found -}} {{- end -}} {{- define "domainHostMap" -}} @@ -42,12 +29,18 @@ {{- end }} {{- define "redirectUris" -}} - {{- $domains := (include "domainHostMap" . | fromJson).domains -}} + {{- $ctx := .context -}} + {{- $svc := .serviceOfferingName -}} + {{- $domains := (include "domainHostMap" $ctx | fromJson).domains -}} {{- $redirectUris := list -}} {{- range $domains }} {{- $redirectUris = append $redirectUris (printf "https://*.%s/**" .) -}} {{- end -}} - {{- toJson (dict "redirect-uris" $redirectUris) -}} + {{- if eq $svc "identity" }} + {{- toJson (dict "redirect-uris" $redirectUris "post-logout-redirect-uris" $redirectUris) -}} + {{- else }} + {{- toJson (dict "redirect-uris" $redirectUris) -}} + {{- end -}} {{- end }} {{- define "tenantHostPattern" -}} diff --git a/test/files/expectedConfigurableTemplatesChart/templates/cap-operator-cros-ias.yaml b/test/files/expectedConfigurableTemplatesChart/templates/cap-operator-cros-ias.yaml new file mode 100644 index 0000000..fab18c6 --- /dev/null +++ b/test/files/expectedConfigurableTemplatesChart/templates/cap-operator-cros-ias.yaml @@ -0,0 +1,131 @@ +--- +apiVersion: sme.sap.com/v1alpha1 +kind: CAPApplication +metadata: + name: {{ include "appName" $ }} + annotations: + sme.sap.com/vs-route-request-header-set: | + { + "x-forwarded-client-cert": "%DOWNSTREAM_PEER_CERT%" + } +spec: + domainRefs: + - kind: Domain + name: {{ include "domainName" $ }} + {{- range .Values.app.domains.additionalDomainRefs }} + - kind: {{ .kind }} + name: {{ .name }} + {{- end }} + btpAppName: {{ include "appName" $ }} + globalAccountId: {{ .Values.btp.globalAccountId }} + provider: + subDomain: {{ .Values.btp.provider.subdomain }} + tenantId: {{ .Values.btp.provider.tenantId }} + btp: + services: + {{- $serviceInstances := .Values.serviceInstances }} + {{- range $k, $v := .Values.serviceBindings }} + {{- $serviceInstance := dict }} + {{- range $sik, $siv := $serviceInstances }} + {{- if eq $siv.name $v.serviceInstanceName }} + {{- $serviceInstance = $siv }} + {{- end }} + {{- end }} + {{- if hasKey $serviceInstance "serviceOfferingName" }} + - class: {{ get $serviceInstance "serviceOfferingName" | default "invalidValue" }} + {{- if $v.externalName }} + name: {{ $v.externalName | default "invalidValue" }} + {{- else }} + name: {{ $v.name | default "invalidValue" }} + {{- end }} + secret: {{ $v.secretName | default "invalidValue" }} + {{- end }} + {{- end }} +--- +apiVersion: sme.sap.com/v1alpha1 +kind: CAPApplicationVersion +metadata: + annotations: + helm.sh/hook: post-install,post-upgrade + helm.sh/resource-policy: keep + name: {{ include "capApplicationVersionName" $ }} +spec: + capApplicationInstance: {{ include "appName" $ }} + version: "{{ .Release.Revision }}" + registrySecrets: + {{- range .Values.imagePullSecrets }} + - {{ . }} + {{- end }} + workloads: + - name: server + labels: + sme.sap.com/app-type: {{ include "appName" $ }} + consumedBTPServices: + - {{ include "originalAppName" $ }}-identity-bind + - {{ include "originalAppName" $ }}-subscription-manager-bind + - {{ include "originalAppName" $ }}-service-manager-bind + deploymentDefinition: + type: CAP + image: {{ .Values.workloads.server.image }} + env: + - name: AMS_DCL_ROOT + value: ams/dcl + {{- if .Values.hanaInstanceId }} + - name: CDS_CONFIG + value: '{"requires":{"cds.xt.DeploymentService":{"hdi":{"create":{"database_id":"{{ .Values.hanaInstanceId }}"}}}}}' + {{- end }} + securityContext: + runAsUser: 1000 + runAsGroup: 1000 + - name: app-router + labels: + sme.sap.com/app-type: {{ include "appName" $ }} + consumedBTPServices: + - {{ include "originalAppName" $ }}-identity-bind + - {{ include "originalAppName" $ }}-subscription-manager-bind + - {{ include "originalAppName" $ }}-destination-bind + - {{ include "originalAppName" $ }}-html5-repo-runtime-bind + deploymentDefinition: + type: Router + image: {{ .Values.workloads.appRouter.image }} + env: + - name: TENANT_HOST_PATTERN + value: {{ include "tenantHostPattern" . }} + ports: + - name: router-port + port: 5000 + - name: tenant-job + labels: + sme.sap.com/app-type: {{ include "appName" $ }} + consumedBTPServices: + - {{ include "originalAppName" $ }}-identity-bind + - {{ include "originalAppName" $ }}-subscription-manager-bind + - {{ include "originalAppName" $ }}-service-manager-bind + jobDefinition: + type: TenantOperation + image: {{ .Values.workloads.tenantJob.image }} + {{- if .Values.hanaInstanceId }} + env: + - name: CDS_CONFIG + value: '{"requires":{"cds.xt.DeploymentService":{"hdi":{"create":{"database_id":"{{ .Values.hanaInstanceId }}"}}}}}' + {{- end }} + - name: content-deploy + labels: + sme.sap.com/app-type: {{ include "appName" $ }} + consumedBTPServices: + - {{ include "originalAppName" $ }}-identity-bind + - {{ include "originalAppName" $ }}-html5-repo-host-bind + jobDefinition: + type: Content + image: {{ .Values.workloads.contentDeploy.image }} + - name: ams-deployer + labels: + sme.sap.com/app-type: {{ include "appName" $ }} + consumedBTPServices: + - {{ include "originalAppName" $ }}-identity-bind + jobDefinition: + type: Content + image: {{ .Values.workloads.amsDeployer.image }} + contentJobs: + - content-deploy + - ams-deployer diff --git a/test/files/expectedConfigurableTemplatesChart/templates/cap-operator-cros-modified-svc.yaml b/test/files/expectedConfigurableTemplatesChart/templates/cap-operator-cros-modified-svc.yaml index 00fa54c..38832bf 100644 --- a/test/files/expectedConfigurableTemplatesChart/templates/cap-operator-cros-modified-svc.yaml +++ b/test/files/expectedConfigurableTemplatesChart/templates/cap-operator-cros-modified-svc.yaml @@ -12,7 +12,7 @@ spec: name: {{ .name }} {{- end }} btpAppName: {{ include "appName" $ }} - globalAccountId: {{.Values.btp.globalAccountId}} + globalAccountId: {{ .Values.btp.globalAccountId }} btp: services: {{- $serviceInstances := .Values.serviceInstances }} @@ -45,19 +45,17 @@ spec: capApplicationInstance: {{ include "appName" $ }} version: "{{ .Release.Revision }}" registrySecrets: - {{- range .Values.imagePullSecrets }} - - {{.}} - {{- end }} + {{- range .Values.imagePullSecrets }} + - {{ . }} + {{- end }} workloads: - name: server labels: sme.sap.com/app-type: bookshop consumedBTPServices: - bookshop-uaa-bind - - bookshop-saas-registry-bind - - bookshop-service-manager-bind deploymentDefinition: - type: service + type: Service image: "{{.Values.workloads.server.image}}" env: - name: CDS_CONFIG @@ -71,7 +69,6 @@ spec: sme.sap.com/app-type: bookshop consumedBTPServices: - bookshop-uaa-bind - - bookshop-saas-registry-bind - bookshop-html5-repo-host-bind jobDefinition: type: Content diff --git a/test/files/expectedConfigurableTemplatesChart/templates/cap-operator-cros-modified.yaml b/test/files/expectedConfigurableTemplatesChart/templates/cap-operator-cros-modified.yaml index 40d3ba3..310b5e2 100644 --- a/test/files/expectedConfigurableTemplatesChart/templates/cap-operator-cros-modified.yaml +++ b/test/files/expectedConfigurableTemplatesChart/templates/cap-operator-cros-modified.yaml @@ -12,10 +12,10 @@ spec: name: {{ .name }} {{- end }} btpAppName: {{ include "appName" $ }} - globalAccountId: {{.Values.btp.globalAccountId}} + globalAccountId: {{ .Values.btp.globalAccountId }} provider: - subDomain: {{.Values.btp.provider.subdomain}} - tenantId: {{.Values.btp.provider.tenantId}} + subDomain: {{ .Values.btp.provider.subdomain }} + tenantId: {{ .Values.btp.provider.tenantId }} btp: services: {{- $serviceInstances := .Values.serviceInstances }} @@ -48,9 +48,9 @@ spec: capApplicationInstance: {{ include "appName" $ }} version: "{{ .Release.Revision }}" registrySecrets: - {{- range .Values.imagePullSecrets }} - - {{.}} - {{- end }} + {{- range .Values.imagePullSecrets }} + - {{ . }} + {{- end }} workloads: - name: app-router labels: @@ -87,7 +87,6 @@ spec: sme.sap.com/app-type: bookshop consumedBTPServices: - bookshop-uaa-bind - - bookshop-saas-registry-bind - bookshop-html5-repo-host-bind jobDefinition: type: Content diff --git a/test/files/expectedConfigurableTemplatesChart/templates/cap-operator-cros-mta.yaml b/test/files/expectedConfigurableTemplatesChart/templates/cap-operator-cros-mta.yaml index 5c75ff5..af430bc 100644 --- a/test/files/expectedConfigurableTemplatesChart/templates/cap-operator-cros-mta.yaml +++ b/test/files/expectedConfigurableTemplatesChart/templates/cap-operator-cros-mta.yaml @@ -12,10 +12,10 @@ spec: name: {{ .name }} {{- end }} btpAppName: {{ include "appName" $ }} - globalAccountId: {{.Values.btp.globalAccountId}} + globalAccountId: {{ .Values.btp.globalAccountId }} provider: - subDomain: {{.Values.btp.provider.subdomain}} - tenantId: {{.Values.btp.provider.tenantId}} + subDomain: {{ .Values.btp.provider.subdomain }} + tenantId: {{ .Values.btp.provider.tenantId }} btp: services: {{- $serviceInstances := .Values.serviceInstances }} @@ -48,9 +48,9 @@ spec: capApplicationInstance: {{ include "appName" $ }} version: "{{ .Release.Revision }}" registrySecrets: - {{- range .Values.imagePullSecrets }} - - {{.}} - {{- end }} + {{- range .Values.imagePullSecrets }} + - {{ . }} + {{- end }} workloads: - name: author-readings-approuter consumedBTPServices: diff --git a/test/files/expectedConfigurableTemplatesChart/templates/cap-operator-cros-svc-ias.yaml b/test/files/expectedConfigurableTemplatesChart/templates/cap-operator-cros-svc-ias.yaml new file mode 100644 index 0000000..51f77d1 --- /dev/null +++ b/test/files/expectedConfigurableTemplatesChart/templates/cap-operator-cros-svc-ias.yaml @@ -0,0 +1,103 @@ +--- +apiVersion: sme.sap.com/v1alpha1 +kind: CAPApplication +metadata: + name: {{ include "appName" $ }} + annotations: + sme.sap.com/vs-route-request-header-set: | + { + "x-forwarded-client-cert": "%DOWNSTREAM_PEER_CERT%" + } +spec: + domainRefs: + - kind: Domain + name: {{ include "domainName" $ }} + {{- range .Values.app.domains.additionalDomainRefs }} + - kind: {{ .kind }} + name: {{ .name }} + {{- end }} + btpAppName: {{ include "appName" $ }} + globalAccountId: {{ .Values.btp.globalAccountId }} + btp: + services: + {{- $serviceInstances := .Values.serviceInstances }} + {{- range $k, $v := .Values.serviceBindings }} + {{- $serviceInstance := dict }} + {{- range $sik, $siv := $serviceInstances }} + {{- if eq $siv.name $v.serviceInstanceName }} + {{- $serviceInstance = $siv }} + {{- end }} + {{- end }} + {{- if hasKey $serviceInstance "serviceOfferingName" }} + - class: {{ get $serviceInstance "serviceOfferingName" | default "invalidValue" }} + {{- if $v.externalName }} + name: {{ $v.externalName | default "invalidValue" }} + {{- else }} + name: {{ $v.name | default "invalidValue" }} + {{- end }} + secret: {{ $v.secretName | default "invalidValue" }} + {{- end }} + {{- end }} +--- +apiVersion: sme.sap.com/v1alpha1 +kind: CAPApplicationVersion +metadata: + annotations: + helm.sh/hook: post-install,post-upgrade + helm.sh/resource-policy: keep + name: {{ include "capApplicationVersionName" $ }} +spec: + capApplicationInstance: {{ include "appName" $ }} + version: "{{ .Release.Revision }}" + registrySecrets: + {{- range .Values.imagePullSecrets }} + - {{ . }} + {{- end }} + workloads: + - name: server + labels: + sme.sap.com/app-type: {{ include "appName" $ }} + consumedBTPServices: + - {{ include "originalAppName" $ }}-identity-bind + deploymentDefinition: + type: Service + ports: + - name: server-port + port: 4004 + appProtocol: http + image: {{ .Values.workloads.server.image }} + env: + - name: AMS_DCL_ROOT + value: ams/dcl + {{- if .Values.hanaInstanceId }} + - name: CDS_CONFIG + value: '{"requires":{"cds.xt.DeploymentService":{"hdi":{"create":{"database_id":"{{ .Values.hanaInstanceId }}"}}}}}' + {{- end }} + securityContext: + runAsUser: 1000 + runAsGroup: 1000 + - name: content-deploy + labels: + sme.sap.com/app-type: {{ include "appName" $ }} + consumedBTPServices: + - {{ include "originalAppName" $ }}-identity-bind + - {{ include "originalAppName" $ }}-html5-repo-host-bind + jobDefinition: + type: Content + image: {{ .Values.workloads.contentDeploy.image }} + - name: ams-deployer + labels: + sme.sap.com/app-type: {{ include "appName" $ }} + consumedBTPServices: + - {{ include "originalAppName" $ }}-identity-bind + jobDefinition: + type: Content + image: {{ .Values.workloads.amsDeployer.image }} + serviceExposures: + - subDomain: {{ include "appName" $ }} + routes: + - workloadName: server + port: 4004 + contentJobs: + - content-deploy + - ams-deployer diff --git a/files/configurableTemplatesChart/templates/cap-operator-cros-svc.yaml b/test/files/expectedConfigurableTemplatesChart/templates/cap-operator-cros-svc.yaml similarity index 72% rename from files/configurableTemplatesChart/templates/cap-operator-cros-svc.yaml rename to test/files/expectedConfigurableTemplatesChart/templates/cap-operator-cros-svc.yaml index 1deb9b0..e53bb93 100644 --- a/files/configurableTemplatesChart/templates/cap-operator-cros-svc.yaml +++ b/test/files/expectedConfigurableTemplatesChart/templates/cap-operator-cros-svc.yaml @@ -12,7 +12,7 @@ spec: name: {{ .name }} {{- end }} btpAppName: {{ include "appName" $ }} - globalAccountId: {{.Values.btp.globalAccountId}} + globalAccountId: {{ .Values.btp.globalAccountId }} btp: services: {{- $serviceInstances := .Values.serviceInstances }} @@ -45,46 +45,38 @@ spec: capApplicationInstance: {{ include "appName" $ }} version: "{{ .Release.Revision }}" registrySecrets: - {{- range .Values.imagePullSecrets }} - - {{.}} - {{- end }} + {{- range .Values.imagePullSecrets }} + - {{ . }} + {{- end }} workloads: - name: server labels: sme.sap.com/app-type: {{ include "appName" $ }} consumedBTPServices: - {{ include "originalAppName" $ }}-uaa-bind - - {{ include "originalAppName" $ }}-saas-registry-bind - - {{ include "originalAppName" $ }}-service-manager-bind deploymentDefinition: - type: service + type: Service + ports: + - name: server-port + port: 4004 + appProtocol: http image: {{ .Values.workloads.server.image }} {{- if .Values.hanaInstanceId }} env: - name: CDS_CONFIG - value: '{"requires":{"cds.xt.DeploymentService":{"hdi": { "create": {"database_id": "{{.Values.hanaInstanceId}}"}}}}}' + value: '{"requires":{"cds.xt.DeploymentService":{"hdi":{"create":{"database_id":"{{ .Values.hanaInstanceId }}"}}}}}' {{- end }} - ports: - - name: server-port - port: 4004 - appProtocol: http - name: content-deploy labels: sme.sap.com/app-type: {{ include "appName" $ }} consumedBTPServices: - {{ include "originalAppName" $ }}-uaa-bind - - {{ include "originalAppName" $ }}-saas-registry-bind - {{- if eq (include "hasService" (dict "si" .Values.serviceInstances "offeringName" "html5-apps-repo" "planName" "app-host")) "true" }} - {{ include "originalAppName" $ }}-html5-repo-host-bind - {{- end }} - {{- if eq (include "hasService" (dict "si" .Values.serviceInstances "offeringName" "content-agent" "planName" "application")) "true" }} - - {{ include "originalAppName" $ }}-content-agent-bind - {{- end }} jobDefinition: type: Content image: {{ .Values.workloads.contentDeploy.image }} serviceExposures: - - subDomain: {{ include "originalAppName" $ }} + - subDomain: {{ include "appName" $ }} routes: - workloadName: server port: 4004 diff --git a/files/configurableTemplatesChart/templates/cap-operator-cros.yaml b/test/files/expectedConfigurableTemplatesChart/templates/cap-operator-cros.yaml similarity index 73% rename from files/configurableTemplatesChart/templates/cap-operator-cros.yaml rename to test/files/expectedConfigurableTemplatesChart/templates/cap-operator-cros.yaml index 4d1d97f..20c988b 100644 --- a/files/configurableTemplatesChart/templates/cap-operator-cros.yaml +++ b/test/files/expectedConfigurableTemplatesChart/templates/cap-operator-cros.yaml @@ -12,10 +12,10 @@ spec: name: {{ .name }} {{- end }} btpAppName: {{ include "appName" $ }} - globalAccountId: {{.Values.btp.globalAccountId}} + globalAccountId: {{ .Values.btp.globalAccountId }} provider: - subDomain: {{.Values.btp.provider.subdomain}} - tenantId: {{.Values.btp.provider.tenantId}} + subDomain: {{ .Values.btp.provider.subdomain }} + tenantId: {{ .Values.btp.provider.tenantId }} btp: services: {{- $serviceInstances := .Values.serviceInstances }} @@ -48,9 +48,9 @@ spec: capApplicationInstance: {{ include "appName" $ }} version: "{{ .Release.Revision }}" registrySecrets: - {{- range .Values.imagePullSecrets }} - - {{.}} - {{- end }} + {{- range .Values.imagePullSecrets }} + - {{ . }} + {{- end }} workloads: - name: server labels: @@ -65,7 +65,7 @@ spec: {{- if .Values.hanaInstanceId }} env: - name: CDS_CONFIG - value: '{"requires":{"cds.xt.DeploymentService":{"hdi": { "create": {"database_id": "{{.Values.hanaInstanceId}}"}}}}}' + value: '{"requires":{"cds.xt.DeploymentService":{"hdi":{"create":{"database_id":"{{ .Values.hanaInstanceId }}"}}}}}' {{- end }} - name: app-router labels: @@ -73,12 +73,8 @@ spec: consumedBTPServices: - {{ include "originalAppName" $ }}-uaa-bind - {{ include "originalAppName" $ }}-saas-registry-bind - {{- if eq (include "hasService" (dict "si" .Values.serviceInstances "offeringName" "destination" "planName" "lite")) "true" }} - {{ include "originalAppName" $ }}-destination-bind - {{- end}} - {{- if eq (include "hasService" (dict "si" .Values.serviceInstances "offeringName" "html5-apps-repo" "planName" "app-runtime")) "true" }} - {{ include "originalAppName" $ }}-html5-repo-runtime-bind - {{- end }} deploymentDefinition: type: Router image: {{ .Values.workloads.appRouter.image }} @@ -101,20 +97,14 @@ spec: {{- if .Values.hanaInstanceId }} env: - name: CDS_CONFIG - value: '{"requires":{"cds.xt.DeploymentService":{"hdi": { "create": {"database_id": "{{.Values.hanaInstanceId}}"}}}}}' + value: '{"requires":{"cds.xt.DeploymentService":{"hdi":{"create":{"database_id":"{{ .Values.hanaInstanceId }}"}}}}}' {{- end }} - name: content-deploy labels: sme.sap.com/app-type: {{ include "appName" $ }} consumedBTPServices: - {{ include "originalAppName" $ }}-uaa-bind - - {{ include "originalAppName" $ }}-saas-registry-bind - {{- if eq (include "hasService" (dict "si" .Values.serviceInstances "offeringName" "html5-apps-repo" "planName" "app-host")) "true" }} - {{ include "originalAppName" $ }}-html5-repo-host-bind - {{- end }} - {{- if eq (include "hasService" (dict "si" .Values.serviceInstances "offeringName" "content-agent" "planName" "application")) "true" }} - - {{ include "originalAppName" $ }}-content-agent-bind - {{- end }} jobDefinition: type: Content image: {{ .Values.workloads.contentDeploy.image }} diff --git a/test/files/expectedConfigurableTemplatesChart/values-ias.yaml b/test/files/expectedConfigurableTemplatesChart/values-ias.yaml new file mode 100644 index 0000000..c58ca43 --- /dev/null +++ b/test/files/expectedConfigurableTemplatesChart/values-ias.yaml @@ -0,0 +1,121 @@ +serviceInstances: + destination: + name: bookshop-destination + serviceOfferingName: destination + servicePlanName: lite + parameters: + HTML5Runtime_enabled: true + html5RepoRuntime: + name: bookshop-html5-repo-runtime + serviceOfferingName: html5-apps-repo + servicePlanName: app-runtime + parameters: {} + html5RepoHost: + name: bookshop-html5-repo-host + serviceOfferingName: html5-apps-repo + servicePlanName: app-host + parameters: {} + identity: + name: bookshop-identity + serviceOfferingName: identity + servicePlanName: application + parameters: + display-name: bookshop + multi-tenant: true + xsuaa-cross-consumption: true + authorization: + enabled: true + oauth2-configuration: + redirect-uris: [] + post-logout-redirect-uris: [] + home-url: "" + subscriptionManager: + name: bookshop-subscription-manager + serviceOfferingName: subscription-manager + servicePlanName: provider + parameters: + iasServiceInstanceName: bookshop-identity + applicationType: application + appName: bookshop + commercialAppName: bookshop + displayName: (bookshop) + description: (A simple CAP project.) + category: CAP + appCallbacks: + dependenciesCallbacks: + url: "" + subscriptionCallbacks: + url: "" + async: + subscribeEnable: true + unSubscribeEnable: true + timeoutInMillis: 300000 + serviceManager: + name: bookshop-service-manager + serviceOfferingName: service-manager + servicePlanName: container + parameters: {} +serviceBindings: + destination: + name: bookshop-destination-bind + serviceInstanceName: bookshop-destination + secretName: bookshop-destination-bind-secret + secretKey: credentials + parameters: {} + html5RepoRuntime: + name: bookshop-html5-repo-runtime-bind + serviceInstanceName: bookshop-html5-repo-runtime + secretName: bookshop-html5-repo-runtime-bind-secret + secretKey: credentials + parameters: {} + html5RepoHost: + name: bookshop-html5-repo-host-bind + serviceInstanceName: bookshop-html5-repo-host + secretName: bookshop-html5-repo-host-bind-secret + secretKey: credentials + parameters: {} + identity: + name: bookshop-identity-bind + serviceInstanceName: bookshop-identity + secretName: bookshop-identity-bind-secret + secretKey: credentials + parameters: + credential-type: X509_GENERATED + app-identifier: bookshop + subscriptionManager: + name: bookshop-subscription-manager-bind + serviceInstanceName: bookshop-subscription-manager + secretName: bookshop-subscription-manager-bind-secret + secretKey: credentials + parameters: {} + serviceManager: + name: bookshop-service-manager-bind + serviceInstanceName: bookshop-service-manager + secretName: bookshop-service-manager-bind-secret + secretKey: credentials + parameters: {} +app: + domains: + primary: null + additionalDomainRefs: [] + istioIngressGatewayLabels: + istio: ingressgateway + app: istio-ingressgateway +btp: + globalAccountId: null + provider: + subdomain: null + tenantId: null +imagePullSecrets: [] +hanaInstanceId: null +workloads: + server: + image: null + appRouter: + image: null + tenantJob: + image: null + contentDeploy: + image: null + amsDeployer: + image: null diff --git a/test/files/expectedConfigurableTemplatesChart/values-modified-svc.yaml b/test/files/expectedConfigurableTemplatesChart/values-modified-svc.yaml index 7cd7ca6..8d4e74a 100644 --- a/test/files/expectedConfigurableTemplatesChart/values-modified-svc.yaml +++ b/test/files/expectedConfigurableTemplatesChart/values-modified-svc.yaml @@ -26,26 +26,6 @@ serviceInstances: credential-types: - binding-secret redirect-uris: [] - saasRegistry: - name: bookshop-saas-registry - serviceOfferingName: saas-registry - servicePlanName: application - parameters: - plan: general - xsappname: bookshop - appName: bookshop - displayName: (bookshop) - description: (A simple CAP project.) - appUrls: - callbackTimeoutMillis: 300000 - onSubscriptionAsync: true - onUnSubscriptionAsync: true - category: CAP - serviceManager: - name: bookshop-service-manager - serviceOfferingName: service-manager - servicePlanName: container - parameters: {} serviceBindings: destination: name: bookshop-destination-bind @@ -71,18 +51,6 @@ serviceBindings: secretName: bookshop-uaa-bind-secret secretKey: credentials parameters: {} - saasRegistry: - name: bookshop-saas-registry-bind - serviceInstanceName: bookshop-saas-registry - secretName: bookshop-saas-registry-bind-secret - secretKey: credentials - parameters: {} - serviceManager: - name: bookshop-service-manager-bind - serviceInstanceName: bookshop-service-manager - secretName: bookshop-service-manager-bind-secret - secretKey: credentials - parameters: {} app: domains: primary: null diff --git a/test/files/expectedConfigurableTemplatesChart/values-modified.yaml b/test/files/expectedConfigurableTemplatesChart/values-modified.yaml index e24c6ce..cb430eb 100644 --- a/test/files/expectedConfigurableTemplatesChart/values-modified.yaml +++ b/test/files/expectedConfigurableTemplatesChart/values-modified.yaml @@ -37,6 +37,8 @@ serviceInstances: displayName: (bookshop) description: (A simple CAP project.) appUrls: + getDependencies: "" + onSubscription: "" callbackTimeoutMillis: 300000 onSubscriptionAsync: true onUnSubscriptionAsync: true diff --git a/test/files/expectedConfigurableTemplatesChart/values-svc-ias.yaml b/test/files/expectedConfigurableTemplatesChart/values-svc-ias.yaml new file mode 100644 index 0000000..264bcf1 --- /dev/null +++ b/test/files/expectedConfigurableTemplatesChart/values-svc-ias.yaml @@ -0,0 +1,76 @@ +serviceInstances: + destination: + name: bookshop-destination + serviceOfferingName: destination + servicePlanName: lite + parameters: + HTML5Runtime_enabled: true + html5RepoRuntime: + name: bookshop-html5-repo-runtime + serviceOfferingName: html5-apps-repo + servicePlanName: app-runtime + parameters: {} + html5RepoHost: + name: bookshop-html5-repo-host + serviceOfferingName: html5-apps-repo + servicePlanName: app-host + parameters: {} + identity: + name: bookshop-identity + serviceOfferingName: identity + servicePlanName: application + parameters: + display-name: bookshop + multi-tenant: true + xsuaa-cross-consumption: true + authorization: + enabled: true + oauth2-configuration: + redirect-uris: [] + post-logout-redirect-uris: [] + home-url: "" +serviceBindings: + destination: + name: bookshop-destination-bind + serviceInstanceName: bookshop-destination + secretName: bookshop-destination-bind-secret + secretKey: credentials + parameters: {} + html5RepoRuntime: + name: bookshop-html5-repo-runtime-bind + serviceInstanceName: bookshop-html5-repo-runtime + secretName: bookshop-html5-repo-runtime-bind-secret + secretKey: credentials + parameters: {} + html5RepoHost: + name: bookshop-html5-repo-host-bind + serviceInstanceName: bookshop-html5-repo-host + secretName: bookshop-html5-repo-host-bind-secret + secretKey: credentials + parameters: {} + identity: + name: bookshop-identity-bind + serviceInstanceName: bookshop-identity + secretName: bookshop-identity-bind-secret + secretKey: credentials + parameters: + credential-type: X509_GENERATED + app-identifier: bookshop +app: + domains: + primary: null + additionalDomainRefs: [] + istioIngressGatewayLabels: + istio: ingressgateway + app: istio-ingressgateway +btp: + globalAccountId: null +imagePullSecrets: [] +hanaInstanceId: null +workloads: + server: + image: null + contentDeploy: + image: null + amsDeployer: + image: null diff --git a/test/files/expectedConfigurableTemplatesChart/values-svc.yaml b/test/files/expectedConfigurableTemplatesChart/values-svc.yaml index da2cade..36cb949 100644 --- a/test/files/expectedConfigurableTemplatesChart/values-svc.yaml +++ b/test/files/expectedConfigurableTemplatesChart/values-svc.yaml @@ -26,26 +26,6 @@ serviceInstances: credential-types: - binding-secret redirect-uris: [] - saasRegistry: - name: bookshop-saas-registry - serviceOfferingName: saas-registry - servicePlanName: application - parameters: - plan: general - xsappname: bookshop - appName: bookshop - displayName: (bookshop) - description: (A simple CAP project.) - appUrls: - callbackTimeoutMillis: 300000 - onSubscriptionAsync: true - onUnSubscriptionAsync: true - category: CAP - serviceManager: - name: bookshop-service-manager - serviceOfferingName: service-manager - servicePlanName: container - parameters: {} serviceBindings: destination: name: bookshop-destination-bind @@ -71,18 +51,6 @@ serviceBindings: secretName: bookshop-uaa-bind-secret secretKey: credentials parameters: {} - saasRegistry: - name: bookshop-saas-registry-bind - serviceInstanceName: bookshop-saas-registry - secretName: bookshop-saas-registry-bind-secret - secretKey: credentials - parameters: {} - serviceManager: - name: bookshop-service-manager-bind - serviceInstanceName: bookshop-service-manager - secretName: bookshop-service-manager-bind-secret - secretKey: credentials - parameters: {} app: domains: primary: null diff --git a/test/files/expectedConfigurableTemplatesChart/values.yaml b/test/files/expectedConfigurableTemplatesChart/values.yaml index 463ea9a..b1f3533 100644 --- a/test/files/expectedConfigurableTemplatesChart/values.yaml +++ b/test/files/expectedConfigurableTemplatesChart/values.yaml @@ -37,6 +37,8 @@ serviceInstances: displayName: (bookshop) description: (A simple CAP project.) appUrls: + getDependencies: "" + onSubscription: "" callbackTimeoutMillis: 300000 onSubscriptionAsync: true onUnSubscriptionAsync: true diff --git a/test/files/runtime-values-of-simple-service-chart.yaml b/test/files/runtime-values-of-simple-service-chart.yaml index f01cce4..e6c8290 100644 --- a/test/files/runtime-values-of-simple-service-chart.yaml +++ b/test/files/runtime-values-of-simple-service-chart.yaml @@ -1,19 +1,7 @@ serviceInstances: - saasRegistry: - parameters: - xsappname: bkshop - appName: bkshop - displayName: bkshop - description: A simple CAP project. - appUrls: - getDependencies: https://bem-aad-sadad-123456789012.bkshop.c-abc.kyma.ondemand.com/callback/v1.0/dependencies - onSubscription: https://cap-op.c-abc.kyma.ondemand.com/provision/tenants/{tenantId} xsuaa: parameters: xsappname: bkshop - oauth2-configuration: - redirect-uris: - - https://*bkshop.c-abc.kyma.ondemand.com/** app: domains: primary: bkshop.c-abc.kyma.ondemand.com diff --git a/test/files/values-of-simple-chart-filled.yaml b/test/files/values-of-simple-chart-filled.yaml index 361b4f3..8342c35 100644 --- a/test/files/values-of-simple-chart-filled.yaml +++ b/test/files/values-of-simple-chart-filled.yaml @@ -37,6 +37,8 @@ serviceInstances: displayName: (bookshop) description: (A simple CAP project.) appUrls: + getDependencies: "" + onSubscription: "" callbackTimeoutMillis: 300000 onSubscriptionAsync: true onUnSubscriptionAsync: true @@ -132,7 +134,6 @@ workloads: sme.sap.com/app-type: bookshop consumedBTPServices: - bookshop-uaa-bind - - bookshop-saas-registry-bind - bookshop-html5-repo-host-bind jobDefinition: type: Content diff --git a/test/files/values-of-simple-service-chart-filled.yaml b/test/files/values-of-simple-service-chart-filled.yaml index 056d424..426d401 100644 --- a/test/files/values-of-simple-service-chart-filled.yaml +++ b/test/files/values-of-simple-service-chart-filled.yaml @@ -26,26 +26,6 @@ serviceInstances: credential-types: - binding-secret redirect-uris: [] - saasRegistry: - name: bookshop-saas-registry - serviceOfferingName: saas-registry - servicePlanName: application - parameters: - plan: general - xsappname: bookshop - appName: bookshop - displayName: (bookshop) - description: (A simple CAP project.) - appUrls: - callbackTimeoutMillis: 300000 - onSubscriptionAsync: true - onUnSubscriptionAsync: true - category: CAP - serviceManager: - name: bookshop-service-manager - serviceOfferingName: service-manager - servicePlanName: container - parameters: {} serviceBindings: destination: name: bookshop-destination-bind @@ -71,18 +51,6 @@ serviceBindings: secretName: bookshop-uaa-bind-secret secretKey: credentials parameters: {} - saasRegistry: - name: bookshop-saas-registry-bind - serviceInstanceName: bookshop-saas-registry - secretName: bookshop-saas-registry-bind-secret - secretKey: credentials - parameters: {} - serviceManager: - name: bookshop-service-manager-bind - serviceInstanceName: bookshop-service-manager - secretName: bookshop-service-manager-bind-secret - secretKey: credentials - parameters: {} app: domains: primary: null @@ -100,10 +68,8 @@ workloads: sme.sap.com/app-type: bookshop consumedBTPServices: - bookshop-uaa-bind - - bookshop-saas-registry-bind - - bookshop-service-manager-bind deploymentDefinition: - type: service + type: Service image: gcr.io/test/server env: - name: CDS_CONFIG @@ -118,7 +84,6 @@ workloads: sme.sap.com/app-type: bookshop consumedBTPServices: - bookshop-uaa-bind - - bookshop-saas-registry-bind - bookshop-html5-repo-host-bind jobDefinition: type: Content