From 9e47f32dae7f2b405f119de5e81f5834f250d2f5 Mon Sep 17 00:00:00 2001 From: Ben Hardill Date: Wed, 24 Apr 2024 14:48:00 +0100 Subject: [PATCH 01/18] First pass custom hostnames --- README.md | 8 ++++ kubernetes.js | 123 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 131 insertions(+) diff --git a/README.md b/README.md index 2e217bb..d0a4edd 100644 --- a/README.md +++ b/README.md @@ -21,6 +21,10 @@ driver: k8sDelay: 1000 k8sRetries: 10 logPassthrough: true + customHostname: + enabled: true + certManagerIssuer: lets-encrypt + ingressClass: custom-nginx ``` - `registry` is the Docker Registry to load Stack Containers from @@ -34,6 +38,10 @@ AWS EKS specific annotation for ALB Ingress. or `openshift` to allow running on - `k8sRetries` how many times to retry actions against the K8s API - `k8sDelay` how long to wait (in ms) between retries to the K8s API - `logPassthrough` Have Node-RED logs printed in JSON format to container stdout (default false) +- `customHostname` Settings linked to allowing instances to have a second hostname +- `customHostname.enabled` (default false) +- `customHostname.certManagerIssuer` Name of the Cluster issuer to use to create HTTPS certs for the custom hostname (default not set) +- `customHostname.ingressClass` Name of the IngressClass to use to expose the custom hostname (default not set) Expects to pick up K8s credentials from the environment diff --git a/kubernetes.js b/kubernetes.js index d253cdc..736a0cf 100644 --- a/kubernetes.js +++ b/kubernetes.js @@ -131,6 +131,36 @@ const ingressTemplate = { } } +const customIngressTemplate = { + apiVersion: 'networking.k8s.io/v1', + kind: 'Ingress', + metadata: { + + }, + spec: { + rules: [ + { + http: { + paths: [ + { + pathType: 'Prefix', + path: '/', + backend: { + service: { + port: { number: 1880 } + } + } + } + ] + } + } + ], + tls: [ + + ] + } +} + const createDeployment = async (project, options) => { const stack = project.ProjectStack.properties @@ -340,6 +370,50 @@ const createIngress = async (project, options) => { return localIngress } +const createCustomIngress = async (project, hostname, options) => { + const prefix = project.safeName.match(/^[0-9]/) ? 'srv-' : '' + const url = new URL(project.url) + url.host = hostname + + // exposedData available for annotation replacements + const exposedData = { + serviceName: `${prefix}${project.safeName}`, + instanceURL: url.href, + instanceHost: url.host, + instanceProtocol: url.protocol + } + + this._app.log.info('K8S DRIVER: start custom hostname ingress template') + const customIngress = JSON.parse(JSON.stringify(customIngressTemplate)) + + customIngress.metadata.name = `${project.safeName}-custom` + customIngress.spec.rules[0].host = hostname + customIngress.spec.rules[0].http.paths[0].backend.service.name = `${prefix}${project.safeName}` + + if (this._customHostname?.certManagerIssuer) { + customIngress.metadata.annotations['cert-manager.io/cluster-issuer'] = this._certManagerIssuer + customIngress.spec.tls = [ + { + hosts: [ + hostname + ], + secretName: `${project.safeName}-custom` + } + ] + } + + // process annotations with potential replacements + Object.keys(customIngress.metadata.annotations).forEach((key) => { + customIngress.metadata.annotations[key] = mustache(customIngress.metadata.annotations[key], exposedData) + }) + + if (this._customHostname?.ingressClass) { + customIngress.spec.ingressClassName = `${this._customHostname.ingressClass}` + } + + return customIngress +} + const createProject = async (project, options) => { const namespace = this._app.config.driver.options.projectNamespace || 'flowforge' @@ -434,6 +508,24 @@ const createProject = async (project, options) => { } } } + if (this._customHostname?.enabled) { + const customHostname = await project.getSetting('customHostname') + if (customHostname) { + const customHostnameIngress = await createCustomIngress(project, customHostname, options) + try { + await this._k8sNetApi.createNamespacedIngress(namespace, customHostnameIngress) + } catch (err) { + if (err.statusCode === 409) { + this._app.log.warn(`[k8s] Custom Hostname Ingress for project ${project.id} already exists, proceeding...`) + } else { + if (project.state !== 'suspended') { + this._app.log.error(`[k8s] Project ${project.id} - error creating custom hostname ingress: ${err.toString()}`) + throw err + } + } + } + } + } await new Promise((resolve, reject) => { let counter = 0 @@ -495,6 +587,7 @@ module.exports = { this._certManagerIssuer = this._app.config.driver.options?.certManagerIssuer this._logPassthrough = this._app.config.driver.options?.logPassthrough || false this._cloudProvider = this._app.config.driver.options?.cloudProvider + this._customHostname = this._app.config.driver.options?.customHostname const kc = new k8s.KubeConfig() @@ -663,6 +756,22 @@ module.exports = { } } + if (this._customHostname?.enabled) { + try { + await this._k8sNetApi.deleteNamespacedIngress(`${project.safeName}-custom`, this._namespace) + } catch (err) { + this._app.log.error(`[k8s] Project ${project.id} - error deleting custom ingress: ${err.toString()}`) + } + + if (this._customHostname?.certManagerIssuer) { + try { + await this._k8sApi.deleteNamespacedSecret(`${project.safeName}-custom`, this._namespace) + } catch (err) { + this._app.log.error(`[k8s] Project ${project.id} - error deleting custom tls secret: ${err.toString()}`) + } + } + } + // Note that, regardless, the main objective is to delete deployment (runnable) // Even if some k8s resources like ingress or service are still not deleted (maybe because of // k8s service latency), the most important thing is to get to deployment. @@ -768,6 +877,20 @@ module.exports = { this._app.log.error(`[k8s] Project ${project.id} - error deleting tls secret: ${err.toString()}`) } } + if (this._customHostname?.enabled) { + try { + await this._k8sNetApi.deleteNamespacedIngress(`${project.safeName}-custom`, this._namespace) + } catch (err) { + this._app.log.error(`[k8s] Project ${project.id} - error deleting custom ingress: ${err.toString()}`) + } + if (this._customHostname?.certManagerIssuer) { + try { + await this._k8sApi.deleteNamespacedSecret(`${project.safeName}-custom`, this._namespace) + } catch (err) { + this._app.log.error(`[k8s] Project ${project.id} - error deleting custom tls secret: ${err.toString()}`) + } + } + } try { if (project.safeName.match(/^[0-9]/)) { await this._k8sApi.deleteNamespacedService('srv-' + project.safeName, this._namespace) From b628e99b26b4cb3b3efaa8e05c652787586c19e6 Mon Sep 17 00:00:00 2001 From: Ben Hardill Date: Thu, 25 Apr 2024 15:25:43 +0100 Subject: [PATCH 02/18] change settings key --- kubernetes.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kubernetes.js b/kubernetes.js index 736a0cf..c58758c 100644 --- a/kubernetes.js +++ b/kubernetes.js @@ -509,7 +509,7 @@ const createProject = async (project, options) => { } } if (this._customHostname?.enabled) { - const customHostname = await project.getSetting('customHostname') + const customHostname = await project.getSetting('hostname') if (customHostname) { const customHostnameIngress = await createCustomIngress(project, customHostname, options) try { From d9b361ac0329f2c8d35a5cead27ddf3dd5c1d8be Mon Sep 17 00:00:00 2001 From: Ben Hardill Date: Mon, 13 May 2024 17:29:07 +0100 Subject: [PATCH 03/18] Better feature checking --- kubernetes.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kubernetes.js b/kubernetes.js index c58758c..a3938e9 100644 --- a/kubernetes.js +++ b/kubernetes.js @@ -587,7 +587,7 @@ module.exports = { this._certManagerIssuer = this._app.config.driver.options?.certManagerIssuer this._logPassthrough = this._app.config.driver.options?.logPassthrough || false this._cloudProvider = this._app.config.driver.options?.cloudProvider - this._customHostname = this._app.config.driver.options?.customHostname + this._customHostname = this._app.config.driver.options?.customHostname && this._app.config.features.enabled('customHostnames') const kc = new k8s.KubeConfig() From cb2ddfb6391627e891acef004ff625bcd927c236 Mon Sep 17 00:00:00 2001 From: Ben Hardill Date: Mon, 20 May 2024 09:40:43 +0100 Subject: [PATCH 04/18] Fix settings name --- kubernetes.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kubernetes.js b/kubernetes.js index a3938e9..e24e1f9 100644 --- a/kubernetes.js +++ b/kubernetes.js @@ -509,7 +509,7 @@ const createProject = async (project, options) => { } } if (this._customHostname?.enabled) { - const customHostname = await project.getSetting('hostname') + const customHostname = await project.getSetting('customHostname') if (customHostname) { const customHostnameIngress = await createCustomIngress(project, customHostname, options) try { From c2d4f58b5659bc520c0fe8195b30401303814626 Mon Sep 17 00:00:00 2001 From: Ben Hardill Date: Tue, 21 May 2024 10:14:54 +0100 Subject: [PATCH 05/18] Fix config enablement --- kubernetes.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/kubernetes.js b/kubernetes.js index e24e1f9..f6eeea7 100644 --- a/kubernetes.js +++ b/kubernetes.js @@ -587,7 +587,9 @@ module.exports = { this._certManagerIssuer = this._app.config.driver.options?.certManagerIssuer this._logPassthrough = this._app.config.driver.options?.logPassthrough || false this._cloudProvider = this._app.config.driver.options?.cloudProvider - this._customHostname = this._app.config.driver.options?.customHostname && this._app.config.features.enabled('customHostnames') + if (this._app.config.features.enabled('customHostnames')) { + this._customHostname = this._app.config.driver.options?.customHostname + } const kc = new k8s.KubeConfig() From bb64661d81033a90ebc105c2c0131f8b6aadcd34 Mon Sep 17 00:00:00 2001 From: Ben Hardill Date: Tue, 21 May 2024 12:01:44 +0100 Subject: [PATCH 06/18] Add logging to say custom hostname enabled --- kubernetes.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/kubernetes.js b/kubernetes.js index f6eeea7..9fbe7c5 100644 --- a/kubernetes.js +++ b/kubernetes.js @@ -587,7 +587,8 @@ module.exports = { this._certManagerIssuer = this._app.config.driver.options?.certManagerIssuer this._logPassthrough = this._app.config.driver.options?.logPassthrough || false this._cloudProvider = this._app.config.driver.options?.cloudProvider - if (this._app.config.features.enabled('customHostnames')) { + if (this._app.config.features.enabled('customHostnames') && this._app.config.driver.options?.customHostname?.enabled) { + this._app.log.info('[k8s] Enabling Custom Hostname Support') this._customHostname = this._app.config.driver.options?.customHostname } From 949e3d8e0bd53dd00374c5fba5667e348abffa5a Mon Sep 17 00:00:00 2001 From: Ben Hardill Date: Tue, 21 May 2024 14:05:23 +0100 Subject: [PATCH 07/18] Remove feature check as not complete when driver loaded --- kubernetes.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kubernetes.js b/kubernetes.js index 9fbe7c5..e38a2b6 100644 --- a/kubernetes.js +++ b/kubernetes.js @@ -587,7 +587,7 @@ module.exports = { this._certManagerIssuer = this._app.config.driver.options?.certManagerIssuer this._logPassthrough = this._app.config.driver.options?.logPassthrough || false this._cloudProvider = this._app.config.driver.options?.cloudProvider - if (this._app.config.features.enabled('customHostnames') && this._app.config.driver.options?.customHostname?.enabled) { + if (this._app.config.driver.options?.customHostname?.enabled) { this._app.log.info('[k8s] Enabling Custom Hostname Support') this._customHostname = this._app.config.driver.options?.customHostname } From d34cc06d05e0db3d7e403b53fbfed4835f8378dc Mon Sep 17 00:00:00 2001 From: Ben Hardill Date: Tue, 21 May 2024 16:25:21 +0100 Subject: [PATCH 08/18] Change to bump hash --- kubernetes.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/kubernetes.js b/kubernetes.js index e38a2b6..0714231 100644 --- a/kubernetes.js +++ b/kubernetes.js @@ -571,11 +571,11 @@ const getEndpoints = async (project) => { module.exports = { /** - * Initialises this driver - * @param {string} app - the Vue application - * @param {object} options - A set of configuration options for the driver - * @return {forge.containers.ProjectArguments} - */ + * Initialises this driver + * @param {string} app - the Vue application + * @param {object} options - A set of configuration options for the driver + * @return {forge.containers.ProjectArguments} + */ init: async (app, options) => { this._app = app this._projects = {} From 8b243f406c537e2f9c08d3ac589758d0aaf3e59e Mon Sep 17 00:00:00 2001 From: Ben Hardill Date: Tue, 21 May 2024 20:41:10 +0100 Subject: [PATCH 09/18] find error --- kubernetes.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/kubernetes.js b/kubernetes.js index 0714231..95c74aa 100644 --- a/kubernetes.js +++ b/kubernetes.js @@ -371,6 +371,7 @@ const createIngress = async (project, options) => { } const createCustomIngress = async (project, hostname, options) => { + try { const prefix = project.safeName.match(/^[0-9]/) ? 'srv-' : '' const url = new URL(project.url) url.host = hostname @@ -412,6 +413,9 @@ const createCustomIngress = async (project, hostname, options) => { } return customIngress + } catch (err) { + console.log(err) + } } const createProject = async (project, options) => { From 0c7d67cc9c21789fc4b660684781f242b5f8aad6 Mon Sep 17 00:00:00 2001 From: Ben Hardill Date: Tue, 21 May 2024 20:43:10 +0100 Subject: [PATCH 10/18] log customIngress --- kubernetes.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/kubernetes.js b/kubernetes.js index 95c74aa..343fb9c 100644 --- a/kubernetes.js +++ b/kubernetes.js @@ -412,6 +412,8 @@ const createCustomIngress = async (project, hostname, options) => { customIngress.spec.ingressClassName = `${this._customHostname.ingressClass}` } + console.log(JSON.stringify(customIngress)) + return customIngress } catch (err) { console.log(err) From edad8ea2b880003a375e8d7f8f4a841f2993eee3 Mon Sep 17 00:00:00 2001 From: Ben Hardill Date: Tue, 21 May 2024 21:59:10 +0100 Subject: [PATCH 11/18] Fix annotations --- kubernetes.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kubernetes.js b/kubernetes.js index 343fb9c..aff723e 100644 --- a/kubernetes.js +++ b/kubernetes.js @@ -135,7 +135,7 @@ const customIngressTemplate = { apiVersion: 'networking.k8s.io/v1', kind: 'Ingress', metadata: { - + annotations: {} }, spec: { rules: [ From d4a6550716a969bd1fb29b030453d0d8c6313c0c Mon Sep 17 00:00:00 2001 From: Ben Hardill Date: Wed, 22 May 2024 13:31:11 +0100 Subject: [PATCH 12/18] fix lint --- kubernetes.js | 4 ---- 1 file changed, 4 deletions(-) diff --git a/kubernetes.js b/kubernetes.js index aff723e..45ea715 100644 --- a/kubernetes.js +++ b/kubernetes.js @@ -371,7 +371,6 @@ const createIngress = async (project, options) => { } const createCustomIngress = async (project, hostname, options) => { - try { const prefix = project.safeName.match(/^[0-9]/) ? 'srv-' : '' const url = new URL(project.url) url.host = hostname @@ -415,9 +414,6 @@ const createCustomIngress = async (project, hostname, options) => { console.log(JSON.stringify(customIngress)) return customIngress - } catch (err) { - console.log(err) - } } const createProject = async (project, options) => { From 6855cd9c70548c3a20aba5fc9bdeda9aaa98a073 Mon Sep 17 00:00:00 2001 From: Ben Hardill Date: Wed, 22 May 2024 16:22:23 +0100 Subject: [PATCH 13/18] Add try/catch back --- kubernetes.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/kubernetes.js b/kubernetes.js index 45ea715..aff723e 100644 --- a/kubernetes.js +++ b/kubernetes.js @@ -371,6 +371,7 @@ const createIngress = async (project, options) => { } const createCustomIngress = async (project, hostname, options) => { + try { const prefix = project.safeName.match(/^[0-9]/) ? 'srv-' : '' const url = new URL(project.url) url.host = hostname @@ -414,6 +415,9 @@ const createCustomIngress = async (project, hostname, options) => { console.log(JSON.stringify(customIngress)) return customIngress + } catch (err) { + console.log(err) + } } const createProject = async (project, options) => { From 9da4bc800e0cd69df307317fbc375eeaa81aa0cf Mon Sep 17 00:00:00 2001 From: Ben Hardill Date: Wed, 22 May 2024 16:31:53 +0100 Subject: [PATCH 14/18] Fix certManager --- kubernetes.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kubernetes.js b/kubernetes.js index aff723e..90c43b7 100644 --- a/kubernetes.js +++ b/kubernetes.js @@ -392,7 +392,7 @@ const createCustomIngress = async (project, hostname, options) => { customIngress.spec.rules[0].http.paths[0].backend.service.name = `${prefix}${project.safeName}` if (this._customHostname?.certManagerIssuer) { - customIngress.metadata.annotations['cert-manager.io/cluster-issuer'] = this._certManagerIssuer + customIngress.metadata.annotations['cert-manager.io/cluster-issuer'] = this._customHostname.certManagerIssuer customIngress.spec.tls = [ { hosts: [ From a7dd154dfbccf1d6dc05bd53ad8c21d532af98cd Mon Sep 17 00:00:00 2001 From: Ben Hardill Date: Thu, 23 May 2024 13:12:47 +0100 Subject: [PATCH 15/18] Fix lint --- kubernetes.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/kubernetes.js b/kubernetes.js index 90c43b7..ebea55c 100644 --- a/kubernetes.js +++ b/kubernetes.js @@ -371,7 +371,7 @@ const createIngress = async (project, options) => { } const createCustomIngress = async (project, hostname, options) => { - try { + // try { const prefix = project.safeName.match(/^[0-9]/) ? 'srv-' : '' const url = new URL(project.url) url.host = hostname @@ -415,9 +415,9 @@ const createCustomIngress = async (project, hostname, options) => { console.log(JSON.stringify(customIngress)) return customIngress - } catch (err) { - console.log(err) - } + // } catch (err) { + // console.log(err) + // } } const createProject = async (project, options) => { From 04b3941272e27fd7091f5e55d64e3f729efae414 Mon Sep 17 00:00:00 2001 From: Ben Hardill Date: Wed, 29 May 2024 16:17:00 +0100 Subject: [PATCH 16/18] Update kubernetes.js Co-authored-by: Nick O'Leary --- kubernetes.js | 1 - 1 file changed, 1 deletion(-) diff --git a/kubernetes.js b/kubernetes.js index ebea55c..6a01719 100644 --- a/kubernetes.js +++ b/kubernetes.js @@ -412,7 +412,6 @@ const createCustomIngress = async (project, hostname, options) => { customIngress.spec.ingressClassName = `${this._customHostname.ingressClass}` } - console.log(JSON.stringify(customIngress)) return customIngress // } catch (err) { From e54722e311c9c6f4c77f8e42a144324a1d885051 Mon Sep 17 00:00:00 2001 From: Ben Hardill Date: Wed, 29 May 2024 16:18:25 +0100 Subject: [PATCH 17/18] Fix lint --- kubernetes.js | 5 ----- 1 file changed, 5 deletions(-) diff --git a/kubernetes.js b/kubernetes.js index 6a01719..8f7601c 100644 --- a/kubernetes.js +++ b/kubernetes.js @@ -371,7 +371,6 @@ const createIngress = async (project, options) => { } const createCustomIngress = async (project, hostname, options) => { - // try { const prefix = project.safeName.match(/^[0-9]/) ? 'srv-' : '' const url = new URL(project.url) url.host = hostname @@ -412,11 +411,7 @@ const createCustomIngress = async (project, hostname, options) => { customIngress.spec.ingressClassName = `${this._customHostname.ingressClass}` } - return customIngress - // } catch (err) { - // console.log(err) - // } } const createProject = async (project, options) => { From 0336307fae96dfba05b8b0c5183a39f3a579759b Mon Sep 17 00:00:00 2001 From: Nick O'Leary Date: Wed, 5 Jun 2024 13:55:56 +0100 Subject: [PATCH 18/18] Update log messaging --- README.md | 2 ++ kubernetes.js | 70 +++++++++++++++++++++++++-------------------------- 2 files changed, 37 insertions(+), 35 deletions(-) diff --git a/README.md b/README.md index d0a4edd..4f51f9e 100644 --- a/README.md +++ b/README.md @@ -23,6 +23,7 @@ driver: logPassthrough: true customHostname: enabled: true + cnameTarget: custom-loadbalancer.example.com certManagerIssuer: lets-encrypt ingressClass: custom-nginx ``` @@ -40,6 +41,7 @@ AWS EKS specific annotation for ALB Ingress. or `openshift` to allow running on - `logPassthrough` Have Node-RED logs printed in JSON format to container stdout (default false) - `customHostname` Settings linked to allowing instances to have a second hostname - `customHostname.enabled` (default false) +- `customHostname.cnameTarget` The hostname users should configure their DNS entries to point at. Required. (default not set) - `customHostname.certManagerIssuer` Name of the Cluster issuer to use to create HTTPS certs for the custom hostname (default not set) - `customHostname.ingressClass` Name of the IngressClass to use to expose the custom hostname (default not set) diff --git a/kubernetes.js b/kubernetes.js index 8f7601c..4db47d1 100644 --- a/kubernetes.js +++ b/kubernetes.js @@ -426,7 +426,7 @@ const createProject = async (project, options) => { } catch (err) { if (err.statusCode === 409) { // If deployment exists, perform an upgrade - this._app.log.warn(`[k8s] Deployment for project ${project.id} already exists. Upgrading deployment`) + this._app.log.warn(`[k8s] Deployment for instance ${project.id} already exists. Upgrading deployment`) const result = await this._k8sAppApi.readNamespacedDeployment(project.safeName, namespace) const existingDeployment = result.body @@ -437,7 +437,7 @@ const createProject = async (project, options) => { } } else { // Log other errors and rethrow them for additional higher-level handling - this._app.log.error(`[k8s] Unexpected error creating deployment for project ${project.id}.`) + this._app.log.error(`[k8s] Unexpected error creating deployment for instance ${project.id}.`) this._app.log.error(`[k8s] deployment ${JSON.stringify(localDeployment, undefined, 2)}`) this._app.log.error(err) // rethrow the error so the wrapper knows this hasn't worked @@ -457,7 +457,7 @@ const createProject = async (project, options) => { counter++ if (counter > this._k8sRetries) { clearInterval(pollInterval) - this._app.log.error(`[k8s] Project ${project.id} - timeout waiting for Deployment`) + this._app.log.error(`[k8s] Instance ${project.id} - timeout waiting for Deployment`) reject(new Error('Timed out to creating Deployment')) } } @@ -468,10 +468,10 @@ const createProject = async (project, options) => { await this._k8sApi.createNamespacedService(namespace, localService) } catch (err) { if (err.statusCode === 409) { - this._app.log.warn(`[k8s] Service for project ${project.id} already exists, proceeding...`) + this._app.log.warn(`[k8s] Service for instance ${project.id} already exists, proceeding...`) } else { if (project.state !== 'suspended') { - this._app.log.error(`[k8s] Project ${project.id} - error creating service: ${err.toString()}`) + this._app.log.error(`[k8s] Instance ${project.id} - error creating service: ${err.toString()}`) throw err } } @@ -489,7 +489,7 @@ const createProject = async (project, options) => { counter++ if (counter > this._k8sRetries) { clearInterval(pollInterval) - this._app.log.error(`[k8s] Project ${project.id} - timeout waiting for Service`) + this._app.log.error(`[k8s] Instance ${project.id} - timeout waiting for Service`) reject(new Error('Timed out to creating Service')) } } @@ -500,10 +500,10 @@ const createProject = async (project, options) => { await this._k8sNetApi.createNamespacedIngress(namespace, localIngress) } catch (err) { if (err.statusCode === 409) { - this._app.log.warn(`[k8s] Ingress for project ${project.id} already exists, proceeding...`) + this._app.log.warn(`[k8s] Ingress for instance ${project.id} already exists, proceeding...`) } else { if (project.state !== 'suspended') { - this._app.log.error(`[k8s] Project ${project.id} - error creating ingress: ${err.toString()}`) + this._app.log.error(`[k8s] Instance ${project.id} - error creating ingress: ${err.toString()}`) throw err } } @@ -516,10 +516,10 @@ const createProject = async (project, options) => { await this._k8sNetApi.createNamespacedIngress(namespace, customHostnameIngress) } catch (err) { if (err.statusCode === 409) { - this._app.log.warn(`[k8s] Custom Hostname Ingress for project ${project.id} already exists, proceeding...`) + this._app.log.warn(`[k8s] Custom Hostname Ingress for instance ${project.id} already exists, proceeding...`) } else { if (project.state !== 'suspended') { - this._app.log.error(`[k8s] Project ${project.id} - error creating custom hostname ingress: ${err.toString()}`) + this._app.log.error(`[k8s] Instance ${project.id} - error creating custom hostname ingress: ${err.toString()}`) throw err } } @@ -538,7 +538,7 @@ const createProject = async (project, options) => { counter++ if (counter > this._k8sRetries) { clearInterval(pollInterval) - this._app.log.error(`[k8s] Project ${project.id} - timeout waiting for Ingress`) + this._app.log.error(`[k8s] Instance ${project.id} - timeout waiting for Ingress`) reject(new Error('Timed out to creating Ingress')) } } @@ -666,7 +666,7 @@ module.exports = { this._app.log.info(`[k8s] deployment ${project.id} in ${namespace} found`) } catch (err) { this._app.log.error(`[k8s] Error while reading namespaced deployment for project '${project.safeName}' ${project.id}. Error msg=${err.message}, stack=${err.stack}`) - this._app.log.info(`[k8s] Project ${project.id} - recreating deployment`) + this._app.log.info(`[k8s] Instance ${project.id} - recreating deployment`) const fullProject = await this._app.db.models.Project.byId(project.id) await createProject(fullProject, options) } @@ -677,13 +677,13 @@ module.exports = { await this._k8sApi.readNamespacedPodStatus(project.safeName, namespace) this._app.log.info(`[k8s] pod ${project.id} in ${namespace} found`) } catch (err) { - this._app.log.debug(`[k8s] Project ${project.id} - recreating deployment`) + this._app.log.debug(`[k8s] Instance ${project.id} - recreating deployment`) const fullProject = await this._app.db.models.Project.byId(project.id) await createProject(fullProject, options) } } } catch (err) { - this._app.log.error(`[k8s] Project ${project.id} - error resuming project: ${err.stack}`) + this._app.log.error(`[k8s] Instance ${project.id} - error resuming project: ${err.stack}`) } }) }, 1000) @@ -748,14 +748,14 @@ module.exports = { try { await this._k8sNetApi.deleteNamespacedIngress(project.safeName, this._namespace) } catch (err) { - this._app.log.error(`[k8s] Project ${project.id} - error deleting ingress: ${err.toString()}`) + this._app.log.error(`[k8s] Instance ${project.id} - error deleting ingress: ${err.toString()}`) } if (this._certManagerIssuer) { try { await this._k8sApi.deleteNamespacedSecret(project.safeName, this._namespace) } catch (err) { - this._app.log.error(`[k8s] Project ${project.id} - error deleting tls secret: ${err.toString()}`) + this._app.log.error(`[k8s] Instance ${project.id} - error deleting tls secret: ${err.toString()}`) } } @@ -763,14 +763,14 @@ module.exports = { try { await this._k8sNetApi.deleteNamespacedIngress(`${project.safeName}-custom`, this._namespace) } catch (err) { - this._app.log.error(`[k8s] Project ${project.id} - error deleting custom ingress: ${err.toString()}`) + this._app.log.error(`[k8s] Instance ${project.id} - error deleting custom ingress: ${err.toString()}`) } if (this._customHostname?.certManagerIssuer) { try { await this._k8sApi.deleteNamespacedSecret(`${project.safeName}-custom`, this._namespace) } catch (err) { - this._app.log.error(`[k8s] Project ${project.id} - error deleting custom tls secret: ${err.toString()}`) + this._app.log.error(`[k8s] Instance ${project.id} - error deleting custom tls secret: ${err.toString()}`) } } } @@ -791,20 +791,20 @@ module.exports = { counter++ if (counter > this._k8sRetries) { clearInterval(pollInterval) - this._app.log.error(`[k8s] Project ${project.id} - timed out deleting ingress`) + this._app.log.error(`[k8s] Instance ${project.id} - timed out deleting ingress`) reject(new Error('Timed out to deleting Ingress')) } }, this._k8sDelay) }) } catch (err) { - this._app.log.error(`[k8s] Project ${project.id} - Ingress was not deleted: ${err.toString()}`) + this._app.log.error(`[k8s] Instance ${project.id} - Ingress was not deleted: ${err.toString()}`) } const prefix = project.safeName.match(/^[0-9]/) ? 'srv-' : '' try { await this._k8sApi.deleteNamespacedService(prefix + project.safeName, this._namespace) } catch (err) { - this._app.log.error(`[k8s] Project ${project.id} - error deleting service: ${err.toString()}`) + this._app.log.error(`[k8s] Instance ${project.id} - error deleting service: ${err.toString()}`) } try { @@ -820,13 +820,13 @@ module.exports = { counter++ if (counter > this._k8sRetries) { clearInterval(pollInterval) - this._app.log.error(`[k8s] Project ${project.id} - timed deleting service`) + this._app.log.error(`[k8s] Instance ${project.id} - timed deleting service`) reject(new Error('Timed out to deleting Service')) } }, this._k8sDelay) }) } catch (err) { - this._app.log.error(`[k8s] Project ${project.id} - Service was not deleted: ${err.toString()}`) + this._app.log.error(`[k8s] Instance ${project.id} - Service was not deleted: ${err.toString()}`) } const currentType = await project.getSetting('k8sType') @@ -851,7 +851,7 @@ module.exports = { counter++ if (counter > this._k8sRetries) { clearInterval(pollInterval) - this._app.log.error(`[k8s] Project ${project.id} - timed deleting ${pod ? 'Pod' : 'Deployment'}`) + this._app.log.error(`[k8s] Instance ${project.id} - timed deleting ${pod ? 'Pod' : 'Deployment'}`) reject(new Error('Timed out to deleting Deployment')) } } catch (err) { @@ -871,26 +871,26 @@ module.exports = { try { await this._k8sNetApi.deleteNamespacedIngress(project.safeName, this._namespace) } catch (err) { - this._app.log.error(`[k8s] Project ${project.id} - error deleting ingress: ${err.toString()}`) + this._app.log.error(`[k8s] Instance ${project.id} - error deleting ingress: ${err.toString()}`) } if (this._certManagerIssuer) { try { await this._k8sApi.deleteNamespacedSecret(project.safeName, this._namespace) } catch (err) { - this._app.log.error(`[k8s] Project ${project.id} - error deleting tls secret: ${err.toString()}`) + this._app.log.error(`[k8s] Instance ${project.id} - error deleting tls secret: ${err.toString()}`) } } if (this._customHostname?.enabled) { try { await this._k8sNetApi.deleteNamespacedIngress(`${project.safeName}-custom`, this._namespace) } catch (err) { - this._app.log.error(`[k8s] Project ${project.id} - error deleting custom ingress: ${err.toString()}`) + this._app.log.error(`[k8s] Instance ${project.id} - error deleting custom ingress: ${err.toString()}`) } if (this._customHostname?.certManagerIssuer) { try { await this._k8sApi.deleteNamespacedSecret(`${project.safeName}-custom`, this._namespace) } catch (err) { - this._app.log.error(`[k8s] Project ${project.id} - error deleting custom tls secret: ${err.toString()}`) + this._app.log.error(`[k8s] Instance ${project.id} - error deleting custom tls secret: ${err.toString()}`) } } } @@ -901,7 +901,7 @@ module.exports = { await this._k8sApi.deleteNamespacedService(project.safeName, this._namespace) } } catch (err) { - this._app.log.error(`[k8s] Project ${project.id} - error deleting service: ${err.toString()}`) + this._app.log.error(`[k8s] Instance ${project.id} - error deleting service: ${err.toString()}`) } const currentType = await project.getSetting('k8sType') try { @@ -915,9 +915,9 @@ module.exports = { } catch (err) { if (project.state !== 'suspended') { if (currentType === 'deployment') { - this._app.log.error(`[k8s] Project ${project.id} - error deleting deployment: ${err.toString()}`) + this._app.log.error(`[k8s] Instance ${project.id} - error deleting deployment: ${err.toString()}`) } else { - this._app.log.error(`[k8s] Project ${project.id} - error deleting pod: ${err.toString()}`) + this._app.log.error(`[k8s] Instance ${project.id} - error deleting pod: ${err.toString()}`) } } } @@ -967,7 +967,7 @@ module.exports = { this._projects[project.id].state = info.state return info } catch (err) { - this._app.log.debug(`error getting state from project ${project.id}: ${err}`) + this._app.log.debug(`error getting state from instance ${project.id}: ${err}`) return { id: project.id, state: 'starting', @@ -1000,7 +1000,7 @@ module.exports = { this._projects[project.id].state = info.state return info } catch (err) { - this._app.log.debug(`error getting state from project ${project.id}: ${err}`) + this._app.log.debug(`error getting state from instance ${project.id}: ${err}`) return { id: project.id, state: 'starting', @@ -1017,7 +1017,7 @@ module.exports = { } } } catch (err) { - this._app.log.debug(`error getting pod status for project ${project.id}: ${err}`) + this._app.log.debug(`error getting pod status for instance ${project.id}: ${err}`) return { id: project?.id, error: err, @@ -1140,7 +1140,7 @@ module.exports = { * @return {forge.Status} */ revokeUserToken: async (project, token) => { // logout:nodered(step-3) - this._app.log.debug(`[k8s] Project ${project.id} - logging out node-red instance`) + this._app.log.debug(`[k8s] Instance ${project.id} - logging out node-red instance`) const endpoints = await getEndpoints(project) const commands = [] for (const address in endpoints) {