@toa.io/operations 0.2.0-dev.2 → 0.2.1-dev.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/package.json +5 -3
- package/src/deployment/.deployment/.describe/components.js +19 -0
- package/src/deployment/.deployment/.describe/dependencies.js +18 -0
- package/src/deployment/.deployment/.describe/index.js +9 -0
- package/src/deployment/.deployment/.describe/variables.js +27 -0
- package/src/deployment/.deployment/declare.js +29 -0
- package/src/deployment/.deployment/describe.js +28 -0
- package/src/deployment/.deployment/index.js +9 -0
- package/src/deployment/.deployment/merge.js +42 -0
- package/src/deployment/chart/Chart.yaml +7 -0
- package/src/deployment/chart/templates/components.yaml +16 -0
- package/src/deployment/chart/templates/compositions.yaml +38 -0
- package/src/deployment/chart/templates/proxies.yaml +10 -0
- package/src/deployment/chart/templates/services.yaml +63 -0
- package/src/deployment/chart/templates/variables.yaml +12 -0
- package/src/deployment/chart/values.yaml +47 -0
- package/src/deployment/composition.js +30 -0
- package/src/deployment/deployment.js +82 -0
- package/src/deployment/factory.js +100 -0
- package/src/deployment/images/composition.Dockerfile +14 -0
- package/src/deployment/images/composition.js +50 -0
- package/src/deployment/images/factory.js +39 -0
- package/src/deployment/images/image.js +91 -0
- package/src/deployment/images/index.js +7 -0
- package/src/deployment/images/registry.js +102 -0
- package/src/deployment/images/service.Dockerfile +12 -0
- package/src/deployment/images/service.js +70 -0
- package/src/deployment/index.js +5 -0
- package/src/deployment/operator.js +85 -0
- package/src/deployment/service.js +25 -0
- package/src/index.js +1 -5
- package/src/process.js +25 -0
- package/test/deployment/deployment.fixtures.js +18 -0
- package/test/deployment/deployment.test.js +41 -0
- package/test/deployment/images/image.fixtures.js +33 -0
- package/test/deployment/images/image.test.js +25 -0
- package/types/deployment/composition.d.ts +13 -0
- package/types/deployment/dependency.d.ts +77 -0
- package/types/deployment/deployment.d.ts +67 -0
- package/types/deployment/factory.d.ts +12 -0
- package/types/deployment/images/factory.d.ts +17 -0
- package/types/deployment/images/image.d.ts +14 -0
- package/types/deployment/images/registry.d.ts +20 -0
- package/types/deployment/index.d.ts +1 -0
- package/types/deployment/operator.d.ts +21 -0
- package/types/deployment/service.d.ts +20 -0
- package/types/process.d.ts +13 -0
- package/LICENSE +0 -22
- package/src/deployment/chart.js +0 -15
- package/src/deployment/dependencies.js +0 -25
- package/src/deployment/directory.js +0 -21
- package/src/deployment/values.js +0 -7
- package/src/deployment.js +0 -64
- package/src/images/Dockerfile +0 -10
- package/src/images/image.js +0 -38
- package/src/images.js +0 -26
- package/test/deployment.fixtures.js +0 -34
- package/test/deployment.test.js +0 -88
- package/test/image.fixtures.js +0 -24
- package/test/image.test.js +0 -45
- package/test/images.fixtures.js +0 -29
- package/test/images.test.js +0 -35
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const { Composition } = require('./composition')
|
|
4
|
+
const { Service } = require('./service')
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* @implements {toa.deployment.images.Factory}
|
|
8
|
+
*/
|
|
9
|
+
class Factory {
|
|
10
|
+
/** @type {string} */
|
|
11
|
+
#scope
|
|
12
|
+
/** @type {toa.norm.context.Runtime} */
|
|
13
|
+
#runtime
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* @param scope {string}
|
|
17
|
+
* @param runtime {toa.norm.context.Runtime}
|
|
18
|
+
*/
|
|
19
|
+
constructor (scope, runtime) {
|
|
20
|
+
this.#scope = scope
|
|
21
|
+
this.#runtime = runtime
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* @returns {Composition}
|
|
26
|
+
*/
|
|
27
|
+
composition (composition) {
|
|
28
|
+
return new Composition(this.#scope, this.#runtime, composition)
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* @returns {Service}
|
|
33
|
+
*/
|
|
34
|
+
service (path, service) {
|
|
35
|
+
return new Service(this.#scope, this.#runtime, path, service)
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
exports.Factory = Factory
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const { join, posix } = require('node:path')
|
|
4
|
+
const { readFile: read, writeFile: write } = require('node:fs/promises')
|
|
5
|
+
|
|
6
|
+
const { hash } = require('@toa.io/generic')
|
|
7
|
+
const { directory } = require('@toa.io/filesystem')
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* @implements {toa.deployment.images.Image}
|
|
11
|
+
* @abstract
|
|
12
|
+
*/
|
|
13
|
+
class Image {
|
|
14
|
+
context
|
|
15
|
+
reference
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* @protected
|
|
19
|
+
* @type {string}
|
|
20
|
+
*/
|
|
21
|
+
dockerfile
|
|
22
|
+
|
|
23
|
+
/** @type {string} */
|
|
24
|
+
#scope
|
|
25
|
+
/** @type {toa.norm.context.Runtime} */
|
|
26
|
+
#runtime
|
|
27
|
+
/** @type {string} */
|
|
28
|
+
#type
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* @param scope {string}
|
|
32
|
+
* @param runtime {toa.norm.context.Runtime}
|
|
33
|
+
*/
|
|
34
|
+
constructor (scope, runtime) {
|
|
35
|
+
this.#scope = scope
|
|
36
|
+
this.#runtime = runtime
|
|
37
|
+
this.#type = this.constructor.name.toLowerCase()
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* @abstract
|
|
42
|
+
* @protected
|
|
43
|
+
* @type {string}
|
|
44
|
+
*/
|
|
45
|
+
get name () {}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* @abstract
|
|
49
|
+
* @protected
|
|
50
|
+
* @type {string}
|
|
51
|
+
*/
|
|
52
|
+
get version () {}
|
|
53
|
+
|
|
54
|
+
tag (base) {
|
|
55
|
+
const tag = hash(this.#runtime.version + ';' + this.version)
|
|
56
|
+
|
|
57
|
+
this.reference = posix.join(base, `${this.#scope}/${this.#type}-${this.name}:${tag}`)
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
async prepare (root) {
|
|
61
|
+
if (this.dockerfile === undefined) throw new Error('Dockerfile isn\'t specified')
|
|
62
|
+
|
|
63
|
+
const path = join(root, `${this.#type}-${this.name}.${this.version}`)
|
|
64
|
+
|
|
65
|
+
await directory.ensure(path)
|
|
66
|
+
|
|
67
|
+
const template = await read(this.dockerfile, 'utf-8')
|
|
68
|
+
const contents = template.replace(/{{(\.?\w+)}}/g, (_, key) => this.#value(key))
|
|
69
|
+
const ignore = 'Dockerfile'
|
|
70
|
+
|
|
71
|
+
await write(join(path, 'Dockerfile'), contents)
|
|
72
|
+
await write(join(path, '.dockerignore'), ignore)
|
|
73
|
+
|
|
74
|
+
this.context = path
|
|
75
|
+
|
|
76
|
+
return path
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* @param key {string}
|
|
81
|
+
* @returns {string}
|
|
82
|
+
*/
|
|
83
|
+
#value (key) {
|
|
84
|
+
const [, property] = key.split('.')
|
|
85
|
+
|
|
86
|
+
if (property !== undefined) return this[property]
|
|
87
|
+
else return this.#runtime[key]
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
exports.Image = Image
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const { directory: { remove } } = require('@toa.io/filesystem')
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @implements {toa.deployment.images.Registry}
|
|
7
|
+
*/
|
|
8
|
+
class Registry {
|
|
9
|
+
/** @type {toa.norm.context.Registry} */
|
|
10
|
+
#registry
|
|
11
|
+
/** @type {toa.deployment.images.Factory} */
|
|
12
|
+
#factory
|
|
13
|
+
/** @type {toa.operations.Process} */
|
|
14
|
+
#process
|
|
15
|
+
/** @type {Array<toa.deployment.images.Image>} */
|
|
16
|
+
#images = []
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* @param {toa.norm.context.Registry} registry
|
|
20
|
+
* @param {toa.deployment.images.Factory} factory
|
|
21
|
+
* @param {toa.operations.Process} process
|
|
22
|
+
*/
|
|
23
|
+
constructor (registry, factory, process) {
|
|
24
|
+
this.#registry = registry
|
|
25
|
+
this.#factory = factory
|
|
26
|
+
this.#process = process
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
composition (composition) {
|
|
30
|
+
return this.#create('composition', composition)
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
service (path, service) {
|
|
34
|
+
return this.#create('service', path, service)
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
async prepare (target) {
|
|
38
|
+
await Promise.all(this.#images.map((image) => image.prepare(target)))
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
async push () {
|
|
42
|
+
for (const image of this.#images) {
|
|
43
|
+
await this.#push(image)
|
|
44
|
+
await remove(image.context)
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* @param {"composition" | "service"} type
|
|
50
|
+
* @param {...any} args
|
|
51
|
+
* @returns {toa.deployment.images.Image}
|
|
52
|
+
*/
|
|
53
|
+
#create (type, ...args) {
|
|
54
|
+
const image = this.#factory[type](...args)
|
|
55
|
+
|
|
56
|
+
image.tag(this.#registry.base)
|
|
57
|
+
this.#images.push(image)
|
|
58
|
+
|
|
59
|
+
return image
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* @param {toa.deployment.images.Image} image
|
|
64
|
+
* @returns {Promise<void>}
|
|
65
|
+
*/
|
|
66
|
+
async #push (image) {
|
|
67
|
+
const args = ['buildx', 'build', '--push', '--tag', image.reference, image.context]
|
|
68
|
+
const local = this.#registry.platforms === null
|
|
69
|
+
|
|
70
|
+
if (local) {
|
|
71
|
+
args.push('--builder', 'default')
|
|
72
|
+
} else {
|
|
73
|
+
const platform = this.#registry.platforms.join(',')
|
|
74
|
+
|
|
75
|
+
args.push('--platform', platform)
|
|
76
|
+
args.push('--builder', BUILDER)
|
|
77
|
+
|
|
78
|
+
await this.#builder()
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
await this.#process.execute('docker', args)
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
async #builder () {
|
|
85
|
+
const ls = 'buildx ls'.split(' ')
|
|
86
|
+
const output = await this.#process.execute('docker', ls, { silently: true })
|
|
87
|
+
|
|
88
|
+
const exists = output.split('\n').find((line) => line.startsWith('toa '))
|
|
89
|
+
|
|
90
|
+
if (exists === undefined) {
|
|
91
|
+
const create = `buildx create --name ${BUILDER} --use`.split(' ')
|
|
92
|
+
const bootstrap = 'buildx inspect --bootstrap'.split(' ')
|
|
93
|
+
|
|
94
|
+
await this.#process.execute('docker', create)
|
|
95
|
+
await this.#process.execute('docker', bootstrap)
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
const BUILDER = 'toa'
|
|
101
|
+
|
|
102
|
+
exports.Registry = Registry
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const { join, dirname } = require('node:path')
|
|
4
|
+
|
|
5
|
+
const { Image } = require('./image')
|
|
6
|
+
const { directory: { copy } } = require('@toa.io/filesystem')
|
|
7
|
+
|
|
8
|
+
class Service extends Image {
|
|
9
|
+
dockerfile = join(__dirname, 'service.Dockerfile')
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Used by Dockerfile
|
|
13
|
+
*
|
|
14
|
+
* @readonly
|
|
15
|
+
* @type {string}
|
|
16
|
+
* */
|
|
17
|
+
service
|
|
18
|
+
|
|
19
|
+
/** @type {string} */
|
|
20
|
+
#group
|
|
21
|
+
/** @type {string} */
|
|
22
|
+
#name
|
|
23
|
+
/** @type {string} */
|
|
24
|
+
#path
|
|
25
|
+
/** @type {string} */
|
|
26
|
+
#version
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* @param {string} scope
|
|
30
|
+
* @param {toa.norm.context.Runtime} runtime
|
|
31
|
+
* @param {string} reference
|
|
32
|
+
* @param {toa.deployment.dependency.Service} service
|
|
33
|
+
*/
|
|
34
|
+
constructor (scope, runtime, reference, service) {
|
|
35
|
+
super(scope, runtime)
|
|
36
|
+
|
|
37
|
+
this.service = service.name
|
|
38
|
+
|
|
39
|
+
this.#group = service.group
|
|
40
|
+
this.#name = service.name
|
|
41
|
+
this.#path = find(reference)
|
|
42
|
+
this.#version = service.version
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
get name () {
|
|
46
|
+
return this.#group + '-' + this.#name
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
get version () {
|
|
50
|
+
return this.#version
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
async prepare (root) {
|
|
54
|
+
const context = await super.prepare(root)
|
|
55
|
+
|
|
56
|
+
await copy(this.#path, context)
|
|
57
|
+
|
|
58
|
+
return context
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* @param {string} reference
|
|
64
|
+
* @returns {string}
|
|
65
|
+
*/
|
|
66
|
+
const find = (reference) => {
|
|
67
|
+
return dirname(require.resolve(join(reference, 'package.json')))
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
exports.Service = Service
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const { directory } = require('@toa.io/filesystem')
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @implements {toa.deployment.Operator}
|
|
7
|
+
*/
|
|
8
|
+
class Operator {
|
|
9
|
+
/** @type {toa.deployment.Deployment} */
|
|
10
|
+
#deployment
|
|
11
|
+
/** @type {toa.deployment.images.Registry} */
|
|
12
|
+
#registry
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* @param deployment {toa.deployment.Deployment}
|
|
16
|
+
* @param registry {toa.deployment.images.Registry}
|
|
17
|
+
*/
|
|
18
|
+
constructor (deployment, registry) {
|
|
19
|
+
this.#deployment = deployment
|
|
20
|
+
this.#registry = registry
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
async export (path) {
|
|
24
|
+
const target = await Operator.#target('deployment', path)
|
|
25
|
+
|
|
26
|
+
await this.#deployment.export(target)
|
|
27
|
+
|
|
28
|
+
return target
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
async prepare (path) {
|
|
32
|
+
const target = await Operator.#target('images', path)
|
|
33
|
+
|
|
34
|
+
await this.#registry.prepare(target)
|
|
35
|
+
|
|
36
|
+
return target
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
async build () {
|
|
40
|
+
const target = await Operator.#target('images')
|
|
41
|
+
|
|
42
|
+
await this.#registry.prepare(target)
|
|
43
|
+
await this.#registry.push()
|
|
44
|
+
|
|
45
|
+
await directory.remove(target)
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
async install (options = {}) {
|
|
49
|
+
options = Object.assign({}, OPTIONS, options)
|
|
50
|
+
|
|
51
|
+
const [source] = await Promise.all([this.export(), this.build()])
|
|
52
|
+
|
|
53
|
+
await this.#deployment.install(options)
|
|
54
|
+
|
|
55
|
+
await directory.remove(source)
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
async template (options = {}) {
|
|
59
|
+
const source = await this.export()
|
|
60
|
+
const output = await this.#deployment.template(options)
|
|
61
|
+
|
|
62
|
+
await directory.remove(source)
|
|
63
|
+
|
|
64
|
+
return output
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* @param type {string}
|
|
69
|
+
* @param [path] {string}
|
|
70
|
+
* @returns {Promise<string>}
|
|
71
|
+
*/
|
|
72
|
+
static async #target (type, path) {
|
|
73
|
+
if (path === undefined) path = await directory.temp('toa-' + type)
|
|
74
|
+
else path = await directory.ensure(path)
|
|
75
|
+
|
|
76
|
+
return path
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/** @type {toa.deployment.installation.Options} */
|
|
81
|
+
const OPTIONS = {
|
|
82
|
+
wait: false
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
exports.Operator = Operator
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
// noinspection JSClosureCompilerSyntax
|
|
4
|
+
/**
|
|
5
|
+
* @implements {toa.deployment.Service}
|
|
6
|
+
*/
|
|
7
|
+
class Service {
|
|
8
|
+
name
|
|
9
|
+
image
|
|
10
|
+
port
|
|
11
|
+
ingress
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* @param service {toa.deployment.dependency.Service}
|
|
15
|
+
* @param image {toa.deployment.images.Image}
|
|
16
|
+
*/
|
|
17
|
+
constructor (service, image) {
|
|
18
|
+
this.name = service.group + '-' + service.name
|
|
19
|
+
this.port = service.port
|
|
20
|
+
this.image = image.reference
|
|
21
|
+
this.ingress = service.ingress
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
exports.Service = Service
|
package/src/index.js
CHANGED
package/src/process.js
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const execa = require('execa')
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @implements {toa.operations.Process}
|
|
7
|
+
*/
|
|
8
|
+
class Process {
|
|
9
|
+
async execute (cmd, args, options = {}) {
|
|
10
|
+
/** @type {execa.ExecaReturnValue<import('stream').Stream>} */
|
|
11
|
+
const command = execa(cmd, args)
|
|
12
|
+
|
|
13
|
+
if (options.silently !== true) {
|
|
14
|
+
command.stdout.pipe(process.stdout)
|
|
15
|
+
command.stderr.pipe(process.stderr)
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/** @type {execa.ExecaReturnValue<string>} */
|
|
19
|
+
const result = await command
|
|
20
|
+
|
|
21
|
+
return result.stdout
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
exports.Process = Process
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const { generate } = require('randomstring')
|
|
4
|
+
|
|
5
|
+
const context = /** @type {toa.norm.Context} */ { name: generate() }
|
|
6
|
+
const compositions = []
|
|
7
|
+
const dependencies = []
|
|
8
|
+
const process = /** @type {toa.operations.Process} */ { execute: jest.fn() }
|
|
9
|
+
const options = /** @type {toa.deployment.installation.Options} */ {
|
|
10
|
+
namespace: generate(),
|
|
11
|
+
target: generate()
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
exports.context = context
|
|
15
|
+
exports.compositions = compositions
|
|
16
|
+
exports.dependencies = dependencies
|
|
17
|
+
exports.process = process
|
|
18
|
+
exports.options = options
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const clone = require('clone-deep')
|
|
4
|
+
|
|
5
|
+
const fixtures = require('./deployment.fixtures')
|
|
6
|
+
const { Deployment } = require('../../src/deployment/deployment')
|
|
7
|
+
|
|
8
|
+
/** @type {toa.deployment.Deployment} */
|
|
9
|
+
let deployment
|
|
10
|
+
/** @type {toa.deployment.installation.Options} */
|
|
11
|
+
let options
|
|
12
|
+
|
|
13
|
+
beforeEach(() => {
|
|
14
|
+
deployment = new Deployment(fixtures.context, fixtures.compositions, fixtures.dependencies, fixtures.process)
|
|
15
|
+
options = clone(fixtures.options)
|
|
16
|
+
})
|
|
17
|
+
|
|
18
|
+
it('should pass -n argument if options.namespace is set', async () => {
|
|
19
|
+
await deployment.install(options)
|
|
20
|
+
|
|
21
|
+
const call = fixtures.process.execute.mock.calls.find((call) => call[0] === 'helm' && call[1][0] === 'upgrade')
|
|
22
|
+
|
|
23
|
+
expect(call).toBeDefined()
|
|
24
|
+
|
|
25
|
+
const args = call[1]
|
|
26
|
+
const index = args.findIndex((value) => value === '-n')
|
|
27
|
+
const namespace = args[index + 1]
|
|
28
|
+
|
|
29
|
+
expect(index).not.toStrictEqual(-1)
|
|
30
|
+
expect(namespace).toStrictEqual(fixtures.options.namespace)
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
it('should forbid local deployment environment', () => {
|
|
34
|
+
const context = clone(fixtures.context)
|
|
35
|
+
|
|
36
|
+
context.environment = 'local'
|
|
37
|
+
|
|
38
|
+
const create = () => new Deployment(context, fixtures.compositions, fixtures.dependencies, fixtures.process)
|
|
39
|
+
|
|
40
|
+
expect(create).toThrow(/name 'local' is not allowed/)
|
|
41
|
+
})
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const { Image } = require('../../../src/deployment/images/image')
|
|
4
|
+
const { generate } = require('randomstring')
|
|
5
|
+
const { hash } = require('@toa.io/generic')
|
|
6
|
+
|
|
7
|
+
const version = generate()
|
|
8
|
+
const name = generate()
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* @implements {toa.deployment.images.Image}
|
|
12
|
+
*/
|
|
13
|
+
class Class extends Image {
|
|
14
|
+
get name () {
|
|
15
|
+
return name
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
get version () {
|
|
19
|
+
return version
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/** @type {toa.norm.context.Runtime} */
|
|
24
|
+
const runtime = {
|
|
25
|
+
version: generate()
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
exports.scope = generate()
|
|
29
|
+
exports.name = name
|
|
30
|
+
exports.version = hash(runtime.version + ';' + version)
|
|
31
|
+
exports.Class = Class
|
|
32
|
+
exports.runtime = runtime
|
|
33
|
+
exports.process = process
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const fixtures = require('./image.fixtures')
|
|
4
|
+
const { generate } = require('randomstring')
|
|
5
|
+
|
|
6
|
+
/** @type {toa.deployment.images.Image} */
|
|
7
|
+
let instance
|
|
8
|
+
|
|
9
|
+
beforeEach(() => {
|
|
10
|
+
instance = new fixtures.Class(fixtures.scope, fixtures.runtime)
|
|
11
|
+
})
|
|
12
|
+
|
|
13
|
+
it('should assign url', () => {
|
|
14
|
+
const registry = generate()
|
|
15
|
+
|
|
16
|
+
instance.tag(registry)
|
|
17
|
+
|
|
18
|
+
expect(instance.reference).toEqual(`${registry}/${fixtures.scope}/class-${fixtures.name}:${fixtures.version}`)
|
|
19
|
+
})
|
|
20
|
+
|
|
21
|
+
describe('prepare', () => {
|
|
22
|
+
it('should throw error if no dockerfile specified', async () => {
|
|
23
|
+
await expect(instance.prepare(generate())).rejects.toThrow(/Dockerfile isn't specified/)
|
|
24
|
+
})
|
|
25
|
+
})
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
// noinspection ES6UnusedImports
|
|
2
|
+
|
|
3
|
+
import type { Deployable } from './deployment'
|
|
4
|
+
|
|
5
|
+
declare namespace toa.deployment {
|
|
6
|
+
|
|
7
|
+
interface Composition extends Deployable {
|
|
8
|
+
components: Array<string>
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export type Composition = toa.deployment.Composition
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
// noinspection JSUnusedGlobalSymbols,ES6UnusedImports
|
|
2
|
+
|
|
3
|
+
import { Service } from './service'
|
|
4
|
+
import { dependencies } from '@toa.io/norm/types/context'
|
|
5
|
+
|
|
6
|
+
declare namespace toa.deployment {
|
|
7
|
+
|
|
8
|
+
namespace dependency {
|
|
9
|
+
|
|
10
|
+
type Constructor = (instances: dependencies.Instance[], annotation: any) => Declaration
|
|
11
|
+
|
|
12
|
+
type Reference = {
|
|
13
|
+
name: string
|
|
14
|
+
version: string
|
|
15
|
+
repository?: string
|
|
16
|
+
alias?: string
|
|
17
|
+
values?: Object
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
type Service = {
|
|
21
|
+
group: string
|
|
22
|
+
name: string
|
|
23
|
+
version: string
|
|
24
|
+
port: number
|
|
25
|
+
ingress?: {
|
|
26
|
+
host: string
|
|
27
|
+
class: string
|
|
28
|
+
annotations?: object
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
type Proxy = {
|
|
33
|
+
name: string
|
|
34
|
+
target: string
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
type Variable = {
|
|
38
|
+
name: string
|
|
39
|
+
value?: string | number
|
|
40
|
+
secret?: {
|
|
41
|
+
name: string,
|
|
42
|
+
key: string
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
type Variables = {
|
|
47
|
+
[key: string]: Variable[]
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
type Declaration = {
|
|
51
|
+
references?: Reference[]
|
|
52
|
+
services?: Service[] // dependency.Service
|
|
53
|
+
proxies?: Proxy[]
|
|
54
|
+
variables?: Variables
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
type Dependency = {
|
|
60
|
+
references?: dependency.Reference[]
|
|
61
|
+
services?: Service[] // deployment.Service
|
|
62
|
+
proxies?: dependency.Proxy[]
|
|
63
|
+
variables?: dependency.Variables
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export namespace dependency {
|
|
69
|
+
export type Declaration = toa.deployment.dependency.Declaration
|
|
70
|
+
export type Reference = toa.deployment.dependency.Reference
|
|
71
|
+
export type Service = toa.deployment.dependency.Service
|
|
72
|
+
export type Proxy = toa.deployment.dependency.Proxy
|
|
73
|
+
export type Variables = toa.deployment.dependency.Variables
|
|
74
|
+
export type Variable = toa.deployment.dependency.Variable
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export type Dependency = toa.deployment.Dependency
|