@ossy/deployment-tools 0.0.53 → 0.0.55

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 (76) hide show
  1. package/jsdoc/AwsCredentialsService.html +166 -0
  2. package/jsdoc/AwsProfile.html +166 -0
  3. package/jsdoc/CaddyService.html +293 -0
  4. package/jsdoc/ContainerServer.html +265 -0
  5. package/jsdoc/DeploymentQueueService.html +166 -0
  6. package/jsdoc/DeploymentToolsService.html +166 -0
  7. package/jsdoc/DockerService.html +166 -0
  8. package/jsdoc/EstablishTrustStack.html +268 -0
  9. package/jsdoc/PlatformConfigService.html +166 -0
  10. package/jsdoc/PlatformDeploymentService.html +166 -0
  11. package/jsdoc/PlatformServerService.html +166 -0
  12. package/jsdoc/PlatformStack.html +166 -0
  13. package/jsdoc/PlatformTemplateService.html +502 -0
  14. package/jsdoc/RestApiService.html +166 -0
  15. package/jsdoc/aws-credentials_aws-credentials.js.html +138 -0
  16. package/jsdoc/config_platform-config.js.html +113 -0
  17. package/jsdoc/deploy_platform-deployment.js.html +155 -0
  18. package/jsdoc/deployment-queue_deployment-queue.js.html +132 -0
  19. package/jsdoc/fonts/OpenSans-Bold-webfont.eot +0 -0
  20. package/jsdoc/fonts/OpenSans-Bold-webfont.svg +1830 -0
  21. package/jsdoc/fonts/OpenSans-Bold-webfont.woff +0 -0
  22. package/jsdoc/fonts/OpenSans-BoldItalic-webfont.eot +0 -0
  23. package/jsdoc/fonts/OpenSans-BoldItalic-webfont.svg +1830 -0
  24. package/jsdoc/fonts/OpenSans-BoldItalic-webfont.woff +0 -0
  25. package/jsdoc/fonts/OpenSans-Italic-webfont.eot +0 -0
  26. package/jsdoc/fonts/OpenSans-Italic-webfont.svg +1830 -0
  27. package/jsdoc/fonts/OpenSans-Italic-webfont.woff +0 -0
  28. package/jsdoc/fonts/OpenSans-Light-webfont.eot +0 -0
  29. package/jsdoc/fonts/OpenSans-Light-webfont.svg +1831 -0
  30. package/jsdoc/fonts/OpenSans-Light-webfont.woff +0 -0
  31. package/jsdoc/fonts/OpenSans-LightItalic-webfont.eot +0 -0
  32. package/jsdoc/fonts/OpenSans-LightItalic-webfont.svg +1835 -0
  33. package/jsdoc/fonts/OpenSans-LightItalic-webfont.woff +0 -0
  34. package/jsdoc/fonts/OpenSans-Regular-webfont.eot +0 -0
  35. package/jsdoc/fonts/OpenSans-Regular-webfont.svg +1831 -0
  36. package/jsdoc/fonts/OpenSans-Regular-webfont.woff +0 -0
  37. package/jsdoc/global.html +800 -0
  38. package/jsdoc/index.html +65 -0
  39. package/jsdoc/infrastructure_container-server_aws-profile.js.html +76 -0
  40. package/jsdoc/infrastructure_container-server_caddy.service.js.html +123 -0
  41. package/jsdoc/infrastructure_container-server_container-server.js.html +229 -0
  42. package/jsdoc/infrastructure_container-server_deployment-tools.service.js.html +91 -0
  43. package/jsdoc/infrastructure_establish-trust-stack.js.html +119 -0
  44. package/jsdoc/infrastructure_platform-stack.js.html +107 -0
  45. package/jsdoc/scripts/linenumber.js +25 -0
  46. package/jsdoc/scripts/prettify/Apache-License-2.0.txt +202 -0
  47. package/jsdoc/scripts/prettify/lang-css.js +2 -0
  48. package/jsdoc/scripts/prettify/prettify.js +28 -0
  49. package/jsdoc/server_caddy.js.html +165 -0
  50. package/{src/server/docker.js → jsdoc/server_docker.js.html} +55 -1
  51. package/jsdoc/server_platform-server.js.html +91 -0
  52. package/jsdoc/server_rest-api.js.html +82 -0
  53. package/jsdoc/styles/jsdoc-default.css +358 -0
  54. package/jsdoc/styles/prettify-jsdoc.css +111 -0
  55. package/jsdoc/styles/prettify-tomorrow.css +132 -0
  56. package/jsdoc/template_platform-template.js.html +134 -0
  57. package/package.json +7 -6
  58. package/src/aws-credentials/aws-credentials.js +3 -0
  59. package/src/config/platform-config.js +9 -0
  60. package/src/deploy/platform-deployment.js +30 -0
  61. package/src/deployment-queue/deployment-queue.js +6 -3
  62. package/src/docker/docker-service.js +62 -0
  63. package/src/docker/docker-service.playground.js +17 -0
  64. package/src/docker/index.js +1 -0
  65. package/src/infrastructure/container-server/aws-profile.js +3 -0
  66. package/src/infrastructure/container-server/caddy.service.js +3 -0
  67. package/src/infrastructure/container-server/container-server.js +7 -0
  68. package/src/infrastructure/container-server/deployment-tools.service.js +5 -2
  69. package/src/infrastructure/establish-trust-stack.js +3 -0
  70. package/src/infrastructure/platform-stack.js +6 -2
  71. package/src/log.js +1 -1
  72. package/src/server/caddy.js +3 -0
  73. package/src/server/platform-server.js +5 -2
  74. package/src/server/rest-api.js +3 -0
  75. package/src/template/platform-template.js +24 -9
  76. package/src/types.js +0 -32
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ossy/deployment-tools",
3
- "version": "0.0.53",
3
+ "version": "0.0.55",
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,15 +18,16 @@
18
18
  "@aws-sdk/client-sqs": "^3.186.0",
19
19
  "@aws-sdk/client-sts": "^3.188.0",
20
20
  "arg": "^5.0.2",
21
+ "aws-cdk-lib": "2.47.0",
22
+ "constructs": "^10.0.0",
23
+ "dockerode": "^3.3.4",
21
24
  "express": "^4.18.1",
22
25
  "nanoid": "^3.3.4",
23
- "node-fetch": "^2.6.7",
24
- "aws-cdk-lib": "2.47.0",
25
- "constructs": "^10.0.0"
26
+ "node-fetch": "^2.6.7"
26
27
  },
27
28
  "devDependencies": {
28
- "jsdoc": "^3.6.11",
29
29
  "aws-cdk": "2.47.0",
30
- "jest": "^27.5.1"
30
+ "jest": "^27.5.1",
31
+ "jsdoc": "^3.6.11"
31
32
  }
32
33
  }
@@ -3,6 +3,9 @@ const { STSClient, AssumeRoleWithWebIdentityCommand } = require('@aws-sdk/client
3
3
 
4
4
  const { logInfo, logError } = require('../log')
5
5
 
6
+ /**
7
+ * @class
8
+ */
6
9
  class AwsCredentialsService {
7
10
 
8
11
  static resolveAwsCredentials(platformConfig) {
@@ -15,6 +15,15 @@ const SupportedDeploymentTypes = {
15
15
  // Static = 'STATIC'
16
16
  }
17
17
 
18
+ // export interface PlatformConfig extends Required<Omit<PlatformTemplate, 'awsRoleToAssume' | 'awsKeyPairName'>> {
19
+ // activeEnvironment: SupportedEnvironments;
20
+ // awsRoleToAssume?: string;
21
+ // awsKeyPairName?: string;
22
+ // }
23
+
24
+ /**
25
+ * @class
26
+ */
18
27
  class PlatformConfigService {
19
28
 
20
29
  static from(template) {
@@ -5,6 +5,36 @@ const { PlatformConfigService, SupportedDeploymentTypes } = require('../config')
5
5
  const { DeploymentQueueService } = require('../deployment-queue')
6
6
  const { logError } = require('../log')
7
7
 
8
+ // export interface DeploymentTemplate {
9
+ // type: SupportedDeploymentTypes;
10
+ // targetDeploymentPlatform: string;
11
+ // subdomain?: string;
12
+ // env?: {
13
+ // shared?: { [name: string]: string | number };
14
+ // prod?: { [name: string]: string | number };
15
+ // test?: { [name: string]: string | number };
16
+ // qa?: { [name: string]: string | number };
17
+ // }
18
+ // }
19
+
20
+ // export interface ContainerDeploymentTemplate extends DeploymentTemplate {
21
+ // type: SupportedDeploymentTypes.Container;
22
+ // dockerFile: string;
23
+ // dockerContext: string;
24
+ // image: string;
25
+ // hostPort: number;
26
+ // containerPort: number;
27
+ // registry: string;
28
+ // }
29
+
30
+ // export interface ContainerDeploymentRequest extends ContainerDeploymentTemplate {
31
+ // authentication?: string;
32
+ // username?: string;
33
+ // }
34
+
35
+ /**
36
+ * @class
37
+ */
8
38
  class PlatformDeploymentService {
9
39
 
10
40
  static deploy({
@@ -7,6 +7,9 @@ const {
7
7
  const { AwsCredentialsService } = require('../aws-credentials')
8
8
  const { logInfo, logError, logDebug } = require('../log')
9
9
 
10
+ /**
11
+ * @class
12
+ */
10
13
  class DeploymentQueueService {
11
14
 
12
15
  static sendDeploymentRequest(platformConfig, deploymentRequest) {
@@ -32,14 +35,14 @@ class DeploymentQueueService {
32
35
  static pollForDeploymentRequests(platformConfig, handleDeploymentRequest) {
33
36
  logInfo({ message: '[DeploymentQueueService] Starting polling for deployment requests' })
34
37
  DeploymentQueueService.createAwsSqsClient(platformConfig).then(sqsClient => {
35
- const FIVE_MINUTES = 3000
38
+ const FIVE_MINUTES = 300000
36
39
 
37
40
  setInterval(() => {
38
41
 
39
42
  const receiveMessageCommand = new ReceiveMessageCommand({ QueueUrl: platformConfig.awsDeploymentSqsArn })
40
43
 
41
44
  sqsClient.send(receiveMessageCommand)
42
- .then(data => data.Messages.map(message => {
45
+ .then(data => data && data.Messages && data.Messages.map(message => {
43
46
 
44
47
  logInfo({ message: '[DeploymentQueueService] Received deployment request' })
45
48
 
@@ -57,7 +60,7 @@ class DeploymentQueueService {
57
60
  })
58
61
 
59
62
  }))
60
- .catch(error => logError({ message: '[ContainerManagerServer] Could not handle incoming deployment request', error }))
63
+ .catch(error => logError({ message: '[DeploymentQueueService] Could not handle incoming deployment request', error }))
61
64
  }, FIVE_MINUTES)
62
65
 
63
66
  })
@@ -0,0 +1,62 @@
1
+ const { exec: execBash } = require('child_process')
2
+ const { logInfo, logDebug } = require('../log')
3
+
4
+ const exec = command => new Promise((resolve, reject) => {
5
+ execBash(command, (error, stdout, stderr) => {
6
+ if (error) return reject(error)
7
+ if (stderr) return reject(stderr)
8
+ resolve(stdout)
9
+ })
10
+ })
11
+
12
+ /**
13
+ * @class
14
+ */
15
+ class DockerService {
16
+
17
+ static createDockerNetworkForContainerManagerServer(platformConfig) {
18
+ logInfo({ message: '[DockerService] Creating docker network for comunication between containers' })
19
+ return exec(`docker network create ${platformConfig.ciDockerNetworkName}`)
20
+ }
21
+
22
+ static stopContainer(deploymentRequest) {
23
+ const name = deploymentRequest.image.replaceAll('/', '_')
24
+ logInfo({ message: `[DockerService] Running docker stop for image with the name of ${name}` })
25
+ return exec(`docker stop ${name}`)
26
+ .catch(() => {}) // no worries if container isn't there
27
+ }
28
+
29
+ static startContainer(platformConfig, { image, containerPort, hostPort, registry, env }) {
30
+ const name = image.replaceAll('/', '_')
31
+ const imageUrl = !!registry ? `${registry}/${image}` : image
32
+ const envsAsString = Object.entries(env || {}).reduce((envs, [name, value]) => `${envs} --env ${name}=${value}`, '')
33
+ logInfo({ message: `[DockerService] Running docker start for image with the name of ${name} with port mapping ${hostPort}:${containerPort} and source ${imageUrl}` })
34
+ return exec(`docker run -d -p ${hostPort}:${containerPort} --name=${name} --network=${platformConfig.ciDockerNetworkName} --network-alias=${name} --rm ${envsAsString} ${imageUrl}`)
35
+ }
36
+
37
+ static resolveCredentials({ registry, username, authentication }) {
38
+ const shouldAuthenticate = username || authentication
39
+
40
+ shouldAuthenticate
41
+ ? logInfo({ message: '[DockerService] Docker credentials provided, logging in to private repository' })
42
+ : logInfo({ message: '[DockerService] No docker credentials provided, assuming image is publicly hosted' })
43
+
44
+ return shouldAuthenticate
45
+ ? exec(`docker login ${registry} -u ${username} -p ${authentication}`)
46
+ : Promise.resolve()
47
+ }
48
+
49
+ static deploy(platformConfig, deploymentRequest) {
50
+ logInfo({ message: '[DockerService] Starting docker deployment sequence' })
51
+ logDebug({ message: '[DockerService] deploymentRequest', data: deploymentRequest })
52
+
53
+ return DockerService.resolveCredentials(deploymentRequest)
54
+ .then(() => DockerService.stop(deploymentRequest))
55
+ .then(() => DockerService.startContainer(platformConfig, deploymentRequest))
56
+ }
57
+
58
+ }
59
+
60
+ module.exports = {
61
+ DockerService
62
+ }
@@ -0,0 +1,17 @@
1
+ const { DockerService } = require('./docker-service')
2
+
3
+ DockerService.deploy(
4
+ { ciDockerNetworkName: 'deployment-tools' },
5
+ {
6
+ type: 'CONTAINER',
7
+ dockerFile: './Dockerfile-prod',
8
+ dockerContext: './',
9
+ targetDeploymentPlatform: 'oskarssylwan',
10
+ image: 'mongo',
11
+ hostPort: '3005',
12
+ containerPort: '3000',
13
+ subdomain: 'cms',
14
+ env: {},
15
+ registry: 'ghcr.io'
16
+ }
17
+ )
@@ -0,0 +1 @@
1
+ module.exports = require('./docker-service')
@@ -1,3 +1,6 @@
1
+ /**
2
+ * @class
3
+ */
1
4
  class AwsProfile {
2
5
 
3
6
  static writeFile(roleArn, region) {
@@ -30,6 +30,9 @@ AmbientCapabilities=CAP_NET_BIND_SERVICE
30
30
  WantedBy=multi-user.target cloud-init.target
31
31
  `
32
32
 
33
+ /**
34
+ * @class
35
+ */
33
36
  class CaddyService {
34
37
 
35
38
  static install() {
@@ -35,6 +35,9 @@ const InstanceImages = {
35
35
  UBUNTU: 'ami-092cce4a19b438926'
36
36
  }
37
37
 
38
+ /**
39
+ * @class
40
+ */
38
41
  class ContainerServer extends Construct {
39
42
 
40
43
  /**
@@ -108,6 +111,9 @@ class ContainerServer extends Construct {
108
111
  const userData = UserData.forLinux()
109
112
 
110
113
  userData.addCommands(
114
+ 'sudo groupadd docker',
115
+ 'sudo usermod -aG docker ubuntu',
116
+ 'newgrp docker',
111
117
  'sudo apt update -y',
112
118
  ...getInstallNodeJs(),
113
119
  ...getInstallNpm(),
@@ -148,6 +154,7 @@ class ContainerServer extends Construct {
148
154
  })
149
155
 
150
156
  props.platformConfigBucket.grantRead(ec2Instance, '*')
157
+ props.deploymentQueue.grant(ec2Instance, '*')
151
158
 
152
159
  // const hostedZone = !!props.createNewHostedZone
153
160
  // ? new PublicHostedZone(this, 'HostedZone', { zoneName: props.domain })
@@ -5,8 +5,8 @@ After=network.target caddy-route53.service
5
5
 
6
6
  [Service]
7
7
  EnvironmentFile=/etc/environment
8
- User=caddy
9
- Group=caddy
8
+ User=ubuntu
9
+ Group=docker
10
10
  AmbientCapabilities=CAP_NET_BIND_SERVICE
11
11
  CapabilityBoundingSet=CAP_NET_BIND_SERVICE
12
12
  ExecStart=/usr/bin/npx --yes @ossy/deployment-tools server start --platforms /home/ubuntu/platform-config.json
@@ -16,6 +16,9 @@ Restart=on-failure
16
16
  WantedBy=multi-user.target cloud-init.target
17
17
  `
18
18
 
19
+ /**
20
+ * @class
21
+ */
19
22
  class DeploymentToolsService {
20
23
 
21
24
  static install() {
@@ -8,6 +8,9 @@ const {
8
8
  PolicyStatement
9
9
  } = require('aws-cdk-lib/aws-iam')
10
10
 
11
+ /**
12
+ * @class
13
+ */
11
14
  class EstablishTrustStack extends Stack {
12
15
  /**
13
16
  * Establishes trust between GithHub and Amazon Web Services.
@@ -8,6 +8,9 @@ const { ContainerServer } = require('./container-server')
8
8
 
9
9
  const { SupportedDeploymentTypes } = require('../config')
10
10
 
11
+ /**
12
+ * @class
13
+ */
11
14
  class PlatformStack extends Stack {
12
15
  constructor(scope, id, props) {
13
16
  super(scope, id, props)
@@ -20,7 +23,7 @@ class PlatformStack extends Stack {
20
23
 
21
24
  if (isContainerDeploymentsEnabled) {
22
25
 
23
- new Queue(this, 'DeploymentQueue', {
26
+ const deploymentQueue = new Queue(this, 'DeploymentQueue', {
24
27
  queueName: `${props.config.platformName}-${props.config.activeEnvironment}`,
25
28
  receiveMessageWaitTime: Duration.seconds(20)
26
29
  })
@@ -40,7 +43,8 @@ class PlatformStack extends Stack {
40
43
 
41
44
  new ContainerServer(this, 'ContainerServer', {
42
45
  platformConfig: props.config,
43
- platformConfigBucket: platformConfigDeployment.deployedBucket
46
+ platformConfigBucket: platformConfigDeployment.deployedBucket,
47
+ deploymentQueue: deploymentQueue
44
48
  })
45
49
 
46
50
  }
package/src/log.js CHANGED
@@ -26,7 +26,7 @@ const logError = logInput => {
26
26
  }
27
27
 
28
28
  const logDebug = logInput => {
29
- const isDebugOn = process.env.DEBUG || false
29
+ const isDebugOn = process.env.DEBUG || true
30
30
  if (!isDebugOn) return
31
31
  const messagePrefix = prefixTo(TypeOfMessage.Debug, logInput.message)
32
32
  log(`${messagePrefix}${logInput.message}`)
@@ -17,6 +17,9 @@ const Handlers = {
17
17
  })
18
18
  }
19
19
 
20
+ /**
21
+ * @class
22
+ */
20
23
  class CaddyService {
21
24
 
22
25
  static addDeployment(platformConfig, deploymentRequest) {
@@ -1,5 +1,5 @@
1
1
  const { CaddyService } = require('./caddy')
2
- const { DockerService } = require('./docker')
2
+ const { DockerService } = require('../docker')
3
3
  const { RestApiService } = require('./rest-api')
4
4
 
5
5
  const { PlatformTemplateService } = require('../template')
@@ -7,7 +7,10 @@ const { PlatformConfigService } = require('../config')
7
7
  const { DeploymentQueueService } = require('../deployment-queue')
8
8
  const { logError } = require('../log')
9
9
 
10
- // journalctl -u service-name.service
10
+ // journalctl -u deployment-tools.service
11
+ /**
12
+ * @class
13
+ */
11
14
  class PlatformServerService {
12
15
 
13
16
  static start(platformTemplatesFilePath) {
@@ -1,6 +1,9 @@
1
1
  const express = require('express')
2
2
  const { logInfo } = require('../log')
3
3
 
4
+ /**
5
+ * @class
6
+ */
4
7
  class RestApiService {
5
8
 
6
9
  static start(platformConfig) {
@@ -4,27 +4,33 @@ const { logError, logInfo } = require('../log')
4
4
 
5
5
  /**
6
6
  * Platform template definition
7
- * @namespace PlatformTemplate
8
7
  * @typedef {Object} PlatformTemplate
9
8
  * @property {string} platformName - Name of platform
10
9
  * @property {string} domain - example.com
11
10
  * @property {string[]} supportedDeploymentTypes - container
12
11
  * @property {string[]} supportedEnvironments - qa
12
+ *
13
13
  * @property {string} awsAccountId - Aws account id
14
- * @property {string} awsRegion - ?
15
- * @property {string} awsKeyPairName - ?
14
+ * @property {string=} awsRegion - ?
15
+ * @property {string=} awsKeyPairName - ?
16
16
  * @property {string} awsRoleToAssume - ?
17
- * @property {string} awsDeploymentSqsArn - ?
18
- * @property {string} ciSubDomain - ?
19
- * @property {string} ciInternalServerPort- ? | number;
20
- * @property {string} ciServerName - ?
21
- * @property {string} ciDockerNetworkName - ?
17
+ * @property {string=} awsDeploymentSqsArn - ?
18
+ *
19
+ * @property {string=} ciSubDomain - ?
20
+ * @property {string|mumber=} ciInternalServerPort - ? | number;
21
+ * @property {string=} ciServerName - ?
22
+ * @property {string=} ciDockerNetworkName - ?
22
23
  * @property {string} ciGithubActionsRepo - organisation/repoName
23
24
  */
25
+
26
+ /**
27
+ * Utility class that helps you read and validate platfor templates from file system
28
+ * @class
29
+ */
24
30
  class PlatformTemplateService {
25
31
 
26
32
  /**
27
- * Reads the json file that holds the platform templates
33
+ * Read and validat platform template(s) from file system
28
34
  *
29
35
  * @param {string} path - File path to platform templates json
30
36
  * @return @Async {PlatformTemplate[]} - List of platform templates
@@ -57,6 +63,15 @@ class PlatformTemplateService {
57
63
  return Promise.resolve(templates)
58
64
  }
59
65
 
66
+ /**
67
+ * Validates the template
68
+ *
69
+ * @param {PlatformTemplate} platformTemplate - File path to platform templates json
70
+ * @return @Async {PlatformTemplate} - List of platform templates
71
+ *
72
+ * @example
73
+ * const platformTemplate = PlatformTemplateService.readFromFile('./platforms.json')
74
+ */
60
75
  static fakeValidateTemplate(obj) {
61
76
  // todo: implement real one
62
77
  return obj
package/src/types.js DELETED
@@ -1,32 +0,0 @@
1
- // export interface PlatformConfig extends Required<Omit<PlatformTemplate, 'awsRoleToAssume' | 'awsKeyPairName'>> {
2
- // activeEnvironment: SupportedEnvironments;
3
- // awsRoleToAssume?: string;
4
- // awsKeyPairName?: string;
5
- // }
6
-
7
- // export interface DeploymentTemplate {
8
- // type: SupportedDeploymentTypes;
9
- // targetDeploymentPlatform: string;
10
- // subdomain?: string;
11
- // env?: {
12
- // shared?: { [name: string]: string | number };
13
- // prod?: { [name: string]: string | number };
14
- // test?: { [name: string]: string | number };
15
- // qa?: { [name: string]: string | number };
16
- // }
17
- // }
18
- //
19
- // export interface ContainerDeploymentTemplate extends DeploymentTemplate {
20
- // type: SupportedDeploymentTypes.Container;
21
- // dockerFile: string;
22
- // dockerContext: string;
23
- // image: string;
24
- // hostPort: number;
25
- // containerPort: number;
26
- // registry: string;
27
- // }
28
-
29
- // export interface ContainerDeploymentRequest extends ContainerDeploymentTemplate {
30
- // authentication?: string;
31
- // username?: string;
32
- // }