Skip to content

Commit 6a0d37c

Browse files
feat(cc-addon-info.smart-kubernetes): init
1 parent b1f8b92 commit 6a0d37c

File tree

6 files changed

+171
-0
lines changed

6 files changed

+171
-0
lines changed

demo-smart/index.html

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,11 @@
213213
cc-addon-header.smart-kubernetes
214214
</a>
215215
</li>
216+
<li>
217+
<a class="definition-link" href="?definition=cc-addon-info.smart-kubernetes&smart-mode=kubernetes">
218+
cc-addon-info.smart-kubernetes
219+
</a>
220+
</li>
216221
</ul>
217222

218223
<div class="context-buttons">

src/components/cc-addon-header/cc-addon-header.types.d.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,4 +79,6 @@ export interface KubeInfo {
7979
description?: string | null;
8080
tag?: string | null;
8181
status: string;
82+
creationDate: string;
83+
version: string;
8284
}
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
// @ts-expect-error FIXME: remove when clever-client exports types
2+
import { ONE_SECOND } from '@clevercloud/client/esm/with-cache.js';
3+
import { getDocUrl } from '../../lib/dev-hub-url.js';
4+
import { sendToApi } from '../../lib/send-to-api.js';
5+
import { defineSmartComponent } from '../../lib/smart/define-smart-component.js';
6+
import { i18n } from '../../translations/translation.js';
7+
import '../cc-smart-container/cc-smart-container.js';
8+
import './cc-addon-info.js';
9+
10+
/**
11+
* @typedef {import('./cc-addon-info.js').CcAddonInfo} CcAddonInfo
12+
* @typedef {import('./cc-addon-info.types.js').AddonInfoStateLoading} AddonInfoStateLoading
13+
* @typedef {import('../cc-addon-header/cc-addon-header.types.js').KubeInfo} KubeInfo
14+
* @typedef {import('../../lib/smart/smart-component.types.js').OnContextUpdateArgs<CcAddonInfo>} OnContextUpdateArgs
15+
* @typedef {import('../../lib/send-to-api.types.js').ApiConfig} ApiConfig
16+
*/
17+
18+
/** @type {AddonInfoStateLoading} */
19+
const LOADING_STATE = {
20+
type: 'loading',
21+
version: {
22+
stateType: 'up-to-date',
23+
installed: '0.0.0',
24+
latest: '0.0.0',
25+
},
26+
creationDate: '2025-08-06 15:03:00',
27+
};
28+
29+
defineSmartComponent({
30+
selector: 'cc-addon-info[smart-mode="kubernetes"]',
31+
params: {
32+
apiConfig: { type: Object },
33+
ownerId: { type: String },
34+
kubernetesId: { type: String },
35+
},
36+
/** @param {OnContextUpdateArgs} _ */
37+
onContextUpdate({ context, updateComponent, signal }) {
38+
const { apiConfig, ownerId, kubernetesId } = context;
39+
40+
const api = new Api({ apiConfig, ownerId, kubernetesId, signal });
41+
42+
updateComponent('state', LOADING_STATE);
43+
updateComponent('docLink', {
44+
text: i18n('cc-addon-info.doc-link.kubernetes'),
45+
href: getDocUrl('/kubernetes'),
46+
});
47+
48+
api
49+
.getKubeInfo(ownerId, kubernetesId)
50+
.then((kubeInfo) => {
51+
updateComponent('state', {
52+
type: 'loaded',
53+
version: { stateType: 'up-to-date', installed: kubeInfo.version, latest: kubeInfo.version },
54+
creationDate: kubeInfo.creationDate,
55+
});
56+
})
57+
.catch((error) => {
58+
console.error(error);
59+
updateComponent('state', { type: 'error' });
60+
});
61+
},
62+
});
63+
64+
class Api {
65+
/**
66+
* @param {object} params
67+
* @param {ApiConfig} params.apiConfig - API configuration
68+
* @param {string} params.ownerId - Owner identifier
69+
* @param {string} params.kubernetesId - Cluster identifier
70+
* @param {AbortSignal} params.signal - Signal to abort calls
71+
*/
72+
constructor({ apiConfig, ownerId, kubernetesId, signal }) {
73+
this._apiConfig = apiConfig;
74+
this._ownerId = ownerId;
75+
this._kubernetesId = kubernetesId;
76+
this._signal = signal;
77+
}
78+
79+
/**
80+
* @param {string} ownerId
81+
* @param {string} kubernetesId
82+
* @return {Promise<KubeInfo>}
83+
*/
84+
getKubeInfo(ownerId, kubernetesId) {
85+
return getKubeInfo({ ownerId, kubernetesId })
86+
.then(sendToApi({ apiConfig: this._apiConfig, signal: this._signal, cacheDelay: ONE_SECOND }))
87+
.then((kubeInfo) => {
88+
if (kubeInfo.status === 'DELETED') {
89+
throw new Error('This cluster has been deleted');
90+
}
91+
return kubeInfo;
92+
});
93+
}
94+
}
95+
96+
// FIXME: remove and use the clever-client call from the new clever-client
97+
/** @param {{ ownerId: string, kubernetesId: string }} params */
98+
function getKubeInfo(params) {
99+
// no multipath for /self or /organisations/{id}
100+
return Promise.resolve({
101+
method: 'get',
102+
url: `/v4/kubernetes/organisations/${params.ownerId}/clusters/${params.kubernetesId}`,
103+
// no queryParams
104+
// no body
105+
});
106+
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
---
2+
kind: '🛠 Addon/<cc-addon-info>'
3+
title: '💡 Smart (Kubernetes)'
4+
---
5+
# 💡 Smart `<cc-addon-info smart-mode="kubernetes">`
6+
7+
## ℹ️ Details
8+
9+
<table>
10+
<tr><td><strong>Component </strong> <td><a href="🛠-addons-cc-addon-info--default-story"><code>&lt;cc-addon-info&gt;</code></a>
11+
<tr><td><strong>Selector </strong> <td><code>cc-addon-info[smart-mode="kubernetes"]</code>
12+
<tr><td><strong>Requires auth</strong> <td>Yes
13+
</table>
14+
15+
## ⚙️ Params
16+
17+
| Name | Type | Details | Default |
18+
| ------------------- | ----------- | --------------------------------------------------------- | ------- |
19+
| `apiConfig` | `ApiConfig` | Object with API configuration (target host, tokens...) | |
20+
| `ownerId` | `string` | UUID prefixed with orga_ | |
21+
| `kubernetesId` | `string` | ID of the Kubernetes cluster prefixed with kubernetes_ | |
22+
23+
```ts
24+
interface ApiConfig {
25+
API_HOST: string;
26+
API_OAUTH_TOKEN: string;
27+
API_OAUTH_TOKEN_SECRET: string;
28+
OAUTH_CONSUMER_KEY: string;
29+
OAUTH_CONSUMER_SECRET: string;
30+
}
31+
```
32+
33+
## 🌐 API endpoints
34+
35+
| Method | URL | Cache? |
36+
|----------|------------------------------------------------------------------|---------|
37+
| `GET` | `/v4/kubernetes/organisations/${ownerId}/clusters/${kubernetesId}` | Default |
38+
39+
40+
## ⬇️️ Examples
41+
42+
```html
43+
<cc-smart-container context='{
44+
"apiConfig": {
45+
"API_HOST": "",
46+
"API_OAUTH_TOKEN": "",
47+
"API_OAUTH_TOKEN_SECRET": "",
48+
"OAUTH_CONSUMER_KEY": "",
49+
"OAUTH_CONSUMER_SECRET": ""
50+
},
51+
"ownerId": "orga_XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX",
52+
"kubernetesId": "kubernetes_XXXXXXXXXXXXXXXXXXXXXXX",
53+
}'>
54+
<cc-addon-info smart-mode="kubernetes"></cc-addon-info>
55+
</cc-smart-container>
56+
```

src/translations/translations.en.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -301,6 +301,7 @@ export const translations = {
301301
'cc-addon-info.creation-date.human-friendly-date': /** @param {{ date: string | number }} _ */ ({ date }) =>
302302
formatDatetime(date),
303303
'cc-addon-info.doc-link.keycloak': `Keycloak - Documentation`,
304+
'cc-addon-info.doc-link.kubernetes': `Kubernetes - Documentation`,
304305
'cc-addon-info.doc-link.matomo': `Matomo - Documentation`,
305306
'cc-addon-info.doc-link.metabase': `Metabase - Documentation`,
306307
'cc-addon-info.doc-link.otoroshi': `Otoroshi - Documentation`,

src/translations/translations.fr.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -312,6 +312,7 @@ export const translations = {
312312
'cc-addon-info.creation-date.human-friendly-date': /** @param {{ date: string | number }} _ */ ({ date }) =>
313313
formatDatetime(date),
314314
'cc-addon-info.doc-link.keycloak': `Keycloak - Documentation`,
315+
'cc-addon-info.doc-link.kubernetes': `Kubernetes - Documentation`,
315316
'cc-addon-info.doc-link.matomo': `Matomo - Documentation`,
316317
'cc-addon-info.doc-link.metabase': `Metabase - Documentation`,
317318
'cc-addon-info.doc-link.otoroshi': `Otoroshi - Documentation`,

0 commit comments

Comments
 (0)