@ossy/deployment-tools 1.17.12 → 1.19.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/CHANGELOG.md +22 -0
- package/README.md +47 -38
- package/package.json +2 -2
- package/src/config/platform-config.js +1 -15
- package/src/infrastructure/cli.js +5 -9
- package/src/infrastructure/container-deployment-target/ossy-runtime.service.js +1 -0
- package/src/infrastructure/dns-stack.js +39 -47
- package/src/template/index.js +0 -1
- package/src/template/deployment-template.js +0 -83
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,28 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
+
# 1.19.0 (2026-05-25)
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
### Features
|
|
10
|
+
|
|
11
|
+
* **deployment-tools:** Add Docker Buildx setup and multi-platform support ([9eb6db2](https://github.com/ossy-se/ossy/commit/9eb6db29a8e09b29424abe8c013be65c051a0f30))
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
# 1.18.0 (2026-05-25)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
### Features
|
|
21
|
+
|
|
22
|
+
* **deployment-tools:** Add OSSY_API_URL environment variable for container deployment ([d09ae18](https://github.com/ossy-se/ossy/commit/d09ae18b5255e4c49fd5387c76d1af6a24b0ba22))
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
|
|
6
28
|
## 1.17.12 (2026-05-25)
|
|
7
29
|
|
|
8
30
|
**Note:** Version bump only for package @ossy/deployment-tools
|
package/README.md
CHANGED
|
@@ -2,75 +2,79 @@
|
|
|
2
2
|
|
|
3
3
|
Infrastructure and CDK tooling for the Ossy platform EC2 host.
|
|
4
4
|
|
|
5
|
-
The host runs
|
|
5
|
+
The host runs Caddy as a reverse proxy plus several Docker containers managed by systemd. Apps are deployed by running `ossy app publish`.
|
|
6
6
|
|
|
7
7
|
## Architecture
|
|
8
8
|
|
|
9
9
|
```
|
|
10
10
|
Internet → Caddy (:443)
|
|
11
|
-
├── api.ossy.se
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
├── api.ossy.se → ossy-api (:3001)
|
|
12
|
+
├── ossy.se → ossy-website-ossy (:3002) ← temporary
|
|
13
|
+
├── www.plexus-sanitas.com → ossy-website-plexus-sanitas (:3003) ← temporary
|
|
14
|
+
└── *.* (on-demand TLS) → ossy-platform (:3000)
|
|
15
|
+
└── loads build from CMS on first request
|
|
14
16
|
```
|
|
15
17
|
|
|
16
|
-
Caddy uses **on-demand TLS**: before issuing a certificate for any domain, it calls `GET http://localhost:3001/api/v0/apps/ask?domain=<domain>`. If the domain is registered (i.e. `ossy app publish` has been run for it), Caddy issues the cert and proxies to the runtime.
|
|
18
|
+
Caddy uses **on-demand TLS**: before issuing a certificate for any domain, it calls `GET http://localhost:3001/api/v0/apps/ask?domain=<domain>`. If the domain is registered (i.e. `ossy app publish` has been run for it), Caddy issues the cert and proxies to the platform runtime.
|
|
17
19
|
|
|
18
20
|
## Services
|
|
19
21
|
|
|
20
22
|
All services run as Docker containers managed by systemd. Service files are written to the EC2 host by CDK user data at instance creation.
|
|
21
23
|
|
|
22
|
-
| Service | Unit file | Port | Auto-start |
|
|
23
|
-
|
|
24
|
-
| Caddy | `caddy-route53.service` | 80, 443 | Yes |
|
|
25
|
-
| Ossy API | `ossy-api.service` | 3001 | Yes |
|
|
26
|
-
| Ossy
|
|
24
|
+
| Service | Unit file | Port | Auto-start | Image |
|
|
25
|
+
|---|---|---|---|---|
|
|
26
|
+
| Caddy | `caddy-route53.service` | 80, 443 | Yes | — |
|
|
27
|
+
| Ossy API | `ossy-api.service` | 3001 | Yes | `ghcr.io/ossy-se/api:latest` |
|
|
28
|
+
| Ossy Platform | `ossy-runtime.service` | 3000 | Yes | `ghcr.io/ossy-se/platform:latest` |
|
|
29
|
+
| website-ossy | `ossy-website-ossy.service` | 3002 | Yes | `ghcr.io/ossy-se/website-ossy:latest` |
|
|
30
|
+
| website-plexus-sanitas | `ossy-website-plexus-sanitas.service` | 3003 | Yes | `ghcr.io/ossy-se/website-plexus-sanitas:latest` |
|
|
27
31
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
- **Runtime** — image built from the published `@ossy/platform` npm package (no repo needed)
|
|
31
|
-
- **API** — image pulled from `ghcr.io/ossy-se/api:latest` (pushed by CI on every merge to main). The `ExecStartPre` in the service unit pulls the latest image before each start, so redeploying is just `systemctl restart ossy-api`
|
|
32
|
+
> **TODO (website-ossy, website-plexus-sanitas):** These are temporary services. Once `ossy app publish` is validated for each site, remove their service files and Caddy blocks so traffic flows through the platform runtime instead.
|
|
32
33
|
|
|
33
34
|
> **TODO:** Pin `@ossy/platform` to a specific version at CDK deploy time (thread through `PlatformConfig`) rather than always pulling `@latest`.
|
|
34
35
|
|
|
36
|
+
## Configuration — `platforms.json`
|
|
37
|
+
|
|
38
|
+
`packages/infrastructure/platforms.json` is the single source of truth for a platform. It contains:
|
|
39
|
+
|
|
40
|
+
- **AWS config** — account ID, key pair, S3 bucket name, IAM role
|
|
41
|
+
- **`domains`** — list of domains to create Route53 A records for, all pointing to the EC2 host IP
|
|
42
|
+
- **`env`** — environment variables written to `/etc/environment` on the EC2 host at boot time. **These are never uploaded to S3.**
|
|
43
|
+
|
|
44
|
+
To add or change environment variables, update the `env` block in `platforms.json` and redeploy. To add a new domain, add it to `domains` and redeploy.
|
|
45
|
+
|
|
35
46
|
## Bootstrapping a new host
|
|
36
47
|
|
|
37
|
-
CDK provisions the instance
|
|
48
|
+
CDK provisions the instance, writes all service files, writes `/etc/environment` from `platforms.json`, and starts all services automatically. No manual SSH steps required.
|
|
38
49
|
|
|
39
50
|
```bash
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
DB_URL=mongodb+srv://...
|
|
43
|
-
DB_NAME=ossy
|
|
44
|
-
TOKEN_SECRET=...
|
|
45
|
-
MEDIA_REPOSITORY=...
|
|
46
|
-
MEDIA_CDN_DOMAIN_NAME=...
|
|
47
|
-
AWS_ACCESS_KEY_ID=...
|
|
48
|
-
AWS_SECRET_ACCESS_KEY=...
|
|
49
|
-
OSSY_API_KEY=...
|
|
50
|
-
EOF
|
|
51
|
-
|
|
52
|
-
# Restart services to pick up the new env vars
|
|
53
|
-
sudo systemctl restart ossy-api ossy-runtime
|
|
51
|
+
cd packages/deployment-tools
|
|
52
|
+
npx cdk deploy ossybot-deployment-target --require-approval never
|
|
54
53
|
```
|
|
55
54
|
|
|
56
|
-
> Note:
|
|
55
|
+
> Note: EC2 user data only runs on **first boot**. To apply infrastructure changes to an existing instance you must terminate and recreate it, or SSH in and apply the changes manually.
|
|
57
56
|
|
|
58
57
|
## Redeploying after a code change
|
|
59
58
|
|
|
60
|
-
|
|
59
|
+
All services pull the latest image from GHCR on every restart — no manual build step needed.
|
|
61
60
|
|
|
62
61
|
```bash
|
|
63
|
-
# API — push to main triggers CI
|
|
62
|
+
# API — push to main triggers CI → ghcr.io/ossy-se/api:latest
|
|
64
63
|
sudo systemctl restart ossy-api
|
|
65
64
|
|
|
66
|
-
#
|
|
67
|
-
# builds and pushes ghcr.io/ossy-se/platform:latest
|
|
65
|
+
# Platform runtime — merge to main in ossy monorepo → ghcr.io/ossy-se/platform:latest
|
|
68
66
|
sudo systemctl restart ossy-runtime
|
|
67
|
+
|
|
68
|
+
# website-ossy — push to main in website-ossy repo → ghcr.io/ossy-se/website-ossy:latest
|
|
69
|
+
sudo systemctl restart ossy-website-ossy
|
|
70
|
+
|
|
71
|
+
# website-plexus-sanitas — push to main → ghcr.io/ossy-se/website-plexus-sanitas:latest
|
|
72
|
+
sudo systemctl restart ossy-website-plexus-sanitas
|
|
69
73
|
```
|
|
70
74
|
|
|
71
75
|
## Environment variables
|
|
72
76
|
|
|
73
|
-
|
|
77
|
+
All env vars are defined in the `env` block of `platforms.json` and written to `/etc/environment` at boot. Reference:
|
|
74
78
|
|
|
75
79
|
| Variable | Used by | Description |
|
|
76
80
|
|---|---|---|
|
|
@@ -81,17 +85,20 @@ Service env vars are read from `/etc/environment` on the host. Set these before
|
|
|
81
85
|
| `MEDIA_CDN_DOMAIN_NAME` | API | CloudFront domain for public media |
|
|
82
86
|
| `AWS_ACCESS_KEY_ID` | API | AWS credentials for S3 |
|
|
83
87
|
| `AWS_SECRET_ACCESS_KEY` | API | AWS credentials for S3 |
|
|
84
|
-
| `OSSY_API_KEY` |
|
|
88
|
+
| `OSSY_API_KEY` | Platform, websites | API JWT for CMS reads |
|
|
89
|
+
| `OSSY_COOKIE_SECRET` | Websites | Cookie signing secret |
|
|
90
|
+
| `OPENAI_API_KEY` | Worker | OpenAI API key |
|
|
91
|
+
| `OPENAI_ORGANIZATION` | Worker | OpenAI organisation ID |
|
|
85
92
|
|
|
86
93
|
## Infrastructure (CDK)
|
|
87
94
|
|
|
88
|
-
CDK stacks are defined in `src/infrastructure/`. Run
|
|
95
|
+
CDK stacks are defined in `src/infrastructure/`. Run via `cdk deploy` from the `deployment-tools` package.
|
|
89
96
|
|
|
90
97
|
| Stack | Description |
|
|
91
98
|
|---|---|
|
|
92
99
|
| `trust-ci` | IAM role for CI to deploy infrastructure |
|
|
93
100
|
| `deployment-target` | EC2 host, S3 bucket, CloudFront CDN for media |
|
|
94
|
-
| `dns` | Route53 records |
|
|
101
|
+
| `dns` | Route53 A records for all domains in `platforms.json` |
|
|
95
102
|
| `ses` | SES email sending |
|
|
96
103
|
|
|
97
104
|
## Useful commands
|
|
@@ -105,6 +112,7 @@ ssh -i path/to/keys ubuntu@<ip>
|
|
|
105
112
|
```bash
|
|
106
113
|
journalctl -u ossy-runtime.service -n 200 -f
|
|
107
114
|
journalctl -u ossy-api.service -n 200 -f
|
|
115
|
+
journalctl -u ossy-website-ossy.service -n 200 -f
|
|
108
116
|
journalctl -u caddy-route53.service -n 200 -f
|
|
109
117
|
```
|
|
110
118
|
|
|
@@ -117,6 +125,7 @@ docker ps
|
|
|
117
125
|
```bash
|
|
118
126
|
docker logs ossy-runtime
|
|
119
127
|
docker logs ossy-api
|
|
128
|
+
docker logs ossy-website-ossy
|
|
120
129
|
```
|
|
121
130
|
|
|
122
131
|
**Reload Caddy config**
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ossy/deployment-tools",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.19.0",
|
|
4
4
|
"description": "Collection of scripts and tools to aid deployment of containers and static files to Amazon Web Services through GitHub Actions",
|
|
5
5
|
"source": "./src/index.js",
|
|
6
6
|
"main": "./src/index.js",
|
|
@@ -26,5 +26,5 @@
|
|
|
26
26
|
"devDependencies": {
|
|
27
27
|
"jest": "^27.5.1"
|
|
28
28
|
},
|
|
29
|
-
"gitHead": "
|
|
29
|
+
"gitHead": "a40e3b439ced37f52db9526f799189e6d0809349"
|
|
30
30
|
}
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
* @typedef {Object} PlatformConfig
|
|
4
4
|
* @property {string} platformName - Name of platform
|
|
5
5
|
* @property {string[]=} sesDomains - list of domains to configure AWS SES email identity and DKIM records for
|
|
6
|
+
* @property {string[]=} domains - list of domains to create Route53 A records for, pointing to the EC2 host
|
|
6
7
|
* @property {object} dnsRecords - map of dns records by root domain, only supports MX records so that we can add dns records for our email service
|
|
7
8
|
* @property {Record<string,string>=} env - environment variables written to /etc/environment on the EC2 host at boot time; never uploaded to S3
|
|
8
9
|
*
|
|
@@ -10,8 +11,6 @@
|
|
|
10
11
|
* @property {string=} awsRegion - ?
|
|
11
12
|
* @property {string=} awsKeyPairName - ?
|
|
12
13
|
* @property {string} awsRoleToAssume - ?
|
|
13
|
-
* @property {string=} awsDeploymentSqsName - ?
|
|
14
|
-
* @property {string=} awsDeploymentSqsArn - ?
|
|
15
14
|
*
|
|
16
15
|
* @property {string=} ciDockerNetworkName - ?
|
|
17
16
|
* @property {string} ciGithubActionsRepo - organisation/repoName
|
|
@@ -21,11 +20,6 @@ const SupportedRegions = {
|
|
|
21
20
|
North: 'eu-north-1'
|
|
22
21
|
}
|
|
23
22
|
|
|
24
|
-
const SupportedDeploymentTypes = {
|
|
25
|
-
Container: 'CONTAINER',
|
|
26
|
-
Static: 'STATIC'
|
|
27
|
-
}
|
|
28
|
-
|
|
29
23
|
/**
|
|
30
24
|
* @class
|
|
31
25
|
*/
|
|
@@ -41,15 +35,8 @@ class PlatformConfigService {
|
|
|
41
35
|
ciDockerNetworkName: 'deployment-tools',
|
|
42
36
|
}
|
|
43
37
|
|
|
44
|
-
const awsDeploymentSqsName = `${withDefaults.platformName}-container-deployments-requests`
|
|
45
|
-
|
|
46
|
-
const awsDeploymentSqsArn =
|
|
47
|
-
`https://sqs.${withDefaults.awsRegion}.amazonaws.com/${withDefaults.awsAccountId}/${awsDeploymentSqsName}`
|
|
48
|
-
|
|
49
38
|
return {
|
|
50
39
|
...withDefaults,
|
|
51
|
-
awsDeploymentSqsName,
|
|
52
|
-
awsDeploymentSqsArn
|
|
53
40
|
}
|
|
54
41
|
|
|
55
42
|
}
|
|
@@ -59,5 +46,4 @@ class PlatformConfigService {
|
|
|
59
46
|
module.exports = {
|
|
60
47
|
PlatformConfigService,
|
|
61
48
|
SupportedRegions,
|
|
62
|
-
SupportedDeploymentTypes
|
|
63
49
|
}
|
|
@@ -5,16 +5,13 @@ const { TrustCiStack } = require('./trust-ci-stack')
|
|
|
5
5
|
const { DeploymentTargetStack } = require('./deployment-target-stack')
|
|
6
6
|
const { DnsStack } = require('./dns-stack')
|
|
7
7
|
const { SesStack } = require('./ses-stack')
|
|
8
|
-
const { PlatformTemplateService
|
|
8
|
+
const { PlatformTemplateService } = require('../template')
|
|
9
9
|
const { PlatformConfigService } = require('../config')
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
.then(templates => templates.map(PlatformConfigService.from))
|
|
16
|
-
])
|
|
17
|
-
.then(([deploymentMap, configs]) => {
|
|
11
|
+
PlatformTemplateService
|
|
12
|
+
.readFromFile('../infrastructure/platforms.json')
|
|
13
|
+
.then(templates => templates.map(PlatformConfigService.from))
|
|
14
|
+
.then(configs => {
|
|
18
15
|
const app = new App()
|
|
19
16
|
|
|
20
17
|
configs.forEach(config => {
|
|
@@ -33,7 +30,6 @@ Promise.all([
|
|
|
33
30
|
|
|
34
31
|
new DnsStack(app, `${config.platformName}-dns`, {
|
|
35
32
|
...stackProps,
|
|
36
|
-
deployments: deploymentMap[config.platformName],
|
|
37
33
|
containerDeploymentTargetPublicIp: deploymentTarget.containerDeploymentTargetPublicIp
|
|
38
34
|
})
|
|
39
35
|
|
|
@@ -12,6 +12,7 @@ ExecStart=/usr/bin/docker run --name ossy-runtime \\
|
|
|
12
12
|
--network ossy-network \\
|
|
13
13
|
-p 3000:3000 \\
|
|
14
14
|
-e OSSY_API_KEY=\${OSSY_API_KEY} \\
|
|
15
|
+
-e OSSY_API_URL=http://ossy-api:3001/api/v0 \\
|
|
15
16
|
ghcr.io/ossy-se/platform:latest
|
|
16
17
|
ExecStop=/usr/bin/docker stop ossy-runtime
|
|
17
18
|
Restart=on-failure
|
|
@@ -5,22 +5,15 @@ const {
|
|
|
5
5
|
MxRecord,
|
|
6
6
|
RecordTarget
|
|
7
7
|
} = require('aws-cdk-lib/aws-route53')
|
|
8
|
-
const { SupportedDeploymentTypes } = require('../config')
|
|
9
|
-
const { DeploymentTemplateService } = require('../template')
|
|
10
8
|
|
|
11
9
|
/**
|
|
12
10
|
* DnsStackProps
|
|
13
11
|
* @namespace DnsStack
|
|
14
12
|
* @typedef {Object} DnsStackProps
|
|
15
13
|
* @property {PlatformConfig} config - platform config
|
|
16
|
-
* @property {
|
|
17
|
-
* @property {string} containerDeploymentTargetPublicIp - public ip address of ec2 instance that hosts our containerss
|
|
14
|
+
* @property {string} containerDeploymentTargetPublicIp - public ip address of ec2 instance
|
|
18
15
|
*/
|
|
19
16
|
|
|
20
|
-
const InstanceImages = {
|
|
21
|
-
UBUNTU: 'ami-092cce4a19b438926'
|
|
22
|
-
}
|
|
23
|
-
|
|
24
17
|
/**
|
|
25
18
|
* @class
|
|
26
19
|
*/
|
|
@@ -29,57 +22,56 @@ class DnsStack extends Stack {
|
|
|
29
22
|
/**
|
|
30
23
|
* @param {object} scope - scope
|
|
31
24
|
* @param {string} id - id
|
|
32
|
-
* @param {
|
|
25
|
+
* @param {DnsStackProps} props - DnsStackProps
|
|
33
26
|
*/
|
|
34
27
|
constructor(scope, id, props) {
|
|
35
28
|
super(scope, id, props)
|
|
36
29
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
.
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
30
|
+
// Group domains by root domain so we can look up each hosted zone once.
|
|
31
|
+
const domainsByRoot = (props.config.domains ?? []).reduce((map, domain) => {
|
|
32
|
+
const parts = domain.split('.')
|
|
33
|
+
const rootDomain = parts.slice(-2).join('.')
|
|
34
|
+
map.has(rootDomain)
|
|
35
|
+
? map.set(rootDomain, [...map.get(rootDomain), domain])
|
|
36
|
+
: map.set(rootDomain, [domain])
|
|
37
|
+
return map
|
|
38
|
+
}, new Map())
|
|
39
|
+
|
|
40
|
+
domainsByRoot.forEach((domains, rootDomain) => {
|
|
41
|
+
const zone = HostedZone.fromLookup(this, `${rootDomain}-zone`, { domainName: rootDomain })
|
|
42
|
+
|
|
43
|
+
domains.forEach(domain => {
|
|
44
|
+
new ARecord(this, `${domain}-record`, {
|
|
45
|
+
zone,
|
|
46
|
+
recordName: domain,
|
|
47
|
+
target: RecordTarget.fromIpAddresses(props.containerDeploymentTargetPublicIp),
|
|
48
|
+
ttl: Duration.seconds(60)
|
|
52
49
|
})
|
|
50
|
+
})
|
|
53
51
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
records.forEach(({ type, ttl, recordName, values }) => {
|
|
58
|
-
switch (type) {
|
|
59
|
-
|
|
60
|
-
case 'MX':
|
|
61
|
-
new MxRecord(
|
|
62
|
-
this,
|
|
63
|
-
`${recordName}-MX-Record`,
|
|
64
|
-
{ type, recordName, values, ttl: Duration.seconds(ttl), zone }
|
|
65
|
-
)
|
|
66
|
-
break
|
|
52
|
+
if (props.config.dnsRecords && props.config.dnsRecords[rootDomain]) {
|
|
53
|
+
const records = props.config.dnsRecords[rootDomain] || []
|
|
67
54
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
}
|
|
71
|
-
})
|
|
72
|
-
}
|
|
55
|
+
records.forEach(({ type, ttl, recordName, values }) => {
|
|
56
|
+
switch (type) {
|
|
73
57
|
|
|
74
|
-
|
|
58
|
+
case 'MX':
|
|
59
|
+
new MxRecord(
|
|
60
|
+
this,
|
|
61
|
+
`${recordName}-MX-Record`,
|
|
62
|
+
{ type, recordName, values, ttl: Duration.seconds(ttl), zone }
|
|
63
|
+
)
|
|
64
|
+
break
|
|
75
65
|
|
|
66
|
+
default:
|
|
67
|
+
throw new Error(`Unsupported record type: ${type}`)
|
|
68
|
+
}
|
|
69
|
+
})
|
|
70
|
+
}
|
|
71
|
+
})
|
|
76
72
|
}
|
|
77
73
|
}
|
|
78
74
|
|
|
79
|
-
function createDnsRecords(zone, records) {
|
|
80
|
-
|
|
81
|
-
}
|
|
82
|
-
|
|
83
75
|
module.exports = {
|
|
84
76
|
DnsStack
|
|
85
77
|
}
|
package/src/template/index.js
CHANGED
|
@@ -1,83 +0,0 @@
|
|
|
1
|
-
const { glob } = require('glob')
|
|
2
|
-
const { readFileSync } = require('fs')
|
|
3
|
-
const { SupportedDeploymentTypes } = require('../config')
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Deployment template definition
|
|
7
|
-
* @typedef {Object} DeploymentTemplate
|
|
8
|
-
* @property {string} type - CONTAINER | STATIC
|
|
9
|
-
* @property {string} domain - example.com
|
|
10
|
-
* @property {string} targetDeploymentPlatform - name of platform to deploy to
|
|
11
|
-
*
|
|
12
|
-
* @property {string} image - name of image to be deployed
|
|
13
|
-
* @property {string} registry - registry where the image is hosted
|
|
14
|
-
* @property {string=} hostPort - host port
|
|
15
|
-
* @property {string=} containerPort - port that the container exposes
|
|
16
|
-
*/
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* Utility class that helps you read and validate platfor templates from file system
|
|
20
|
-
* @class
|
|
21
|
-
*/
|
|
22
|
-
class DeploymentTemplateService {
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* Read and and group deployments by targetDeploymentPlatform
|
|
26
|
-
*
|
|
27
|
-
* @param {string} blob - blob pattern for deployments.json files
|
|
28
|
-
*/
|
|
29
|
-
static readFromFiles(blob) {
|
|
30
|
-
return glob(blob, { ignore: 'node_modules/**' })
|
|
31
|
-
.then(filePaths => filePaths
|
|
32
|
-
.map(path => readFileSync(path, 'utf-8'))
|
|
33
|
-
.flatMap(json => JSON.parse(json))
|
|
34
|
-
.map(deploymentTemplate => ({
|
|
35
|
-
containerPort: '3000',
|
|
36
|
-
...deploymentTemplate
|
|
37
|
-
}))
|
|
38
|
-
.reduce((deploymentsMap, deployment) => {
|
|
39
|
-
if (!!deploymentsMap[deployment.targetDeploymentPlatform]) {
|
|
40
|
-
return {
|
|
41
|
-
...deploymentsMap,
|
|
42
|
-
[deployment.targetDeploymentPlatform]: [
|
|
43
|
-
...deploymentsMap[deployment.targetDeploymentPlatform],
|
|
44
|
-
deployment
|
|
45
|
-
]
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
return {
|
|
50
|
-
...deploymentsMap,
|
|
51
|
-
[deployment.targetDeploymentPlatform]: [deployment]
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
}, {})
|
|
55
|
-
)
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
static getContainerDeployments(deployments) {
|
|
59
|
-
return deployments
|
|
60
|
-
.filter(deployment => deployment.type === SupportedDeploymentTypes.Container)
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
static groupDeploymentDomainsByRootDomain(deployments) {
|
|
64
|
-
return deployments
|
|
65
|
-
.map(deployment => deployment.domain)
|
|
66
|
-
.reduce((domainGroups, domain) => {
|
|
67
|
-
const [topLevelDomain, domainName] = domain.split('.').reverse()
|
|
68
|
-
const rootDomain = `${domainName}.${topLevelDomain}`
|
|
69
|
-
|
|
70
|
-
domainGroups.has(rootDomain)
|
|
71
|
-
? domainGroups.set(rootDomain, [...domainGroups.get(rootDomain), domain])
|
|
72
|
-
: domainGroups.set(rootDomain, [domain])
|
|
73
|
-
|
|
74
|
-
return domainGroups
|
|
75
|
-
}, new Map())
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
module.exports = {
|
|
82
|
-
DeploymentTemplateService
|
|
83
|
-
}
|