@toa.io/operations 0.20.0-dev.8 → 0.20.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.
Files changed (40) hide show
  1. package/package.json +6 -5
  2. package/readme.md +14 -2
  3. package/src/deployment/.deployment/.describe/components.js +1 -0
  4. package/src/deployment/.deployment/.describe/compositions.js +11 -0
  5. package/src/deployment/.deployment/.describe/index.js +4 -0
  6. package/src/deployment/.deployment/.describe/services.js +11 -0
  7. package/src/deployment/.deployment/.describe/variables.js +13 -13
  8. package/src/deployment/.deployment/describe.js +9 -12
  9. package/src/deployment/.deployment/merge.js +0 -8
  10. package/src/deployment/chart/templates/compositions.yaml +7 -12
  11. package/src/deployment/chart/templates/services.yaml +10 -10
  12. package/src/deployment/chart/values.yaml +13 -13
  13. package/src/deployment/composition.js +0 -12
  14. package/src/deployment/deployment.js +28 -25
  15. package/src/deployment/factory.js +3 -29
  16. package/src/deployment/images/composition.Dockerfile +6 -5
  17. package/src/deployment/images/composition.js +1 -1
  18. package/src/deployment/images/image.js +2 -6
  19. package/src/deployment/images/image.test.js +1 -1
  20. package/src/deployment/images/service.Dockerfile +7 -5
  21. package/src/deployment/images/service.js +4 -1
  22. package/src/deployment/operator.js +0 -3
  23. package/src/deployment/service.js +2 -15
  24. package/types/_deployment/operator.d.ts +20 -0
  25. package/types/dependency.d.ts +29 -0
  26. package/types/index.d.ts +1 -0
  27. package/src/deployment/chart/templates/proxies.yaml +0 -10
  28. package/src/deployment/deployment.fixtures.js +0 -42
  29. package/src/deployment/deployment.test.js +0 -78
  30. package/types/deployment/operator.d.ts +0 -18
  31. package/types/process.d.ts +0 -13
  32. /package/types/{deployment → _deployment}/composition.d.ts +0 -0
  33. /package/types/{deployment → _deployment}/dependency.d.ts +0 -0
  34. /package/types/{deployment → _deployment}/deployment.d.ts +0 -0
  35. /package/types/{deployment → _deployment}/factory.d.ts +0 -0
  36. /package/types/{deployment → _deployment}/images/factory.d.ts +0 -0
  37. /package/types/{deployment → _deployment}/images/image.d.ts +0 -0
  38. /package/types/{deployment → _deployment}/images/registry.d.ts +0 -0
  39. /package/types/{deployment → _deployment}/registry.d.ts +0 -0
  40. /package/types/{deployment → _deployment}/service.d.ts +0 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@toa.io/operations",
3
- "version": "0.20.0-dev.8",
3
+ "version": "0.20.0",
4
4
  "description": "Toa Deployment",
5
5
  "homepage": "https://toa.io",
6
6
  "author": {
@@ -22,14 +22,15 @@
22
22
  "access": "public"
23
23
  },
24
24
  "main": "src/index.js",
25
+ "types": "types/index.d.ts",
25
26
  "scripts": {
26
27
  "test": "echo \"Error: run tests from root\" && exit 1"
27
28
  },
28
29
  "dependencies": {
29
- "@toa.io/filesystem": "0.20.0-dev.8",
30
- "@toa.io/generic": "0.20.0-dev.8",
31
- "@toa.io/yaml": "0.20.0-dev.8",
30
+ "@toa.io/filesystem": "0.20.0",
31
+ "@toa.io/generic": "0.20.0",
32
+ "@toa.io/yaml": "0.20.0",
32
33
  "execa": "5.1.1"
33
34
  },
34
- "gitHead": "d8c08ec7def70ad93de06541af497cce8c4c1b50"
35
+ "gitHead": "28fc4b45c224c3683acaaf0e4abd1eb04e07b408"
35
36
  }
package/readme.md CHANGED
@@ -11,8 +11,8 @@
11
11
 
12
12
  registry:
13
13
  build:
14
- arguments: [NPM_TOKEN]
15
- run: echo //npm.pkg.github.com/:_authToken=${NPM_TOKEN} > .npmrc
14
+ arguments: [GITHUB_TOKEN]
15
+ run: npm config set //npm.pkg.github.com/:_authToken ${GITHUB_TOKEN}
16
16
  ```
17
17
 
18
18
  `arguments` is a list of environemt varialbes to be passed to `docker build`.
@@ -28,3 +28,15 @@ registry:
28
28
  echo test > .test
29
29
  rm .test
30
30
  ```
31
+
32
+ #### Registry Credentials
33
+
34
+ When using private container registry,
35
+ a secret containing required credentials can be specified using `registry.credentials` option.
36
+
37
+ ```yaml
38
+ # context.toa.yaml
39
+
40
+ registry:
41
+ credentials: docker-credentials-secret-name
42
+ ```
@@ -16,4 +16,5 @@ const components = (compositions) => {
16
16
 
17
17
  return Array.from(components)
18
18
  }
19
+
19
20
  exports.components = components
@@ -0,0 +1,11 @@
1
+ 'use strict'
2
+
3
+ const { addVariables } = require('./variables')
4
+
5
+ function compositions (compositions, variables) {
6
+ for (const composition of compositions) {
7
+ addVariables(composition, variables)
8
+ }
9
+ }
10
+
11
+ exports.compositions = compositions
@@ -2,8 +2,12 @@
2
2
 
3
3
  const { dependencies } = require('./dependencies')
4
4
  const { components } = require('./components')
5
+ const { compositions } = require('./compositions')
5
6
  const { variables } = require('./variables')
7
+ const { services } = require('./services')
6
8
 
7
9
  exports.dependencies = dependencies
8
10
  exports.components = components
11
+ exports.compositions = compositions
9
12
  exports.variables = variables
13
+ exports.services = services
@@ -0,0 +1,11 @@
1
+ 'use strict'
2
+
3
+ const { addVariables } = require('./variables')
4
+
5
+ function services (services, variables) {
6
+ for (const service of services) {
7
+ addVariables(service, variables)
8
+ }
9
+ }
10
+
11
+ exports.services = services
@@ -1,20 +1,20 @@
1
1
  'use strict'
2
2
 
3
- /**
4
- * @param {toa.norm.Context} context
5
- * @param {toa.deployment.dependency.Variables} variables
6
- * @returns {toa.deployment.dependency.Variables}
7
- */
8
- const variables = (context, variables) => {
9
- if (variables.global === undefined) variables.global = []
3
+ function addVariables (deployment, variables) {
4
+ const used = new Set()
10
5
 
11
- if (context.environment !== undefined) {
12
- const variable = { name: 'TOA_ENV', value: context.environment }
6
+ deployment.variables ??= []
13
7
 
14
- variables.global.unshift(variable)
15
- }
8
+ for (const [key, set] of Object.entries(variables)) {
9
+ if (key !== 'global' && !deployment.components?.includes(key)) continue
10
+
11
+ for (const variable of set) {
12
+ if (used.has(variable.name)) continue
16
13
 
17
- return variables
14
+ deployment.variables.push(variable)
15
+ used.add(variable.name)
16
+ }
17
+ }
18
18
  }
19
19
 
20
- exports.variables = variables
20
+ exports.addVariables = addVariables
@@ -2,26 +2,23 @@
2
2
 
3
3
  const get = require('./.describe')
4
4
 
5
- /**
6
- * @param {toa.norm.Context} context
7
- * @param {toa.deployment.Composition[]} compositions
8
- * @param {toa.deployment.Dependency} dependency
9
- * @returns {toa.deployment.Contents}
10
- */
11
5
  const describe = (context, compositions, dependency) => {
12
- const { references, services, proxies } = dependency
6
+ const { services } = dependency
7
+
8
+ dependency.variables.global ??= []
9
+ dependency.variables.global.unshift({ name: 'TOA_ENV', value: context.environment })
13
10
 
14
11
  const components = get.components(compositions)
15
- const dependencies = get.dependencies(references)
16
- const variables = get.variables(context, dependency.variables)
12
+ const credentials = context.registry?.credentials
13
+
14
+ get.compositions(compositions, dependency.variables, context.environment)
15
+ get.services(services, dependency.variables)
17
16
 
18
17
  return {
19
18
  compositions,
20
19
  components,
21
20
  services,
22
- proxies,
23
- variables,
24
- ...dependencies
21
+ credentials,
25
22
  }
26
23
  }
27
24
 
@@ -1,9 +1,5 @@
1
1
  'use strict'
2
2
 
3
- /**
4
- * @param {toa.deployment.Dependency[]} dependencies
5
- * @returns {toa.deployment.Dependency}
6
- */
7
3
  const merge = (dependencies) => {
8
4
  /** @type {toa.deployment.dependency.Reference[]} */
9
5
  const references = []
@@ -27,10 +23,6 @@ const merge = (dependencies) => {
27
23
  return { references, services, proxies, variables }
28
24
  }
29
25
 
30
- /**
31
- * @param {toa.deployment.dependency.Variables} merged
32
- * @param {toa.deployment.dependency.Variables} variables
33
- */
34
26
  const append = (merged, variables) => {
35
27
  for (const [component, vars] of Object.entries(variables)) {
36
28
  if (merged[component] === undefined) merged[component] = []
@@ -2,7 +2,7 @@
2
2
  apiVersion: apps/v1
3
3
  kind: Deployment
4
4
  metadata:
5
- name: composition-{{ required "deployment name is required" .name }}
5
+ name: composition-{{ required "composition name is required" .name }}
6
6
  spec:
7
7
  replicas: {{ .replicas | default 2 }}
8
8
  selector:
@@ -19,20 +19,15 @@ spec:
19
19
  containers:
20
20
  - name: {{ .name }}
21
21
  image: {{ .image }}
22
- {{- if $.Values.variables }}
22
+ {{- if .variables }}
23
23
  env:
24
- {{- range $component := .components }}
25
- {{- range $key, $vars := $.Values.variables }}
26
- {{- if eq $component $key }}
27
- {{- range $vars }}
28
- {{- include "env.var" . | indent 12 }}
29
- {{- end }}
30
- {{- end }}
31
- {{- end }}
32
- {{- end }}
33
- {{- range $.Values.variables.global }}
24
+ {{- range .variables }}
34
25
  {{- include "env.var" . | indent 12 }}
35
26
  {{- end }}
36
27
  {{- end }}
28
+ {{- if $.Values.credentials }}
29
+ imagePullSecrets:
30
+ - name: {{ $.Values.credentials }}
31
+ {{- end }}
37
32
  ---
38
33
  {{- end }}
@@ -2,23 +2,23 @@
2
2
  apiVersion: apps/v1
3
3
  kind: Deployment
4
4
  metadata:
5
- name: service-{{ required "deployment name is required" .name }}
5
+ name: extension-{{ required "deployment name is required" .name }}
6
6
  spec:
7
7
  replicas: {{ .replicas | default 2 }}
8
8
  selector:
9
9
  matchLabels:
10
- toa.io/service: {{ .name }}
10
+ toa.io/service: extension-{{ .name }}
11
11
  template:
12
12
  metadata:
13
13
  labels:
14
- toa.io/service: {{ .name }}
14
+ toa.io/service: extension-{{ .name }}
15
15
  spec:
16
16
  containers:
17
- - name: {{ .name }}
17
+ - name: extension-{{ .name }}
18
18
  image: {{ .image }}
19
- {{- if $.Values.variables }}
19
+ {{- if .variables }}
20
20
  env:
21
- {{- range $.Values.variables.global }}
21
+ {{- range .variables }}
22
22
  {{- include "env.var" . | indent 12 }}
23
23
  {{- end }}
24
24
  {{- end }}
@@ -26,11 +26,11 @@ spec:
26
26
  apiVersion: v1
27
27
  kind: Service
28
28
  metadata:
29
- name: service-{{ .name }}
29
+ name: extension-{{ .name }}
30
30
  spec:
31
31
  type: ClusterIP
32
32
  selector:
33
- toa.io/service: {{ .name }}
33
+ toa.io/service: extension-{{ .name }}
34
34
  ports:
35
35
  - name: port-{{ .port }}
36
36
  protocol: TCP
@@ -41,7 +41,7 @@ spec:
41
41
  apiVersion: networking.k8s.io/v1
42
42
  kind: Ingress
43
43
  metadata:
44
- name: {{ .name }}
44
+ name: extension-{{ .name }}
45
45
  {{- if .ingress.annotations }}
46
46
  annotations:
47
47
  {{ toYaml .ingress.annotations | indent 4 }}
@@ -58,7 +58,7 @@ spec:
58
58
  pathType: Prefix
59
59
  backend:
60
60
  service:
61
- name: service-{{ .name }}
61
+ name: extension-{{ .name }}
62
62
  port:
63
63
  number: 8000
64
64
  {{- end }}
@@ -6,6 +6,12 @@ compositions:
6
6
  components:
7
7
  - todos-tasks
8
8
  - todos-stats
9
+ variables:
10
+ - name: TOA_CONFIGURATION_TODOS_TASKS
11
+ value: foo
12
+ secret:
13
+ name: secret-name
14
+ key: secret-key
9
15
  - name: users
10
16
  image: localhost:5000/composition-users:0.0.0
11
17
  replicas: 3
@@ -16,19 +22,6 @@ components:
16
22
  - todos-tasks
17
23
  - todos-stats
18
24
  - users-users
19
- variables:
20
- global:
21
- - name: TOA_BINDINGS_AMQP_SYSTEM_USERNAME
22
- value: foo
23
- secret:
24
- name: secret-name
25
- key: secret-key
26
- todos-tasks:
27
- - name: TOA_CONFIGURATION_TODOS_TASKS
28
- value: foo
29
- secret:
30
- name: secret-name
31
- key: secret-key
32
25
  services:
33
26
  - name: resources-gateway
34
27
  image: localhost:5000/resources-gateway:0.0.0
@@ -41,7 +34,14 @@ services:
41
34
  alb.ingress.kubernetes.io/scheme: internet-facing
42
35
  alb.ingress.kubernetes.io/target-type: ip
43
36
  alb.ingress.kubernetes.io/listen-ports: '[{"HTTPS": 443}]'
37
+ variables:
38
+ - name: TOA_CONFIGURATION_TODOS_TASKS
39
+ value: foo
40
+ secret:
41
+ name: secret-name
42
+ key: secret-key
44
43
  proxies:
45
44
  - name: storage-proxy
46
45
  target: host.docker.internal
47
46
  environment: development
47
+ credentials: docker-credentials
@@ -1,19 +1,11 @@
1
1
  'use strict'
2
2
 
3
- // noinspection JSClosureCompilerSyntax
4
- /**
5
- * @implements {toa.deployment.Composition}
6
- */
7
3
  class Composition {
8
4
  name
9
5
  image
10
6
  /** @type {string[]} */
11
7
  components
12
8
 
13
- /**
14
- * @param composition {toa.norm.context.Composition}
15
- * @param image {toa.deployment.images.Image}
16
- */
17
9
  constructor (composition, image) {
18
10
  this.name = composition.name
19
11
  this.image = image.reference
@@ -21,10 +13,6 @@ class Composition {
21
13
  }
22
14
  }
23
15
 
24
- /**
25
- * @param {toa.norm.Component} component
26
- * @returns {string}
27
- */
28
16
  const component = (component) => component.locator.label
29
17
 
30
18
  exports.Composition = Composition
@@ -7,39 +7,23 @@ const { dump } = require('@toa.io/yaml')
7
7
 
8
8
  const { merge, declare, describe } = require('./.deployment')
9
9
 
10
- /**
11
- * @implements {toa.deployment.Deployment}
12
- */
13
10
  class Deployment {
14
- /** @type {toa.deployment.Declaration} */
15
- #declaration
16
-
17
- /** @type {toa.deployment.Contents} */
18
- #contents
19
-
20
- /** @type {toa.operations.Process} */
11
+ #chart
12
+ #values
21
13
  #process
22
-
23
- /** @type {string} */
24
14
  #target
25
15
 
26
- /**
27
- * @param context {toa.norm.Context}
28
- * @param compositions {toa.deployment.Composition[]}
29
- * @param dependencies {toa.deployment.Dependency[]}
30
- * @param process {toa.operations.Process}
31
- */
32
16
  constructor (context, compositions, dependencies, process) {
33
17
  const dependency = merge(dependencies)
34
18
 
35
- this.#declaration = declare(context, dependency)
36
- this.#contents = describe(context, compositions, dependency)
19
+ this.#chart = declare(context, dependency)
20
+ this.#values = describe(context, compositions, dependency)
37
21
  this.#process = process
38
22
  }
39
23
 
40
24
  async export (target) {
41
- const chart = dump(this.#declaration)
42
- const values = dump(this.#contents)
25
+ const chart = dump(this.#chart)
26
+ const values = dump(this.#values)
43
27
 
44
28
  await Promise.all([
45
29
  write(join(target, 'Chart.yaml'), chart),
@@ -60,7 +44,7 @@ class Deployment {
60
44
  if (options.wait === true) args.push('--wait')
61
45
 
62
46
  await this.#process.execute('helm', ['dependency', 'update', this.#target])
63
- await this.#process.execute('helm', ['upgrade', this.#declaration.name, '-i', ...args, this.#target])
47
+ await this.#process.execute('helm', ['upgrade', this.#chart.name, '-i', ...args, this.#target])
64
48
  }
65
49
 
66
50
  async template (options) {
@@ -73,12 +57,31 @@ class Deployment {
73
57
  if (options.namespace !== undefined) args.push('-n', options.namespace)
74
58
 
75
59
  return await this.#process.execute('helm',
76
- ['template', this.#declaration.name, ...args, this.#target],
60
+ ['template', this.#chart.name, ...args, this.#target],
77
61
  { silently: true })
78
62
  }
79
63
 
80
64
  variables () {
81
- return this.#contents.variables
65
+ const variables = []
66
+ const used = new Set()
67
+
68
+ addVariables(this.#values.compositions, variables, used)
69
+ addVariables(this.#values.services, variables, used)
70
+
71
+ return variables
72
+ }
73
+ }
74
+
75
+ function addVariables (list, variables, used = new Set()) {
76
+ for (const item of list) {
77
+ if (item.variables === undefined) continue
78
+
79
+ for (const variable of item.variables) {
80
+ if (used.has(variable.name)) continue
81
+
82
+ variables.push(variable)
83
+ used.add(variable.name)
84
+ }
82
85
  }
83
86
  }
84
87
 
@@ -8,28 +8,14 @@ const { Registry } = require('./registry')
8
8
  const { Composition } = require('./composition')
9
9
  const { Service } = require('./service')
10
10
 
11
- /**
12
- * @implements {toa.deployment.Factory}
13
- */
14
11
  class Factory {
15
- /** @type {toa.norm.Context} */
16
12
  #context
17
-
18
- /** @type {Composition[]} */
19
13
  #compositions
20
-
21
- /** @type {toa.deployment.Dependency[]} */
22
14
  #dependencies
23
-
24
- /** @type {toa.deployment.Registry} */
25
15
  #registry
26
-
27
- /** @type {toa.operations.Process} */
28
16
  #process
17
+ #extensionComponents = []
29
18
 
30
- /**
31
- * @param context {toa.norm.Context}
32
- */
33
19
  constructor (context) {
34
20
  this.#context = context
35
21
  this.#process = new Process()
@@ -51,19 +37,12 @@ class Factory {
51
37
  return this.#registry
52
38
  }
53
39
 
54
- /**
55
- * @param composition {toa.norm.context.Composition}
56
- * @returns {Composition}
57
- */
58
40
  #composition (composition) {
59
41
  const image = this.#registry.composition(composition)
60
42
 
61
43
  return new Composition(composition, image)
62
44
  }
63
45
 
64
- /**
65
- * @returns {toa.deployment.Dependency[]}
66
- */
67
46
  #getDependencies () {
68
47
  /** @type {toa.deployment.Dependency[]} */
69
48
  const dependencies = []
@@ -79,21 +58,16 @@ class Factory {
79
58
  return dependencies
80
59
  }
81
60
 
82
- /**
83
- * @param {string} path
84
- * @param {toa.norm.context.dependencies.Instance[]} instances
85
- * @returns {toa.deployment.Dependency | undefined}
86
- */
87
61
  #getDependency (path, instances) {
88
62
  const module = require(path)
89
63
  const pkg = require(path + '/package.json')
90
64
 
91
65
  if (module.deployment === undefined) return
92
66
 
93
- const annotations = this.#context.annotations?.[pkg.name]
67
+ const annotation = this.#context.annotations?.[pkg.name]
94
68
 
95
69
  /** @type {toa.deployment.dependency.Declaration} */
96
- const dependency = module.deployment(instances, annotations)
70
+ const dependency = module.deployment(instances, annotation)
97
71
 
98
72
  /** @type {toa.deployment.Service[]} */
99
73
  const services = dependency.services?.map((service) => this.#service(path, service))
@@ -3,16 +3,17 @@ FROM node:18.16.0-alpine3.17
3
3
  {{build.arguments}}
4
4
 
5
5
  ENV NODE_ENV=production
6
- RUN if [ {{runtime.registry}} != undefined ]; then npm set registry {{runtime.registry}}; fi
7
- RUN if [ {{runtime.proxy}} != undefined ]; then npm set proxy {{runtime.proxy}}; fi
8
- RUN npm i -g @toa.io/runtime@{{runtime.version}}
6
+ RUN if [ "{{runtime.registry}}" != "" ]; then npm set registry {{runtime.registry}}; fi
7
+ RUN if [ "{{runtime.proxy}}" != "" ]; then npm set proxy {{runtime.proxy}}; fi
8
+ RUN npm i -g @toa.io/runtime@{{runtime.version}} --omit=dev
9
9
 
10
10
  WORKDIR /composition
11
- ADD . .
11
+ COPY --chown=node:node . /composition
12
12
 
13
13
  {{build.run}}
14
14
 
15
15
  # run 'npm i' in each component
16
- RUN find . -maxdepth 1 -type d \( ! -name . \) -exec /bin/sh -c "cd '{}' && if [ -f package.json ]; then npm i; fi" \;
16
+ RUN for entry in *; do if [ -f "$entry/package.json" ]; then (cd $entry && npm i --omit=dev); fi; done
17
17
 
18
+ USER node
18
19
  CMD toa compose *
@@ -29,7 +29,7 @@ class Composition extends Image {
29
29
  }
30
30
 
31
31
  get name () {
32
- return this.#name
32
+ return 'composition-' + this.#name
33
33
  }
34
34
 
35
35
  get version () {
@@ -29,9 +29,6 @@ class Image {
29
29
  /** @type {toa.norm.context.Runtime} */
30
30
  #runtime
31
31
 
32
- /** @type {string} */
33
- #type
34
-
35
32
  /** @type {{ runtime?: Partial<toa.norm.context.Runtime>, build: object }} */
36
33
  #values = { build: { command: 'echo hello' } }
37
34
 
@@ -44,7 +41,6 @@ class Image {
44
41
  this.#scope = scope
45
42
  this.#registry = registry
46
43
  this.#runtime = runtime
47
- this.#type = this.constructor.name.toLowerCase()
48
44
 
49
45
  this.#setValues()
50
46
  }
@@ -52,7 +48,7 @@ class Image {
52
48
  tag () {
53
49
  const tag = hash(this.#runtime?.version + ';' + this.version)
54
50
 
55
- this.reference = posix.join(this.#registry.base ?? '', this.#scope, `${this.#type}-${this.name}:${tag}`)
51
+ this.reference = posix.join(this.#registry.base ?? '', this.#scope, `${this.name}:${tag}`)
56
52
  }
57
53
 
58
54
  /**
@@ -72,7 +68,7 @@ class Image {
72
68
  async prepare (root) {
73
69
  if (this.dockerfile === undefined) throw new Error('Dockerfile isn\'t specified')
74
70
 
75
- const path = join(root, `${this.#type}-${this.name}.${this.version}`)
71
+ const path = join(root, `${this.name}.${this.version}`)
76
72
 
77
73
  await directory.ensure(path)
78
74
 
@@ -13,7 +13,7 @@ beforeEach(() => {
13
13
  it('should assign url', () => {
14
14
  instance.tag()
15
15
 
16
- expect(instance.reference).toEqual(`${fixtures.registry.base}/${fixtures.scope}/class-${fixtures.name}:${fixtures.version}`)
16
+ expect(instance.reference).toEqual(`${fixtures.registry.base}/${fixtures.scope}/${fixtures.name}:${fixtures.version}`)
17
17
  })
18
18
 
19
19
  describe('prepare', () => {
@@ -1,12 +1,14 @@
1
1
  FROM node:18.16.0-alpine3.17
2
2
 
3
3
  ENV NODE_ENV=production
4
- RUN if [ {{runtime.registry}} != undefined ]; then npm set registry {{runtime.registry}}; fi
5
- RUN if [ {{runtime.proxy}} != undefined ]; then npm set proxy {{runtime.proxy}}; fi
6
- RUN npm i -g @toa.io/runtime@{{runtime.version}}
4
+ RUN if [ "{{runtime.registry}}" != "" ]; then npm set registry {{runtime.registry}}; fi
5
+ RUN if [ "{{runtime.proxy}}" != "" ]; then npm set proxy {{runtime.proxy}}; fi
6
+ RUN npm i -g @toa.io/runtime@{{runtime.version}} --omit=dev
7
7
 
8
8
  WORKDIR /service
9
- ADD . .
10
- RUN npm i
9
+ COPY --chown=node:node . /service
11
10
 
11
+ RUN npm i --omit=dev
12
+
13
+ USER node
12
14
  CMD toa serve .
@@ -18,10 +18,13 @@ class Service extends Image {
18
18
 
19
19
  /** @type {string} */
20
20
  #group
21
+
21
22
  /** @type {string} */
22
23
  #name
24
+
23
25
  /** @type {string} */
24
26
  #path
27
+
25
28
  /** @type {string} */
26
29
  #version
27
30
 
@@ -44,7 +47,7 @@ class Service extends Image {
44
47
  }
45
48
 
46
49
  get name () {
47
- return this.#group + '-' + this.#name
50
+ return 'extension-' + this.#group + '-' + this.#name
48
51
  }
49
52
 
50
53
  get version () {
@@ -2,9 +2,6 @@
2
2
 
3
3
  const workspace = require('./workspace')
4
4
 
5
- /**
6
- * @implements {toa.deployment.Operator}
7
- */
8
5
  class Operator {
9
6
  /** @type {toa.deployment.Deployment} */
10
7
  #deployment
@@ -1,24 +1,11 @@
1
1
  'use strict'
2
2
 
3
- // noinspection JSClosureCompilerSyntax
4
- /**
5
- * @implements {toa.deployment.Service}
6
- */
7
3
  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
4
  constructor (service, image) {
5
+ Object.assign(this, service)
6
+
18
7
  this.name = service.group + '-' + service.name
19
- this.port = service.port
20
8
  this.image = image.reference
21
- this.ingress = service.ingress
22
9
  }
23
10
  }
24
11
 
@@ -0,0 +1,20 @@
1
+ import * as _deployment from './deployment'
2
+ import * as _dependency from './dependency'
3
+
4
+ declare namespace toa.deployment {
5
+
6
+ interface Operator {
7
+ export (path?: string): Promise<string>
8
+
9
+ install (options?: _deployment.installation.Options): Promise<void>
10
+
11
+ template (options?: _deployment.template.Options): Promise<string>
12
+
13
+ variables (): _dependency.Variables
14
+
15
+ listVariables (): _dependency.Variable[]
16
+ }
17
+
18
+ }
19
+
20
+ export type Operator = toa.deployment.Operator
@@ -0,0 +1,29 @@
1
+ export type Service = {
2
+ group: string
3
+ name: string
4
+ version: string
5
+ port: number
6
+ ingress?: {
7
+ host: string
8
+ class?: string
9
+ annotations?: object
10
+ }
11
+ variables: Variable[]
12
+ components?: string[]
13
+ }
14
+
15
+ export type Variable = {
16
+ name: string
17
+ value?: string
18
+ secret?: {
19
+ name: string,
20
+ key: string
21
+ }
22
+ }
23
+
24
+ export type Variables = Record<string, Variable[]>
25
+
26
+ export type Dependency = {
27
+ services?: Service[]
28
+ variables?: Variables
29
+ }
@@ -0,0 +1 @@
1
+ export * from './dependency'
@@ -1,10 +0,0 @@
1
- {{- range .Values.proxies }}
2
- apiVersion: v1
3
- kind: Service
4
- metadata:
5
- name: {{ .name }}
6
- spec:
7
- type: ExternalName
8
- externalName: {{ .target }}
9
- ---
10
- {{- end }}
@@ -1,42 +0,0 @@
1
- 'use strict'
2
-
3
- const { generate } = require('randomstring')
4
-
5
- const context = /** @type {toa.norm.Context} */ { name: generate() }
6
- const compositions = []
7
- /** @type {toa.deployment.Dependency[]} */
8
-
9
- /** @type {toa.deployment.dependency.Variable} */
10
- const bindingVariable = {
11
- name: 'TOA_BINDINGS_AMQP_POINTER',
12
- value: 'eyJkZWZhdWx0IjoiYW1xcDovL3doYXRldmVyIiwic3lzdGVtIjoiYW1xcDovL2hvc3QwIn0='
13
- }
14
-
15
- /** @type {toa.deployment.dependency.Variable} */
16
- const secretVariable = {
17
- name: 'TOA_BINDINGS_AMQP_DEFAULT_USERNAME',
18
- secret: {
19
- name: 'toa-bindings-amqp-default',
20
- key: 'username'
21
- }
22
- }
23
-
24
- /** @type {toa.deployment.Dependency[]} */
25
- const dependencies = [{
26
- variables: { global: [bindingVariable, secretVariable] }
27
- }]
28
-
29
- const process = /** @type {toa.operations.Process} */ { execute: jest.fn() }
30
-
31
- const options = /** @type {toa.deployment.installation.Options} */ {
32
- namespace: generate(),
33
- target: generate()
34
- }
35
-
36
- exports.context = context
37
- exports.compositions = compositions
38
- exports.dependencies = dependencies
39
- exports.process = process
40
- exports.options = options
41
- exports.bindingVariable = bindingVariable
42
- exports.secretVariable = secretVariable
@@ -1,78 +0,0 @@
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
- describe('variables', () => {
34
- let deployment /** @type {toa.deployment.Deployment} */
35
-
36
- it('should be define', () => {
37
- const context = clone(fixtures.context)
38
-
39
- deployment = new Deployment(context, fixtures.compositions, fixtures.dependencies, fixtures.process)
40
-
41
- expect(typeof deployment.variables).toBe('function')
42
- })
43
-
44
- it('should return variables', () => {
45
- const context = clone(fixtures.context)
46
- const [{ variables }] = fixtures.dependencies
47
-
48
- deployment = new Deployment(context, fixtures.compositions, fixtures.dependencies, fixtures.process)
49
- expect(deployment.variables()).toEqual(variables)
50
- })
51
-
52
- it('should return variables', () => {
53
- const context = clone(fixtures.context)
54
- const [{ variables }] = fixtures.dependencies
55
-
56
- deployment = new Deployment(context, fixtures.compositions, fixtures.dependencies, fixtures.process)
57
-
58
- expect(deployment.variables()).toEqual(variables)
59
- })
60
-
61
- it('should merge all variables', () => {
62
- const context = clone(fixtures.context)
63
-
64
- /** @type {toa.deployment.Dependency} */
65
- const dep1 = { variables: { global: [fixtures.secretVariable] } }
66
-
67
- /** @type {toa.deployment.Dependency} */
68
- const dep2 = { variables: { global: [fixtures.bindingVariable] } }
69
-
70
- deployment = new Deployment(context, fixtures.compositions, [dep1, dep2], fixtures.process)
71
-
72
- const result = deployment.variables()
73
- const expectedVariables = [fixtures.bindingVariable, fixtures.secretVariable]
74
-
75
- expect(result.global.length).toBe(expectedVariables.length)
76
- expect(result.global).toStrictEqual(expect.arrayContaining(expectedVariables))
77
- })
78
- })
@@ -1,18 +0,0 @@
1
- import * as _deployment from './deployment'
2
- import * as _dependency from './dependency'
3
-
4
- declare namespace toa.deployment {
5
-
6
- interface Operator {
7
- export(path?: string): Promise<string>
8
-
9
- install(options?: _deployment.installation.Options): Promise<void>
10
-
11
- template(options?: _deployment.template.Options): Promise<string>
12
-
13
- variables(): _dependency.Variables
14
- }
15
-
16
- }
17
-
18
- export type Operator = toa.deployment.Operator
@@ -1,13 +0,0 @@
1
- declare namespace toa.operations {
2
-
3
- namespace process {
4
- interface Options {
5
- silently?: boolean
6
- }
7
- }
8
-
9
- interface Process {
10
- execute(cmd: string, args: Array<string>, options?: process.Options): Promise<string>
11
- }
12
-
13
- }
File without changes
File without changes
File without changes