freelens-eso-extension 1.0.2 → 1.0.3
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 +130 -139
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,177 +1,168 @@
|
|
|
1
1
|
# freelens-eso-extension
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
v5.3.1 (electron-vite, `out/`, bundles CommonJS).
|
|
3
|
+
A Freelens extension for the [External Secrets Operator](https://external-secrets.io/) (ESO):
|
|
4
|
+
browse ExternalSecrets, SecretStores and ClusterSecretStores, see their sync status at a
|
|
5
|
+
glance, and trigger a manual sync from the UI.
|
|
7
6
|
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
Built for the Freelens **extension API v1** (Freelens 1.x, `engines.freelens: ^1.8.0`), with
|
|
8
|
+
the build layout of the official
|
|
9
|
+
[`freelensapp/freelens-fluxcd-extension`](https://github.com/freelensapp/freelens-fluxcd-extension)
|
|
10
|
+
v5.3.1 (electron-vite, CommonJS bundles in `out/`).
|
|
10
11
|
|
|
11
|
-
|
|
12
|
+
Repository: <https://github.com/nidiodolfini/freelens-eso-extension> ·
|
|
13
|
+
npm package: [`freelens-eso-extension`](https://www.npmjs.com/package/freelens-eso-extension) ·
|
|
14
|
+
Proposed in [freelensapp/freelens discussion #2840](https://github.com/freelensapp/freelens/discussions/2840).
|
|
12
15
|
|
|
13
|
-
|
|
16
|
+
## What the extension does
|
|
14
17
|
|
|
15
|
-
|
|
16
|
-
Type, Store, Refresh Interval, Status, Ready, Last Sync e Age.
|
|
17
|
-
- **Secret Stores** (`ss`) — colunas espelhando `kubectl get ss`: Name, Namespace, Provider,
|
|
18
|
-
Status, Capabilities, Ready e Age.
|
|
19
|
-
- **Cluster Secret Stores** (`css`) — o mesmo, sem Namespace.
|
|
18
|
+
Three cluster pages, one per ESO resource, grouped under a single sidebar entry:
|
|
20
19
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
20
|
+
- **External Secrets** (`es`) — columns mirroring `kubectl get es`: Name, Namespace, Store
|
|
21
|
+
Type, Store, Refresh Interval, Status, Ready, Last Sync and Age.
|
|
22
|
+
- **Secret Stores** (`ss`) — columns mirroring `kubectl get ss`: Name, Namespace, Provider,
|
|
23
|
+
Status, Capabilities, Ready and Age.
|
|
24
|
+
- **Cluster Secret Stores** (`css`) — the same, without Namespace.
|
|
24
25
|
|
|
25
|
-
|
|
26
|
-
|
|
26
|
+
Sync status comes from each resource's `Ready` condition and is rendered as a colored badge
|
|
27
|
+
(`success` / `error` / `warning`) with the controller's reason (`SecretSynced`,
|
|
28
|
+
`SecretSyncedError`, `Valid`, `ValidationFailed`, ...). When the CRD is not installed in the
|
|
29
|
+
cluster, the page shows a friendly "Not Available" message.
|
|
27
30
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
annotation muda. SecretStore e ClusterSecretStore não têm essa ação.
|
|
31
|
+
Each resource also gets a details panel in the drawer: target Secret, store, refresh
|
|
32
|
+
policy/interval, last sync time, synced resource version and the full conditions with their
|
|
33
|
+
messages as tooltips.
|
|
32
34
|
|
|
33
|
-
|
|
35
|
+
**Force Sync**: the `ExternalSecret` menu gains a "Force Sync" action, which writes a fresh
|
|
36
|
+
timestamp to the `external-secrets.io/force-sync` annotation — the same as
|
|
37
|
+
`kubectl annotate es <name> force-sync=$(date +%s) --overwrite`. The controller reconciles
|
|
38
|
+
whenever the annotation changes, so the secret is refreshed immediately. `SecretStore` and
|
|
39
|
+
`ClusterSecretStore` do not support this action, so they have no menu item.
|
|
34
40
|
|
|
35
|
-
|
|
36
|
-
- Um cluster com o External Secrets Operator instalado (`external-secrets.io/v1`).
|
|
41
|
+
## Requirements
|
|
37
42
|
|
|
38
|
-
|
|
43
|
+
- Freelens 1.8 or newer (extension API v1; tested on 1.10.x).
|
|
44
|
+
- A cluster with the External Secrets Operator installed (`external-secrets.io/v1`).
|
|
39
45
|
|
|
40
|
-
|
|
41
|
-
- **pnpm 11.28.6** (vendored em `.tools/pnpm11/`; o pnpm 12 do harness usa um lock de
|
|
42
|
-
store em `%LOCALAPPDATA%`, que o sandbox bloqueia). Um shim está em
|
|
43
|
-
[`.tools/bin/pnpm.cmd`](.tools/bin/pnpm.cmd) — adicione `.tools\bin` ao `PATH`:
|
|
46
|
+
## Installation
|
|
44
47
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
+
In Freelens, open **Extensions**, choose **Install** and type `freelens-eso-extension`
|
|
49
|
+
(no path). Freelens resolves the package from the npm registry, exactly like the official
|
|
50
|
+
extensions. Enable it, and the "External Secrets" sidebar group appears on every cluster.
|
|
48
51
|
|
|
49
|
-
|
|
52
|
+
To install from a local checkout instead (for development), see
|
|
53
|
+
[Development](#development) below.
|
|
50
54
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
pnpm install
|
|
55
|
-
node .tools\patch-vite.mjs # patch idempotente do vite p/ o sandbox
|
|
56
|
-
```
|
|
55
|
+
## Usage
|
|
56
|
+
|
|
57
|
+
1. Apply the example objects to a cluster with ESO installed:
|
|
57
58
|
|
|
58
|
-
|
|
59
|
-
|
|
59
|
+
```powershell
|
|
60
|
+
kubectl apply -f examples/eso/secretstore.yaml
|
|
61
|
+
kubectl apply -f examples/eso/clustersecretstore.yaml
|
|
62
|
+
kubectl apply -f examples/eso/externalsecret.yaml
|
|
63
|
+
```
|
|
60
64
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
> no electron-vite, a transpilação do config por TypeScript in-process em vez do
|
|
65
|
-
> serviço esbuild (que spawna um binário). Rode o script novamente após qualquer
|
|
66
|
-
> `pnpm install` que recrie as dependências.
|
|
65
|
+
These use ESO's `fake` provider, which serves the pair `/hello -> world` without touching
|
|
66
|
+
any real secret backend; the ExternalSecret creates a Secret named `hello-world` with the
|
|
67
|
+
key `hello`.
|
|
67
68
|
|
|
68
|
-
|
|
69
|
+
2. Open the cluster in Freelens. The pages list `fake-store`, `fake-cluster-store` and
|
|
70
|
+
`hello-world`; the ExternalSecret details panel shows `Ready=SecretSynced` after the first
|
|
71
|
+
sync.
|
|
72
|
+
|
|
73
|
+
3. Open the `hello-world` menu and click **Force Sync**; the "Last Sync" column updates
|
|
74
|
+
within seconds as the controller reconciles.
|
|
75
|
+
|
|
76
|
+
## Development
|
|
77
|
+
|
|
78
|
+
Node 22+ and pnpm are required.
|
|
69
79
|
|
|
70
80
|
```powershell
|
|
71
|
-
pnpm
|
|
81
|
+
pnpm install
|
|
82
|
+
pnpm type:check # tsc -p tsconfig.json (single program, as in the fluxcd extension)
|
|
72
83
|
pnpm test:unit # vitest
|
|
73
|
-
pnpm build # electron-vite build
|
|
74
|
-
pnpm biome:fix #
|
|
84
|
+
pnpm build # electron-vite build -> out/main and out/renderer (CommonJS)
|
|
85
|
+
pnpm biome:fix # formatting/lint (TypeScript, TSX, JSON, CSS, HTML)
|
|
75
86
|
pnpm biome:check
|
|
76
|
-
pnpm knip:check #
|
|
77
|
-
pnpm pack:dev # bump prerelease + build + .tgz
|
|
87
|
+
pnpm knip:check # unused files and dependencies (downloads knip via pnpm dlx)
|
|
88
|
+
pnpm pack:dev # bump prerelease + build + .tgz to install in Freelens
|
|
78
89
|
pnpm clean # remove out/
|
|
79
90
|
```
|
|
80
91
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
92
|
+
To load the checkout in Freelens, run `pnpm install && pnpm build`, then in **Extensions**
|
|
93
|
+
choose **Install from directory** and point at this directory; confirm loading the
|
|
94
|
+
extension "in place" so rebuilds reload it automatically.
|
|
95
|
+
|
|
96
|
+
### Development environment notes (this workspace)
|
|
97
|
+
|
|
98
|
+
The development machine runs inside a sandbox that blocks some standard tooling, so this
|
|
99
|
+
checkout carries a few workarounds; they are documented here because they differ from the
|
|
100
|
+
upstream template:
|
|
101
|
+
|
|
102
|
+
- `packageManager` is `pnpm@11.28.6`, vendored under `.tools/` with a shim at
|
|
103
|
+
`.tools/bin/pnpm.cmd` (add `.tools\bin` to `PATH`). pnpm 12 keeps its store lock in
|
|
104
|
+
`%LOCALAPPDATA%`, which the sandbox blocks.
|
|
105
|
+
- `nodeLinker: hoisted` is set in `pnpm-workspace.yaml`.
|
|
106
|
+
- The sandbox blocks spawning child processes with piped stdio, so `.tools/patch-vite.mjs`
|
|
107
|
+
applies three environment fixes after `pnpm install`: the `net use` realpath call of Vite
|
|
108
|
+
(try/catch), the pure-JS `sass` compiler instead of `sass-embedded` (which spawns the Dart
|
|
109
|
+
Sass binary), and in-process TypeScript transpilation of the electron-vite config instead
|
|
110
|
+
of the esbuild service (which spawns a binary).
|
|
111
|
+
- The electron-vite config therefore does not use `@vitejs/plugin-react` (the config's
|
|
112
|
+
CommonJS loader cannot `require()` the plugin's ESM graph with top-level `await`); JSX uses
|
|
113
|
+
Vite's native automatic transform (`react/jsx-runtime` mapped to the host global). The
|
|
114
|
+
plugin stays as a devDependency to mirror the fluxcd extension, and knip ignores it.
|
|
115
|
+
- `test:unit` uses `--pool=threads` and `knip:check` uses `&&` instead of the parallel
|
|
116
|
+
regex script, both because of the same spawn restriction.
|
|
117
|
+
- `biome:*` and `knip:*` download via `pnpm dlx`, whose default cache lives in
|
|
118
|
+
`%LOCALAPPDATA%`; set `$env:LOCALAPPDATA` to a workspace-local directory before running
|
|
119
|
+
them on this machine.
|
|
120
|
+
|
|
121
|
+
## Project structure
|
|
90
122
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
123
|
+
```text
|
|
124
|
+
electron.vite.config.js # electron-vite config (main + renderer in preload)
|
|
125
|
+
build/global-externals.js # plugin: react/mobx/... -> host globals (v1)
|
|
126
|
+
src/
|
|
127
|
+
main/index.ts # main entry (stateless)
|
|
128
|
+
renderer/index.tsx # v1 registrations: apiManager, 3 pages, details, menu
|
|
129
|
+
renderer/api/types.ts # ESO spec/status types
|
|
130
|
+
renderer/api/store-helpers.ts # pure status helpers shared by the stores
|
|
131
|
+
renderer/api/externalsecret/externalsecret-v1.ts # ExternalSecret model (+ Api/Store, test)
|
|
132
|
+
renderer/api/secretstore/secretstore-v1.ts # SecretStore model (+ Api/Store, test)
|
|
133
|
+
renderer/api/clustersecretstore/clustersecretstore-v1.ts # ClusterSecretStore model (+ Api/Store, test)
|
|
134
|
+
renderer/pages/ # 3 pages + CSS module
|
|
135
|
+
renderer/details/ # 3 details panels
|
|
136
|
+
renderer/menus/ # Force Sync (ExternalSecret)
|
|
137
|
+
renderer/icons/ # External Secrets Operator logo (currentColor)
|
|
138
|
+
renderer/components/ # createAvailableVersionPage, error boundaries
|
|
139
|
+
examples/eso/ # test objects (kubectl apply -f)
|
|
101
140
|
```
|
|
102
141
|
|
|
103
|
-
|
|
104
|
-
|
|
142
|
+
Build output goes to `out/main/index.js` and `out/renderer/index.js` (CommonJS bundles, like
|
|
143
|
+
the other Freelens 1.x extensions); `package.json` points `main`/`renderer` at them.
|
|
105
144
|
|
|
106
|
-
##
|
|
145
|
+
## Supported API versions
|
|
107
146
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
147
|
+
The extension supports **`external-secrets.io/v1` only** (one version per kind, with the
|
|
148
|
+
"Not Available" page when the CRD is missing). `v1beta1` has been unserved since ESO 0.9
|
|
149
|
+
(2023); to add it later, follow the same per-version model/page/details pattern and list
|
|
150
|
+
both versions in `createAvailableVersionPage`, newest first.
|
|
111
151
|
|
|
112
|
-
##
|
|
113
|
-
|
|
114
|
-
Aplique os objetos de exemplo em um cluster com o ESO instalado:
|
|
152
|
+
## Publishing a release
|
|
115
153
|
|
|
116
154
|
```powershell
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
155
|
+
pnpm bump-version patch # or minor/major/prerelease
|
|
156
|
+
pnpm build
|
|
157
|
+
pnpm publish # requires npmjs.com authentication (NODE_AUTH_TOKEN)
|
|
120
158
|
```
|
|
121
159
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
`/hello → world`, usado para criar o Secret `hello-world` com a chave `hello`).
|
|
126
|
-
|
|
127
|
-
## Estrutura
|
|
160
|
+
The `.github/workflows/release.yaml` workflow also publishes automatically when a `v*` tag
|
|
161
|
+
is pushed (it needs the npm registry `NPM_TOKEN` secret in the GitHub repository, or npm
|
|
162
|
+
Trusted Publishing / provenance).
|
|
128
163
|
|
|
129
|
-
|
|
130
|
-
electron.vite.config.js # config do electron-vite (main + renderer em preload)
|
|
131
|
-
build/global-externals.js # plugin: react/mobx/... → globals do host (v1)
|
|
132
|
-
src/
|
|
133
|
-
main/index.ts # entry main (sem estado)
|
|
134
|
-
renderer/index.tsx # registros v1: apiManager, 3 páginas, details, menu
|
|
135
|
-
renderer/api/types.ts # tipos do spec/status do ESO
|
|
136
|
-
renderer/api/store-helpers.ts # helpers puros de status dos stores
|
|
137
|
-
renderer/api/externalsecret/externalsecret-v1.ts # modelo ExternalSecret (+ Api/Store consts, teste)
|
|
138
|
-
renderer/api/secretstore/secretstore-v1.ts # modelo SecretStore (+ Api/Store consts, teste)
|
|
139
|
-
renderer/api/clustersecretstore/clustersecretstore-v1.ts # modelo ClusterSecretStore (+ Api/Store consts, teste)
|
|
140
|
-
renderer/pages/ # 3 páginas + CSS module
|
|
141
|
-
renderer/details/ # 3 painéis de detalhes
|
|
142
|
-
renderer/menus/ # Force Sync (ExternalSecret)
|
|
143
|
-
renderer/icons/ # ícone cadeado + seta de refresh
|
|
144
|
-
renderer/components/ # createAvailableVersionPage, error boundaries
|
|
145
|
-
examples/eso/ # objetos de teste (kubectl apply -f)
|
|
146
|
-
```
|
|
164
|
+
## License
|
|
147
165
|
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
## Versões da API
|
|
152
|
-
|
|
153
|
-
A extensão suporta **somente `external-secrets.io/v1`** (uma versão por kind, com a página
|
|
154
|
-
"Not Available" quando a CRD não está instalada). O `v1beta1` está unserved desde o ESO 0.9
|
|
155
|
-
(2023); para adicioná-lo depois, siga o mesmo padrão de modelo/página/details por versão e
|
|
156
|
-
liste as duas em `createAvailableVersionPage`, da mais nova para a mais antiga.
|
|
157
|
-
|
|
158
|
-
## Desvios do template
|
|
159
|
-
|
|
160
|
-
- `packageManager` = `pnpm@11.28.6` (pnpm 12 exige lock em `%LOCALAPPDATA%`, negado no sandbox).
|
|
161
|
-
- `nodeLinker: hoisted` em `pnpm-workspace.yaml`.
|
|
162
|
-
- O build usa electron-vite (`electron.vite.config.js` + `build/global-externals.js`, espelhando
|
|
163
|
-
o fluxcd v5.3.1): `react`/`react-dom`/`mobx`/`mobx-react`/`@freelensapp/extensions` são
|
|
164
|
-
fornecidos pelo host v1 via `global.*` e ficam externos; main e renderer saem como CommonJS.
|
|
165
|
-
- A seção `preload` do electron-vite compila o renderer (sem HTML de entrada) para `out/renderer`.
|
|
166
|
-
- CSS dos módulos entra nas páginas via `?inline` + `<style>` (padrão do fluxcd v1), porque o
|
|
167
|
-
build com `preserveModules` não garante um único `renderer.css` carregado pelo host.
|
|
168
|
-
- O config do electron-vite **não** usa `@vitejs/plugin-react` (ao contrário do fluxcd): o
|
|
169
|
-
carregador CommonJS do config não consegue `require()` o grafo ESM do plugin (tem
|
|
170
|
-
top-level `await`) e o sandbox não executa o bundler esbuild do electron-vite; o JSX do
|
|
171
|
-
renderer usa o transform automático nativo do Vite (`react/jsx-runtime` → global do host).
|
|
172
|
-
O plugin permanece como devDependency (espelho do fluxcd) e o knip o ignora.
|
|
173
|
-
- `test:unit` usa `--pool=threads` porque o pool forks do vitest spawna processos filhos,
|
|
174
|
-
bloqueados no sandbox.
|
|
175
|
-
- `knip:check` usa `&&` em vez do padrão regex `pnpm "/^...$/"` (sintaxe de aspas quebra no
|
|
176
|
-
`cmd.exe` do Windows).
|
|
177
|
-
- Sem preferências/ExtensionStore e sem testes de integração (o main é uma classe mínima).
|
|
166
|
+
MIT. The sidebar icon is the External Secrets Operator logo
|
|
167
|
+
([external-secrets.io](https://external-secrets.io/), Apache-2.0), recolored with
|
|
168
|
+
`currentColor` so it follows the Freelens theme.
|