Skip to content

Commit

Permalink
feat: support new naming system
Browse files Browse the repository at this point in the history
  • Loading branch information
ArnaudTA committed Jan 31, 2025
1 parent 046acc8 commit cbf73a8
Show file tree
Hide file tree
Showing 11 changed files with 299 additions and 283 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ jobs:
run: rm -rf ./node_modules && npm install --ignore-scripts --omit=dev

- name: Zip build folder
run: zip -r ./package.zip ./package.json ./dist ./node_modules
run: zip -r ./package.zip ./package.json ./dist ./node_modules ./files

- name: Upload release artifact
uses: actions/upload-release-asset@v1
Expand Down
Binary file added files/logo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
346 changes: 154 additions & 192 deletions package-lock.json

Large diffs are not rendered by default.

12 changes: 6 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@cpn-console/observability-plugin",
"type": "module",
"version": "0.1.2",
"version": "0.1.3-rc1",
"description": "Loki plugin for DSO console",
"exports": {
".": {
Expand All @@ -26,7 +26,7 @@
"prepare": "husky"
},
"dependencies": {
"@cpn-console/hooks": "^2.5.0",
"@cpn-console/hooks": "^4.0.0",
"@gitbeaker/core": "~40.6.0",
"@gitbeaker/requester-utils": "~40.6.0",
"@gitbeaker/rest": "~40.6.0",
Expand All @@ -39,12 +39,12 @@
"devDependencies": {
"@antfu/eslint-config": "^3.16.0",
"@cpn-console/eslint-config": "^1.0.2",
"@cpn-console/gitlab-plugin": "^3.0.0",
"@cpn-console/keycloak-plugin": "^2.0.6",
"@cpn-console/kubernetes-plugin": "^2.1.1",
"@cpn-console/gitlab-plugin": "^3.1.0",
"@cpn-console/keycloak-plugin": "^2.1.0",
"@cpn-console/kubernetes-plugin": "^2.3.0",
"@cpn-console/shared": "^1.2.0",
"@cpn-console/ts-config": "^1.1.0",
"@cpn-console/vault-plugin": "^2.2.1",
"@cpn-console/vault-plugin": "^2.2.2",
"@types/js-yaml": "^4.0.9",
"@types/node": "^22.10.7",
"@types/uuid": "^10.0.0",
Expand Down
2 changes: 2 additions & 0 deletions src/env.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,5 @@
/// <reference types="@cpn-console/keycloak-plugin/types/index.d.ts" />
/// <reference types="@cpn-console/kubernetes-plugin/types/index.d.ts" />
/// <reference types="@cpn-console/vault-plugin/types/index.d.ts" />
/// <reference types="@cpn-console/hooks/types/index.d.ts" />
/// <reference types="@cpn-console/shared/types/index.d.ts" />
65 changes: 41 additions & 24 deletions src/function.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,19 @@
import type { Environment, Project, StepCall, UserObject } from '@cpn-console/hooks'
import type { Environment, PluginResult, Project, StepCall, UserObject } from '@cpn-console/hooks'
import type { KeycloakProjectApi } from '@cpn-console/keycloak-plugin/types/class.js'
import type { Gitlab as GitlabInterface } from '@gitbeaker/core'
import type { BaseParams, Stage } from './utils.js'
import { parseError } from '@cpn-console/hooks'
import { removeTrailingSlash, requiredEnv } from '@cpn-console/shared'
import { parseError, specificallyDisabled } from '@cpn-console/hooks'
import { compressUUID, removeTrailingSlash, requiredEnv } from '@cpn-console/shared'
import { Gitlab } from '@gitbeaker/rest'
import { deleteKeycloakGroup, ensureKeycloakGroups } from './keycloak.js'
import { isNewNsName, type TenantKeycloakMapper } from './utils.js'
import { deleteGitlabYamlConfig, upsertGitlabConfig } from './yaml.js'

const getBaseParams = (project: Project, stage: Stage): BaseParams => ({ organizationName: project.organization.name, projectName: project.name, stage })
const okSkipped: PluginResult = {
status: {
result: 'OK',
message: 'Plugin disabled',
},
}

export type ListPerms = Record<'prod' | 'hors-prod', Record<'view' | 'edit', UserObject['id'][]>>

Expand Down Expand Up @@ -58,35 +64,46 @@ function getGitlabApi(): GitlabInterface {

export const upsertProject: StepCall<Project> = async (payload) => {
try {
if (specificallyDisabled(payload.config.observability?.enabled)) {
return okSkipped
}
// init args
const project = payload.args
const keycloakApi = payload.apis.keycloak
const vaultApi = payload.apis.vault
const keycloakApi = payload.apis.keycloak as KeycloakProjectApi
// init gitlab api
const gitlabApi = getGitlabApi()
const keycloakRootGroupPath = await keycloakApi.getProjectGroupPath()
const tenantRbacProd = [`${keycloakRootGroupPath}/grafana/prod-RW`, `${keycloakRootGroupPath}/grafana/prod-RO`]
const tenantRbacHProd = [`${keycloakRootGroupPath}/grafana/hprod-RW`, `${keycloakRootGroupPath}/grafana/hprod-RO`]

const compressedUUID = compressUUID(project.id)

const tenantsToCreate: TenantKeycloakMapper = {}

for (const environment of payload.args.environments) {
if (!environment.apis.kubernetes) {
throw new Error(`no kubernetes apis on environment ${environment.name}`)
}
const gen = isNewNsName(await environment.apis.kubernetes.getNsName()) ? compressedUUID : project.slug
if (environment.stage === 'prod') {
tenantsToCreate[`prod-${gen}`] = tenantRbacProd
} else {
tenantsToCreate[`hprod-${gen}`] = tenantRbacHProd
}
}

const hasProd = project.environments.find(env => env.stage === 'prod')
const hasNonProd = project.environments.find(env => env.stage !== 'prod')
const hProdParams = getBaseParams(project, 'hprod')
const prodParams = getBaseParams(project, 'prod')
const listPerms = getListPrems(project.environments)

await Promise.all([
const [_, yamlResult] = await Promise.all([
ensureKeycloakGroups(listPerms, keycloakApi),
// Upsert or delete Gitlab config based on prod/non-prod environment
...(hasProd
? [await upsertGitlabConfig(prodParams, keycloakRootGroupPath, project, gitlabApi, vaultApi)]
: [await deleteGitlabYamlConfig(prodParams, project, gitlabApi)]),
...(hasNonProd
? [await upsertGitlabConfig(hProdParams, keycloakRootGroupPath, project, gitlabApi, vaultApi)]
: [await deleteGitlabYamlConfig(hProdParams, project, gitlabApi)]),
upsertGitlabConfig(project, gitlabApi, tenantsToCreate),
])

return {
status: {
result: 'OK',
message: 'Created',
message: yamlResult,
},
}
} catch (error) {
Expand All @@ -102,16 +119,16 @@ export const upsertProject: StepCall<Project> = async (payload) => {

export const deleteProject: StepCall<Project> = async (payload) => {
try {
if (specificallyDisabled(payload.config.observability?.enabled)) {
return okSkipped
}
const project = payload.args
const gitlabApi = getGitlabApi()
const keycloakApi = payload.apis.keycloak
const hProdParams = getBaseParams(project, 'hprod')
const prodParams = getBaseParams(project, 'prod')
const keycloakApi = payload.apis.keycloak as KeycloakProjectApi

await Promise.all([
deleteKeycloakGroup(keycloakApi),
deleteGitlabYamlConfig(prodParams, project, gitlabApi),
deleteGitlabYamlConfig(hProdParams, project, gitlabApi),
deleteGitlabYamlConfig(project, gitlabApi),
])

return {
Expand Down
1 change: 0 additions & 1 deletion src/gitlab.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,6 @@ export async function getGitlabYamlFileContent(api: IGitlab, project: Project, f

// Fonction pour éditer, committer et pousser un fichier YAML
export async function commitAndPushYamlFile(api: IGitlab, project: Project, filePath: string, branch: string, commitMessage: string, yamlString: string): Promise<void> {
console.log('yamlString: ', yamlString)
const encodedContent = Buffer.from(yamlString).toString('utf-8')
try {
// Vérifier si le fichier existe déjà
Expand Down
6 changes: 5 additions & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { Plugin } from '@cpn-console/hooks'
import type { DeclareModuleGenerator, Plugin } from '@cpn-console/hooks'
import { requiredEnv } from '@cpn-console/shared'
import { deleteProject, upsertProject } from './function.js'
import infos from './infos.js'
Expand All @@ -19,3 +19,7 @@ export const plugin: Plugin = {
},
start: () => { requiredEnv('GRAFANA_URL') }, // to check is the variable is set, unless it crashes the app
}

declare module '@cpn-console/hooks' {
interface Config extends DeclareModuleGenerator<typeof infos, 'global'> {}
}
44 changes: 36 additions & 8 deletions src/infos.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,49 @@
import type { ServiceInfos } from '@cpn-console/hooks'
import { readFileSync } from 'node:fs'
import { join } from 'node:path'
import { compressUUID, ENABLED } from '@cpn-console/shared'
import { getConfig } from './utils.js'

const infos: ServiceInfos = {
const imageData = Buffer.from((readFileSync(join(import.meta.dirname, '../files/logo.png'))).toString('base64'))

const infos = {
name: 'observability',
to: ({ project, organization }) => [
to: ({ project }) => [
{
to: `${getConfig().grafanaUrl}/prod-${compressUUID(project.id)}`,
description: 'Production',
},
{
to: `${getConfig().grafanaUrl}/prod-${project.slug}`,
description: 'Production, ancien',
},
{
to: `${getConfig().grafanaUrl}/hprod-${organization}-${project}`,
title: 'Hors production',
to: `${getConfig().grafanaUrl}/hprod-${compressUUID(project.id)}`,
description: 'Hors production',
},
{
to: `${getConfig().grafanaUrl}/prod-${organization}-${project}`,
title: 'Production',
to: `${getConfig().grafanaUrl}/hprod-${project.slug}`,
description: 'Hors production, ancien',
},
],
title: 'Grafana',
imgSrc: 'https://upload.wikimedia.org/wikipedia/commons/a/a1/Grafana_logo.svg',
imgSrc: `data:image/png;base64,${imageData}`,
description: 'Grafana est un outil de métrique et de logs',
}
config: {
global: [{
kind: 'switch',
key: 'enabled',
initialValue: ENABLED,
permissions: {
admin: { read: true, write: true },
user: { read: true, write: false },
},
title: 'Activer le plugin',
value: ENABLED,
description: 'Activer le plugin',
}],
project: [],
},
} as const satisfies ServiceInfos

export default infos
11 changes: 7 additions & 4 deletions src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,11 @@ export function getCustomK8sApi(): CustomObjectsApi {

export type Stage = 'prod' | 'hprod'

export interface BaseParams {
organizationName: string
projectName: string
stage: Stage
export interface TenantKeycloakMapper {
[x: string]: string[]
}

const re = /[a-z0-9]{25}--[a-z0-9]{25}/
export function isNewNsName(ns: string) {
return re.test(ns)
}
Loading

0 comments on commit cbf73a8

Please sign in to comment.