@toa.io/operations 1.0.0-alpha.4 → 1.0.0-alpha.41

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.4",
3
+ "version": "1.0.0-alpha.41",
4
4
  "description": "Toa Deployment",
5
5
  "homepage": "https://toa.io",
6
6
  "author": {
@@ -27,12 +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.4",
31
- "@toa.io/generic": "1.0.0-alpha.4",
32
- "@toa.io/norm": "1.0.0-alpha.4",
33
- "@toa.io/yaml": "1.0.0-alpha.4",
30
+ "@toa.io/filesystem": "1.0.0-alpha.41",
31
+ "@toa.io/generic": "1.0.0-alpha.41",
32
+ "@toa.io/norm": "1.0.0-alpha.41",
33
+ "@toa.io/yaml": "1.0.0-alpha.41",
34
34
  "execa": "5.1.1",
35
35
  "fs-extra": "11.1.1"
36
36
  },
37
- "gitHead": "80a91c0d9c167484247a91e69a0c0a3c344f90d0"
37
+ "gitHead": "3b338a3f21ff9113cefa75d7789d9267917d41e3"
38
38
  }
@@ -6,7 +6,16 @@ const describe = (context, compositions, dependency) => {
6
6
  const { services } = dependency
7
7
 
8
8
  dependency.variables.global ??= []
9
- dependency.variables.global.unshift({ name: 'TOA_ENV', value: context.environment })
9
+
10
+ dependency.variables.global.unshift(
11
+ {
12
+ name: 'TOA_CONTEXT',
13
+ value: context.name
14
+ }, {
15
+ name: 'TOA_ENV',
16
+ value: context.environment
17
+ }
18
+ )
10
19
 
11
20
  const components = get.components(compositions)
12
21
  const credentials = context.registry?.credentials
@@ -18,7 +27,7 @@ const describe = (context, compositions, dependency) => {
18
27
  compositions,
19
28
  components,
20
29
  services,
21
- credentials,
30
+ credentials
22
31
  }
23
32
  }
24
33
 
@@ -22,6 +22,15 @@ spec:
22
22
  {{- include "env.var" . | indent 12 }}
23
23
  {{- end }}
24
24
  {{- end }}
25
+ {{- if .probe }}
26
+ readinessProbe:
27
+ httpGet:
28
+ path: {{ .probe.path }}
29
+ port: {{ .probe.port }}
30
+ {{- if .probe.delay }}
31
+ initialDelaySeconds: {{ .probe.delay }}
32
+ {{- end }}
33
+ {{- end }}
25
34
  ---
26
35
  apiVersion: v1
27
36
  kind: Service
@@ -38,6 +47,7 @@ spec:
38
47
  targetPort: {{ .port }}
39
48
  ---
40
49
  {{- if .ingress }}
50
+ {{- $service := .name }}
41
51
  apiVersion: networking.k8s.io/v1
42
52
  kind: Ingress
43
53
  metadata:
@@ -51,15 +61,17 @@ spec:
51
61
  ingressClassName: {{ .ingress.class }}
52
62
  {{- end }}
53
63
  rules:
54
- - host: {{ required "ingress.host is required" .ingress.host }}
64
+ {{- range .ingress.hosts }}
65
+ - host: {{ . }}
55
66
  http:
56
67
  paths:
57
68
  - path: /
58
69
  pathType: Prefix
59
70
  backend:
60
71
  service:
61
- name: extension-{{ .name }}
72
+ name: extension-{{ $service }}
62
73
  port:
63
74
  number: 8000
75
+ {{- end }}
64
76
  {{- end }}
65
77
  {{- end }}
@@ -29,7 +29,7 @@ services:
29
29
  port: 8000
30
30
  replicas: 2
31
31
  ingress:
32
- host: dummies.toa.io
32
+ hosts: [dummies.toa.io]
33
33
  class: alb
34
34
  annotations:
35
35
  alb.ingress.kubernetes.io/scheme: internet-facing
@@ -41,6 +41,11 @@ services:
41
41
  secret:
42
42
  name: secret-name
43
43
  key: secret-key
44
+ probe:
45
+ port: 8000
46
+ path: /.ready
47
+ delay: 1
48
+
44
49
  proxies:
45
50
  - name: storage-proxy
46
51
  target: host.docker.internal
@@ -1,8 +1,8 @@
1
1
  'use strict'
2
2
 
3
3
  const { join } = require('node:path')
4
- const { hash } = require('@toa.io/generic')
5
4
  const fs = require('fs-extra')
5
+ const { createHash } = require('node:crypto')
6
6
 
7
7
  const { Image } = require('./image')
8
8
 
@@ -26,22 +26,29 @@ class Composition extends Image {
26
26
  }
27
27
 
28
28
  get version () {
29
- const tags = this.#components.map((component) => component.locator.id + ':' + component.version)
29
+ const hash = createHash('sha256')
30
30
 
31
- return hash(tags.join(';'))
31
+ for (const component of this.#components) {
32
+ hash.update(component.locator.id)
33
+ hash.update(component.version)
34
+ }
35
+
36
+ return hash.digest('hex').slice(0, 8)
32
37
  }
33
38
 
34
39
  get base () {
35
- if (this.#image !== undefined)
40
+ if (this.#image !== undefined) {
36
41
  return this.#image
42
+ }
37
43
 
38
44
  let image = null
39
45
 
40
46
  for (const component of this.#components) {
41
47
  const value = component.build?.image
42
48
 
43
- if (image !== null && image !== value)
49
+ if (image !== null && image !== value) {
44
50
  throw new Error(`Composition '${this.#name}' requires different base images for its components. Specify base image for the composition in the context.`)
51
+ }
45
52
 
46
53
  image = value
47
54
  }
@@ -2,9 +2,8 @@
2
2
 
3
3
  const { Image } = require('./image')
4
4
  const { generate } = require('randomstring')
5
- const { hash } = require('@toa.io/generic')
6
5
 
7
- const version = generate()
6
+ const version = '168b04ff'
8
7
  const name = generate()
9
8
 
10
9
  /**
@@ -22,17 +21,17 @@ class Class extends Image {
22
21
 
23
22
  /** @type {toa.norm.context.Runtime} */
24
23
  const runtime = {
25
- version: generate()
24
+ version: '0.0.0'
26
25
  }
27
26
 
28
27
  /** @type {toa.norm.context.Registry} */
29
28
  const registry = {
30
- base: generate()
29
+ base: 'node:alpine'
31
30
  }
32
31
 
33
32
  exports.scope = generate()
34
33
  exports.name = name
35
- exports.version = hash(runtime.version + ';' + version)
34
+ exports.version = 'ba2409fc'
36
35
  exports.Class = Class
37
36
  exports.runtime = runtime
38
37
  exports.registry = registry
@@ -1,10 +1,17 @@
1
1
  'use strict'
2
2
 
3
- const { join, posix } = require('node:path')
4
- const { readFile: read, writeFile: write } = require('node:fs/promises')
5
-
6
- const { hash, overwrite } = require('@toa.io/generic')
7
- const fs = require('fs-extra')
3
+ const {
4
+ join,
5
+ posix
6
+ } = require('node:path')
7
+ const {
8
+ readFile: read,
9
+ writeFile: write
10
+ } = require('node:fs/promises')
11
+ const { createHash } = require('node:crypto')
12
+
13
+ const { overwrite } = require('@toa.io/generic')
14
+ const { mkdir } = require('node:fs/promises')
8
15
 
9
16
  /**
10
17
  * @implements {toa.deployment.images.Image}
@@ -31,7 +38,12 @@ class Image {
31
38
  }
32
39
 
33
40
  tag () {
34
- const tag = hash(this.#runtime?.version + ';' + this.version)
41
+ const hash = createHash('sha256')
42
+
43
+ hash.update(this.#runtime.version)
44
+ hash.update(this.version)
45
+
46
+ const tag = hash.digest('hex').slice(0, 8)
35
47
 
36
48
  this.reference = posix.join(this.#registry.base ?? '', this.#scope, `${this.name}:${tag}`)
37
49
  }
@@ -49,7 +61,7 @@ class Image {
49
61
 
50
62
  const path = join(root, `${this.name}.${this.version}`)
51
63
 
52
- await fs.ensureDir(path)
64
+ await mkdir(path, { recursive: true })
53
65
 
54
66
  const template = await read(this.dockerfile, 'utf-8')
55
67
  const contents = template.replace(/{{(\S{1,32})}}/g, (_, key) => this.#value(key))
@@ -69,8 +81,9 @@ class Image {
69
81
 
70
82
  const image = this.base
71
83
 
72
- if (image !== undefined)
84
+ if (image !== undefined) {
73
85
  this.#values.build.image = image
86
+ }
74
87
 
75
88
  if (this.#values.build.arguments !== undefined) this.#values.build.arguments = createArguments(this.#values.build.arguments)
76
89
  if (this.#values.build.run !== undefined) this.#values.build.run = createRunCommands(this.#values.build.run)
@@ -1,6 +1,7 @@
1
1
  'use strict'
2
2
 
3
3
  const workspace = require('./workspace')
4
+ const { newid } = require('@toa.io/generic')
4
5
 
5
6
  /**
6
7
  * @implements {toa.deployment.Registry}
@@ -39,7 +40,9 @@ class Registry {
39
40
  async build () {
40
41
  await this.prepare()
41
42
 
42
- for (const image of this.#images) await this.#build(image)
43
+ for (const image of this.#images) {
44
+ await this.#build(image)
45
+ }
43
46
  }
44
47
 
45
48
  async push () {
@@ -69,7 +72,11 @@ class Registry {
69
72
  async #build (image, push = false) {
70
73
  const args = ['--context=default', 'buildx', 'build']
71
74
 
72
- if (push) args.push('--push')
75
+ if (push) {
76
+ args.push('--push')
77
+ } else {
78
+ args.push('--load')
79
+ }
73
80
 
74
81
  args.push('--tag', image.reference, image.context)
75
82
 
@@ -81,12 +88,14 @@ class Registry {
81
88
 
82
89
  if (multiarch) {
83
90
  const platform = this.#registry.platforms.join(',')
91
+ const builder = await this.#createBuilder()
84
92
 
85
93
  args.push('--platform', platform)
86
- args.push('--builder', BUILDER)
94
+ args.push('--builder', builder)
87
95
 
88
- await this.#ensureBuilder()
89
- } else args.push('--builder', 'default')
96
+ } else {
97
+ args.push('--builder', 'default')
98
+ }
90
99
 
91
100
  args.push('--progress', 'plain')
92
101
 
@@ -97,20 +106,13 @@ class Registry {
97
106
  await this.#build(image, true)
98
107
  }
99
108
 
100
- async #ensureBuilder () {
101
- const ls = 'buildx ls'.split(' ')
102
- const output = await this.#process.execute('docker', ls, { silently: true })
103
- const exists = output.split('\n').findIndex((line) => line.startsWith('toa '))
104
-
105
- if (exists === -1) await this.#createBuilder()
106
- }
107
-
108
109
  async #createBuilder () {
109
- const create = `buildx create --name ${BUILDER} --use`.split(' ')
110
- const bootstrap = 'buildx inspect --bootstrap'.split(' ')
110
+ const name = `toa-${newid()}`
111
+ const create = `buildx create --name ${name} --bootstrap --use`.split(' ')
111
112
 
112
113
  await this.#process.execute('docker', create)
113
- await this.#process.execute('docker', bootstrap)
114
+
115
+ return name
114
116
  }
115
117
  }
116
118
 
@@ -3,13 +3,10 @@ export type Service = {
3
3
  name: string
4
4
  version: string
5
5
  port: number
6
- ingress?: {
7
- host: string
8
- class?: string
9
- annotations?: object
10
- }
6
+ ingress: Ingress
11
7
  variables: Variable[]
12
8
  components?: string[]
9
+ probe?: Probe
13
10
  }
14
11
 
15
12
  export type Variable = {
@@ -28,3 +25,15 @@ export type Dependency = {
28
25
  services?: Service[]
29
26
  variables?: Variables
30
27
  }
28
+
29
+ type Ingress = {
30
+ hosts: string[]
31
+ class?: string
32
+ annotations?: object
33
+ }
34
+
35
+ interface Probe {
36
+ port: number
37
+ path: string
38
+ delay?: number
39
+ }