@ossy/deployment-tools 0.0.39 → 0.0.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/bin/aws-credentials-client.d.ts +2 -2
- package/bin/caddy-client.d.ts +3 -3
- package/bin/ci-rest-api.d.ts +2 -2
- package/bin/deployment-queue-client.d.ts +4 -4
- package/bin/docker-client.d.ts +4 -4
- package/bin/index.d.ts +3 -1
- package/bin/index.js +4 -4
- package/bin/index.js.map +1 -1
- package/bin/{dist/index.cli.d.ts → platform-cli.d.ts} +0 -0
- package/bin/platform-client.d.ts +13 -0
- package/bin/platform-config.d.ts +4 -0
- package/bin/platform-template.d.ts +5 -0
- package/bin/types/index.d.ts +2 -2
- package/{dist/dist/types/index.d.ts → bin/types.d.ts} +2 -2
- package/dist/aws-credentials-client.d.ts +2 -2
- package/dist/caddy-client.d.ts +3 -3
- package/dist/ci-rest-api.d.ts +2 -2
- package/dist/deployment-queue-client.d.ts +4 -4
- package/dist/docker-client.d.ts +4 -4
- package/dist/index.d.ts +3 -1
- package/dist/index.js +4 -4
- package/dist/index.js.map +1 -1
- package/dist/{dist/index.cli.d.ts → platform-cli.d.ts} +0 -0
- package/dist/platform-client.d.ts +13 -0
- package/dist/platform-config.d.ts +4 -0
- package/dist/platform-template.d.ts +5 -0
- package/dist/types/index.d.ts +2 -2
- package/{bin/dist/types/index.d.ts → dist/types.d.ts} +2 -2
- package/package.json +2 -2
- package/src/aws-credentials-client.ts +2 -2
- package/src/caddy-client.ts +10 -10
- package/src/ci-rest-api.ts +4 -4
- package/src/cli-commands/deploy-handler.ts +10 -10
- package/src/cli-commands/index.ts +1 -1
- package/src/cli-commands/start-handler.ts +4 -4
- package/src/cli-commands/status-handler.ts +2 -2
- package/src/cli-commands/stop-handler.ts +1 -1
- package/src/deployment-queue-client.ts +15 -15
- package/src/docker-client.ts +7 -7
- package/src/index.d.ts +2 -0
- package/src/index.ts +3 -1
- package/src/{index.cli.ts → platform-cli.ts} +0 -0
- package/src/platform-client.ts +102 -0
- package/src/platform-config.ts +36 -0
- package/src/platform-template.ts +31 -0
- package/src/{types/index.ts → types.ts} +2 -2
- package/tsconfig.json +1 -2
- package/bin/deployment-platform-client.d.ts +0 -11
- package/bin/dist/aws-credentials-client.d.ts +0 -4
- package/bin/dist/caddy-client.d.ts +0 -13
- package/bin/dist/ci-rest-api.d.ts +0 -4
- package/bin/dist/cli-commands/deploy-handler.d.ts +0 -1
- package/bin/dist/cli-commands/index.d.ts +0 -4
- package/bin/dist/cli-commands/start-handler.d.ts +0 -1
- package/bin/dist/cli-commands/status-handler.d.ts +0 -1
- package/bin/dist/cli-commands/stop-handler.d.ts +0 -1
- package/bin/dist/deployment-platform-client.d.ts +0 -11
- package/bin/dist/deployment-queue-client.d.ts +0 -7
- package/bin/dist/docker-client.d.ts +0 -8
- package/bin/dist/index.d.ts +0 -2
- package/bin/dist/log/index.d.ts +0 -3
- package/bin/index.cli.d.ts +0 -1
- package/dist/deployment-platform-client.d.ts +0 -11
- package/dist/dist/aws-credentials-client.d.ts +0 -4
- package/dist/dist/caddy-client.d.ts +0 -13
- package/dist/dist/ci-rest-api.d.ts +0 -4
- package/dist/dist/cli-commands/deploy-handler.d.ts +0 -1
- package/dist/dist/cli-commands/index.d.ts +0 -4
- package/dist/dist/cli-commands/start-handler.d.ts +0 -1
- package/dist/dist/cli-commands/status-handler.d.ts +0 -1
- package/dist/dist/cli-commands/stop-handler.d.ts +0 -1
- package/dist/dist/deployment-platform-client.d.ts +0 -11
- package/dist/dist/deployment-queue-client.d.ts +0 -7
- package/dist/dist/docker-client.d.ts +0 -8
- package/dist/dist/index.d.ts +0 -2
- package/dist/dist/log/index.d.ts +0 -3
- package/dist/index.cli.d.ts +0 -2
- package/src/deployment-platform-client.ts +0 -141
|
File without changes
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { SupportedEnvironments, DeploymentTemplate } from 'types';
|
|
2
|
+
export declare class PlatformClient {
|
|
3
|
+
static start(platformTemplatesFilePath: string): void;
|
|
4
|
+
static deploy({ username, authentication, targetEnvironment, pathToPlatformTemplates, pathToOssyFile }: {
|
|
5
|
+
username: any;
|
|
6
|
+
authentication: any;
|
|
7
|
+
targetEnvironment: any;
|
|
8
|
+
pathToPlatformTemplates: any;
|
|
9
|
+
pathToOssyFile: any;
|
|
10
|
+
}): Promise<void>;
|
|
11
|
+
static getDeploymentTemplates(pathToOssyFile: string): Promise<DeploymentTemplate[]>;
|
|
12
|
+
static getEnvironmentVariables(targetEnvironment: SupportedEnvironments, deploymentRequest: DeploymentTemplate): any;
|
|
13
|
+
}
|
package/dist/types/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export interface
|
|
1
|
+
export interface PlatformTemplate {
|
|
2
2
|
platformName: string;
|
|
3
3
|
domain: string;
|
|
4
4
|
supportedDeploymentTypes: SupportedDeploymentTypes[];
|
|
@@ -13,7 +13,7 @@ export interface DeploymentPlatformTemplate {
|
|
|
13
13
|
ciServerName?: string;
|
|
14
14
|
ciDockerNetworkName?: string;
|
|
15
15
|
}
|
|
16
|
-
export interface
|
|
16
|
+
export interface PlatformConfig extends Required<Omit<PlatformTemplate, 'awsRoleToAssume' | 'awsKeyPairName'>> {
|
|
17
17
|
activeEnvironment: SupportedEnvironments;
|
|
18
18
|
awsRoleToAssume?: string;
|
|
19
19
|
awsKeyPairName?: string;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export interface
|
|
1
|
+
export interface PlatformTemplate {
|
|
2
2
|
platformName: string;
|
|
3
3
|
domain: string;
|
|
4
4
|
supportedDeploymentTypes: SupportedDeploymentTypes[];
|
|
@@ -13,7 +13,7 @@ export interface DeploymentPlatformTemplate {
|
|
|
13
13
|
ciServerName?: string;
|
|
14
14
|
ciDockerNetworkName?: string;
|
|
15
15
|
}
|
|
16
|
-
export interface
|
|
16
|
+
export interface PlatformConfig extends Required<Omit<PlatformTemplate, 'awsRoleToAssume' | 'awsKeyPairName'>> {
|
|
17
17
|
activeEnvironment: SupportedEnvironments;
|
|
18
18
|
awsRoleToAssume?: string;
|
|
19
19
|
awsKeyPairName?: string;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ossy/deployment-tools",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.41",
|
|
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
|
"type": "module",
|
|
6
6
|
"types": "dist/index.d.ts" ,
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
"test": "echo \"Error: no test specified\" && exit 1",
|
|
10
10
|
"build": "npm run build:public-exports && npm run build:cli",
|
|
11
11
|
"build:public-exports": "npx --yes @vercel/ncc build src/index.ts --source-map --out dist --license licenses.txt --minify",
|
|
12
|
-
"build:cli": "npx --yes @vercel/ncc build src/
|
|
12
|
+
"build:cli": "npx --yes @vercel/ncc build src/platform-cli.ts --source-map --out bin --license licenses.txt --minify"
|
|
13
13
|
},
|
|
14
14
|
"author": "Ossy",
|
|
15
15
|
"license": "ISC",
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import * as core from '@actions/core'
|
|
2
2
|
import { STSClient, AssumeRoleWithWebIdentityCommand } from '@aws-sdk/client-sts'
|
|
3
|
-
import {
|
|
3
|
+
import { PlatformConfig } from 'types'
|
|
4
4
|
import { logInfo, logError } from 'log'
|
|
5
5
|
|
|
6
6
|
export class AwsCredentialsClient {
|
|
7
7
|
|
|
8
|
-
static resolveAwsCredentials({ awsAccountId, awsRegion, awsRoleToAssume }:
|
|
8
|
+
static resolveAwsCredentials({ awsAccountId, awsRegion, awsRoleToAssume }: PlatformConfig) {
|
|
9
9
|
// If awsRoleToAssume is present, then we assume we run in a github workflow
|
|
10
10
|
// If awsRoleToAssume is not present, then we assume they are resolved localy by aws-sdk
|
|
11
11
|
if (!awsRoleToAssume) {
|
package/src/caddy-client.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import fetch from 'node-fetch'
|
|
2
2
|
import { logInfo, logError } from './log'
|
|
3
|
-
import {
|
|
3
|
+
import { PlatformConfig, ContainerDeploymentRequest } from 'types'
|
|
4
4
|
|
|
5
5
|
export const Matchers = {
|
|
6
6
|
host: host => ({ host: [host] }),
|
|
@@ -20,13 +20,13 @@ const Handlers = {
|
|
|
20
20
|
|
|
21
21
|
export class CaddyClient {
|
|
22
22
|
|
|
23
|
-
static deploy(
|
|
23
|
+
static deploy(platformConfig: PlatformConfig, deploymentRequest: ContainerDeploymentRequest) {
|
|
24
24
|
|
|
25
|
-
const url = `${deploymentRequest.subdomain}.${
|
|
25
|
+
const url = `${deploymentRequest.subdomain}.${platformConfig.activeEnvironment}.${platformConfig.domain}`
|
|
26
26
|
|
|
27
27
|
logInfo({ message: `[CaddyClient] Updating caddy config to route ${url} to localhost:${deploymentRequest.hostPort}` })
|
|
28
28
|
|
|
29
|
-
return fetch(`http://localhost:2019/config/apps/http/servers/${
|
|
29
|
+
return fetch(`http://localhost:2019/config/apps/http/servers/${platformConfig.ciServerName}/routes/0/handle`, {
|
|
30
30
|
method: 'POST',
|
|
31
31
|
headers: { 'Content-Type': 'application/json' },
|
|
32
32
|
body: JSON.stringify(Handlers.subroute([
|
|
@@ -39,7 +39,7 @@ export class CaddyClient {
|
|
|
39
39
|
.catch(error => logError({ message: `[CaddyClient] Could not update caddy config to include ${url}`, error }))
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
-
static applyDefaultServerConfig(
|
|
42
|
+
static applyDefaultServerConfig(platformConfig: PlatformConfig) {
|
|
43
43
|
logInfo({ message: '[CaddyClient] Applying default caddy config' })
|
|
44
44
|
return fetch('http://localhost:2019/load', {
|
|
45
45
|
method: 'POST',
|
|
@@ -48,15 +48,15 @@ export class CaddyClient {
|
|
|
48
48
|
apps: {
|
|
49
49
|
http: {
|
|
50
50
|
servers: {
|
|
51
|
-
[
|
|
51
|
+
[platformConfig.ciServerName]: {
|
|
52
52
|
listen: [':80', ':443'],
|
|
53
53
|
routes: [
|
|
54
54
|
{
|
|
55
|
-
match: [Matchers.host(`*.${
|
|
55
|
+
match: [Matchers.host(`*.${platformConfig.activeEnvironment}.${platformConfig.domain}`)],
|
|
56
56
|
handle: [Handlers.subroute([
|
|
57
57
|
{
|
|
58
|
-
match: [Matchers.host(`${
|
|
59
|
-
handle: [Handlers.subroute([{ handle: [Handlers.reverseProxy(
|
|
58
|
+
match: [Matchers.host(`${platformConfig.ciSubDomain}.${platformConfig.activeEnvironment}.${platformConfig.domain}`)],
|
|
59
|
+
handle: [Handlers.subroute([{ handle: [Handlers.reverseProxy(platformConfig.ciInternalServerPort)]}])]
|
|
60
60
|
}
|
|
61
61
|
])],
|
|
62
62
|
terminal: true
|
|
@@ -69,7 +69,7 @@ export class CaddyClient {
|
|
|
69
69
|
automation: {
|
|
70
70
|
policies: [
|
|
71
71
|
{
|
|
72
|
-
subjects:[
|
|
72
|
+
subjects:[`*.${platformConfig.activeEnvironment}.${platformConfig.domain}`],
|
|
73
73
|
issuers:[
|
|
74
74
|
{
|
|
75
75
|
challenges:{
|
package/src/ci-rest-api.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import express from 'express'
|
|
2
|
-
import {
|
|
2
|
+
import { PlatformConfig } from 'types'
|
|
3
3
|
import { logInfo } from './log'
|
|
4
4
|
|
|
5
5
|
export class CiRestApi {
|
|
6
6
|
|
|
7
|
-
static start(
|
|
7
|
+
static start(platformConfig: PlatformConfig) {
|
|
8
8
|
const server = express()
|
|
9
9
|
|
|
10
10
|
server.use(express.json())
|
|
@@ -17,8 +17,8 @@ export class CiRestApi {
|
|
|
17
17
|
res.send('Server is live')
|
|
18
18
|
})
|
|
19
19
|
|
|
20
|
-
server.listen(
|
|
21
|
-
logInfo({ message: `[ContainerManagerServer] API is live on port ${
|
|
20
|
+
server.listen(platformConfig.ciInternalServerPort, () => {
|
|
21
|
+
logInfo({ message: `[ContainerManagerServer] API is live on port ${platformConfig.ciInternalServerPort}`})
|
|
22
22
|
})
|
|
23
23
|
}
|
|
24
24
|
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import arg from 'arg'
|
|
2
|
-
import { logInfo } from '
|
|
3
|
-
import {
|
|
2
|
+
import { logInfo } from 'log'
|
|
3
|
+
import { PlatformClient } from 'platform-client'
|
|
4
4
|
|
|
5
5
|
export const deployHandler = cliArgs => {
|
|
6
|
-
logInfo({
|
|
6
|
+
logInfo({ message: 'Running deploy command' })
|
|
7
7
|
|
|
8
8
|
const parsedArgs = arg({
|
|
9
9
|
'--username': String,
|
|
@@ -22,11 +22,11 @@ export const deployHandler = cliArgs => {
|
|
|
22
22
|
'-p': '--platforms'
|
|
23
23
|
}, { argv: cliArgs })
|
|
24
24
|
|
|
25
|
-
|
|
26
|
-
parsedArgs['--username'],
|
|
27
|
-
parsedArgs['--authentication'],
|
|
28
|
-
parsedArgs['--target-env'],
|
|
29
|
-
parsedArgs['--platforms'],
|
|
30
|
-
parsedArgs['--ossyfile']
|
|
31
|
-
)
|
|
25
|
+
PlatformClient.deploy({
|
|
26
|
+
username: parsedArgs['--username'],
|
|
27
|
+
authentication: parsedArgs['--authentication'],
|
|
28
|
+
targetEnvironment: parsedArgs['--target-env'],
|
|
29
|
+
pathToPlatformTemplates: parsedArgs['--platforms'],
|
|
30
|
+
pathToOssyFile: parsedArgs['--ossyfile']
|
|
31
|
+
})
|
|
32
32
|
}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import arg from 'arg'
|
|
2
2
|
import { platform } from 'os'
|
|
3
3
|
import { logInfo, logError } from '../log'
|
|
4
|
-
import {
|
|
4
|
+
import { PlatformClient } from 'platform-client'
|
|
5
5
|
|
|
6
6
|
export const startHandler = cliArgs => {
|
|
7
|
-
logInfo({
|
|
7
|
+
logInfo({ message: 'Running start command' })
|
|
8
8
|
|
|
9
9
|
const Platforms = {
|
|
10
10
|
windows: 'win32',
|
|
@@ -12,7 +12,7 @@ export const startHandler = cliArgs => {
|
|
|
12
12
|
}
|
|
13
13
|
|
|
14
14
|
if ([Platforms.windows].includes(platform())) {
|
|
15
|
-
return logError({
|
|
15
|
+
return logError({ message: 'Deployment tools do not support this os' })
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
const parsedArgs = arg({
|
|
@@ -20,5 +20,5 @@ export const startHandler = cliArgs => {
|
|
|
20
20
|
'-p': '--platforms'
|
|
21
21
|
}, { argv: cliArgs })
|
|
22
22
|
|
|
23
|
-
|
|
23
|
+
PlatformClient.start(parsedArgs['--platforms'])
|
|
24
24
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { exec } from 'child_process'
|
|
2
|
-
import { logInfo } from '
|
|
2
|
+
import { logInfo } from 'log'
|
|
3
3
|
|
|
4
4
|
export const statusHandler = () => {
|
|
5
|
-
logInfo({
|
|
5
|
+
logInfo({ message: 'Running status command' })
|
|
6
6
|
exec('systemctl status deployment-tools.service')
|
|
7
7
|
}
|
|
@@ -4,19 +4,19 @@ import {
|
|
|
4
4
|
DeleteMessageCommand,
|
|
5
5
|
ReceiveMessageCommand
|
|
6
6
|
} from '@aws-sdk/client-sqs'
|
|
7
|
-
import {
|
|
7
|
+
import { PlatformConfig, ContainerDeploymentRequest } from 'types'
|
|
8
8
|
import { AwsCredentialsClient } from 'aws-credentials-client'
|
|
9
9
|
import { logInfo, logError, logDebug } from 'log'
|
|
10
10
|
|
|
11
11
|
export class DeploymentQueueClient {
|
|
12
12
|
|
|
13
|
-
static sendDeploymentRequest(
|
|
13
|
+
static sendDeploymentRequest(platformConfig: PlatformConfig, deploymentRequest: ContainerDeploymentRequest) {
|
|
14
14
|
logInfo({ message: '[DeploymentQueueClient] Starting deployment sequence' })
|
|
15
|
-
return DeploymentQueueClient.createAwsSqsClient(
|
|
15
|
+
return DeploymentQueueClient.createAwsSqsClient(platformConfig)
|
|
16
16
|
.then(sqsClient => {
|
|
17
17
|
|
|
18
18
|
const sendMessageParams = {
|
|
19
|
-
QueueUrl:
|
|
19
|
+
QueueUrl: platformConfig.awsDeploymentSqsArn,
|
|
20
20
|
MessageBody: JSON.stringify(deploymentRequest)
|
|
21
21
|
}
|
|
22
22
|
|
|
@@ -30,44 +30,44 @@ export class DeploymentQueueClient {
|
|
|
30
30
|
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
-
static pollForDeploymentRequests(
|
|
33
|
+
static pollForDeploymentRequests(platformConfig: PlatformConfig, handleDeploymentRequest: (deploymentRequest: ContainerDeploymentRequest) => Promise<void>) {
|
|
34
34
|
logInfo({ message: '[DeploymentQueueClient] Starting polling for deployment requests' })
|
|
35
|
-
DeploymentQueueClient.createAwsSqsClient(
|
|
35
|
+
DeploymentQueueClient.createAwsSqsClient(platformConfig).then(sqsClient => {
|
|
36
36
|
const FIVE_MINUTES = 3000
|
|
37
37
|
|
|
38
38
|
setInterval(() => {
|
|
39
39
|
|
|
40
|
-
const receiveMessageCommand = new ReceiveMessageCommand({ QueueUrl:
|
|
40
|
+
const receiveMessageCommand = new ReceiveMessageCommand({ QueueUrl: platformConfig.awsDeploymentSqsArn })
|
|
41
41
|
|
|
42
42
|
sqsClient.send(receiveMessageCommand)
|
|
43
43
|
.then(data => data.Messages.map(message => {
|
|
44
44
|
|
|
45
|
-
logInfo({
|
|
45
|
+
logInfo({ message: '[DeploymentQueueClient] Received deployment request' })
|
|
46
46
|
|
|
47
47
|
handleDeploymentRequest(JSON.parse(message.Body))
|
|
48
48
|
.then(() => {
|
|
49
49
|
|
|
50
50
|
const deleteMessageCommand = new DeleteMessageCommand({
|
|
51
|
-
QueueUrl:
|
|
51
|
+
QueueUrl: platformConfig.awsDeploymentSqsArn,
|
|
52
52
|
ReceiptHandle: message.ReceiptHandle
|
|
53
53
|
})
|
|
54
54
|
|
|
55
55
|
sqsClient.send(deleteMessageCommand)
|
|
56
|
-
.then(() => logInfo({
|
|
57
|
-
.catch(error => logError({
|
|
56
|
+
.then(() => logInfo({ message: '[DeploymentQueueClient] Removing deployment request from queue' }))
|
|
57
|
+
.catch(error => logError({ message: '[DeploymentQueueClient] Could not delete message from queue', error }))
|
|
58
58
|
})
|
|
59
59
|
|
|
60
60
|
}))
|
|
61
|
-
.catch(error => logError({
|
|
61
|
+
.catch(error => logError({ message: '[ContainerManagerServer] Could not handle incoming deployment request', error }))
|
|
62
62
|
}, FIVE_MINUTES)
|
|
63
63
|
|
|
64
64
|
})
|
|
65
65
|
}
|
|
66
66
|
|
|
67
|
-
static createAwsSqsClient(
|
|
68
|
-
return AwsCredentialsClient.resolveAwsCredentials(
|
|
67
|
+
static createAwsSqsClient(platformConfig: PlatformConfig) {
|
|
68
|
+
return AwsCredentialsClient.resolveAwsCredentials(platformConfig)
|
|
69
69
|
.then(awsCredentials => new SQSClient({
|
|
70
|
-
region:
|
|
70
|
+
region: platformConfig.awsRegion,
|
|
71
71
|
credentials: awsCredentials
|
|
72
72
|
}))
|
|
73
73
|
}
|
package/src/docker-client.ts
CHANGED
|
@@ -4,16 +4,16 @@ import { nanoid } from 'nanoid'
|
|
|
4
4
|
import path from 'path'
|
|
5
5
|
import { fileURLToPath } from 'url'
|
|
6
6
|
import { logInfo, logError } from './log'
|
|
7
|
-
import {
|
|
7
|
+
import { PlatformConfig, ContainerDeploymentRequest } from 'types'
|
|
8
8
|
|
|
9
9
|
const __filename = fileURLToPath(import.meta.url)
|
|
10
10
|
const __dirname = path.dirname(__filename)
|
|
11
11
|
|
|
12
12
|
export class DockerClient {
|
|
13
13
|
|
|
14
|
-
static createDockerNetworkForContainerManagerServer(
|
|
14
|
+
static createDockerNetworkForContainerManagerServer(platformConfig: PlatformConfig) {
|
|
15
15
|
logInfo({ message: '[DockerClient] Creating docker network for comunication between containers' })
|
|
16
|
-
exec(`sudo docker network create ${
|
|
16
|
+
exec(`sudo docker network create ${platformConfig.ciDockerNetworkName}`)
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
static stopContainer(deploymentRequest: ContainerDeploymentRequest) {
|
|
@@ -22,12 +22,12 @@ export class DockerClient {
|
|
|
22
22
|
return `sudo docker stop ${name} ||`
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
-
static startContainer(
|
|
25
|
+
static startContainer(platformConfig: PlatformConfig, { image, containerPort, hostPort, registry, env }: ContainerDeploymentRequest) {
|
|
26
26
|
const name = image.replaceAll('/', '_')
|
|
27
27
|
const imageUrl = !!registry ? `${registry}/${image}` : image
|
|
28
28
|
const envsAsString = Object.entries(env || {}).reduce((envs, [name, value]) => `${envs} --env ${name}=${value}`, '')
|
|
29
29
|
logInfo({ message: `Running docker start for image with the name of ${name} with port mapping ${hostPort}:${containerPort} and source ${imageUrl}` })
|
|
30
|
-
return `sudo docker run -d -p ${hostPort}:${containerPort} --name=${name} --network=${
|
|
30
|
+
return `sudo docker run -d -p ${hostPort}:${containerPort} --name=${name} --network=${platformConfig.ciDockerNetworkName} --network-alias=${name} --rm ${envsAsString} ${imageUrl}`
|
|
31
31
|
}
|
|
32
32
|
|
|
33
33
|
static resolveCredentials({ registry, username, authentication }: ContainerDeploymentRequest) {
|
|
@@ -42,14 +42,14 @@ export class DockerClient {
|
|
|
42
42
|
return `sudo docker login ${registry} -u ${username} -p ${authentication}`
|
|
43
43
|
}
|
|
44
44
|
|
|
45
|
-
static deploy(
|
|
45
|
+
static deploy(platformConfig: PlatformConfig, deploymentRequest: ContainerDeploymentRequest): Promise<void> {
|
|
46
46
|
return new Promise(resolve => {
|
|
47
47
|
logInfo({ message: 'Starting docker deployment sequence' })
|
|
48
48
|
|
|
49
49
|
const dockerCommandScript = `'#!/bin/bash'
|
|
50
50
|
${DockerClient.stopContainer(deploymentRequest)}
|
|
51
51
|
${DockerClient.resolveCredentials(deploymentRequest)}
|
|
52
|
-
${DockerClient.startContainer(
|
|
52
|
+
${DockerClient.startContainer(platformConfig, deploymentRequest)}`
|
|
53
53
|
|
|
54
54
|
const deploymentId = nanoid()
|
|
55
55
|
|
package/src/index.d.ts
ADDED
package/src/index.ts
CHANGED
|
File without changes
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { resolve } from 'path'
|
|
2
|
+
import { readFileSync } from 'fs'
|
|
3
|
+
import {
|
|
4
|
+
SupportedEnvironments,
|
|
5
|
+
ContainerDeploymentRequest,
|
|
6
|
+
DeploymentTemplate,
|
|
7
|
+
ContainerDeploymentTemplate,
|
|
8
|
+
SupportedDeploymentTypes
|
|
9
|
+
} from 'types'
|
|
10
|
+
import { PlatformTemplateService } from 'platform-template'
|
|
11
|
+
import { PlatformConfigService } from 'platform-config'
|
|
12
|
+
import { CaddyClient } from './caddy-client'
|
|
13
|
+
import { DockerClient } from './docker-client'
|
|
14
|
+
import { DeploymentQueueClient } from './deployment-queue-client'
|
|
15
|
+
import { CiRestApi } from './ci-rest-api'
|
|
16
|
+
import { logInfo, logError } from 'log'
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
// journalctl -u service-name.service
|
|
20
|
+
export class PlatformClient {
|
|
21
|
+
|
|
22
|
+
static start(platformTemplatesFilePath: string) {
|
|
23
|
+
PlatformTemplateService.readFromFile(platformTemplatesFilePath).then(([firstPlatformTemplateFound]) => {
|
|
24
|
+
const platformConfig = PlatformConfigService.from(firstPlatformTemplateFound)
|
|
25
|
+
|
|
26
|
+
CiRestApi.start(platformConfig)
|
|
27
|
+
CaddyClient.applyDefaultServerConfig(platformConfig)
|
|
28
|
+
|
|
29
|
+
DeploymentQueueClient.pollForDeploymentRequests(
|
|
30
|
+
platformConfig,
|
|
31
|
+
(deploymentRequest: ContainerDeploymentRequest) => {
|
|
32
|
+
DockerClient.deploy(platformConfig, deploymentRequest)
|
|
33
|
+
CaddyClient.deploy(platformConfig, deploymentRequest)
|
|
34
|
+
return Promise.resolve()
|
|
35
|
+
}
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
})
|
|
39
|
+
.catch(error => logError({ message: '[PlatformClient] Could not start the deployment platform', error }))
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
//eslint-disable-next-line max-params
|
|
43
|
+
static deploy({
|
|
44
|
+
username,
|
|
45
|
+
authentication,
|
|
46
|
+
targetEnvironment,
|
|
47
|
+
pathToPlatformTemplates,
|
|
48
|
+
pathToOssyFile
|
|
49
|
+
}) {
|
|
50
|
+
|
|
51
|
+
const platformConfigRequest = PlatformTemplateService.readFromFile(pathToPlatformTemplates)
|
|
52
|
+
.then(templates => templates.map(x => ({ ...x, activeEnvironment: targetEnvironment })))
|
|
53
|
+
.then(templates => templates.map(x => PlatformConfigService.from(x)))
|
|
54
|
+
|
|
55
|
+
const deploymentTemplatesRequest = PlatformClient.getDeploymentTemplates(pathToOssyFile)
|
|
56
|
+
|
|
57
|
+
return Promise.all([ platformConfigRequest, deploymentTemplatesRequest ])
|
|
58
|
+
.then(([platformConfigs, deploymentTemplates]) => {
|
|
59
|
+
deploymentTemplates.map(deploymentTemplate => {
|
|
60
|
+
|
|
61
|
+
const platformConfig = platformConfigs.find(config => config.platformName === deploymentTemplate.targetDeploymentPlatform)
|
|
62
|
+
|
|
63
|
+
if (!platformConfig) {
|
|
64
|
+
logError({ message: `[PlatformClient] Could not find a deployment platform with the name ${deploymentTemplate.targetDeploymentPlatform}` })
|
|
65
|
+
return Promise.reject()
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0'
|
|
69
|
+
|
|
70
|
+
if (deploymentTemplate.type !== SupportedDeploymentTypes.Container) {
|
|
71
|
+
logError({ message: `[PlatformClient] Unsupported deployment type of ${deploymentTemplate.type}` })
|
|
72
|
+
return Promise.reject()
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const deploymentRequest: ContainerDeploymentRequest = {
|
|
76
|
+
...deploymentTemplate as ContainerDeploymentTemplate,
|
|
77
|
+
env: PlatformClient.getEnvironmentVariables(targetEnvironment, deploymentTemplate),
|
|
78
|
+
username: username,
|
|
79
|
+
authentication: authentication
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
return DeploymentQueueClient.sendDeploymentRequest(platformConfig, deploymentRequest)
|
|
83
|
+
|
|
84
|
+
})
|
|
85
|
+
})
|
|
86
|
+
.catch(error => logError({ message: '[PlatformClient] Could not send deployment request', error }))
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
static getDeploymentTemplates(pathToOssyFile: string): Promise<DeploymentTemplate[]> {
|
|
90
|
+
const ossyfile = JSON.parse(readFileSync(resolve(pathToOssyFile), 'utf8'))
|
|
91
|
+
return Promise.resolve(ossyfile.deployments || [])
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
static getEnvironmentVariables(targetEnvironment: SupportedEnvironments, deploymentRequest: DeploymentTemplate) {
|
|
95
|
+
const envs = deploymentRequest.env || {}
|
|
96
|
+
return {
|
|
97
|
+
...(envs.shared || {}),
|
|
98
|
+
...(envs[targetEnvironment] || {})
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import {
|
|
2
|
+
PlatformConfig,
|
|
3
|
+
PlatformTemplate,
|
|
4
|
+
SupportedEnvironments,
|
|
5
|
+
SupportedRegions
|
|
6
|
+
} from 'types'
|
|
7
|
+
|
|
8
|
+
export class PlatformConfigService {
|
|
9
|
+
|
|
10
|
+
static from(template: PlatformTemplate): PlatformConfig {
|
|
11
|
+
|
|
12
|
+
const withDefaults = {
|
|
13
|
+
platformName: SupportedEnvironments.LOCAL,
|
|
14
|
+
domain: 'localhost',
|
|
15
|
+
activeEnvironment: SupportedEnvironments.LOCAL,
|
|
16
|
+
supportedDeploymentTypes: ['CONTAINER'],
|
|
17
|
+
ciSubDomain: 'ci',
|
|
18
|
+
ciInternalServerPort: 3000,
|
|
19
|
+
ciServerName: 'ci-client',
|
|
20
|
+
ciDockerNetworkName: 'deployment-tools',
|
|
21
|
+
awsRegion: SupportedRegions.North,
|
|
22
|
+
...template
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const awsDeploymentSqsArn = `https://sqs.${withDefaults.awsRegion}.amazonaws.com/${withDefaults.awsAccountId}/${withDefaults.platformName}-${withDefaults.activeEnvironment}`
|
|
26
|
+
const awsRoleToAssume = process.env.CI ? 'github-ci-role' : undefined
|
|
27
|
+
|
|
28
|
+
return {
|
|
29
|
+
...withDefaults,
|
|
30
|
+
awsDeploymentSqsArn,
|
|
31
|
+
awsRoleToAssume
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { resolve } from 'path'
|
|
2
|
+
import { readFileSync } from 'fs'
|
|
3
|
+
import { PlatformTemplate } from 'types'
|
|
4
|
+
import { logError, logInfo } from 'log'
|
|
5
|
+
|
|
6
|
+
export class PlatformTemplateService {
|
|
7
|
+
|
|
8
|
+
static readFromFile(path: string): Promise<PlatformTemplate[]> {
|
|
9
|
+
const fileData = readFileSync(resolve(path), 'utf8')
|
|
10
|
+
|
|
11
|
+
if (!fileData && typeof fileData !== 'string') {
|
|
12
|
+
logError({ message: `[DeploymentPlatformClient] Could not find a deployment platform at ${path}` })
|
|
13
|
+
return Promise.reject()
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
let potentialTemplates = JSON.parse(fileData)
|
|
17
|
+
|
|
18
|
+
if (!Array.isArray(potentialTemplates)) {
|
|
19
|
+
potentialTemplates = [potentialTemplates]
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const templates = potentialTemplates.map(PlatformTemplateService.fakeValidateTemplate)
|
|
23
|
+
logInfo({ message: `[PlatformTemplateService]: Found platforms [${templates.map(x => x.platformName).join(', ')}]` })
|
|
24
|
+
return Promise.resolve(templates)
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
static fakeValidateTemplate(obj: any): PlatformTemplate {
|
|
28
|
+
// todo: implement real one
|
|
29
|
+
return obj
|
|
30
|
+
}
|
|
31
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export interface
|
|
1
|
+
export interface PlatformTemplate {
|
|
2
2
|
platformName: string;
|
|
3
3
|
domain: string;
|
|
4
4
|
supportedDeploymentTypes: SupportedDeploymentTypes[];
|
|
@@ -14,7 +14,7 @@ export interface DeploymentPlatformTemplate {
|
|
|
14
14
|
ciDockerNetworkName?: string;
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
-
export interface
|
|
17
|
+
export interface PlatformConfig extends Required<Omit<PlatformTemplate, 'awsRoleToAssume' | 'awsKeyPairName'>> {
|
|
18
18
|
activeEnvironment: SupportedEnvironments;
|
|
19
19
|
awsRoleToAssume?: string;
|
|
20
20
|
awsKeyPairName?: string;
|
package/tsconfig.json
CHANGED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import { DeploymentPlatform, SupportedEnvironments, DeploymentTemplate } from 'types';
|
|
2
|
-
export declare class DeploymentPlatformClient {
|
|
3
|
-
static start(pathToDeploymentPlatforms: string): void;
|
|
4
|
-
static deploy(username: any, authentication: any, targetEnvironment: any, pathToDeploymentPlatforms: any, pathToOssyFile: any): Promise<void>;
|
|
5
|
-
static getDeploymentTemplates(pathToOssyFile: string): Promise<DeploymentTemplate[]>;
|
|
6
|
-
static getDeploymentPlatforms(pathToDeploymentPlatforms: string): Promise<DeploymentPlatform[]>;
|
|
7
|
-
static getEnvironmentVariables(targetEnvironment: SupportedEnvironments, deploymentRequest: DeploymentTemplate): any;
|
|
8
|
-
static resolveDeploymentPlatformValues(deploymentPlatform: DeploymentPlatform): DeploymentPlatform;
|
|
9
|
-
static setDefaultDeploymentPlatformValues(deploymentPlatform: DeploymentPlatform): DeploymentPlatform;
|
|
10
|
-
static setCalculatedDeploymentPlatformValues(deploymentPlatform: DeploymentPlatform): DeploymentPlatform;
|
|
11
|
-
}
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import { DeploymentPlatform, ContainerDeploymentRequest } from 'types';
|
|
2
|
-
export declare const Matchers: {
|
|
3
|
-
host: (host: any) => {
|
|
4
|
-
host: any[];
|
|
5
|
-
};
|
|
6
|
-
path: (path: any) => {
|
|
7
|
-
path: any[];
|
|
8
|
-
};
|
|
9
|
-
};
|
|
10
|
-
export declare class CaddyClient {
|
|
11
|
-
static deploy(deploymentPlatform: DeploymentPlatform, deploymentRequest: ContainerDeploymentRequest): Promise<void | import("node-fetch").Response>;
|
|
12
|
-
static applyDefaultServerConfig(deploymentPlatform: DeploymentPlatform): Promise<void | import("node-fetch").Response>;
|
|
13
|
-
}
|