@sap/cds-dk 8.8.1 → 8.9.0
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 +30 -1
- package/bin/deploy/index.js +7 -3
- package/bin/init.js +5 -5
- package/bin/repl.js +4 -0
- package/bin/test.js +6 -4
- package/bin/up.js +77 -0
- package/bin/watch.js +0 -43
- package/lib/bind/shared.js +1 -1
- package/lib/build/buildTaskEngine.js +10 -9
- package/lib/build/buildTaskFactory.js +0 -45
- package/lib/build/plugins/helm/files/subcharts/content-deployment/Chart.yaml +1 -1
- package/lib/build/plugins/helm/files/subcharts/content-deployment/templates/job.yaml +8 -0
- package/lib/build/plugins/helm/files/subcharts/content-deployment/values.schema.json +87 -0
- package/lib/build/plugins/helm/files/subcharts/content-deployment/values.yaml +29 -1
- package/lib/build/plugins/helm/files/subcharts/service-instance/Chart.yaml +1 -1
- package/lib/build/plugins/helm/files/subcharts/service-instance/templates/serviceinstance.yaml +1 -0
- package/lib/build/plugins/helm/files/subcharts/service-instance/values.yaml +1 -1
- package/lib/build/plugins/helm/files/subcharts/web-application/Chart.yaml +1 -1
- package/lib/build/plugins/helm/files/subcharts/web-application/templates/deployment.yaml +8 -0
- package/lib/build/plugins/helm/files/subcharts/web-application/values.schema.json +87 -0
- package/lib/build/plugins/helm/files/subcharts/web-application/values.yaml +29 -1
- package/lib/build/provider/internalBuildTaskProvider.js +1 -1
- package/lib/build/provider/mtx-extension/index.js +5 -0
- package/lib/deploy/to-hana/hana.js +95 -43
- package/lib/deploy/to-hana/mtaUtil.js +1 -2
- package/lib/env/schema.js +12 -88
- package/lib/import/common.js +23 -15
- package/lib/import/odata.package.json +7 -0
- package/lib/init/constants.js +2 -1
- package/lib/init/index.js +13 -16
- package/lib/init/mvn.js +1 -1
- package/lib/init/plugin.js +1 -1
- package/lib/init/projectReader.js +5 -1
- package/lib/init/template/approuter/files/package.json +1 -4
- package/lib/init/template/attachments/files/package.json.hbs +1 -1
- package/lib/init/template/cloud-logging/files/java-cdsrc.json +5 -0
- package/lib/init/template/cloud-logging/index.js +9 -5
- package/lib/init/template/containerize/files/containerize.yaml.hbs +1 -1
- package/lib/init/template/data/index.js +3 -3
- package/lib/init/template/extension/files/.base/index.cds +15 -0
- package/lib/init/template/extension/files/app/extension.cds.hbs +47 -0
- package/lib/init/template/extension/files/test/data/Authors.csv +4 -0
- package/lib/init/template/extension/files/test/data/my.bookshop-Books.csv +8 -0
- package/lib/init/template/extension/index.js +99 -0
- package/lib/init/template/handler/files/extension/handler.xs.hbs +10 -0
- package/lib/init/template/handler/files/extension/package.json +10 -0
- package/lib/init/template/handler/index.js +83 -20
- package/lib/init/template/http/index.js +3 -3
- package/lib/init/template/java/index.js +3 -3
- package/lib/init/template/mta/index.js +1 -1
- package/lib/init/template/nodejs/index.js +3 -3
- package/lib/init/template/pipeline/index.js +1 -1
- package/lib/init/template/sample/index.js +6 -0
- package/lib/init/template/typer/files/package.json +0 -3
- package/lib/init/template/typer/index.js +2 -2
- package/lib/init/validate.js +4 -7
- package/lib/mtx/pull.js +9 -1
- package/lib/util/question.js +24 -21
- package/npm-shrinkwrap.json +20 -20
- package/package.json +2 -2
- /package/lib/init/template/handler/files/{handler.xs.hbs → standard/handler.xs.hbs} +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -7,14 +7,43 @@ This project adheres to [Semantic Versioning](https://semver.org/).
|
|
|
7
7
|
|
|
8
8
|
The format is based on [Keep a Changelog](https://keepachangelog.com/).
|
|
9
9
|
|
|
10
|
+
## Version 8.9.0 - 2025-03-31
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- `cds import` now adds Cloud SDK dependencies to package.json if an OData service is imported.
|
|
15
|
+
- `cds deploy --to hana --on k8s` is now supported.
|
|
16
|
+
- `cds up` automates freezing dependencies, building, and deploying your application.
|
|
17
|
+
- `cds pull` includes existing extensions if the server is configured accordingly.
|
|
18
|
+
|
|
19
|
+
### Changed
|
|
20
|
+
|
|
21
|
+
- `cds build` logging is simplified.
|
|
22
|
+
- `cds add html5-repo` ignores folders in `app/` starting with `.`
|
|
23
|
+
|
|
24
|
+
### Fixed
|
|
25
|
+
|
|
26
|
+
- `cds add telemetry` is order-independent with other `cds add` commands for Java.
|
|
27
|
+
- Build task `mtx-extension` now fails with exit code 1 in case of build errors.
|
|
28
|
+
|
|
29
|
+
### Removed
|
|
30
|
+
|
|
31
|
+
- Removed `before:cds-watch` script.
|
|
32
|
+
|
|
33
|
+
## Version 8.8.2 - 2025-03-21
|
|
34
|
+
|
|
35
|
+
### Fixed
|
|
36
|
+
|
|
37
|
+
- Bump axios to 1.8.4, fixing CVE-2025-27152
|
|
38
|
+
|
|
10
39
|
## Version 8.8.1 - 2025-03-11
|
|
11
40
|
|
|
12
41
|
### Fixed
|
|
13
42
|
|
|
14
43
|
- `cds init` uses latest Maven Java archetype version 3.8.0 for creating Java projects.
|
|
15
|
-
- `cds import` json schema now contains correct references.
|
|
16
44
|
- `cds init --add lint` writes complete eslint.config.mjs.
|
|
17
45
|
- `cds import` no longer fails with an `EXDEV` error in `docker` containers.
|
|
46
|
+
- `cds import` json schema now contains correct references.
|
|
18
47
|
|
|
19
48
|
## Version 8.8.0 - 2025-03-03
|
|
20
49
|
|
package/bin/deploy/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
module.exports = Object.assign(deploy, {
|
|
2
|
-
options: ['--to', '--for', '--out', '--tunnel-address', '--vcap-file', '--delta-from' ],
|
|
2
|
+
options: ['--to', '--for', '--out', '--on', '--tunnel-address', '--vcap-file', '--delta-from' ],
|
|
3
3
|
flags: ['--no-save', '--auto-undeploy', '--dry', '--xdry', '--with-mocks', '--store-credentials', '--no-build', '--model-only', '--script', '--with-auto-schema-evolution' ],
|
|
4
|
-
shortcuts: ['-2', '-4', '-o'],
|
|
4
|
+
shortcuts: ['-2', '-4', '-o', '-n'],
|
|
5
5
|
help: `
|
|
6
6
|
# SYNOPSIS
|
|
7
7
|
|
|
@@ -46,6 +46,10 @@ module.exports = Object.assign(deploy, {
|
|
|
46
46
|
Write the DDL statements to the given file.
|
|
47
47
|
Not available in combination with '--to hana'.
|
|
48
48
|
|
|
49
|
+
*--on* | *-n* cf|k8s
|
|
50
|
+
|
|
51
|
+
The target platform. Default is 'cf'.
|
|
52
|
+
|
|
49
53
|
*--with-mocks*
|
|
50
54
|
|
|
51
55
|
Also create tables for all entities from imported models.
|
|
@@ -103,7 +107,7 @@ module.exports = Object.assign(deploy, {
|
|
|
103
107
|
|
|
104
108
|
`})
|
|
105
109
|
|
|
106
|
-
async function deploy(_model, options) {
|
|
110
|
+
async function deploy(_model, options) {
|
|
107
111
|
|
|
108
112
|
if (process.stdout.isTTY && options['no-save']) {
|
|
109
113
|
console.warn('Option --no-save is deprecated. By default, package.json will no longer be modified.')
|
package/bin/init.js
CHANGED
|
@@ -7,7 +7,7 @@ cds.root = join(process.cwd(), process.argv[3]?.startsWith('--') ? '.' : process
|
|
|
7
7
|
|
|
8
8
|
module.exports = Object.assign(init, {
|
|
9
9
|
handleCompletion,
|
|
10
|
-
options: ['--add', '--java:mvn', '--java:package', '--lint:custom', '--lint:custom:example', '--no-db'],
|
|
10
|
+
options: ['--add', '--java:mvn', '--java:package', '--lint:custom', '--lint:custom:example', '--no-db', '--base'],
|
|
11
11
|
shortcuts: ['-a'],
|
|
12
12
|
flags: ['--java', '--force', '--verbose'],
|
|
13
13
|
help: `
|
|
@@ -20,10 +20,6 @@ module.exports = Object.assign(init, {
|
|
|
20
20
|
|
|
21
21
|
# OPTIONS
|
|
22
22
|
|
|
23
|
-
*--java*
|
|
24
|
-
|
|
25
|
-
Create a CAP Java project.
|
|
26
|
-
|
|
27
23
|
*--add* <feature | comma-separated list of features>
|
|
28
24
|
|
|
29
25
|
Add one or more features while creating the project.
|
|
@@ -31,6 +27,10 @@ module.exports = Object.assign(init, {
|
|
|
31
27
|
|
|
32
28
|
${require('../lib/init').help()}
|
|
33
29
|
|
|
30
|
+
*--java*
|
|
31
|
+
|
|
32
|
+
Create a CAP Java project.
|
|
33
|
+
|
|
34
34
|
*--java:mvn* <Comma separated maven archetype specific parameters>
|
|
35
35
|
|
|
36
36
|
Add the given parameters to the archetype call.
|
package/bin/repl.js
CHANGED
|
@@ -46,6 +46,7 @@ async function repl (_, options={}) {
|
|
|
46
46
|
inspect.defaultOptions.depth = 11
|
|
47
47
|
|
|
48
48
|
Object.defineProperty (cds,'repl',{value:true})
|
|
49
|
+
await cds.service.bindings
|
|
49
50
|
let context={}, repl = { context, displayPrompt(){} }
|
|
50
51
|
if (options.run) await _run (options.run)
|
|
51
52
|
if (options.use) _export (...options.use.split(','))
|
|
@@ -87,6 +88,9 @@ async function repl (_, options={}) {
|
|
|
87
88
|
process.on('uncaughtException', console.error)
|
|
88
89
|
process.on('unhandledRejection', console.error)
|
|
89
90
|
|
|
91
|
+
// Ugly hack to prevent "[ERR_INVALID_REPL_INPUT]: Listeners for `uncaughtException` cannot be used in the REPL" errors caused by winston when connecting to remote services
|
|
92
|
+
process.on = (event, listener) => event !== 'uncaughtException' && event !== 'unhandledRejection' && process.addListener(event, listener)
|
|
93
|
+
|
|
90
94
|
async function _run (project) {
|
|
91
95
|
await cds.test (project) // await cds.exec ('--project', project, '--port', '0')
|
|
92
96
|
_export ('entities', 'services')
|
package/bin/test.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
const require =
|
|
1
|
+
// Overwrite require to support IntelliSense in VS Code...
|
|
2
|
+
const {resolve} = require, paths = [ process.cwd(), __dirname ]
|
|
3
|
+
require = id => module.require (resolve(id,{paths})) // eslint-disable-line no-global-assign
|
|
3
4
|
|
|
4
|
-
//
|
|
5
|
-
|
|
5
|
+
// FIXME: that check below doesn't work correctly!
|
|
6
|
+
// eslint-disable-next-line cds-dk/no-missing-dependencies
|
|
7
|
+
module.exports = require ('@cap-js/cds-test/bin/chest.js')
|
package/bin/up.js
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
module.exports = Object.assign(up, {
|
|
2
|
+
options: ['--to'],
|
|
3
|
+
shortcuts: ['-2'],
|
|
4
|
+
flags: [],
|
|
5
|
+
help: `
|
|
6
|
+
# SYNOPSIS
|
|
7
|
+
|
|
8
|
+
*cds up*
|
|
9
|
+
|
|
10
|
+
Builds and deploys the application to Cloud Foundry or Kubernetes.
|
|
11
|
+
|
|
12
|
+
# OPTIONS
|
|
13
|
+
|
|
14
|
+
*-2* | *--to* cf|k8s
|
|
15
|
+
|
|
16
|
+
The platform to deploy to. Default is 'cf'.
|
|
17
|
+
|
|
18
|
+
# EXAMPLES
|
|
19
|
+
|
|
20
|
+
*cds up*
|
|
21
|
+
*cds up --to k8s*
|
|
22
|
+
`})
|
|
23
|
+
|
|
24
|
+
const { execSync } = require('node:child_process')
|
|
25
|
+
const cds = require('../lib/cds')
|
|
26
|
+
const { highlight } = require('../lib/util/term')
|
|
27
|
+
const { exists, path: { join } } = cds.utils
|
|
28
|
+
const { readProject } = require('../lib/init/projectReader')
|
|
29
|
+
|
|
30
|
+
const run = cmd => {
|
|
31
|
+
console.log(highlight(cmd))
|
|
32
|
+
try {
|
|
33
|
+
execSync(cmd, { stdio: 'inherit', env: { ...process.env, FORCE_COLOR: cds.utils.colors.enabled }})
|
|
34
|
+
} catch (error) {
|
|
35
|
+
throw error.message
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
async function up() {
|
|
40
|
+
const { apps, appName, hasMultitenancy, hasApprouter, hasXsuaa } = readProject()
|
|
41
|
+
|
|
42
|
+
for (const { app } of apps) {
|
|
43
|
+
const appPath = join(cds.root, cds.env.folders.app, app)
|
|
44
|
+
if (exists(join(appPath, 'package.json')) && !exists(join(appPath, 'package-lock.json'))) {
|
|
45
|
+
run(`npm i --package-lock-only --prefix ${appPath}`)
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
if (hasMultitenancy && !exists('mtx/sidecar/package-lock.json')) {
|
|
50
|
+
run('npm i --package-lock-only --prefix mtx/sidecar')
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
if (cds.cli.options.to === 'k8s') {
|
|
54
|
+
if (!exists('chart')) run('cds add helm')
|
|
55
|
+
if (!exists('containerize.yaml')) run('cds add containerize')
|
|
56
|
+
} else {
|
|
57
|
+
if (!exists('mta.yaml')) {
|
|
58
|
+
run('cds add mta')
|
|
59
|
+
run('npm i --package-lock-only')
|
|
60
|
+
} else if (!exists('package-lock.json')) {
|
|
61
|
+
run('npm i --package-lock-only')
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
if (cds.cli.options.to === 'k8s') {
|
|
66
|
+
run('ctz containerize.yaml --log --push')
|
|
67
|
+
let helmUpgrade = `helm upgrade --install ${appName} ./gen/chart --wait --wait-for-jobs`
|
|
68
|
+
if (hasXsuaa) helmUpgrade += ' --set-file xsuaa.jsonParameters=xs-security.json'
|
|
69
|
+
run(helmUpgrade)
|
|
70
|
+
run(`kubectl rollout status deployment ${appName}-srv --timeout=8m`)
|
|
71
|
+
if (hasApprouter) run(`kubectl rollout status deployment ${appName}-approuter --timeout=8m`)
|
|
72
|
+
if (hasMultitenancy) run(`kubectl rollout status deployment ${appName}-sidecar --timeout=8m`)
|
|
73
|
+
} else {
|
|
74
|
+
run('mbt build -t gen --mtar mta.tar')
|
|
75
|
+
run('cf deploy gen/mta.tar -f')
|
|
76
|
+
}
|
|
77
|
+
}
|
package/bin/watch.js
CHANGED
|
@@ -1,6 +1,3 @@
|
|
|
1
|
-
const path = require('node:path')
|
|
2
|
-
const { execSync } = require('node:child_process')
|
|
3
|
-
|
|
4
1
|
const watchOnlyOptions = ['--ext', '--livereload', '--open', '--debug', '--inspect', '--inspect-brk', '--include', '--exclude']
|
|
5
2
|
|
|
6
3
|
module.exports = Object.assign ( watch, {
|
|
@@ -174,8 +171,6 @@ async function watch ([cwd], {
|
|
|
174
171
|
const { bindingEnv, updateBindings } = require('../lib/bind/shared')
|
|
175
172
|
Object.assign(env, await bindingEnv({cwd}))
|
|
176
173
|
|
|
177
|
-
runBeforeScript('watch', {cwd})
|
|
178
|
-
|
|
179
174
|
const nodemon = require('../lib/watch/node-watch')
|
|
180
175
|
const watcher = nodemon ({
|
|
181
176
|
script: resolve(__dirname,'../lib/watch/watched'), cwd, env, ext, ignore, watched,
|
|
@@ -251,41 +246,3 @@ function installed(id, ...paths) {
|
|
|
251
246
|
try { return require.resolve (id, { paths }) }
|
|
252
247
|
catch(e) { if (e.code !== 'MODULE_NOT_FOUND') throw e }
|
|
253
248
|
}
|
|
254
|
-
|
|
255
|
-
/**
|
|
256
|
-
* Runs a before-script for the given task.
|
|
257
|
-
* For now, this will only be used for cds watch,
|
|
258
|
-
* but could be used for other tasks in the future,
|
|
259
|
-
* therefore the generic name/ implementation.
|
|
260
|
-
* @param {string} task - The task to run the before-script for.
|
|
261
|
-
* @param {object} options - Options object containing the cwd.
|
|
262
|
-
* @param {[string]} options.cwd - The current working directory.
|
|
263
|
-
*/
|
|
264
|
-
function runBeforeScript(task, {cwd}) {
|
|
265
|
-
cwd ??= '.'
|
|
266
|
-
try {
|
|
267
|
-
const packageJson = getPackageJson(cwd)
|
|
268
|
-
const beforeScript = `before:cds-${task}`
|
|
269
|
-
if (packageJson.scripts?.[beforeScript]) {
|
|
270
|
-
DEBUG(`running before-script '${beforeScript}' for cds ${task}`)
|
|
271
|
-
const cmd = `npm run ${beforeScript} --prefix "${cwd}"`
|
|
272
|
-
execSync(cmd)
|
|
273
|
-
}
|
|
274
|
-
} catch (e) {
|
|
275
|
-
// ignore not finding package.json (happens during cds init)
|
|
276
|
-
if (!(e.code === 'MODULE_NOT_FOUND' && e.message.includes('package.json'))) throw e
|
|
277
|
-
}
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
/**
|
|
281
|
-
* @param {string} project - The project to get the package.json from.
|
|
282
|
-
* @returns {JSON} The package.json of the given project.
|
|
283
|
-
*/
|
|
284
|
-
function getPackageJson (project) {
|
|
285
|
-
try {
|
|
286
|
-
return require(path.join(project, 'package.json'))
|
|
287
|
-
} catch (e) {
|
|
288
|
-
if (e.code !== 'MODULE_NOT_FOUND') throw e
|
|
289
|
-
return require(path.join(cds.root, project, 'package.json'))
|
|
290
|
-
}
|
|
291
|
-
}
|
package/lib/bind/shared.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
const fs = require('fs')
|
|
2
|
-
const path = require('path')
|
|
1
|
+
const fs = require('node:fs')
|
|
2
|
+
const path = require('node:path')
|
|
3
|
+
const { inspect } = require('node:util')
|
|
3
4
|
const cds = require('../cds'), { _log: log } = cds
|
|
4
5
|
const { sortMessagesSeverityAware, deduplicateMessages, CompilationError } = cds.compiler
|
|
5
6
|
const { relativePaths, BuildError, BuildMessage, resolveRequiredSapModels, redactCredentials } = require('./util')
|
|
@@ -25,17 +26,17 @@ class BuildTaskEngine {
|
|
|
25
26
|
async processTasks(tasks) {
|
|
26
27
|
const startTime = Date.now()
|
|
27
28
|
|
|
28
|
-
|
|
29
|
+
tasks ??= await this.taskFactory.getTasks()
|
|
30
|
+
console.log(`building project with`, inspect({
|
|
31
|
+
versions: { cds: cds.version, compiler: cds.compiler.version(), dk: require('../../package.json').version },
|
|
32
|
+
target: cds.env.build.target,
|
|
33
|
+
tasks: tasks.map(({ _uses, ...task }) => task),
|
|
34
|
+
...(!this.options.clean && { clean: this.options.clean }),
|
|
35
|
+
}, { depth: 11, colors: cds.utils.colors.enabled, compact: 3, breakLength: 250 }))
|
|
29
36
|
|
|
30
37
|
DEBUG?.("cds configuration settings:")
|
|
31
38
|
DEBUG?.(redactCredentials(cds.env))
|
|
32
39
|
|
|
33
|
-
console.log(`cds-dk [${require('../../package.json').version}], cds [${cds.version}], compiler [${cds.compiler.version()}], home [${cds.home}]\n`)
|
|
34
|
-
|
|
35
|
-
if (!tasks) {
|
|
36
|
-
tasks = await this.taskFactory.getTasks()
|
|
37
|
-
}
|
|
38
|
-
|
|
39
40
|
// validate required @sap namespace models - log only
|
|
40
41
|
const unresolved = BuildTaskEngine._resolveRequiredSapServices(tasks)
|
|
41
42
|
if (unresolved.length > 0) {
|
|
@@ -4,7 +4,6 @@ const cds = require('../cds')
|
|
|
4
4
|
const BuildTaskProviderFactory = require('./buildTaskProviderFactory')
|
|
5
5
|
const { hasJavaNature, getProperty, getDefaultModelOptions, hasOptionValue, BuildError } = require('./util')
|
|
6
6
|
const { FILE_EXT_CDS, OPTION_WS, IGNORE_DEFAULT_MODELS, NODEJS_MODEL_EXCLUDE_LIST, BUILD_TASK_NODEJS, BUILD_TASK_NODE_CF } = require("./constants")
|
|
7
|
-
const term = require('../util/term')
|
|
8
7
|
const DEBUG = cds.debug('cli|build')
|
|
9
8
|
|
|
10
9
|
class BuildTaskFactory {
|
|
@@ -24,15 +23,6 @@ class BuildTaskFactory {
|
|
|
24
23
|
// 3. create from cds.env.folders config data
|
|
25
24
|
async getTasks() {
|
|
26
25
|
const tasks = await this._createTasks()
|
|
27
|
-
|
|
28
|
-
// log build tasks
|
|
29
|
-
let tasksOutput = "{\n build: {\n target: " + term.info("'" + cds.env.build.target + "'") + ",\n tasks: [\n"
|
|
30
|
-
for (let i = 0; i < tasks.length; i++) {
|
|
31
|
-
tasksOutput += " " + BuildTaskFactory._stringifyTask(tasks[i]) + (i + 1 < tasks.length ? ",\n" : "\n")
|
|
32
|
-
}
|
|
33
|
-
tasksOutput += " ]\n }\n}\n"
|
|
34
|
-
console.log(tasksOutput)
|
|
35
|
-
|
|
36
26
|
// always resolve tasks for input validation
|
|
37
27
|
const resolvedTasks = this.providerFactory.resolveTasks(tasks)
|
|
38
28
|
if (this.options.resolve) {
|
|
@@ -207,41 +197,6 @@ class BuildTaskFactory {
|
|
|
207
197
|
task.options.model = [...new Set(taskModelPaths?.length ? taskModelPaths.concat(modelPaths) : modelPaths)]
|
|
208
198
|
}
|
|
209
199
|
|
|
210
|
-
static _stringifyTask(task) {
|
|
211
|
-
// ensures identical order of properties
|
|
212
|
-
const order = ["for", "use", "src", "dest", "options"]
|
|
213
|
-
const keys = Object.keys(task).filter(key => order.includes(key)).sort((a, b) => order.indexOf(a) - order.indexOf(b))
|
|
214
|
-
|
|
215
|
-
return keys.reduce((acc, key, i) => {
|
|
216
|
-
const prefix = acc !== '{' ? ', ' : (i === 0 ? ' ' : '')
|
|
217
|
-
if (!key.startsWith('_')) {
|
|
218
|
-
// render either "for" OR "use" value
|
|
219
|
-
if (key in { src: 1, for: 1 } || (!task.for && key === 'use')) {
|
|
220
|
-
return `${acc}${prefix}${key}: ${term.info(`'${task[key]}'`)}`
|
|
221
|
-
} else if (key === 'options') {
|
|
222
|
-
const options = Object.entries(task.options)
|
|
223
|
-
.map(([key, value]) => {
|
|
224
|
-
if (Array.isArray(value)) {
|
|
225
|
-
return `${key}: [${value.map(v => term.info(`'${v}'`)).join(', ')}]`
|
|
226
|
-
} else if (typeof value === 'object') {
|
|
227
|
-
const nested = Object.entries(value)
|
|
228
|
-
.map(([key, value]) => `${key}: ${term.info(`'${value}'`)}`)
|
|
229
|
-
.join(', ')
|
|
230
|
-
return `${key}: { ${nested} }`
|
|
231
|
-
} else {
|
|
232
|
-
return `${key}: ${term.info(`'${value}'`)}`
|
|
233
|
-
}
|
|
234
|
-
})
|
|
235
|
-
.join(', ')
|
|
236
|
-
return `${acc}${prefix}${key}: { ${options} }`
|
|
237
|
-
} else if (key !== 'use') {
|
|
238
|
-
return `${acc}${prefix}${key}: ${term.info(`'${task[key]}'`)}`
|
|
239
|
-
}
|
|
240
|
-
}
|
|
241
|
-
return acc
|
|
242
|
-
}, '{') + '}'
|
|
243
|
-
}
|
|
244
|
-
|
|
245
200
|
/**
|
|
246
201
|
* Determines the module folder from the past list that may represent files or folders w or w/o .cds file extension.
|
|
247
202
|
* @param {Array} filesOrFolders
|
|
@@ -71,6 +71,14 @@ spec:
|
|
|
71
71
|
name: tmp
|
|
72
72
|
{{- include "content-deployment.internal.serviceMounts" . | nindent 8 }}
|
|
73
73
|
restartPolicy: OnFailure
|
|
74
|
+
{{- if .Values.nodeSelector }}
|
|
75
|
+
nodeSelector:
|
|
76
|
+
{{- .Values.nodeSelector | toYaml | nindent 8 }}
|
|
77
|
+
{{- end }}
|
|
78
|
+
{{- if .Values.nodeAffinity }}
|
|
79
|
+
affinity:
|
|
80
|
+
{{- .Values.nodeAffinity | toYaml | nindent 8 }}
|
|
81
|
+
{{- end }}
|
|
74
82
|
volumes:
|
|
75
83
|
- name: tmp
|
|
76
84
|
emptyDir: {}
|
|
@@ -496,6 +496,56 @@
|
|
|
496
496
|
}
|
|
497
497
|
}
|
|
498
498
|
}
|
|
499
|
+
},
|
|
500
|
+
"nodeSelector": {
|
|
501
|
+
"$id": "#/properties/nodeSelector",
|
|
502
|
+
"title": "Node selector",
|
|
503
|
+
"type": "object",
|
|
504
|
+
"patternProperties": {
|
|
505
|
+
"^[-._a-zA-Z][-._a-zA-Z0-9]*$": {
|
|
506
|
+
"type": "string"
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
},
|
|
510
|
+
"nodeAffinity": {
|
|
511
|
+
"$id": "#/properties/nodeAffinity",
|
|
512
|
+
"title": "Node affinity",
|
|
513
|
+
"type": "object",
|
|
514
|
+
"additionalProperties": false,
|
|
515
|
+
"properties": {
|
|
516
|
+
"requiredDuringSchedulingIgnoredDuringExecution": {
|
|
517
|
+
"type": "object",
|
|
518
|
+
"additionalProperties": false,
|
|
519
|
+
"properties": {
|
|
520
|
+
"nodeSelectorTerms": {
|
|
521
|
+
"type": "array",
|
|
522
|
+
"description": "A node selector terms, associated with the corresponding weight.",
|
|
523
|
+
"items": {
|
|
524
|
+
"$ref": "#/definitions/NodeSelectorTerm"
|
|
525
|
+
}
|
|
526
|
+
}
|
|
527
|
+
},
|
|
528
|
+
"required": ["nodeSelectorTerms"]
|
|
529
|
+
},
|
|
530
|
+
"preferredDuringSchedulingIgnoredDuringExecution": {
|
|
531
|
+
"type": "array",
|
|
532
|
+
"items": {
|
|
533
|
+
"type": "object",
|
|
534
|
+
"additionalProperties": false,
|
|
535
|
+
"properties": {
|
|
536
|
+
"weight": {
|
|
537
|
+
"type": "integer",
|
|
538
|
+
"description": "Weight associated with matching the corresponding nodeSelectorTerm, in the range 1-100."
|
|
539
|
+
},
|
|
540
|
+
"preference": {
|
|
541
|
+
"description": "A node selector term, associated with the corresponding weight.",
|
|
542
|
+
"$ref": "#/definitions/NodeSelectorTerm"
|
|
543
|
+
}
|
|
544
|
+
},
|
|
545
|
+
"required": ["weight", "preference"]
|
|
546
|
+
}
|
|
547
|
+
}
|
|
548
|
+
}
|
|
499
549
|
}
|
|
500
550
|
},
|
|
501
551
|
"definitions": {
|
|
@@ -519,6 +569,43 @@
|
|
|
519
569
|
"title": "ImagePullPolicy",
|
|
520
570
|
"type": "string",
|
|
521
571
|
"enum": ["Always", "IfNotPresent", "Never"]
|
|
572
|
+
},
|
|
573
|
+
"NodeSelectorRequirement": {
|
|
574
|
+
"description": "A node selector requirement is a selector that contains values, a key, and an operator that relates the key and values.",
|
|
575
|
+
"type": "object",
|
|
576
|
+
"additionalProperties": false,
|
|
577
|
+
"properties": {
|
|
578
|
+
"key": {
|
|
579
|
+
"description": "The label key that the selector applies to.",
|
|
580
|
+
"type": "string"
|
|
581
|
+
},
|
|
582
|
+
"operator": {
|
|
583
|
+
"description": "Represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt.",
|
|
584
|
+
"type": "string",
|
|
585
|
+
"enum": ["In", "NotIn", "Exists", "DoesNotExist", "Gt", "Lt"]
|
|
586
|
+
},
|
|
587
|
+
"values": {
|
|
588
|
+
"description": "An array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. If the operator is Gt or Lt, the values array must have a single element, which will be interpreted as an integer. This array is replaced during a strategic merge patch.",
|
|
589
|
+
"items": {
|
|
590
|
+
"type": "string"
|
|
591
|
+
},
|
|
592
|
+
"type": "array"
|
|
593
|
+
}
|
|
594
|
+
},
|
|
595
|
+
"required": ["key", "operator"]
|
|
596
|
+
},
|
|
597
|
+
"NodeSelectorTerm": {
|
|
598
|
+
"description": "A null or empty node selector term matches no objects. The requirements of them are ANDed.",
|
|
599
|
+
"type": "object",
|
|
600
|
+
"additionalProperties": false,
|
|
601
|
+
"properties": {
|
|
602
|
+
"matchExpressions": {
|
|
603
|
+
"type": "array",
|
|
604
|
+
"items": {
|
|
605
|
+
"$ref": "#/definitions/NodeSelectorRequirement"
|
|
606
|
+
}
|
|
607
|
+
}
|
|
608
|
+
}
|
|
522
609
|
}
|
|
523
610
|
}
|
|
524
611
|
}
|
|
@@ -14,7 +14,7 @@ global:
|
|
|
14
14
|
_internal:
|
|
15
15
|
content-deployment:
|
|
16
16
|
versions:
|
|
17
|
-
1.
|
|
17
|
+
1.8.0: true
|
|
18
18
|
# Will be used instead of the `.Chart.Name`, e.g. when generating the Deployment name.
|
|
19
19
|
# nameOverride: name
|
|
20
20
|
|
|
@@ -97,3 +97,31 @@ ttlDaysAfterFinished: 14
|
|
|
97
97
|
annotations:
|
|
98
98
|
## Annotations to add to the Job and underlying Pods
|
|
99
99
|
job: {}
|
|
100
|
+
## Node label selector. See https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#nodeselector
|
|
101
|
+
# nodeSelector:
|
|
102
|
+
# kubernetes.io/os: linux
|
|
103
|
+
|
|
104
|
+
## Node Affinity configuration. See https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#affinity-and-anti-affinity
|
|
105
|
+
# nodeAffinity:
|
|
106
|
+
# requiredDuringSchedulingIgnoredDuringExecution:
|
|
107
|
+
# nodeSelectorTerms:
|
|
108
|
+
# - matchExpressions:
|
|
109
|
+
# - key: kubernetes.io/os
|
|
110
|
+
# operator: In
|
|
111
|
+
# values:
|
|
112
|
+
# - linux
|
|
113
|
+
# preferredDuringSchedulingIgnoredDuringExecution:
|
|
114
|
+
# - weight: 1
|
|
115
|
+
# preference:
|
|
116
|
+
# matchExpressions:
|
|
117
|
+
# - key: label-1
|
|
118
|
+
# operator: In
|
|
119
|
+
# values:
|
|
120
|
+
# - key-1
|
|
121
|
+
# - weight: 50
|
|
122
|
+
# preference:
|
|
123
|
+
# matchExpressions:
|
|
124
|
+
# - key: label-2
|
|
125
|
+
# operator: In
|
|
126
|
+
# values:
|
|
127
|
+
# - key-2
|
|
@@ -167,6 +167,14 @@ spec:
|
|
|
167
167
|
{{- end }}
|
|
168
168
|
restartPolicy: Always
|
|
169
169
|
terminationGracePeriodSeconds: {{ .Values.terminationGracePeriodSeconds }}
|
|
170
|
+
{{- if .Values.nodeSelector }}
|
|
171
|
+
nodeSelector:
|
|
172
|
+
{{- .Values.nodeSelector | toYaml | nindent 8 }}
|
|
173
|
+
{{- end }}
|
|
174
|
+
{{- if .Values.nodeAffinity }}
|
|
175
|
+
affinity:
|
|
176
|
+
{{- .Values.nodeAffinity | toYaml | nindent 8 }}
|
|
177
|
+
{{- end }}
|
|
170
178
|
topologySpreadConstraints:
|
|
171
179
|
{{- range $constraint := .Values.availability.topologySpreadConstraints }}
|
|
172
180
|
- labelSelector:
|