@toa.io/operations 0.7.6-dev.9 → 0.8.0-dev.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@toa.io/operations",
3
- "version": "0.7.6-dev.9",
3
+ "version": "0.8.0-dev.0",
4
4
  "description": "Toa Deployment",
5
5
  "homepage": "https://toa.io",
6
6
  "author": {
@@ -26,10 +26,10 @@
26
26
  "test": "echo \"Error: run tests from root\" && exit 1"
27
27
  },
28
28
  "dependencies": {
29
- "@toa.io/filesystem": "1.0.2-dev.9",
30
- "@toa.io/generic": "0.11.0-dev.9",
31
- "@toa.io/yaml": "0.7.6-dev.9",
29
+ "@toa.io/filesystem": "1.1.0-dev.2",
30
+ "@toa.io/generic": "0.11.0-dev.16",
31
+ "@toa.io/yaml": "0.7.6-dev.16",
32
32
  "execa": "5.1.1"
33
33
  },
34
- "gitHead": "db624e061c5017062f46561e6d5e4106b7420e28"
34
+ "gitHead": "669be360acebac4dbe49735ec506127d9d0a05e3"
35
35
  }
@@ -9,7 +9,7 @@ const variables = (context, variables) => {
9
9
  if (variables.global === undefined) variables.global = []
10
10
 
11
11
  if (context.environment !== undefined) {
12
- const variable = format('TOA_ENV', context.environment)
12
+ const variable = { name: 'TOA_ENV', value: context.environment }
13
13
 
14
14
  variables.global.unshift(variable)
15
15
  }
@@ -17,11 +17,4 @@ const variables = (context, variables) => {
17
17
  return variables
18
18
  }
19
19
 
20
- /**
21
- * @param {string} name
22
- * @param {string} value
23
- * @returns {toa.deployment.dependency.Variable}
24
- */
25
- const format = (name, value) => ({ name, value })
26
-
27
20
  exports.variables = variables
@@ -2,8 +2,9 @@
2
2
 
3
3
  const { Process } = require('../process')
4
4
  const { Operator } = require('./operator')
5
- const { Factory: Images, Registry } = require('./images')
5
+ const { Factory: ImagesFactory } = require('./images')
6
6
  const { Deployment } = require('./deployment')
7
+ const { Registry } = require('./registry')
7
8
  const { Composition } = require('./composition')
8
9
  const { Service } = require('./service')
9
10
 
@@ -13,8 +14,16 @@ const { Service } = require('./service')
13
14
  class Factory {
14
15
  /** @type {toa.norm.Context} */
15
16
  #context
16
- /** @type {toa.deployment.images.Registry} */
17
+
18
+ /** @type {Composition[]} */
19
+ #compositions
20
+
21
+ /** @type {toa.deployment.Dependency[]} */
22
+ #dependencies
23
+
24
+ /** @type {toa.deployment.Registry} */
17
25
  #registry
26
+
18
27
  /** @type {toa.operations.Process} */
19
28
  #process
20
29
 
@@ -25,18 +34,23 @@ class Factory {
25
34
  this.#context = context
26
35
  this.#process = new Process()
27
36
 
28
- const images = new Images(context.name, context.runtime)
29
- this.#registry = new Registry(context.registry, images, this.#process)
37
+ const imagesFactory = new ImagesFactory(context.name, context.runtime)
38
+
39
+ this.#registry = new Registry(context.registry, imagesFactory, this.#process)
40
+ this.#compositions = context.compositions.map((composition) => this.#composition(composition))
41
+ this.#dependencies = this.#getDependencies()
30
42
  }
31
43
 
32
44
  operator () {
33
- const compositions = this.#context.compositions.map((composition) => this.#composition(composition))
34
- const dependencies = this.#dependencies()
35
- const deployment = new Deployment(this.#context, compositions, dependencies, this.#process)
45
+ const deployment = new Deployment(this.#context, this.#compositions, this.#dependencies, this.#process)
36
46
 
37
47
  return new Operator(deployment, this.#registry)
38
48
  }
39
49
 
50
+ registry () {
51
+ return this.#registry
52
+ }
53
+
40
54
  /**
41
55
  * @param composition {toa.norm.context.Composition}
42
56
  * @returns {Composition}
@@ -50,12 +64,14 @@ class Factory {
50
64
  /**
51
65
  * @returns {toa.deployment.Dependency[]}
52
66
  */
53
- #dependencies () {
67
+ #getDependencies () {
54
68
  /** @type {toa.deployment.Dependency[]} */
55
69
  const dependencies = []
56
70
 
71
+ if (this.#context.dependencies === undefined) return dependencies
72
+
57
73
  for (const [reference, instances] of Object.entries(this.#context.dependencies)) {
58
- const dependency = this.#dependency(reference, instances)
74
+ const dependency = this.#getDependency(reference, instances)
59
75
 
60
76
  if (dependency !== undefined) dependencies.push(dependency)
61
77
  }
@@ -68,7 +84,7 @@ class Factory {
68
84
  * @param {toa.norm.context.dependencies.Instance[]} instances
69
85
  * @returns {toa.deployment.Dependency | undefined}
70
86
  */
71
- #dependency (path, instances) {
87
+ #getDependency (path, instances) {
72
88
  const module = require(path)
73
89
  const pkg = require(path + '/package.json')
74
90
 
@@ -1,4 +1,4 @@
1
- FROM node:18.2.0-alpine3.15
1
+ FROM node:18.16.0-alpine3.17
2
2
 
3
3
  ENV NODE_ENV=production
4
4
  RUN if [ {{registry}} != undefined ]; then npm set registry {{registry}}; fi
@@ -11,7 +11,7 @@ class Composition extends Image {
11
11
 
12
12
  /** @type {string} */
13
13
  #name
14
- /** @type {Array<toa.norm.Component>} */
14
+ /** @type {toa.norm.Component[]} */
15
15
  #components
16
16
 
17
17
  /**
@@ -1,6 +1,6 @@
1
1
  'use strict'
2
2
 
3
- const { Image } = require('../../../src/deployment/images/image')
3
+ const { Image } = require('./image')
4
4
  const { generate } = require('randomstring')
5
5
  const { hash } = require('@toa.io/generic')
6
6
 
@@ -52,9 +52,9 @@ class Image {
52
52
  get version () {}
53
53
 
54
54
  tag (base) {
55
- const tag = hash(this.#runtime.version + ';' + this.version)
55
+ const tag = hash(this.#runtime?.version + ';' + this.version)
56
56
 
57
- this.reference = posix.join(base, `${this.#scope}/${this.#type}-${this.name}:${tag}`)
57
+ this.reference = posix.join(base ?? '', this.#scope, `${this.#type}-${this.name}:${tag}`)
58
58
  }
59
59
 
60
60
  async prepare (root) {
@@ -1,7 +1,5 @@
1
1
  'use strict'
2
2
 
3
3
  const { Factory } = require('./factory')
4
- const { Registry } = require('./registry')
5
4
 
6
5
  exports.Factory = Factory
7
- exports.Registry = Registry
@@ -1,4 +1,4 @@
1
- FROM node:18.2.0-alpine3.15
1
+ FROM node:18.16.0-alpine3.17
2
2
 
3
3
  ENV NODE_ENV=production
4
4
  RUN if [ {{registry}} != undefined ]; then npm set registry {{registry}}; fi
@@ -1,6 +1,6 @@
1
1
  'use strict'
2
2
 
3
- const { directory } = require('@toa.io/filesystem')
3
+ const workspace = require('./workspace')
4
4
 
5
5
  /**
6
6
  * @implements {toa.deployment.Operator}
@@ -8,12 +8,13 @@ const { directory } = require('@toa.io/filesystem')
8
8
  class Operator {
9
9
  /** @type {toa.deployment.Deployment} */
10
10
  #deployment
11
- /** @type {toa.deployment.images.Registry} */
11
+
12
+ /** @type {toa.deployment.Registry} */
12
13
  #registry
13
14
 
14
15
  /**
15
16
  * @param deployment {toa.deployment.Deployment}
16
- * @param registry {toa.deployment.images.Registry}
17
+ * @param registry {toa.deployment.Registry}
17
18
  */
18
19
  constructor (deployment, registry) {
19
20
  this.#deployment = deployment
@@ -21,7 +22,7 @@ class Operator {
21
22
  }
22
23
 
23
24
  async export (path) {
24
- const target = await Operator.#target('deployment', path)
25
+ const target = await workspace.create('deployment', path)
25
26
 
26
27
  await this.#deployment.export(target)
27
28
 
@@ -29,61 +30,32 @@ class Operator {
29
30
  }
30
31
 
31
32
  async prepare (path) {
32
- const target = await Operator.#target('images', path)
33
-
34
- await this.#registry.prepare(target)
35
-
36
- return target
33
+ return await this.#registry.prepare(path)
37
34
  }
38
35
 
39
- async build () {
40
- const target = await Operator.#target('images')
41
-
42
- await this.#registry.prepare(target)
36
+ async push () {
43
37
  await this.#registry.push()
44
-
45
- await directory.remove(target)
46
38
  }
47
39
 
48
40
  async install (options = {}) {
49
41
  options = Object.assign({}, OPTIONS, options)
50
42
 
51
- const [source] = await Promise.all([this.export(), this.build()])
52
-
43
+ await Promise.all([this.export(), this.push()])
53
44
  await this.#deployment.install(options)
54
-
55
- await directory.remove(source)
56
45
  }
57
46
 
58
47
  async template (options = {}) {
59
- const source = await this.export()
60
- const output = await this.#deployment.template(options)
48
+ await this.export()
61
49
 
62
- await directory.remove(source)
63
-
64
- return output
50
+ return await this.#deployment.template(options)
65
51
  }
66
52
 
67
53
  variables () {
68
54
  return this.#deployment.variables()
69
55
  }
70
-
71
- /**
72
- * @param type {string}
73
- * @param [path] {string}
74
- * @returns {Promise<string>}
75
- */
76
- static async #target (type, path) {
77
- if (path === undefined) path = await directory.temp('toa-' + type)
78
- else path = await directory.ensure(path)
79
-
80
- return path
81
- }
82
56
  }
83
57
 
84
58
  /** @type {toa.deployment.installation.Options} */
85
- const OPTIONS = {
86
- wait: false
87
- }
59
+ const OPTIONS = { wait: false }
88
60
 
89
61
  exports.Operator = Operator
@@ -14,12 +14,12 @@ describe('env', () => {
14
14
  /** @type {toa.deployment.Deployment} */
15
15
  let deployment
16
16
 
17
- /** @type {toa.deployment.images.Registry} */
17
+ /** @type {toa.deployment.Registry} */
18
18
  let registry
19
19
 
20
20
  beforeEach(() => {
21
21
  deployment = /** @type {toa.deployment.Deployment} */ {}
22
- registry = /** @type {toa.deployment.images.Registry} */ {}
22
+ registry = /** @type {toa.deployment.Registry} */ {}
23
23
  })
24
24
 
25
25
  it('should be', async () => {
@@ -31,7 +31,10 @@ describe('env', () => {
31
31
  it('should return variables', async () => {
32
32
  const variables = { [generate()]: { name: generate(), value: generate() } }
33
33
 
34
- deployment.variables = jest.fn(() => variables)
34
+ deployment.variables =
35
+ /** @type {typeof toa.deployment.Operator.variables} */
36
+ jest.fn(() => variables)
37
+
35
38
  operator = new Operator(deployment, registry)
36
39
 
37
40
  const output = operator.variables()
@@ -1,18 +1,21 @@
1
1
  'use strict'
2
2
 
3
- const { directory: { remove } } = require('@toa.io/filesystem')
3
+ const workspace = require('./workspace')
4
4
 
5
5
  /**
6
- * @implements {toa.deployment.images.Registry}
6
+ * @implements {toa.deployment.Registry}
7
7
  */
8
8
  class Registry {
9
9
  /** @type {toa.norm.context.Registry} */
10
10
  #registry
11
+
11
12
  /** @type {toa.deployment.images.Factory} */
12
13
  #factory
14
+
13
15
  /** @type {toa.operations.Process} */
14
16
  #process
15
- /** @type {Array<toa.deployment.images.Image>} */
17
+
18
+ /** @type {toa.deployment.images.Image[]} */
16
19
  #images = []
17
20
 
18
21
  /**
@@ -34,15 +37,24 @@ class Registry {
34
37
  return this.#create('service', path, service)
35
38
  }
36
39
 
37
- async prepare (target) {
38
- await Promise.all(this.#images.map((image) => image.prepare(target)))
40
+ async prepare (root) {
41
+ const path = await workspace.create('images', root)
42
+
43
+ await Promise.all(this.#images.map((image) => image.prepare(path)))
44
+
45
+ return path
46
+ }
47
+
48
+ async build () {
49
+ await this.prepare()
50
+
51
+ for (const image of this.#images) await this.#build(image)
39
52
  }
40
53
 
41
54
  async push () {
42
- for (const image of this.#images) {
43
- await this.#push(image)
44
- await remove(image.context)
45
- }
55
+ await this.prepare()
56
+
57
+ for (const image of this.#images) await this.#push(image)
46
58
  }
47
59
 
48
60
  /**
@@ -53,7 +65,7 @@ class Registry {
53
65
  #create (type, ...args) {
54
66
  const image = this.#factory[type](...args)
55
67
 
56
- image.tag(this.#registry.base)
68
+ image.tag(this.#registry?.base)
57
69
  this.#images.push(image)
58
70
 
59
71
  return image
@@ -61,39 +73,48 @@ class Registry {
61
73
 
62
74
  /**
63
75
  * @param {toa.deployment.images.Image} image
76
+ * @param {boolean} [push]
64
77
  * @returns {Promise<void>}
65
78
  */
66
- async #push (image) {
67
- const args = ['--context=default', 'buildx', 'build', '--push', '--tag', image.reference, image.context]
68
- const local = this.#registry.platforms === null
79
+ async #build (image, push = false) {
80
+ const args = ['--context=default', 'buildx', 'build']
81
+
82
+ if (push) args.push('--push')
83
+
84
+ args.push('--tag', image.reference, image.context)
85
+
86
+ const multiarch = this.#registry.platforms !== null
69
87
 
70
- if (local) {
71
- args.push('--builder', 'default')
72
- } else {
88
+ if (multiarch) {
73
89
  const platform = this.#registry.platforms.join(',')
74
90
 
75
91
  args.push('--platform', platform)
76
92
  args.push('--builder', BUILDER)
77
93
 
78
- await this.#builder()
79
- }
94
+ await this.#ensureBuilder()
95
+ } else args.push('--builder', 'default')
80
96
 
81
97
  await this.#process.execute('docker', args)
82
98
  }
83
99
 
84
- async #builder () {
100
+ async #push (image) {
101
+ await this.#build(image, true)
102
+ }
103
+
104
+ async #ensureBuilder () {
85
105
  const ls = 'buildx ls'.split(' ')
86
106
  const output = await this.#process.execute('docker', ls, { silently: true })
107
+ const exists = output.split('\n').findIndex((line) => line.startsWith('toa '))
87
108
 
88
- const exists = output.split('\n').find((line) => line.startsWith('toa '))
109
+ if (exists === -1) await this.#createBuilder()
110
+ }
89
111
 
90
- if (exists === undefined) {
91
- const create = `buildx create --name ${BUILDER} --use`.split(' ')
92
- const bootstrap = 'buildx inspect --bootstrap'.split(' ')
112
+ async #createBuilder () {
113
+ const create = `buildx create --name ${BUILDER} --use`.split(' ')
114
+ const bootstrap = 'buildx inspect --bootstrap'.split(' ')
93
115
 
94
- await this.#process.execute('docker', create)
95
- await this.#process.execute('docker', bootstrap)
96
- }
116
+ await this.#process.execute('docker', create)
117
+ await this.#process.execute('docker', bootstrap)
97
118
  }
98
119
  }
99
120
 
@@ -0,0 +1,17 @@
1
+ 'use strict'
2
+
3
+ const { directory } = require('@toa.io/filesystem')
4
+
5
+ /**
6
+ * @param {string} type
7
+ * @param {string} [path]
8
+ * @return {Promise<string>}
9
+ */
10
+ async function create (type, path) {
11
+ if (path === undefined) path = await directory.temp('toa-' + type)
12
+ else path = await directory.ensure(path)
13
+
14
+ return path
15
+ }
16
+
17
+ exports.create = create
@@ -1,12 +1,10 @@
1
- // noinspection ES6UnusedImports
2
-
3
- import type { Deployable } from './deployment'
1
+ import type * as _deployment from './deployment'
4
2
 
5
3
  declare namespace toa.deployment {
6
4
 
7
- interface Composition extends Deployable {
8
- components: Array<string>
9
- }
5
+ interface Composition extends _deployment.Deployable {
6
+ components: Array<string>
7
+ }
10
8
 
11
9
  }
12
10
 
@@ -1,6 +1,4 @@
1
- // noinspection JSUnusedGlobalSymbols,ES6UnusedImports
2
-
3
- import { Service } from './service'
1
+ import * as _service from './service'
4
2
  import { dependencies } from '@toa.io/norm/types/context'
5
3
 
6
4
  declare namespace toa.deployment {
@@ -58,20 +56,17 @@ declare namespace toa.deployment {
58
56
 
59
57
  type Dependency = {
60
58
  references?: dependency.Reference[]
61
- services?: Service[] // deployment.Service
59
+ services?: _service.Service[] // deployment.Service
62
60
  proxies?: dependency.Proxy[]
63
61
  variables?: dependency.Variables
64
62
  }
65
63
 
66
64
  }
67
65
 
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
-
66
+ export type Declaration = toa.deployment.dependency.Declaration
67
+ export type Reference = toa.deployment.dependency.Reference
68
+ export type Service = toa.deployment.dependency.Service
69
+ export type Proxy = toa.deployment.dependency.Proxy
70
+ export type Variables = toa.deployment.dependency.Variables
71
+ export type Variable = toa.deployment.dependency.Variable
77
72
  export type Dependency = toa.deployment.Dependency
@@ -1,8 +1,6 @@
1
- // noinspection ES6UnusedImports,JSUnusedGlobalSymbols
2
-
3
- import type { Composition } from './composition'
4
- import type { Service } from './service'
5
- import type { dependency } from './dependency'
1
+ import type * as _composition from './composition'
2
+ import type * as _service from './service'
3
+ import type * as _dependency from './dependency'
6
4
 
7
5
  declare namespace toa.deployment {
8
6
 
@@ -13,15 +11,15 @@ declare namespace toa.deployment {
13
11
  description?: string
14
12
  version: string
15
13
  appVersion: string
16
- dependencies: dependency.Reference[]
14
+ dependencies: _dependency.Reference[]
17
15
  }
18
16
 
19
17
  interface Contents {
20
- compositions?: Composition[]
18
+ compositions?: _composition.Composition[]
21
19
  components?: string[]
22
- services?: Service[]
23
- proxies?: dependency.Proxy[]
24
- variables?: dependency.Variables
20
+ services?: _service.Service[]
21
+ proxies?: _dependency.Proxy[]
22
+ variables?: _dependency.Variables
25
23
 
26
24
  [key: string]: Object
27
25
  }
@@ -38,7 +36,7 @@ declare namespace toa.deployment {
38
36
 
39
37
  namespace template {
40
38
  interface Options {
41
- namespace: string
39
+ namespace?: string
42
40
  }
43
41
  }
44
42
 
@@ -54,7 +52,7 @@ declare namespace toa.deployment {
54
52
 
55
53
  template(options: template.Options): Promise<string>
56
54
 
57
- variables(): dependency.Variables
55
+ variables(): _dependency.Variables
58
56
  }
59
57
 
60
58
  }
@@ -1,11 +1,13 @@
1
- // noinspection ES6UnusedImports
2
- import type { Operator } from './operator'
1
+ import type * as _operator from './operator'
2
+ import * as _registry from './registry'
3
3
 
4
4
  declare namespace toa.deployment {
5
5
 
6
- interface Factory {
7
- operator(): Operator
8
- }
6
+ interface Factory {
7
+ operator(): _operator.Operator
8
+
9
+ registry(): _registry.Registry
10
+ }
9
11
 
10
12
  }
11
13
 
@@ -1,5 +1,3 @@
1
- // noinspection ES6UnusedImports
2
-
3
1
  import * as _deployment from './deployment'
4
2
  import * as _dependency from './dependency'
5
3
 
@@ -8,15 +6,11 @@ declare namespace toa.deployment {
8
6
  interface Operator {
9
7
  export(path?: string): Promise<string>
10
8
 
11
- prepare(path?: string): Promise<string>
12
-
13
- build(): Promise<void>
14
-
15
9
  install(options?: _deployment.installation.Options): Promise<void>
16
10
 
17
11
  template(options?: _deployment.template.Options): Promise<string>
18
12
 
19
- variables(): _dependency.dependency.Variables
13
+ variables(): _dependency.Variables
20
14
  }
21
15
 
22
16
  }
@@ -0,0 +1,21 @@
1
+ import type * as _norm from '@toa.io/norm/types'
2
+ import type * as _dependency from './dependency'
3
+ import type * as _image from "./images/image"
4
+
5
+ declare namespace toa.deployment {
6
+
7
+ interface Registry {
8
+ composition(composition: _norm.Composition): _image.Image
9
+
10
+ service(path: string, service: _dependency.Service): _image.Image
11
+
12
+ prepare(path: string): Promise<string>
13
+
14
+ build(): Promise<void>
15
+
16
+ push(): Promise<void>
17
+ }
18
+
19
+ }
20
+
21
+ export type Registry = toa.deployment.Registry
@@ -1,20 +1,18 @@
1
- // noinspection ES6UnusedImports
2
-
3
- import type { Deployable } from './deployment'
1
+ import type * as _deployment from './deployment'
4
2
 
5
3
  declare namespace toa.deployment {
6
4
 
7
- interface Ingress {
8
- host: string
9
- class: string
10
- annotations?: object
11
- }
5
+ interface Ingress {
6
+ host: string
7
+ class: string
8
+ annotations?: object
9
+ }
10
+
11
+ interface Service extends _deployment.Deployable {
12
+ port: number
13
+ ingress?: Ingress
14
+ }
12
15
 
13
- interface Service extends Deployable {
14
- port: number
15
- ingress?: Ingress
16
- }
17
-
18
16
  }
19
17
 
20
18
  export type Service = toa.deployment.Service
@@ -1 +0,0 @@
1
- export { Dependency, dependency } from './dependency'
File without changes
File without changes
File without changes