@ossy/deployment-tools 0.0.77 → 0.0.80
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/README.md +0 -105
- package/package.json +5 -5
- package/src/deploy/cli.js +35 -4
- package/src/deploy/platform-deployment.js +56 -2
- package/src/docker/docker-service.js +2 -1
- package/src/infrastructure/cli.js +1 -1
- package/src/template/deployment-template.js +3 -5
- package/src/template/playground.js +5 -0
package/README.md
CHANGED
|
@@ -37,111 +37,6 @@ npx --yes @ossy/deployment-tools deploy \
|
|
|
37
37
|
--ossyfile packages/${{ github.event.inputs.packageName }}/ossy.json \
|
|
38
38
|
```
|
|
39
39
|
|
|
40
|
-
## Concepts
|
|
41
|
-
|
|
42
|
-
**Workspace**
|
|
43
|
-
|
|
44
|
-
A workspace is an umbrella for our services.
|
|
45
|
-
It needs to be associated with at least one billable account.
|
|
46
|
-
The workspace holds information like what tools and services are in use and should
|
|
47
|
-
be billed, and what users have access to these tools and services.
|
|
48
|
-
|
|
49
|
-
```
|
|
50
|
-
id: string;
|
|
51
|
-
name: string;
|
|
52
|
-
participants: WorkspaceParticipant[];
|
|
53
|
-
services: ServiceDefinition[];
|
|
54
|
-
billingInformation
|
|
55
|
-
|
|
56
|
-
```
|
|
57
|
-
|
|
58
|
-
## Our domains
|
|
59
|
-
|
|
60
|
-
ossy.se
|
|
61
|
-
www.ossy.se
|
|
62
|
-
test.ossy.se
|
|
63
|
-
|
|
64
|
-
api.ossy.se
|
|
65
|
-
api.test.ossy.se
|
|
66
|
-
|
|
67
|
-
plexus.ossy.se
|
|
68
|
-
plexus.test.ossy.se
|
|
69
|
-
|
|
70
|
-
oskarssylwan.se
|
|
71
|
-
www.oskarssylwan.se
|
|
72
|
-
test.oskarssylwan.se
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
## Overview of our infrastructure
|
|
76
|
-
|
|
77
|
-
We use AWS to host our infrastructure and all of it is defined in JavaScript with the help of
|
|
78
|
-
(AWS CDK)[https://aws.amazon.com/cdk/].
|
|
79
|
-
|
|
80
|
-
**Static content**
|
|
81
|
-
|
|
82
|
-
We use a s3 bucket for static content.
|
|
83
|
-
This bucket is used to host websites, images, videos and other static content.
|
|
84
|
-
On root level you'll find directories that represent one workspace each.
|
|
85
|
-
|
|
86
|
-
/<workspacId>/<service>/
|
|
87
|
-
/<workspacId>/websites/website-id
|
|
88
|
-
|
|
89
|
-
The bucket have directories for each workspace that is the workspaceID.
|
|
90
|
-
|
|
91
|
-
The bucket have directories for each workspace that contains a media directory and website directories
|
|
92
|
-
|
|
93
|
-
- a place to host media files like images, videos, pdf documents etc.
|
|
94
|
-
- a platform to host different docker images to
|
|
95
|
-
- a mongodb database that can ensure data persistance without much effort from our our side
|
|
96
|
-
- an email service
|
|
97
|
-
- an easy way to host multiple single page applications
|
|
98
|
-
|
|
99
|
-
Stacks
|
|
100
|
-
|
|
101
|
-
- email service stack per env
|
|
102
|
-
- media bucket stack per env
|
|
103
|
-
- stack for dns records with the account that holds domain names
|
|
104
|
-
|
|
105
|
-
### Adding a new AWS account
|
|
106
|
-
We have a different account for each service and environment.
|
|
107
|
-
To add a new account follow the steps below.
|
|
108
|
-
|
|
109
|
-
- Create an email group in GoogleAdmin with **public post access**.
|
|
110
|
-
The email should follow the pattern <service-name>-<env>@ossy.se.
|
|
111
|
-
If it's an account for prod use <service-name>@ossy.se.
|
|
112
|
-
Don't forgett to add yourself and other relevant people to the group.
|
|
113
|
-
- Log into our root organisation account and create a new aws account
|
|
114
|
-
with the same naming pattern and email as described above.
|
|
115
|
-
- Log out of the organisation account then send a password reset request to the
|
|
116
|
-
newly created account using the new email.
|
|
117
|
-
- Create a new user in the account with the same name as the account.
|
|
118
|
-
In the same process add the AdministratorAccess managed policy to the user.
|
|
119
|
-
- Create an access key to the account and add it as a (named profile)[https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-profiles.html] on your computer
|
|
120
|
-
- Create a keypair in the correct region and download it
|
|
121
|
-
- Add the new environment to the platforms.json file in this repository
|
|
122
|
-
- don't forget to add the keypair
|
|
123
|
-
- run the cdk ls command to make sure the new stack is picked up
|
|
124
|
-
- run cdk bootstrap for the account and region. This will create necessary resources like roles used by aws cdk.
|
|
125
|
-
- run deploy for all stacks
|
|
126
|
-
- add the instanceIp, awsRoleToAssume, and staticBucket name to the platforms.json file
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
<!-- Deploys AWS infrastructure
|
|
130
|
-
```
|
|
131
|
-
npx --yes @ossy/deployment-tools infrastructure deploy
|
|
132
|
-
```
|
|
133
|
-
|
|
134
|
-
Destroys AWS infrastructure
|
|
135
|
-
```
|
|
136
|
-
npx --yes @ossy/deployment-tools infrastructure destroy
|
|
137
|
-
```
|
|
138
|
-
|
|
139
|
-
Prints AWS infrastructure stacks
|
|
140
|
-
```
|
|
141
|
-
npx --yes @ossy/deployment-tools infrastructure ls
|
|
142
|
-
``` -->
|
|
143
|
-
|
|
144
|
-
|
|
145
40
|
The `cdk.json` file tells the CDK Toolkit how to execute your app.
|
|
146
41
|
|
|
147
42
|
* `cdk deploy` deploy this stack to your default AWS account/region
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ossy/deployment-tools",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.80",
|
|
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",
|
|
@@ -18,16 +18,16 @@
|
|
|
18
18
|
"@aws-sdk/client-sqs": "^3.245.0",
|
|
19
19
|
"@aws-sdk/client-sts": "^3.245.0",
|
|
20
20
|
"arg": "^5.0.2",
|
|
21
|
-
"aws-cdk
|
|
22
|
-
"
|
|
21
|
+
"aws-cdk": "^2.73.0",
|
|
22
|
+
"aws-cdk-lib": "^2.73.0",
|
|
23
|
+
"constructs": "^10.1.304",
|
|
23
24
|
"express": "^4.18.1",
|
|
24
25
|
"glob": "^9.3.2",
|
|
25
26
|
"nanoid": "^3.3.4",
|
|
26
27
|
"node-fetch": "^2.6.7"
|
|
27
28
|
},
|
|
28
29
|
"devDependencies": {
|
|
29
|
-
"aws-cdk": "^2.59.0",
|
|
30
30
|
"jest": "^27.5.1",
|
|
31
|
-
"jsdoc": "^
|
|
31
|
+
"jsdoc": "^4.0.2"
|
|
32
32
|
}
|
|
33
33
|
}
|
package/src/deploy/cli.js
CHANGED
|
@@ -22,8 +22,8 @@ const deploy = options => {
|
|
|
22
22
|
'--platforms-path': String,
|
|
23
23
|
'-pp': '--platforms-path',
|
|
24
24
|
|
|
25
|
-
'--
|
|
26
|
-
'-
|
|
25
|
+
'--deployments-path': String,
|
|
26
|
+
'-dp': '--deployments-path',
|
|
27
27
|
|
|
28
28
|
|
|
29
29
|
}, { argv: options })
|
|
@@ -34,14 +34,45 @@ const deploy = options => {
|
|
|
34
34
|
targetDomain: parsedArgs['--domain'],
|
|
35
35
|
targetPlatform: parsedArgs['--platform'],
|
|
36
36
|
pathToPlatformTemplates: parsedArgs['--platforms-path'],
|
|
37
|
-
|
|
37
|
+
pathToDeploymentTemplates: parsedArgs['--deployments-path']
|
|
38
|
+
})
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const deployAll = options => {
|
|
42
|
+
logInfo({ message: '[CLI] Running deploy-all command' })
|
|
43
|
+
|
|
44
|
+
const parsedArgs = arg({
|
|
45
|
+
'--username': String,
|
|
46
|
+
'-u': '--username',
|
|
47
|
+
|
|
48
|
+
'--authentication': String,
|
|
49
|
+
'--a': '--authentication',
|
|
50
|
+
|
|
51
|
+
'--platform': String,
|
|
52
|
+
'-p': '--platform',
|
|
53
|
+
|
|
54
|
+
'--platforms-path': String,
|
|
55
|
+
'-pp': '--platforms-path',
|
|
56
|
+
|
|
57
|
+
'--deployments-path': String,
|
|
58
|
+
'-dp': '--deployments-path',
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
}, { argv: options })
|
|
62
|
+
|
|
63
|
+
PlatformDeploymentService.deployAll({
|
|
64
|
+
username: parsedArgs['--username'],
|
|
65
|
+
authentication: parsedArgs['--authentication'],
|
|
66
|
+
targetPlatform: parsedArgs['--platform'],
|
|
67
|
+
pathToPlatformTemplates: parsedArgs['--platforms-path'],
|
|
68
|
+
pathToDeploymentTemplates: parsedArgs['--deployments-path']
|
|
38
69
|
})
|
|
39
70
|
}
|
|
40
71
|
|
|
41
72
|
module.exports = {
|
|
42
73
|
handler: ([command, ...options]) => {
|
|
43
74
|
!!command
|
|
44
|
-
? { deploy }[command](options)
|
|
75
|
+
? { deploy, 'deploy-all': deployAll }[command](options)
|
|
45
76
|
: logError({ message: 'No command provided' })
|
|
46
77
|
}
|
|
47
78
|
}
|
|
@@ -17,11 +17,11 @@ class PlatformDeploymentService {
|
|
|
17
17
|
targetDomain,
|
|
18
18
|
targetPlatform,
|
|
19
19
|
pathToPlatformTemplates,
|
|
20
|
-
|
|
20
|
+
pathToDeploymentTemplates
|
|
21
21
|
}) {
|
|
22
22
|
|
|
23
23
|
return Promise.all([
|
|
24
|
-
DeploymentTemplateService.
|
|
24
|
+
DeploymentTemplateService.readFromFiles(pathToDeploymentTemplates),
|
|
25
25
|
PlatformTemplateService.readFromFile(pathToPlatformTemplates)
|
|
26
26
|
.then(templates => templates.map(PlatformConfigService.from))
|
|
27
27
|
])
|
|
@@ -63,6 +63,60 @@ class PlatformDeploymentService {
|
|
|
63
63
|
.catch(error => logError({ message: '[PlatformDeploymentService] Could not send deployment request', error }))
|
|
64
64
|
}
|
|
65
65
|
|
|
66
|
+
static deployAll({
|
|
67
|
+
username,
|
|
68
|
+
authentication,
|
|
69
|
+
targetDomain,
|
|
70
|
+
targetPlatform,
|
|
71
|
+
pathToPlatformTemplates,
|
|
72
|
+
pathToDeploymentTemplates
|
|
73
|
+
}) {
|
|
74
|
+
|
|
75
|
+
return Promise.all([
|
|
76
|
+
DeploymentTemplateService.readFromFiles(pathToDeploymentTemplates),
|
|
77
|
+
PlatformTemplateService.readFromFile(pathToPlatformTemplates)
|
|
78
|
+
.then(templates => templates.map(PlatformConfigService.from))
|
|
79
|
+
])
|
|
80
|
+
.then(([deploymentTemplates, platformConfigs]) => {
|
|
81
|
+
|
|
82
|
+
const platformConfig = platformConfigs.find(({ platformName }) => platformName === targetPlatform)
|
|
83
|
+
const deploymentTemplatesForTargetPlatform = deploymentTemplates[targetPlatform] || []
|
|
84
|
+
|
|
85
|
+
if (!platformConfig) {
|
|
86
|
+
logError({ message: `[PlatformDeploymentService] Could not find a platform named ${targetPlatform}` })
|
|
87
|
+
return Promise.reject()
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
if (deploymentTemplatesForTargetPlatform.length === 0) {
|
|
91
|
+
logError({ message: `[PlatformDeploymentService] Could not find a deployment template for ${targetDomain} in ${targetPlatform}` })
|
|
92
|
+
return Promise.reject()
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0'
|
|
96
|
+
|
|
97
|
+
return deploymentTemplatesForTargetPlatform.map(deploymentTemplate => {
|
|
98
|
+
if (deploymentTemplate.type === SupportedDeploymentTypes.Container) {
|
|
99
|
+
|
|
100
|
+
const caddyConfig = CaddyConfigService.createConfig(platformConfig, deploymentTemplatesForTargetPlatform)
|
|
101
|
+
|
|
102
|
+
const deploymentRequest = {
|
|
103
|
+
...deploymentTemplate,
|
|
104
|
+
username: username,
|
|
105
|
+
authentication: authentication,
|
|
106
|
+
caddyConfig
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
return DeploymentQueueService.sendDeploymentRequest(platformConfig, deploymentRequest)
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
logError({ message: `[PlatformDeploymentService] Unsupported deployment type of ${deploymentTemplate.type}` })
|
|
113
|
+
return Promise.reject()
|
|
114
|
+
})
|
|
115
|
+
|
|
116
|
+
})
|
|
117
|
+
.catch(error => logError({ message: '[PlatformDeploymentService] Could not send deployment request', error }))
|
|
118
|
+
}
|
|
119
|
+
|
|
66
120
|
}
|
|
67
121
|
|
|
68
122
|
module.exports = {
|
|
@@ -33,7 +33,8 @@ class DockerService {
|
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
static removeImage(deploymentRequest) {
|
|
36
|
-
const
|
|
36
|
+
const { registry, image } = deploymentRequest
|
|
37
|
+
const name = !!registry ? `${registry}/${image}` : image
|
|
37
38
|
logInfo({ message: `[DockerService] Removing image ${name}` })
|
|
38
39
|
return exec(`docker image rm -f ${name}`)
|
|
39
40
|
.catch(() => {}) // no worries if container isn't there
|
|
@@ -9,7 +9,7 @@ const { PlatformConfigService } = require('../config')
|
|
|
9
9
|
const { PlatformDeploymentService } = require('../deploy')
|
|
10
10
|
|
|
11
11
|
Promise.all([
|
|
12
|
-
DeploymentTemplateService.
|
|
12
|
+
DeploymentTemplateService.readFromFiles(process.env.DEPLOYMENTS),
|
|
13
13
|
PlatformTemplateService
|
|
14
14
|
.readFromFile(process.env.PLATFORMS)
|
|
15
15
|
.then(templates => templates.map(PlatformConfigService.from))
|
|
@@ -25,16 +25,14 @@ class DeploymentTemplateService {
|
|
|
25
25
|
/**
|
|
26
26
|
* Read and and group deployments by targetDeploymentPlatform
|
|
27
27
|
*
|
|
28
|
-
* @param {string} blob - blob pattern for
|
|
28
|
+
* @param {string} blob - blob pattern for deployments.json files
|
|
29
29
|
*/
|
|
30
|
-
static
|
|
30
|
+
static readFromFiles(blob) {
|
|
31
31
|
return glob(blob, { ignore: 'node_modules/**' })
|
|
32
32
|
.then(filePaths => filePaths
|
|
33
33
|
.map(path => readFileSync(path, 'utf-8'))
|
|
34
|
-
.
|
|
35
|
-
.flatMap(ossyFileContent => ossyFileContent.deployments)
|
|
34
|
+
.flatMap(json => JSON.parse(json))
|
|
36
35
|
.reduce((deploymentsMap, deployment) => {
|
|
37
|
-
|
|
38
36
|
if (!!deploymentsMap[deployment.targetDeploymentPlatform]) {
|
|
39
37
|
return {
|
|
40
38
|
...deploymentsMap,
|