@toa.io/operations 1.0.0-alpha.0 → 1.0.0-alpha.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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@toa.io/operations",
3
- "version": "1.0.0-alpha.0",
3
+ "version": "1.0.0-alpha.3",
4
4
  "description": "Toa Deployment",
5
5
  "homepage": "https://toa.io",
6
6
  "author": {
@@ -27,10 +27,12 @@
27
27
  "test": "echo \"Error: run tests from root\" && exit 1"
28
28
  },
29
29
  "dependencies": {
30
- "@toa.io/filesystem": "1.0.0-alpha.0",
31
- "@toa.io/generic": "1.0.0-alpha.0",
32
- "@toa.io/yaml": "1.0.0-alpha.0",
33
- "execa": "5.1.1"
30
+ "@toa.io/filesystem": "1.0.0-alpha.3",
31
+ "@toa.io/generic": "1.0.0-alpha.3",
32
+ "@toa.io/norm": "1.0.0-alpha.3",
33
+ "@toa.io/yaml": "1.0.0-alpha.3",
34
+ "execa": "5.1.1",
35
+ "fs-extra": "11.1.1"
34
36
  },
35
- "gitHead": "06c64546f6292cc07c52f74b31415101037f7616"
37
+ "gitHead": "e36ac7871fc14d15863aaf8f9bbdeace8bdfa9f0"
36
38
  }
@@ -8,5 +8,8 @@
8
8
  secretKeyRef:
9
9
  name: {{ .secret.name }}
10
10
  key: {{ .secret.key }}
11
+ {{- if .secret.optional }}
12
+ optional: {{ .secret.optional }}
13
+ {{- end }}
11
14
  {{- end }}
12
15
  {{- end }}
@@ -12,6 +12,7 @@ compositions:
12
12
  secret:
13
13
  name: secret-name
14
14
  key: secret-key
15
+ optional: false
15
16
  - name: users
16
17
  image: localhost:5000/composition-users:0.0.0
17
18
  replicas: 3
@@ -2,8 +2,8 @@
2
2
 
3
3
  const { join } = require('node:path')
4
4
  const { writeFile: write } = require('node:fs/promises')
5
- const { directory: { copy } } = require('@toa.io/filesystem')
6
5
  const { dump } = require('@toa.io/yaml')
6
+ const fs = require('fs-extra')
7
7
 
8
8
  const { merge, declare, describe } = require('./.deployment')
9
9
 
@@ -28,7 +28,7 @@ class Deployment {
28
28
  await Promise.all([
29
29
  write(join(target, 'Chart.yaml'), chart),
30
30
  write(join(target, 'values.yaml'), values),
31
- copy(TEMPLATES, join(target, 'templates'))
31
+ fs.copy(TEMPLATES, join(target, 'templates'))
32
32
  ])
33
33
 
34
34
  this.#target = target
@@ -1,5 +1,6 @@
1
1
  'use strict'
2
2
 
3
+ const { context: load } = require('@toa.io/norm')
3
4
  const { Process } = require('../process')
4
5
  const { Operator } = require('./operator')
5
6
  const { Factory: ImagesFactory } = require('./images')
@@ -85,6 +86,12 @@ class Factory {
85
86
 
86
87
  return new Service(service, image)
87
88
  }
89
+
90
+ static async create (path, environment) {
91
+ const context = await load(path, environment)
92
+
93
+ return new Factory(context)
94
+ }
88
95
  }
89
96
 
90
97
  exports.Factory = Factory
@@ -1,4 +1,4 @@
1
- FROM node:20.9.0-alpine3.18
1
+ FROM {{build.image}}
2
2
 
3
3
  {{build.arguments}}
4
4
 
@@ -2,29 +2,22 @@
2
2
 
3
3
  const { join } = require('node:path')
4
4
  const { hash } = require('@toa.io/generic')
5
- const { directory: { copy } } = require('@toa.io/filesystem')
5
+ const fs = require('fs-extra')
6
6
 
7
7
  const { Image } = require('./image')
8
8
 
9
9
  class Composition extends Image {
10
10
  dockerfile = join(__dirname, 'composition.Dockerfile')
11
11
 
12
- /** @type {string} */
13
12
  #name
14
-
15
- /** @type {toa.norm.Component[]} */
13
+ #image
16
14
  #components
17
15
 
18
- /**
19
- * @param {string} scope
20
- * @param {toa.norm.context.Runtime} runtime
21
- * @param {toa.norm.context.Registry} registry
22
- * @param {toa.norm.context.Composition} composition
23
- */
24
16
  constructor (scope, runtime, registry, composition) {
25
17
  super(scope, runtime, registry)
26
18
 
27
19
  this.#name = composition.name
20
+ this.#image = composition.image
28
21
  this.#components = composition.components
29
22
  }
30
23
 
@@ -38,11 +31,29 @@ class Composition extends Image {
38
31
  return hash(tags.join(';'))
39
32
  }
40
33
 
34
+ get base () {
35
+ if (this.#image !== undefined)
36
+ return this.#image
37
+
38
+ let image = null
39
+
40
+ for (const component of this.#components) {
41
+ const value = component.build?.image
42
+
43
+ if (image !== null && image !== value)
44
+ throw new Error(`Composition '${this.#name}' requires different base images for its components. Specify base image for the composition in the context.`)
45
+
46
+ image = value
47
+ }
48
+
49
+ return image ?? undefined
50
+ }
51
+
41
52
  async prepare (root) {
42
53
  const context = await super.prepare(root)
43
54
 
44
55
  for (const component of this.#components) {
45
- await copy(component.path, join(context, component.locator.label))
56
+ await fs.copy(component.path, join(context, component.locator.label))
46
57
  }
47
58
 
48
59
  return context
@@ -4,7 +4,7 @@ const { join, posix } = require('node:path')
4
4
  const { readFile: read, writeFile: write } = require('node:fs/promises')
5
5
 
6
6
  const { hash, overwrite } = require('@toa.io/generic')
7
- const { directory } = require('@toa.io/filesystem')
7
+ const fs = require('fs-extra')
8
8
 
9
9
  /**
10
10
  * @implements {toa.deployment.images.Image}
@@ -13,36 +13,21 @@ const { directory } = require('@toa.io/filesystem')
13
13
  class Image {
14
14
  context
15
15
  reference
16
-
17
- /**
18
- * @protected
19
- * @type {string}
20
- */
21
16
  dockerfile
22
17
 
23
- /** @type {string} */
24
18
  #scope
25
-
26
- /** @type {toa.norm.context.Registry} */
27
19
  #registry
28
-
29
- /** @type {toa.norm.context.Runtime} */
30
20
  #runtime
21
+ #values = {
22
+ build: {
23
+ image: 'node:20.9.0-alpine3.18'
24
+ }
25
+ }
31
26
 
32
- /** @type {{ runtime?: Partial<toa.norm.context.Runtime>, build: object }} */
33
- #values = { build: { command: 'echo hello' } }
34
-
35
- /**
36
- * @param {string} scope
37
- * @param {toa.norm.context.Runtime} runtime
38
- * @param {toa.norm.context.Registry} registry
39
- */
40
27
  constructor (scope, runtime, registry) {
41
28
  this.#scope = scope
42
29
  this.#registry = registry
43
30
  this.#runtime = runtime
44
-
45
- this.#setValues()
46
31
  }
47
32
 
48
33
  tag () {
@@ -51,26 +36,20 @@ class Image {
51
36
  this.reference = posix.join(this.#registry.base ?? '', this.#scope, `${this.name}:${tag}`)
52
37
  }
53
38
 
54
- /**
55
- * @abstract
56
- * @protected
57
- * @type {string}
58
- */
59
39
  get name () {}
60
40
 
61
- /**
62
- * @abstract
63
- * @protected
64
- * @type {string}
65
- */
66
41
  get version () {}
67
42
 
43
+ get base () {}
44
+
68
45
  async prepare (root) {
69
46
  if (this.dockerfile === undefined) throw new Error('Dockerfile isn\'t specified')
70
47
 
48
+ this.#setValues()
49
+
71
50
  const path = join(root, `${this.name}.${this.version}`)
72
51
 
73
- await directory.ensure(path)
52
+ await fs.ensureDir(path)
74
53
 
75
54
  const template = await read(this.dockerfile, 'utf-8')
76
55
  const contents = template.replace(/{{(\S{1,32})}}/g, (_, key) => this.#value(key))
@@ -88,6 +67,11 @@ class Image {
88
67
  this.#values.runtime = this.#runtime
89
68
  this.#values.build = overwrite(this.#values.build, this.#registry.build)
90
69
 
70
+ const image = this.base
71
+
72
+ if (image !== undefined)
73
+ this.#values.build.image = image
74
+
91
75
  if (this.#values.build.arguments !== undefined) this.#values.build.arguments = createArguments(this.#values.build.arguments)
92
76
  if (this.#values.build.run !== undefined) this.#values.build.run = createRunCommands(this.#values.build.run)
93
77
  }
@@ -3,7 +3,7 @@
3
3
  const { join, dirname } = require('node:path')
4
4
 
5
5
  const { Image } = require('./image')
6
- const { directory: { copy } } = require('@toa.io/filesystem')
6
+ const fs = require('fs-extra')
7
7
 
8
8
  class Service extends Image {
9
9
  dockerfile = join(__dirname, 'service.Dockerfile')
@@ -57,7 +57,7 @@ class Service extends Image {
57
57
  async prepare (root) {
58
58
  const context = await super.prepare(root)
59
59
 
60
- await copy(this.#path, context)
60
+ await fs.copy(this.#path, context)
61
61
 
62
62
  return context
63
63
  }
@@ -6,23 +6,14 @@ const workspace = require('./workspace')
6
6
  * @implements {toa.deployment.Registry}
7
7
  */
8
8
  class Registry {
9
- /** @type {toa.norm.context.Registry} */
10
9
  #registry
11
10
 
12
- /** @type {toa.deployment.images.Factory} */
13
11
  #factory
14
12
 
15
- /** @type {toa.operations.Process} */
16
13
  #process
17
14
 
18
- /** @type {toa.deployment.images.Image[]} */
19
15
  #images = []
20
16
 
21
- /**
22
- * @param {toa.norm.context.Registry} registry
23
- * @param {toa.deployment.images.Factory} factory
24
- * @param {toa.operations.Process} process
25
- */
26
17
  constructor (registry, factory, process) {
27
18
  this.#registry = registry
28
19
  this.#factory = factory
@@ -58,7 +49,7 @@ class Registry {
58
49
  }
59
50
 
60
51
  /**
61
- * @param {"composition" | "service"} type
52
+ * @param {'composition' | 'service'} type
62
53
  * @param {...any} args
63
54
  * @returns {toa.deployment.images.Image}
64
55
  */
@@ -97,6 +88,8 @@ class Registry {
97
88
  await this.#ensureBuilder()
98
89
  } else args.push('--builder', 'default')
99
90
 
91
+ args.push('--progress', 'plain')
92
+
100
93
  await this.#process.execute('docker', args)
101
94
  }
102
95
 
@@ -18,6 +18,7 @@ export type Variable = {
18
18
  secret?: {
19
19
  name: string,
20
20
  key: string
21
+ optional?: boolean
21
22
  }
22
23
  }
23
24