@ossy/deployment-tools 0.0.19 → 0.0.21
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/dist/index.js +32213 -16169
- package/package.json +4 -1
- package/src/aws-credentials-client.js +24 -0
- package/src/caddy-client.js +1 -1
- package/src/config.js +5 -0
- package/src/{container-manager-commands.js → container-manager-client.js} +22 -22
- package/src/container-manager-server.js +32 -16
- package/src/deployment-queue-client.js +57 -0
- package/src/index.js +3 -3
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ossy/deployment-tools",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.21",
|
|
4
4
|
"description": "Collection of scripts and tools to aid deployment of containers and static files",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -12,6 +12,9 @@
|
|
|
12
12
|
"license": "ISC",
|
|
13
13
|
"bin": "dist/index.js",
|
|
14
14
|
"dependencies": {
|
|
15
|
+
"@actions/core": "^1.10.0",
|
|
16
|
+
"@aws-sdk/client-sqs": "^3.186.0",
|
|
17
|
+
"@aws-sdk/client-sts": "^3.188.0",
|
|
15
18
|
"arg": "^5.0.2",
|
|
16
19
|
"express": "^4.18.1",
|
|
17
20
|
"nanoid": "^4.0.0",
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import * as core from '@actions/core'
|
|
2
|
+
import { STSClient, AssumeRoleWithWebIdentityCommand } from '@aws-sdk/client-sts'
|
|
3
|
+
|
|
4
|
+
export class AwsCredentialsClient {
|
|
5
|
+
|
|
6
|
+
static getTemporaryCredentials(awsAccountId, region, roleToAssume = 'github-ci-role') {
|
|
7
|
+
const stsClient = new STSClient({ region })
|
|
8
|
+
|
|
9
|
+
return core.getIDToken('sts.amazonaws.com')
|
|
10
|
+
.then(webIdentityToken => stsClient.send(new AssumeRoleWithWebIdentityCommand({
|
|
11
|
+
RoleArn: `arn:aws:iam::${awsAccountId}:role/${roleToAssume}`,
|
|
12
|
+
RoleSessionName: 'GitHubActions',
|
|
13
|
+
DurationSeconds: 5 * 60,
|
|
14
|
+
WebIdentityToken: webIdentityToken
|
|
15
|
+
})))
|
|
16
|
+
.then(responseData => ({
|
|
17
|
+
accessKeyId: responseData.Credentials.AccessKeyId,
|
|
18
|
+
secretAccessKey: responseData.Credentials.SecretAccessKey,
|
|
19
|
+
sessionToken: responseData.Credentials.SessionToken
|
|
20
|
+
}))
|
|
21
|
+
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
}
|
package/src/caddy-client.js
CHANGED
package/src/config.js
CHANGED
|
@@ -1,4 +1,9 @@
|
|
|
1
|
+
export const platformName = process.env.DEPLOYMENT_TOOLS_PLATFORM_NAME
|
|
1
2
|
export const domain = process.env.DEPLOYMENT_TOOLS_DOMAIN || 'localhost'
|
|
2
3
|
export const environmentName = process.env.DEPLOYMENT_TOOLS_ENVIRONMENT_NAME || 'dev'
|
|
3
4
|
export const ciSubDomain = process.env.DEPLOYMENT_TOOLS_CI_SUB_DOMAIN || 'ci'
|
|
4
5
|
export const port = process.env.DEPLOYMENT_TOOLS_PORT || 3000
|
|
6
|
+
export const awsAccountId = process.env.AWS_ACCOUNT_ID
|
|
7
|
+
export const awsRegion = process.env.AWS_REGION
|
|
8
|
+
|
|
9
|
+
export const deploymentQueueUrl = `https://sqs.${awsRegion}.amazonaws.com/${awsAccountId}/${platformName}-${environmentName}`
|
|
@@ -1,32 +1,36 @@
|
|
|
1
1
|
import { resolve } from 'path'
|
|
2
2
|
import { readFileSync } from 'fs'
|
|
3
|
-
import
|
|
3
|
+
import { AwsCredentialsClient } from './aws-credentials-client.js'
|
|
4
|
+
import { DeploymentQueueClient } from './deployment-manager-client.js'
|
|
4
5
|
|
|
5
|
-
export class
|
|
6
|
+
export class ContainerManagerClient {
|
|
6
7
|
|
|
8
|
+
//eslint-disable-next-line max-params
|
|
7
9
|
static deploy(
|
|
10
|
+
username,
|
|
11
|
+
authentication,
|
|
8
12
|
targetEnvironment = 'local-dev',
|
|
9
13
|
pathToDeploymentPlatforms,
|
|
10
14
|
pathToOssyFile
|
|
11
15
|
) {
|
|
12
|
-
const
|
|
13
|
-
return
|
|
16
|
+
const containerManagerClient = new ContainerManagerClient()
|
|
17
|
+
return containerManagerClient.deploy(
|
|
18
|
+
username,
|
|
19
|
+
authentication,
|
|
14
20
|
targetEnvironment,
|
|
15
21
|
pathToDeploymentPlatforms,
|
|
16
22
|
pathToOssyFile
|
|
17
23
|
)
|
|
18
24
|
}
|
|
19
25
|
|
|
20
|
-
constructor() {
|
|
21
|
-
|
|
22
|
-
}
|
|
26
|
+
constructor() {}
|
|
23
27
|
|
|
24
28
|
getDeployments(pathToOssyFile) {
|
|
25
29
|
const ossyfile = JSON.parse(readFileSync(resolve(pathToOssyFile), 'utf8'))
|
|
26
30
|
return Promise.resolve(ossyfile.deployments || [])
|
|
27
31
|
}
|
|
28
32
|
|
|
29
|
-
|
|
33
|
+
getDeploymentPlatforms(pathToDeploymentPlatforms) {
|
|
30
34
|
|
|
31
35
|
const localDevPlatform = {
|
|
32
36
|
name: 'dev',
|
|
@@ -36,9 +40,8 @@ export class ContainerManagerCommands {
|
|
|
36
40
|
|
|
37
41
|
if (!pathToDeploymentPlatforms) return [localDevPlatform]
|
|
38
42
|
|
|
39
|
-
const
|
|
40
|
-
|
|
41
|
-
return deploymentPlatforms || [localDevPlatform]
|
|
43
|
+
const deploymentPlatforms = JSON.parse(readFileSync(resolve(pathToDeploymentPlatforms), 'utf8'))
|
|
44
|
+
return Promise.resolve(deploymentPlatforms || [localDevPlatform])
|
|
42
45
|
}
|
|
43
46
|
|
|
44
47
|
getDeploymentTargetURL(targetEnvironment, deploymentPlatform, deployment) {
|
|
@@ -65,7 +68,7 @@ export class ContainerManagerCommands {
|
|
|
65
68
|
deploy(
|
|
66
69
|
username,
|
|
67
70
|
authentication,
|
|
68
|
-
targetEnvironment
|
|
71
|
+
targetEnvironment,
|
|
69
72
|
pathToDeploymentPlatforms,
|
|
70
73
|
pathToOssyFile
|
|
71
74
|
) {
|
|
@@ -99,17 +102,14 @@ export class ContainerManagerCommands {
|
|
|
99
102
|
authentication: authentication
|
|
100
103
|
}
|
|
101
104
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
105
|
+
return AwsCredentialsClient.getTemporaryCredentials(platform.awsAccountId, platform.awsRegion)
|
|
106
|
+
.then(credentials => {
|
|
107
|
+
const deploymentQueueClient = DeploymentQueueClient.new({ credentials })
|
|
108
|
+
return deploymentQueueClient.sendMessage(body)
|
|
109
|
+
.then(() => console.log('[ContainerManagerCommands] Deployment request has been sent'))
|
|
110
|
+
.catch(error => console.log('[ContainerManagerCommands] Could not send deployment request', error))
|
|
107
111
|
|
|
108
|
-
|
|
109
|
-
method: 'POST',
|
|
110
|
-
headers: { 'Content-Type': 'application/json' },
|
|
111
|
-
body: JSON.stringify(body)
|
|
112
|
-
})
|
|
112
|
+
})
|
|
113
113
|
})
|
|
114
114
|
})
|
|
115
115
|
.catch(error => console.log(error))
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import express from 'express'
|
|
2
2
|
import { CaddyClient } from './caddy-client.js'
|
|
3
3
|
import { DockerClient } from './docker-client.js'
|
|
4
|
+
import { DeploymentQueueClient } from './deployment-manager-client.js'
|
|
4
5
|
import * as config from './config.js'
|
|
5
6
|
|
|
6
7
|
export class ContainerManagerServer {
|
|
@@ -10,17 +11,18 @@ export class ContainerManagerServer {
|
|
|
10
11
|
}
|
|
11
12
|
|
|
12
13
|
constructor() {
|
|
14
|
+
this.server = express()
|
|
13
15
|
this.dockerClient = DockerClient.new()
|
|
14
16
|
this.caddyClient = CaddyClient.new()
|
|
15
|
-
this.
|
|
17
|
+
this.deploymentQueueClient = DeploymentQueueClient.new()
|
|
16
18
|
|
|
17
|
-
this.
|
|
19
|
+
this.applyDefaultCaddyConfig()
|
|
20
|
+
this.setupServerEndpoints()
|
|
21
|
+
this.pollForDeploymentRequests()
|
|
22
|
+
}
|
|
18
23
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
domain: `${config.ciSubDomain}.${config.environmentName}.${config.domain}`,
|
|
22
|
-
targetPort: config.port
|
|
23
|
-
}))
|
|
24
|
+
setupServerEndpoints() {
|
|
25
|
+
this.server.use(express.json())
|
|
24
26
|
|
|
25
27
|
this.server.get('/', (req, res) => {
|
|
26
28
|
res.redirect('/status')
|
|
@@ -30,19 +32,34 @@ export class ContainerManagerServer {
|
|
|
30
32
|
res.json('Server is live')
|
|
31
33
|
})
|
|
32
34
|
|
|
33
|
-
this.server.post('/deploy', (req, res) => {
|
|
34
|
-
console.log('/deploy body', req.body)
|
|
35
|
-
this.deploy(req, res)
|
|
36
|
-
})
|
|
37
|
-
|
|
38
35
|
this.server.listen(config.port, () => {
|
|
39
36
|
console.log(`Web API is live on port ${config.port}`)
|
|
40
37
|
})
|
|
41
38
|
}
|
|
42
39
|
|
|
43
|
-
|
|
40
|
+
applyDefaultCaddyConfig() {
|
|
41
|
+
this.caddyClient.applyDefaultServerConfig()
|
|
42
|
+
.then(() => this.caddyClient.deploy({
|
|
43
|
+
domain: `${config.ciSubDomain}.${config.environmentName}.${config.domain}`,
|
|
44
|
+
targetPort: config.port
|
|
45
|
+
}))
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
pollForDeploymentRequests() {
|
|
49
|
+
const FIVE_MINUTES = 3000
|
|
50
|
+
|
|
51
|
+
const handleIcomingMessages = () => this.deploymentQueueClient.receiveMessages()
|
|
52
|
+
.then(data => data.Messages.map(message => {
|
|
53
|
+
console.log('[ContainerManagerServer] handleIcomingMessages')
|
|
54
|
+
this.deploy(message)
|
|
55
|
+
this.deploymentQueueClient.deleteMessage(message.ReceiptHandle)
|
|
56
|
+
}))
|
|
57
|
+
.catch(error => console.log('[ContainerManagerServer] handleIcomingMessages error', error))
|
|
58
|
+
|
|
59
|
+
setInterval(handleIcomingMessages, FIVE_MINUTES)
|
|
60
|
+
}
|
|
44
61
|
|
|
45
|
-
|
|
62
|
+
deploy(deploymentRequestMessage) {
|
|
46
63
|
|
|
47
64
|
const {
|
|
48
65
|
registry,
|
|
@@ -53,7 +70,7 @@ export class ContainerManagerServer {
|
|
|
53
70
|
image,
|
|
54
71
|
domain,
|
|
55
72
|
env
|
|
56
|
-
} =
|
|
73
|
+
} = deploymentRequestMessage
|
|
57
74
|
|
|
58
75
|
this.dockerClient.deploy({
|
|
59
76
|
image,
|
|
@@ -67,7 +84,6 @@ export class ContainerManagerServer {
|
|
|
67
84
|
|
|
68
85
|
domain && this.caddyClient.deploy({ domain, targetPort: hostPort })
|
|
69
86
|
|
|
70
|
-
res.json('Recieved deployment request')
|
|
71
87
|
}
|
|
72
88
|
|
|
73
89
|
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import {
|
|
2
|
+
SQSClient,
|
|
3
|
+
SendMessageCommand,
|
|
4
|
+
DeleteMessageCommand,
|
|
5
|
+
ReceiveMessageCommand
|
|
6
|
+
} from '@aws-sdk/client-sqs'
|
|
7
|
+
import * as config from './config.js'
|
|
8
|
+
|
|
9
|
+
export class DeploymentQueueClient {
|
|
10
|
+
|
|
11
|
+
static new({ queueUrl, region, credentials } = {}) {
|
|
12
|
+
|
|
13
|
+
const deploymentQueueClientDefaultConfig = {
|
|
14
|
+
queueUrl: queueUrl || config.deploymentQueueUrl,
|
|
15
|
+
region: region || config.awsRegion,
|
|
16
|
+
credentials
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
return new DeploymentQueueClient(deploymentQueueClientDefaultConfig)
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
constructor({ queueUrl, region, credentials }) {
|
|
23
|
+
this.queueUrl = queueUrl
|
|
24
|
+
this.sqs = new SQSClient({ region, credentials })
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
sendMessage(messageBody) {
|
|
28
|
+
const command = SendMessageCommand({
|
|
29
|
+
QueueUrl: this.queueUrl,
|
|
30
|
+
MessageBody: JSON.stringify(messageBody)
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
return this.sqs.send(command)
|
|
34
|
+
.then(() => console.log('Success'))
|
|
35
|
+
.catch(err => console.log(err))
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
receiveMessages() {
|
|
39
|
+
const command = ReceiveMessageCommand({ QueueUrl: this.queueUrl })
|
|
40
|
+
|
|
41
|
+
return this.sqs.send(command)
|
|
42
|
+
.catch(error => console.log('Error', error))
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
deleteMessage(receiptHandle) {
|
|
46
|
+
const command = DeleteMessageCommand({
|
|
47
|
+
QueueUrl: this.queueUrl,
|
|
48
|
+
ReceiptHandle: receiptHandle
|
|
49
|
+
})
|
|
50
|
+
|
|
51
|
+
return this.sqs.send(command)
|
|
52
|
+
.then(() => console.log('success'))
|
|
53
|
+
.catch(error => console.log('Error', error))
|
|
54
|
+
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
}
|
package/src/index.js
CHANGED
|
@@ -3,7 +3,7 @@ import { platform } from 'os'
|
|
|
3
3
|
import { exec } from 'child_process'
|
|
4
4
|
import arg from 'arg'
|
|
5
5
|
import { ContainerManagerServer } from './container-manager-server.js'
|
|
6
|
-
import {
|
|
6
|
+
import { ContainerManagerClient } from './container-manager-client.js'
|
|
7
7
|
|
|
8
8
|
const [_, __, command, ...restArgs] = process.argv
|
|
9
9
|
|
|
@@ -40,7 +40,7 @@ const deployHandler = () => {
|
|
|
40
40
|
'-u': '--username',
|
|
41
41
|
|
|
42
42
|
'--authentication': String,
|
|
43
|
-
'--
|
|
43
|
+
'--a': '--authentication',
|
|
44
44
|
|
|
45
45
|
'--target-env': String,
|
|
46
46
|
'-t': '--target-env',
|
|
@@ -54,7 +54,7 @@ const deployHandler = () => {
|
|
|
54
54
|
|
|
55
55
|
console.log('args', args)
|
|
56
56
|
|
|
57
|
-
|
|
57
|
+
ContainerManagerClient.deploy(
|
|
58
58
|
args['--username'],
|
|
59
59
|
args['--authentication'],
|
|
60
60
|
args['--target-env'],
|