diff --git a/client/src/components/apps/form.vue b/client/src/components/apps/form.vue index 140d95c4..37f554c1 100644 --- a/client/src/components/apps/form.vue +++ b/client/src/components/apps/form.vue @@ -61,6 +61,7 @@ true-icon="mdi-sleep" false-icon="mdi-sleep-off" label="Sleep" + :disabled="!kuberoConfig.sleepEnabled" inset > @@ -214,19 +215,19 @@ key="1" label="Nixpacks" value="nixpacks" - :disabled="!buildPipeline" + :disabled="!kuberoConfig.buildPipeline" > @@ -274,7 +275,7 @@
You are building your image on a external CI/CD and deploy it by changing the image tag thrue the API
- +

Buildpipeline not configured

@@ -1314,6 +1315,7 @@ export default defineComponent({ panel: [0], valid: false, sleep: '0s', + sleepEnabled: false, envFile: [], buildpacks: [] as { text: string, value: Buildpack }[], buildpack: { @@ -1605,10 +1607,10 @@ export default defineComponent({ */ }}, computed: { - buildPipeline(){ + kuberoConfig() { const store = useKuberoStore() - return store.kubero.buildPipeline - } + return store.kubero + }, }, mounted() { this.loadPipeline(); diff --git a/client/src/layouts/default/View.vue b/client/src/layouts/default/View.vue index 816489d9..e60a0ba6 100644 --- a/client/src/layouts/default/View.vue +++ b/client/src/layouts/default/View.vue @@ -48,6 +48,7 @@ export default defineComponent({ this.kubero.auditEnabled = result.data.auditEnabled; this.kubero.consoleEnabled = result.data.consoleEnabled; this.kubero.metricsEnabled = result.data.metricsEnabled; + this.kubero.sleepEnabled = result.data.sleepEnabled; }) .catch((err) => { diff --git a/client/src/stores/kubero.ts b/client/src/stores/kubero.ts index 1658f0fd..c503ed3e 100644 --- a/client/src/stores/kubero.ts +++ b/client/src/stores/kubero.ts @@ -18,6 +18,7 @@ export const useKuberoStore = defineStore('kubero', { buildPipeline: false, consoleEnabled: false, metricsEnabled: false, + sleepEnabled: false, }, buildPipeline: false, }), diff --git a/server/src/configure.ts b/server/src/configure.ts index ae09bbaf..74443250 100644 --- a/server/src/configure.ts +++ b/server/src/configure.ts @@ -112,6 +112,7 @@ export const configure = async (app: Express, server: Server) => { const notifications = new Notifications(sockets, audit, kubectl); const kubero = new Kubero(sockets, audit, kubectl, notifications); + kubero.setMetricsStatus(metrics.getStatus()); notifications.setConfig(kubero.config); // sleep 1 seconds to wait for kubernetes availability test diff --git a/server/src/git/bitbucket.ts b/server/src/git/bitbucket.ts index d3b86d3e..74ff0856 100644 --- a/server/src/git/bitbucket.ts +++ b/server/src/git/bitbucket.ts @@ -25,7 +25,7 @@ export class BitbucketApi extends Repo { this.bitbucket = new Bitbucket(clientOptions) } else { this.bitbucket = new Bitbucket() - console.log("No BITBUCKET_USERNAME or BITBUCKET_APP_PASSWORD set") + console.log("☑️ Feature: BitBucket disabled: No BITBUCKET_USERNAME or BITBUCKET_APP_PASSWORD set") } } diff --git a/server/src/git/gitlab.ts b/server/src/git/gitlab.ts index c51d97f2..e09e49e5 100644 --- a/server/src/git/gitlab.ts +++ b/server/src/git/gitlab.ts @@ -18,13 +18,17 @@ export class GitlabApi extends Repo { constructor(baseURL: string, token: string) { super("gitlab"); - - console.log("Gitlab API: "+baseURL) - //console.log("Gitlab token: "+token) + const host = baseURL || 'https://gitlab.com'; + + if (token == undefined) { + console.log('☑️ Feature: Gitlab not configured (no token)'); + } else { + console.log('✅ Feature: Gitlab configured: '+host); + } this.gitlab = new GitlabClient({ token: token, - host: baseURL || 'https://gitlab.com', + host: host, }); } diff --git a/server/src/kubero.ts b/server/src/kubero.ts index dd39cc7d..6b8cdfa9 100644 --- a/server/src/kubero.ts +++ b/server/src/kubero.ts @@ -38,6 +38,21 @@ export class Kubero { public config: IKuberoConfig; private audit: Audit; private execStreams: {[key: string]: {websocket: WebSocket, stream: any}} = {}; + private features: {[key: string]: boolean} = { + sleep: false, + metrics: false, + /* suggested features + console: false, + logs: false, + audit: false, + notifications: false, + templates: false, + addons: false, + deployments: false, + security: false, + settings: false, + */ + } constructor(io: Server, audit: Audit, kubectl: Kubectl, notifications: Notifications) { this.config = this.loadConfig(process.env.KUBERO_CONFIG_PATH as string || './config.yaml'); @@ -68,6 +83,13 @@ export class Kubero { this.githubApi = new GithubApi(process.env.GITHUB_PERSONAL_ACCESS_TOKEN as string); this.gitlabApi = new GitlabApi(process.env.GITLAB_BASEURL as string, process.env.GITLAB_PERSONAL_ACCESS_TOKEN as string); this.bitbucketApi = new BitbucketApi(process.env.BITBUCKET_USERNAME as string, process.env.BITBUCKET_APP_PASSWORD as string); + + this.runFeatureCheck(); + } + + private async runFeatureCheck() { + //this.features.sleep = this.config.sleep.enabled; + this.features.sleep = await this.checkForZeropod() } public getKubernetesVersion() { @@ -854,8 +876,63 @@ export class Kubero { return this.config.kubero?.console?.enabled; } + public setMetricsStatus(status: boolean) { + this.features.metrics = status + } + public getMetricsEnabled(): boolean{ - return process.env.KUBERO_PROMETHEUS_ENDPOINT ? process.env.KUBERO_PROMETHEUS_ENDPOINT != undefined : false + return this.features.metrics + } +/* + private checkForPrometheus(): Promise { + return new Promise((resolve, reject) => { + if (process.env.KUBERO_PROMETHEUS_ENDPOINT) { + fetch(process.env.KUBERO_PROMETHEUS_ENDPOINT) + .then(response => { + if (response.ok) { + console.log('☑️ Feature: Prometheus Metrics disabled'); + resolve(true); + } else { + console.log('❌ Feature: Prometheus not accesible'); + resolve(false); + } + }) + .catch(error => { + console.log('❌ Feature: Prometheus not accesible'); + resolve(false); + }); + } else { + console.log('☑️ Feature: Prometheus Metrics not enabled'); + resolve(false); + } + }); + } +*/ + public getBuildpipelineEnabled(){ + return process.env.KUBERO_BUILD_REGISTRY ? process.env.KUBERO_BUILD_REGISTRY != undefined : false + } + + private async checkForZeropod(): Promise { + // This is a very basic check for Zeropod. It requires the namespace zeropod-system to be present. + // But it does not check if the Zeropod controller is complete and running. + let enabled = false + try { + const nsList = await this.kubectl.getNamespaces() + for (const ns of nsList) { + if (ns.metadata?.name == 'zeropod-system') { + enabled = true + } + } + } catch (error) { + console.log('Error: getSleepEnabled: ', error) + return false + } + + return enabled + } + + public getSleepEnabled(): boolean { + return this.features.sleep } public getAdminDisabled(){ diff --git a/server/src/modules/audit.ts b/server/src/modules/audit.ts index e7368cd2..de2f9f56 100644 --- a/server/src/modules/audit.ts +++ b/server/src/modules/audit.ts @@ -43,9 +43,9 @@ export class Audit { } this.db = new Database(this.dbpath + '/kubero.db', (err) => { if (err) { - console.error(err.message); + console.log('❌ Feature: Audit logging failed to create local sqlite database', err.message); } - console.log('✅ Enabled audit logging'); + console.log('✅ Feature: Audit logging enabled'); this.createTables(); }); } diff --git a/server/src/modules/kubectl.ts b/server/src/modules/kubectl.ts index 1df7c8f7..82de296b 100644 --- a/server/src/modules/kubectl.ts +++ b/server/src/modules/kubectl.ts @@ -121,6 +121,11 @@ export class Kubectl { this.kc.setCurrentContext(context) } + public async getNamespaces(): Promise { + const namespaces = await this.coreV1Api.listNamespace(); + return namespaces.body.items; + } + public async getPipelinesList() { this.kc.setCurrentContext(process.env.KUBERO_CONTEXT || 'default'); try { diff --git a/server/src/modules/metrics.ts b/server/src/modules/metrics.ts index c3f03796..f6271ed2 100644 --- a/server/src/modules/metrics.ts +++ b/server/src/modules/metrics.ts @@ -35,6 +35,7 @@ type Rule = { export class Metrics { private prom: PrometheusDriver + private status: boolean = false; constructor( options: MetricsOptions @@ -47,15 +48,23 @@ export class Metrics { }); if (!options.enabled) { - console.log('❌ Prometheus Metrics disabled'); + console.log('☑️ Feature: Prometheus Metrics not enabled ...'); + this.status = false; return } this.prom.status().then((status) => { - console.log('✅ Prometheus Metrics initialized:', options.endpoint); + console.log('✅ Feature: Prometheus Metrics initialized:::', options.endpoint); + this.status = true; }).catch((error) => { - console.log('❌ Prometheus status:', error); + console.log('❌ Feature: Prometheus not accesible ...'); + this.status = false; }) + + } + + public getStatus(): boolean { + return this.status } public async getLongTermMetrics(query: string): Promise { diff --git a/server/src/routes/auth.ts b/server/src/routes/auth.ts index d316493f..c62311fe 100644 --- a/server/src/routes/auth.ts +++ b/server/src/routes/auth.ts @@ -21,24 +21,17 @@ Router.all("/session", (req: Request, res: Response) => { } } - let buildPipeline = false - if ( process.env.KUBERO_BUILD_REGISTRY != undefined ) { - buildPipeline = true - } - - - templatesEnabled = true - let message = { "isAuthenticated": isAuthenticated, "version": process.env.npm_package_version, "kubernetesVersion": req.app.locals.kubero.getKubernetesVersion(), - "buildPipeline": buildPipeline, + "buildPipeline": req.app.locals.kubero.getBuildpipelineEnabled(), "templatesEnabled": req.app.locals.kubero.getTemplateEnabled(), "auditEnabled": req.app.locals.audit.getAuditEnabled(), "adminDisabled": req.app.locals.kubero.getAdminDisabled(), "consoleEnabled": req.app.locals.kubero.getConsoleEnabled(), "metricsEnabled": req.app.locals.kubero.getMetricsEnabled(), + "sleepEnabled": req.app.locals.kubero.getSleepEnabled(), } res.status(status).send(message) })