@sap/cds-dk 4.9.7 → 6.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +77 -0
- package/bin/activate.js +4 -4
- package/bin/add.js +11 -5
- package/bin/bind.js +16 -28
- package/bin/build/all.js +2 -2
- package/bin/build/index.js +12 -19
- package/bin/cds.js +22 -19
- package/bin/compile/index.js +12 -3
- package/bin/deploy/index.js +15 -9
- package/bin/deploy/to-hana.js +4 -4
- package/bin/deploy/to-sqlite.js +1 -1
- package/bin/env.js +13 -4
- package/bin/eval.js +1 -1
- package/bin/fix-redirects.js +1 -1
- package/bin/import.js +44 -179
- package/bin/repl.js +1 -1
- package/bin/watch.js +10 -15
- package/lib/bind/BindingManager.js +87 -0
- package/lib/bind/bindingResolver.js +15 -87
- package/lib/bind/bindingUtil.js +18 -11
- package/lib/bind/cfKeyProvider.js +58 -29
- package/lib/bind/kubernetesCredentialsProvider.js +44 -21
- package/lib/bind/userCdsrcJsonStorageProvider.js +12 -18
- package/lib/cds.js +13 -0
- package/lib/client/base_command.js +3 -2
- package/lib/client/extend.js +6 -7
- package/lib/client/helper/fs_helper.js +7 -8
- package/lib/client/settings_manager.js +14 -10
- package/lib/compile/index.js +9 -10
- package/lib/compile/openapi/csdl2openapi.js +151 -43
- package/lib/compile/openapi/index.js +2 -2
- package/lib/compile/to-xsuaa.js +3 -2
- package/lib/import/common.js +342 -27
- package/lib/import/importapi.js +81 -13
- package/lib/import/message.js +4 -4
- package/lib/import/odata/index.js +141 -0
- package/lib/import/{utils → odata/metadataconverter}/MetadataConverter.js +2 -2
- package/lib/import/{utils → odata/metadataconverter}/MetadataConverterFactory.js +1 -1
- package/lib/import/{utils → odata/util}/MultiMap.js +0 -0
- package/lib/import/{v2parser.js → odata/v2parser.js} +405 -468
- package/lib/import/{v4parser.js → odata/v4parser.js} +311 -322
- package/lib/import/{vocabularies → odata/vocabularies}/Org.OData.Aggregation.V1.json +0 -0
- package/lib/import/{vocabularies → odata/vocabularies}/Org.OData.Authorization.V1.json +0 -0
- package/lib/import/{vocabularies → odata/vocabularies}/Org.OData.Capabilities.V1.json +0 -0
- package/lib/import/{vocabularies → odata/vocabularies}/Org.OData.Core.V1.json +0 -0
- package/lib/import/{vocabularies → odata/vocabularies}/Org.OData.Measures.V1.json +0 -0
- package/lib/import/{vocabularies → odata/vocabularies}/Org.OData.Validation.V1.json +0 -0
- package/lib/import/openapi/importOpenAPI.js +521 -0
- package/lib/import/openapi/index.js +19 -0
- package/lib/import/openapi/utilities.js +38 -0
- package/lib/index.js +1 -1
- package/lib/init/constants.js +7 -2
- package/lib/init/index.js +10 -3
- package/lib/init/template/_merging/existences.js +79 -19
- package/lib/init/template/approuter/files/mta.yaml.hbs +25 -11
- package/lib/init/template/approuter/files/package.json +1 -1
- package/lib/init/template/approuter/files/xs-app.json.hbs +7 -0
- package/lib/init/template/approuter/index.js +61 -54
- package/lib/init/template/auditlog/index.js +2 -2
- package/lib/init/template/data/index.js +2 -2
- package/lib/init/template/hana/files/mta.yaml.hbs +17 -17
- package/lib/init/template/hana/index.js +8 -4
- package/lib/init/template/helm/index.js +39 -0
- package/lib/init/template/helm/update/index.js +28 -0
- package/lib/init/template/java/index.js +7 -9
- package/lib/init/template/kibana-logging/index.js +5 -6
- package/lib/init/template/lint/index.js +1 -1
- package/lib/init/template/mta/index.js +4 -4
- package/lib/init/template/mtx/files/java/package.json +9 -9
- package/lib/init/template/mtx/files/mta.yaml.hbs +0 -7
- package/lib/init/template/mtx/files/xs-security.json.hbs +11 -20
- package/lib/init/template/mtx/index.js +50 -57
- package/lib/init/template/nodejs/files/package.json.hbs +2 -2
- package/lib/init/template/notebook/index.js +2 -0
- package/lib/init/template/templateBase.js +8 -6
- package/lib/init/template/xsuaa/index.js +9 -5
- package/lib/init/util/fsUtil.js +25 -10
- package/lib/init/util/logger.js +1 -1
- package/lib/init/util/mvnArchetypeUtil.js +4 -10
- package/lib/init/util/projectReader.js +17 -9
- package/lib/init/util/templateUtil.js +30 -34
- package/lib/k8s/ChartAdder.js +65 -0
- package/lib/k8s/ChartBuilder.js +186 -0
- package/lib/k8s/Context.js +71 -0
- package/lib/k8s/ImageUtil.js +21 -0
- package/lib/k8s/Model.d.ts +53 -0
- package/lib/k8s/auditlog/index.js +29 -0
- package/lib/k8s/auditlog/templates/auditlog.yaml +1 -0
- package/lib/k8s/buildModel.js +70 -0
- package/lib/k8s/connectivity/index.js +80 -0
- package/lib/k8s/connectivity/templates/connectivity-binding.yaml +9 -0
- package/lib/k8s/connectivity/templates/connectivity-proxy-info.yaml +20 -0
- package/lib/k8s/connectivity/templates/connectivity.yaml +1 -0
- package/lib/k8s/deployment/index.js +81 -0
- package/lib/k8s/deployment/subchart/Chart.yaml +6 -0
- package/lib/k8s/deployment/subchart/templates/_helpers.tpl +156 -0
- package/lib/k8s/deployment/subchart/templates/api-rule.yaml +24 -0
- package/lib/k8s/deployment/subchart/templates/deployment.yaml +110 -0
- package/lib/k8s/deployment/subchart/templates/network-policy.yaml +16 -0
- package/lib/k8s/deployment/subchart/templates/pod-disruption-budget.yaml +11 -0
- package/lib/k8s/deployment/subchart/templates/secret.yaml +10 -0
- package/lib/k8s/deployment/subchart/templates/service-binding.yaml +27 -0
- package/lib/k8s/deployment/subchart/templates/service.yaml +11 -0
- package/lib/k8s/deployment/subchart/values-lint.yaml +8 -0
- package/lib/k8s/deployment/subchart/values.schema.json +449 -0
- package/lib/k8s/deployment/subchart/values.yaml +76 -0
- package/lib/k8s/deployment/subchart-override/templates/_web_application_helpers.tpl +81 -0
- package/lib/k8s/destinations/index.js +40 -0
- package/lib/k8s/destinations/lib.js +16 -0
- package/lib/k8s/destinations/templates/destinations.yaml +1 -0
- package/lib/k8s/docker/push.js +8 -0
- package/lib/k8s/event-mesh/index.js +53 -0
- package/lib/k8s/event-mesh/lib.js +9 -0
- package/lib/k8s/event-mesh/templates/event-mesh.yaml +1 -0
- package/lib/k8s/hana-deployer/index.js +38 -0
- package/lib/k8s/hana-deployer/templates/hana-deployer-job.yaml +41 -0
- package/lib/k8s/helm/Release.js +80 -0
- package/lib/k8s/html5-apps-deployer/index.js +43 -0
- package/lib/k8s/html5-apps-deployer/templates/_html5_deployment_helpers.tpl +16 -0
- package/lib/k8s/html5-apps-deployer/templates/html5-apps-deployer-job.yaml +53 -0
- package/lib/k8s/html5-apps-repo-host/index.js +26 -0
- package/lib/k8s/html5-apps-repo-host/lib.js +16 -0
- package/lib/k8s/html5-apps-repo-host/templates/html5-apps-repo-host.yaml +1 -0
- package/lib/k8s/index.js +153 -0
- package/lib/k8s/modules.js +36 -0
- package/lib/k8s/multitenancy/index.js +24 -0
- package/lib/k8s/multitenancy/lib.js +25 -0
- package/lib/k8s/multitenancy/templates/saas-registry.yaml +19 -0
- package/lib/k8s/readProject.js +14 -0
- package/lib/k8s/resources/helm/chart/templates/NOTES.txt +11 -0
- package/lib/k8s/resources/helm/chart/templates/_deployment_helpers.tpl +221 -0
- package/lib/k8s/resources/helm/chart/templates/_helpers.tpl +167 -0
- package/lib/k8s/resources/helm/chart/templates/_sapcp_helpers.tpl +103 -0
- package/lib/k8s/util.js +186 -0
- package/lib/k8s/wrapFeature.js +55 -0
- package/lib/k8s/xsuaa/index.js +64 -0
- package/lib/k8s/xsuaa/lib.js +17 -0
- package/lib/k8s/xsuaa/templates/xsuaa.yaml +1 -0
- package/lib/lint/generators.js +1 -1
- package/lib/util/exec.js +1 -1
- package/lib/util/write.js +1 -1
- package/lib/watch/node-watch.js +43 -14
- package/npm-shrinkwrap.json +923 -2705
- package/package.json +5 -5
- package/lib/import/index.js +0 -235
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
const wrapFeature = require('../wrapFeature');
|
|
2
|
+
const { cds } = require('../modules');
|
|
3
|
+
const LOG = cds.log();
|
|
4
|
+
|
|
5
|
+
module.exports = wrapFeature('event_mesh', {
|
|
6
|
+
async isRequired(context) {
|
|
7
|
+
const env = await context.get('env');
|
|
8
|
+
return eventMeshServices(env).length > 0;
|
|
9
|
+
},
|
|
10
|
+
|
|
11
|
+
async getServiceBindings() {
|
|
12
|
+
return {
|
|
13
|
+
messaging: {
|
|
14
|
+
serviceInstanceName: 'event-mesh'
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
},
|
|
18
|
+
|
|
19
|
+
async getChartCapabilities() {
|
|
20
|
+
return {
|
|
21
|
+
"event_mesh": {
|
|
22
|
+
serviceOfferingName: 'enterprise-messaging',
|
|
23
|
+
servicePlanName: 'default',
|
|
24
|
+
config: 'event-mesh.json'
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
|
|
29
|
+
async addToChart(builder, { 'event_mesh': eventMesh }) {
|
|
30
|
+
await builder.addAllTemplates(__dirname);
|
|
31
|
+
|
|
32
|
+
const { config } = eventMesh;
|
|
33
|
+
if (config) {
|
|
34
|
+
if (!await builder.addChartFile(config, { optional: true })) {
|
|
35
|
+
LOG.warn(`Please add the "${config}" file to the chart folder.`);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
function eventMeshServices(env) {
|
|
42
|
+
const kinds = [ '$', '$-http', '$-amqp', '$-shared', 'default-messaging' ].reduce( (map, key) => {
|
|
43
|
+
map[key.replace(/\$/, 'enterprise-messaging')] = true;
|
|
44
|
+
return map;
|
|
45
|
+
}, {});
|
|
46
|
+
const names = [];
|
|
47
|
+
for (const name in env.requires) {
|
|
48
|
+
const service = env.requires[name];
|
|
49
|
+
if (!kinds[name] && kinds[service.kind]) names.push(name);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
return names;
|
|
53
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{{- include "cap.service-instance" . }}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
const wrapFeature = require('../wrapFeature');
|
|
2
|
+
|
|
3
|
+
module.exports = wrapFeature('hana_deployer', {
|
|
4
|
+
async isRequired(context) {
|
|
5
|
+
const env = await context.get('env');
|
|
6
|
+
return env.requires.db && (env.requires.db.kind === 'sql' || env.requires.db.kind === 'hana');
|
|
7
|
+
},
|
|
8
|
+
|
|
9
|
+
async getChartCapabilities(context) {
|
|
10
|
+
const model = await context.get('model');
|
|
11
|
+
|
|
12
|
+
return {
|
|
13
|
+
hana_deployer: {
|
|
14
|
+
image: {
|
|
15
|
+
repository: '<your-container-registry>/'+model.app.name+'-hana-deployer',
|
|
16
|
+
tag: 'latest'
|
|
17
|
+
},
|
|
18
|
+
bindings: {
|
|
19
|
+
hana: {
|
|
20
|
+
fromSecret: null
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
},
|
|
26
|
+
|
|
27
|
+
getServiceBindings() {
|
|
28
|
+
return {
|
|
29
|
+
db: {
|
|
30
|
+
fromSecret: null
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
|
|
35
|
+
async addToChart(builder) {
|
|
36
|
+
await builder.addAllTemplates(__dirname);
|
|
37
|
+
}
|
|
38
|
+
});
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
#
|
|
2
|
+
# HANA single-tenant DB deployment
|
|
3
|
+
#
|
|
4
|
+
{{- if .Values.hana_deployer }}
|
|
5
|
+
{{- if or (not (hasKey .Values.hana_deployer "enabled")) .Values.hana_deployer.enabled }}
|
|
6
|
+
{{- $ := merge (dict "root" . "name" "hana-deployer") .Values.hana_deployer . }}
|
|
7
|
+
{{- template "cap.expect" (list . "hana_deployer.bindings.hana.fromSecret" "hana_deployer.image.repository") }}
|
|
8
|
+
apiVersion: batch/v1
|
|
9
|
+
kind: Job
|
|
10
|
+
metadata:
|
|
11
|
+
name: {{ .Release.Name }}-hana-deployer
|
|
12
|
+
labels: {{- include "cap.labels" $ | nindent 4 }}
|
|
13
|
+
annotations:
|
|
14
|
+
"helm.sh/hook": "post-install,pre-upgrade"
|
|
15
|
+
"helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded
|
|
16
|
+
namespace: {{ .Release.Namespace }}
|
|
17
|
+
spec:
|
|
18
|
+
backoffLimit: 4
|
|
19
|
+
template:
|
|
20
|
+
metadata:
|
|
21
|
+
labels:
|
|
22
|
+
{{- include "cap.labels" $ | nindent 8 }}
|
|
23
|
+
sidecar.istio.io/inject: "false"
|
|
24
|
+
spec:
|
|
25
|
+
restartPolicy: Never
|
|
26
|
+
{{- include "cap.imagePullSecrets" $ | nindent 6 }}
|
|
27
|
+
volumes:
|
|
28
|
+
{{- include "cap.sapcp.bindingsVolumes" $ | nindent 10 }}
|
|
29
|
+
containers:
|
|
30
|
+
- name: hana-deployer
|
|
31
|
+
image: {{ include "cap.image" $ }}
|
|
32
|
+
imagePullPolicy: {{ include "cap.imagePullPolicy" $ }}
|
|
33
|
+
env:
|
|
34
|
+
- name: EXIT
|
|
35
|
+
value: 'true'
|
|
36
|
+
volumeMounts:
|
|
37
|
+
{{- include "cap.sapcp.bindingsVolumeMounts" $ | nindent 10 }}
|
|
38
|
+
---
|
|
39
|
+
{{ include "cap.sapcp.bindings" $ }}
|
|
40
|
+
{{ end }}
|
|
41
|
+
{{ end }}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
const { throwError } = require('../util');
|
|
2
|
+
const { exec } = require('../../util/exec');
|
|
3
|
+
const { yaml } = require('../modules');
|
|
4
|
+
const fs = require('fs').promises;
|
|
5
|
+
const Path = require('path');
|
|
6
|
+
|
|
7
|
+
async function status({ releaseName, namespace }) {
|
|
8
|
+
const result = await exec({stdio: [ 'inherit', 'pipe', 'inherit'], acceptStatuses: '*'}) `helm status ${releaseName} --namespace ${namespace}`;
|
|
9
|
+
if (result.status === 0) {
|
|
10
|
+
const output = Buffer.from(result.output[1]).toString();
|
|
11
|
+
const lines = output.split(/[\n\r]+/sg);
|
|
12
|
+
const status = {};
|
|
13
|
+
for (const line of lines) {
|
|
14
|
+
const m = line.match(/\s*([^:]+)\s*:\s*(.*)/);
|
|
15
|
+
if (m) {
|
|
16
|
+
status[m[1].toLowerCase()] = m[2];
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
if (!status.status) throwError(`Internal error: helm status didn't return STATUS value.`);
|
|
21
|
+
return status;
|
|
22
|
+
} else {
|
|
23
|
+
return { name: releaseName, status: 'not found' }
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
async function deploy({ options, releaseName, namespace, chartPath, values }) {
|
|
28
|
+
const valuesArg = formatValues(values);
|
|
29
|
+
await exec `helm upgrade ${releaseName} ./${chartPath} --install --namespace ${namespace} ${valuesArg && ['--set', valuesArg]} ${formatOptions(options)}`;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
async function template({ options, releaseName, namespace, chartPath, values }) {
|
|
33
|
+
const valuesArg = formatValues(values);
|
|
34
|
+
await exec `helm template ${releaseName} ./${chartPath} --namespace ${namespace} ${valuesArg && ['--set', valuesArg]} ${formatOptions(options)}`;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function formatOptions(options = {}) {
|
|
38
|
+
const args = [];
|
|
39
|
+
if (options.debug) args.push('--debug');
|
|
40
|
+
return args;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
async function undeploy({ releaseName, namespace }) {
|
|
44
|
+
await exec `helm uninstall ${releaseName} --namespace ${namespace}`;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function formatValues(values) {
|
|
48
|
+
const valuesArray = collectValues(values);
|
|
49
|
+
return valuesArray.join(',');
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function collectValues(values, prefix = '') {
|
|
53
|
+
const valuesArray = [];
|
|
54
|
+
|
|
55
|
+
for (const name of Reflect.ownKeys(values)) {
|
|
56
|
+
const value = values[name];
|
|
57
|
+
if (typeof value === 'object') {
|
|
58
|
+
valuesArray.push(...collectValues(value, `${prefix}${name}.`));
|
|
59
|
+
} else if (typeof value !== 'undefined') {
|
|
60
|
+
// @TODO: Escaping?
|
|
61
|
+
valuesArray.push(`${prefix}${name}=${values[name]}`);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
return valuesArray;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
async function values(chartPath) {
|
|
69
|
+
return yaml.parse(await fs.readFile(Path.join(chartPath, 'values.yaml'), 'utf-8'));
|
|
70
|
+
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
module.exports = {
|
|
75
|
+
status,
|
|
76
|
+
deploy,
|
|
77
|
+
undeploy,
|
|
78
|
+
template,
|
|
79
|
+
values
|
|
80
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
const wrapFeature = require('../wrapFeature');
|
|
2
|
+
|
|
3
|
+
module.exports = wrapFeature('html5_apps_deployer', {
|
|
4
|
+
async getChartCapabilities(context) {
|
|
5
|
+
const model = await context.get('model');
|
|
6
|
+
const projectName = model.app.name;
|
|
7
|
+
return {
|
|
8
|
+
'html5_apps_deployer': {
|
|
9
|
+
cloudService: null,
|
|
10
|
+
backendDestinations: {},
|
|
11
|
+
image: {
|
|
12
|
+
repository: "<your-container-registry>/" + projectName + "-html5-deployer" ,
|
|
13
|
+
tag: "latest"
|
|
14
|
+
},
|
|
15
|
+
bindings: {
|
|
16
|
+
xsuaa: {
|
|
17
|
+
serviceInstanceName: 'xsuaa'
|
|
18
|
+
},
|
|
19
|
+
destination: {
|
|
20
|
+
serviceInstanceName: 'destinations'
|
|
21
|
+
},
|
|
22
|
+
html5_apps_repo: {
|
|
23
|
+
serviceInstanceName: 'html5-apps-repo-host'
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
|
|
30
|
+
getDestinationsParameters() {
|
|
31
|
+
return {
|
|
32
|
+
HTML5Runtime_enabled: true
|
|
33
|
+
}
|
|
34
|
+
},
|
|
35
|
+
|
|
36
|
+
isHtml5AppsRepoHostRequired() {
|
|
37
|
+
return true;
|
|
38
|
+
},
|
|
39
|
+
|
|
40
|
+
async addToChart(builder) {
|
|
41
|
+
await builder.addAllTemplates(__dirname);
|
|
42
|
+
}
|
|
43
|
+
});
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{{/*
|
|
2
|
+
Backend Destinations
|
|
3
|
+
*/}}
|
|
4
|
+
{{- define "cap.backendDestinations" -}}
|
|
5
|
+
{{- $ := . -}}
|
|
6
|
+
{{- $destinations := list -}}
|
|
7
|
+
{{- range $destinationName, $destination := .backendDestinations -}}
|
|
8
|
+
{{- $destination := merge (dict "name" $destinationName) $destination -}}
|
|
9
|
+
{{- $deployment := (get $.root.Values $destination.service) -}}
|
|
10
|
+
{{- $srv := merge (dict "name" $destination.service "destination" $destination "deployment" $deployment) $.root -}}
|
|
11
|
+
{{- $destinationHost := include "cap.deploymentHost" $srv -}}
|
|
12
|
+
{{- $currentDestination := dict "Name" $destination.name "Type" "HTTP" "ProxyType" "Internet" "URL" (print "https://" $destinationHost "." $.root.Values.global.domain ($destination.path | default "")) "Authentication" "NoAuthentication" "sap.cloud.service" $.cloudService "HTML5.forwardAuthToken" "true" -}}
|
|
13
|
+
{{- $destinations = (append $destinations $currentDestination) -}}
|
|
14
|
+
{{- end -}}
|
|
15
|
+
{{- $destinations | toJson }}
|
|
16
|
+
{{- end -}}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
{{- if .Values.html5_apps_deployer }}
|
|
2
|
+
{{- if or (not (hasKey .Values.html5_apps_deployer "enabled")) .Values.html5_apps_deployer.enabled }}
|
|
3
|
+
|
|
4
|
+
{{- $ := merge (dict "root" . "name" "html5-apps-deployer") .Values.html5_apps_deployer . }}
|
|
5
|
+
{{- if $.backendDestinations }}
|
|
6
|
+
{{- if not (.Values.destinations.parameters.HTML5Runtime_enabled) }}
|
|
7
|
+
{{- fail "destinations.parameters.HTML5Runtime_enabled must be set to true for use with Launchpad Service" }}
|
|
8
|
+
{{- end }}
|
|
9
|
+
{{- end }}
|
|
10
|
+
{{- template "cap.expect" (list . "html5_apps_deployer.image.repository") }}
|
|
11
|
+
apiVersion: batch/v1
|
|
12
|
+
kind: Job
|
|
13
|
+
metadata:
|
|
14
|
+
name: {{ .Release.Name }}-html5-apps-deployer
|
|
15
|
+
namespace: {{ .Release.Namespace }}
|
|
16
|
+
labels: {{- include "cap.labels" $ | nindent 4 }}
|
|
17
|
+
annotations:
|
|
18
|
+
"helm.sh/hook": "post-install,post-upgrade"
|
|
19
|
+
"helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded
|
|
20
|
+
spec:
|
|
21
|
+
backoffLimit: 4
|
|
22
|
+
template:
|
|
23
|
+
metadata:
|
|
24
|
+
labels:
|
|
25
|
+
{{- include "cap.labels" $ | nindent 8 }}
|
|
26
|
+
sidecar.istio.io/inject: "false"
|
|
27
|
+
spec:
|
|
28
|
+
{{- include "cap.imagePullSecrets" $ | nindent 6 }}
|
|
29
|
+
restartPolicy: Never
|
|
30
|
+
volumes:
|
|
31
|
+
{{- include "cap.sapcp.bindingsVolumes" $ | nindent 10 }}
|
|
32
|
+
containers:
|
|
33
|
+
- name: html5-deployer
|
|
34
|
+
image: {{ include "cap.image" $ }}
|
|
35
|
+
imagePullPolicy: {{ include "cap.imagePullPolicy" $ }}
|
|
36
|
+
volumeMounts:
|
|
37
|
+
{{- include "cap.sapcp.bindingsVolumeMounts" $ | nindent 10 }}
|
|
38
|
+
env:
|
|
39
|
+
- name: EXIT_PROCESS_AFTER_UPLOAD
|
|
40
|
+
value: "true"
|
|
41
|
+
- name: PORT
|
|
42
|
+
value: "5000"
|
|
43
|
+
# TODO: cloud service should be configurable in the HTML5 apps
|
|
44
|
+
- name: SAP_CLOUD_SERVICE
|
|
45
|
+
value: {{ $.cloudService }}
|
|
46
|
+
# TODO: destination name should be configurable in the HTML5 apps
|
|
47
|
+
- name: BACKEND_DESTINATIONS
|
|
48
|
+
value: >
|
|
49
|
+
{{ include "cap.backendDestinations" $ }}
|
|
50
|
+
---
|
|
51
|
+
{{ include "cap.sapcp.bindings" $ }}
|
|
52
|
+
{{- end }}
|
|
53
|
+
{{- end }}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
const wrapFeature = require('../wrapFeature');
|
|
2
|
+
|
|
3
|
+
module.exports = wrapFeature('html5_apps_repo_host', {
|
|
4
|
+
|
|
5
|
+
async isRequired(context) {
|
|
6
|
+
return await context.collectBool('isHtml5AppsRepoHostRequired');
|
|
7
|
+
},
|
|
8
|
+
|
|
9
|
+
async getChartCapabilities() {
|
|
10
|
+
return {
|
|
11
|
+
'html5_apps_repo_host': {
|
|
12
|
+
serviceOfferingName: 'html5-apps-repo',
|
|
13
|
+
servicePlanName: 'app-host'
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
|
|
18
|
+
async addToChart(builder, { html5_apps_repo_host }) {
|
|
19
|
+
await builder.addAllTemplates(__dirname);
|
|
20
|
+
|
|
21
|
+
const { config } = html5_apps_repo_host;
|
|
22
|
+
if (config) {
|
|
23
|
+
await builder.addChartFile(config);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
});
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
function checkNeedDestinations(env) {
|
|
2
|
+
const kinds = [ 'odata', 'odata-v2', 'odata-v4', 'rest' ].reduce( (map, key) => {
|
|
3
|
+
map[key] = true;
|
|
4
|
+
return map;
|
|
5
|
+
}, {});
|
|
6
|
+
for (const service in env.requires) {
|
|
7
|
+
const require = env.requires[service];
|
|
8
|
+
if (!kinds[service] && kinds[require.kind]) return true;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
return false;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
module.exports = {
|
|
15
|
+
checkNeedDestinations
|
|
16
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{{- include "cap.service-instance" . }}
|
package/lib/k8s/index.js
ADDED
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
const Context = require('./Context');
|
|
2
|
+
const buildModel = require('./buildModel');
|
|
3
|
+
const ChartAdder = require('./ChartAdder');
|
|
4
|
+
const ChartBuilder = require('./ChartBuilder');
|
|
5
|
+
const { resource, mergeDeep, readFileIfExists } = require('./util');
|
|
6
|
+
const fs = require('fs');
|
|
7
|
+
const Path = require('path');
|
|
8
|
+
const { cds, yaml } = require('./modules');
|
|
9
|
+
|
|
10
|
+
async function context(projectPath, features = []) {
|
|
11
|
+
if (!Path.isAbsolute(projectPath)) projectPath = Path.join(process.cwd(), projectPath);
|
|
12
|
+
|
|
13
|
+
const projectEnv = cds.env.for('cds', projectPath);
|
|
14
|
+
process.env.NODE_ENV='production';
|
|
15
|
+
process.env.CDS_ENV='production';
|
|
16
|
+
const productiveEnv = cds.env.for('cds', projectPath);
|
|
17
|
+
|
|
18
|
+
const config = JSON.parse(JSON.stringify(projectEnv.k8s || {}));
|
|
19
|
+
|
|
20
|
+
const context = new Context({
|
|
21
|
+
projectPath,
|
|
22
|
+
config,
|
|
23
|
+
'effective-config': context => effectiveConfig(context),
|
|
24
|
+
features: featuresFactory(features),
|
|
25
|
+
env: productiveEnv,
|
|
26
|
+
model: buildModel,
|
|
27
|
+
auth: require('./xsuaa'),
|
|
28
|
+
multitenancy: require('./multitenancy'),
|
|
29
|
+
'hana-deployer': require('./hana-deployer'),
|
|
30
|
+
connectivity: require('./connectivity'),
|
|
31
|
+
destinations: require('./destinations'),
|
|
32
|
+
'event-mesh': require('./event-mesh'),
|
|
33
|
+
'auditlog': require('./auditlog'),
|
|
34
|
+
'html5-apps-deployer': require('./html5-apps-deployer'),
|
|
35
|
+
'html5-apps-repo-host': require('./html5-apps-repo-host'),
|
|
36
|
+
'srv': require('./deployment'),
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
return context;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// eslint-disable-next-line no-unused-vars
|
|
43
|
+
async function addChart(context, path = 'chart', _features) {
|
|
44
|
+
const model = await context.get('model');
|
|
45
|
+
|
|
46
|
+
const mergeSemantics = {
|
|
47
|
+
existences: []
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
context.add('chartPath', path);
|
|
51
|
+
|
|
52
|
+
await context.forEach('prepareChart',
|
|
53
|
+
async plugin => plugin.prepareChart()
|
|
54
|
+
);
|
|
55
|
+
|
|
56
|
+
// Collect chart values
|
|
57
|
+
let chartValues = {};
|
|
58
|
+
await context.forEach('getChartValues',
|
|
59
|
+
async plugin => chartValues = {...chartValues, ...await plugin.getChartValues()}
|
|
60
|
+
);
|
|
61
|
+
|
|
62
|
+
// Collect deployments
|
|
63
|
+
let deployments = {};
|
|
64
|
+
await context.forEach('getChartDeployments',
|
|
65
|
+
async plugin => deployments = {...deployments, ...await plugin.getChartDeployments(context)}
|
|
66
|
+
);
|
|
67
|
+
|
|
68
|
+
// Extend deployments
|
|
69
|
+
for (const name in deployments) {
|
|
70
|
+
await context.forEach('extendChartDeployment',
|
|
71
|
+
async plugin => await plugin.extendChartDeployment(context, name, deployments[name], mergeSemantics)
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
Object.assign(chartValues, deployments);
|
|
76
|
+
|
|
77
|
+
// Collect capabilities
|
|
78
|
+
let capabilities = {};
|
|
79
|
+
await context.forEach('getChartCapabilities',
|
|
80
|
+
async plugin => capabilities = {...capabilities, ...await plugin.getChartCapabilities(context)}
|
|
81
|
+
);
|
|
82
|
+
|
|
83
|
+
Object.assign(chartValues, capabilities);
|
|
84
|
+
|
|
85
|
+
// Collect chart dependencies (subcharts)
|
|
86
|
+
let chartDependencies = [];
|
|
87
|
+
await context.forEach('getChartDependencies',
|
|
88
|
+
async plugin => chartDependencies.push(...await plugin.getChartDependencies(context))
|
|
89
|
+
);
|
|
90
|
+
|
|
91
|
+
// Create chart
|
|
92
|
+
const projectPath = await context.get('projectPath');
|
|
93
|
+
const builder = new ChartBuilder({ path, rootPath: projectPath });
|
|
94
|
+
await builder.begin();
|
|
95
|
+
|
|
96
|
+
const chartAdder = new ChartAdder({ builder, chartValues, chartDependencies, template: resource('helm/chart'), app: model.app, mergeSemantics });
|
|
97
|
+
await chartAdder.execute();
|
|
98
|
+
|
|
99
|
+
let values;
|
|
100
|
+
try {
|
|
101
|
+
values = await chartAdder.getSavedValues();
|
|
102
|
+
} catch (error) {
|
|
103
|
+
console.log('Skip adding features because of broken chart/values.yaml file.')
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
if (values) await context.forEach('addToChart', async plugin => plugin.addToChart(builder, values));
|
|
107
|
+
|
|
108
|
+
await builder.end();
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
async function hasChart(context, path = 'chart') {
|
|
113
|
+
return fs.existsSync(path);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
function featuresFactory(_features) {
|
|
117
|
+
return async function(context) {
|
|
118
|
+
const features = new Set(_features);
|
|
119
|
+
|
|
120
|
+
// Collect enabled features
|
|
121
|
+
const effectiveConfig = await context.get('effective-config');
|
|
122
|
+
for (const name in effectiveConfig) {
|
|
123
|
+
const entry = effectiveConfig[name];
|
|
124
|
+
if (entry && entry.enabled !== false) features.add(name);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
return features;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
async function effectiveConfig(context) {
|
|
132
|
+
const skeleton = { images: {} };
|
|
133
|
+
let result;
|
|
134
|
+
|
|
135
|
+
const chartPath = context.has('chartPath') ? await context.get('chartPath') : 'chart';
|
|
136
|
+
const valuesFile = await readFileIfExists(Path.join(chartPath, 'values.yaml'), 'utf-8');
|
|
137
|
+
if (valuesFile) {
|
|
138
|
+
const values = yaml.parse(valuesFile);
|
|
139
|
+
const config = await context.get('config');
|
|
140
|
+
result = mergeDeep(values, config);
|
|
141
|
+
} else {
|
|
142
|
+
result = await context.get('config');
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
return Object.assign(skeleton, result);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
module.exports = {
|
|
149
|
+
context,
|
|
150
|
+
addChart,
|
|
151
|
+
hasChart,
|
|
152
|
+
effectiveConfig
|
|
153
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/* @sap/cds */
|
|
2
|
+
const cds = require('@sap/cds/lib');
|
|
3
|
+
const cds_cli = require('@sap/cds/bin/cds');
|
|
4
|
+
|
|
5
|
+
/* @sap/cds-dk */
|
|
6
|
+
const term = require('../util/term');
|
|
7
|
+
const ProjectReader = require('../init/util/projectReader');
|
|
8
|
+
const TemplateBase = require('../init/template/templateBase');
|
|
9
|
+
const CDSGenerator = require('../init/index');
|
|
10
|
+
|
|
11
|
+
/* @sap/cds-foss */
|
|
12
|
+
const yaml = require("@sap/cds-foss")("yaml");
|
|
13
|
+
|
|
14
|
+
/* other FOSS */
|
|
15
|
+
const glob = require('glob');
|
|
16
|
+
const xmlJs = require('xml-js');
|
|
17
|
+
|
|
18
|
+
module.exports = {
|
|
19
|
+
/* @sap/cds */
|
|
20
|
+
cds,
|
|
21
|
+
cds_cli,
|
|
22
|
+
env: cds.env,
|
|
23
|
+
|
|
24
|
+
/* @sap/cds-dk */
|
|
25
|
+
term,
|
|
26
|
+
ProjectReader,
|
|
27
|
+
TemplateBase,
|
|
28
|
+
CDSGenerator,
|
|
29
|
+
|
|
30
|
+
/* @sap/cds-foss */
|
|
31
|
+
yaml,
|
|
32
|
+
|
|
33
|
+
/* other FOSS */
|
|
34
|
+
glob,
|
|
35
|
+
xmlJs
|
|
36
|
+
};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
const wrapFeature = require('../wrapFeature');
|
|
2
|
+
|
|
3
|
+
module.exports = wrapFeature('multitenancy', {
|
|
4
|
+
/**
|
|
5
|
+
* @param {import('../ChartBuilder')} builder
|
|
6
|
+
*/
|
|
7
|
+
async addToChart(builder, { multitenancy }) {
|
|
8
|
+
await builder.addAllTemplates(__dirname);
|
|
9
|
+
|
|
10
|
+
if (multitenancy.config) {
|
|
11
|
+
await builder.addChartFile(multitenancy.config);
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
|
|
15
|
+
// eslint-disable-next-line no-unused-vars
|
|
16
|
+
async getChartCapabilities(context) {
|
|
17
|
+
return {
|
|
18
|
+
xsuaa: {
|
|
19
|
+
serviceOfferingName: 'saas-registry',
|
|
20
|
+
servicePlanName: 'application'
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
});
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
const { exec } = require("../../util/exec");
|
|
2
|
+
const Path = require("path");
|
|
3
|
+
|
|
4
|
+
async function renderXsSecurityJson(projectPath) {
|
|
5
|
+
const result = await exec({
|
|
6
|
+
cwd: projectPath,
|
|
7
|
+
stdio: ["inherit", "pipe", "inherit"],
|
|
8
|
+
})`cds compile srv -2 xsuaa`;
|
|
9
|
+
const xsSecurityJson = result.stdout;
|
|
10
|
+
return xsSecurityJson;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* @param {import('../ChartBuilder')} builder
|
|
15
|
+
*/
|
|
16
|
+
async function addTemplates(builder) {
|
|
17
|
+
const templates = Path.join(__dirname, 'templates');
|
|
18
|
+
await builder.addTemplate(templates, 'xsuaa.yaml');
|
|
19
|
+
await builder.addTemplate(templates, 'registry.yaml');
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
module.exports = {
|
|
23
|
+
renderXsSecurityJson,
|
|
24
|
+
addTemplates
|
|
25
|
+
};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{{- if (default dict .Values.multitenancy).enabled }}
|
|
2
|
+
{{- $srvHostFull := include "cap.deploymentHostFull" (merge (dict "name" "srv" "deployment" .Values.srv) . ) }}
|
|
3
|
+
{{- $defaultAppUrls := dict
|
|
4
|
+
"getDependencies" (print "https://" $srvHostFull "/mtx/v1/provisioning/dependencies")
|
|
5
|
+
"onSubscription" (print "https://" $srvHostFull "/mtx/v1/provisioning/tenant/{tenantId}")
|
|
6
|
+
"onSubscriptionAsync" false
|
|
7
|
+
"onUnSubscriptionAsync" false
|
|
8
|
+
"callbackTimeoutMillis" 300000
|
|
9
|
+
}}
|
|
10
|
+
{{- $defaultParameters := dict
|
|
11
|
+
"xsappname" .Values.xsuaa.parameters.xsappname
|
|
12
|
+
"appName" .Values.xsuaa.parameters.xsappname
|
|
13
|
+
"displayName" .Chart.Name
|
|
14
|
+
"description" .Chart.Description
|
|
15
|
+
"category" "CAP Application"
|
|
16
|
+
"appUrls" $defaultAppUrls
|
|
17
|
+
}}
|
|
18
|
+
{{- include "cap.service-instance" (merge (dict "defaultParameters" $defaultParameters . )) }}
|
|
19
|
+
{{ end }}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
|
|
2
|
+
|
|
3
|
+
const { ProjectReader, TemplateBase, CDSGenerator } = require('./modules');
|
|
4
|
+
|
|
5
|
+
async function readProject(path = '') {
|
|
6
|
+
/* TODO: Ugly way to access project information -> talk to the guys */
|
|
7
|
+
const reader = new ProjectReader(new ProjectTemplate(path, new CDSGenerator(), ''));
|
|
8
|
+
return await reader.read();
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
class ProjectTemplate extends TemplateBase {
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
module.exports = readProject;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
Thank you for installing {{ .Chart.Name }} version {{ .Chart.Version }}.
|
|
2
|
+
|
|
3
|
+
The release "{{ .Release.Name }}" is installed in namespace "{{ .Release.Namespace }}".
|
|
4
|
+
|
|
5
|
+
Your services are available at:
|
|
6
|
+
{{- $root := . }}
|
|
7
|
+
{{- range $name := include "cap.deploymentNames" . | split ";" }}
|
|
8
|
+
{{- $deployment := (get $root.Values $name) }}
|
|
9
|
+
{{- $ := merge (dict "name" $name "deployment" $deployment) $root }}
|
|
10
|
+
- https://{{ include "cap.deploymentHostFull" $ }}
|
|
11
|
+
{{- end }}
|