Compare commits
18 commits
main
...
feat/new-u
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
89b543493a | ||
|
|
d2dd687a07 | ||
|
|
b091073e87 | ||
|
|
da7258915f | ||
|
|
fd259692b8 | ||
|
|
caaf4f90d4 | ||
|
|
e8fbd4e8cc | ||
|
|
d7756866eb | ||
|
|
5445e3f213 | ||
|
|
becf8d7572 | ||
|
|
41b355163d | ||
|
|
574dabeb25 | ||
|
|
6f78c23881 | ||
|
|
8b037d3045 | ||
|
|
c7c4f724af | ||
|
|
4de9c50e2f | ||
|
|
ddcc1f2ad6 | ||
|
|
ed01319aa1 |
24 changed files with 173 additions and 713 deletions
1
packages/system/dashboard/.gitignore
vendored
Normal file
1
packages/system/dashboard/.gitignore
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
.tmp-cozystack-ui
|
||||
|
|
@ -4,51 +4,34 @@ export NAMESPACE=cozy-$(NAME)
|
|||
include ../../../hack/common-envs.mk
|
||||
include ../../../hack/package.mk
|
||||
|
||||
update: update-crd update-dockerfiles
|
||||
image: image-openapi-ui image-openapi-ui-k8s-bff image-token-proxy update-tenant-text
|
||||
.PHONY: image image-console image-token-proxy
|
||||
|
||||
image: image-console image-token-proxy
|
||||
|
||||
update-dockerfiles:
|
||||
@echo Update dockerfiles manually
|
||||
CONSOLE_REPO ?= https://github.com/cozystack/cozystack-ui.git
|
||||
CONSOLE_REF ?= dd1ff0bdbd5e6e2fb6614fd1d831c4cb5c8f8025
|
||||
|
||||
update-crd:
|
||||
rm -rf crds
|
||||
mkdir -p crds
|
||||
wget -O- https://github.com/PRO-Robotech/helmfile-manifests/archive/refs/heads/main.tar.gz | tar -C crds -xzvf- helmfile-manifests-main/charts/incloud-main/incloud-web-1.0.0/incloud-web/templates --strip-components=6
|
||||
rm -f crds/_helpers.tpl
|
||||
sed -i '/{{/d' crds/*.yml crds/*.yaml
|
||||
|
||||
image-openapi-ui:
|
||||
docker buildx build images/openapi-ui \
|
||||
image-console:
|
||||
rm -rf .tmp-cozystack-ui
|
||||
git clone --no-checkout $(CONSOLE_REPO) .tmp-cozystack-ui
|
||||
git -C .tmp-cozystack-ui fetch --depth 1 origin $(CONSOLE_REF)
|
||||
git -C .tmp-cozystack-ui checkout FETCH_HEAD
|
||||
docker buildx build .tmp-cozystack-ui \
|
||||
--file .tmp-cozystack-ui/Containerfile \
|
||||
--provenance false \
|
||||
--builder=$(BUILDER) \
|
||||
--platform=linux/amd64 \
|
||||
--tag $(REGISTRY)/openapi-ui:$(call settag,$(TAG)) \
|
||||
--cache-from type=registry,ref=$(REGISTRY)/openapi-ui:latest \
|
||||
--tag $(REGISTRY)/cozystack-ui:$(call settag,$(TAG)) \
|
||||
--cache-from type=registry,ref=$(REGISTRY)/cozystack-ui:latest \
|
||||
--cache-to type=inline \
|
||||
--metadata-file images/openapi-ui.json \
|
||||
--metadata-file images/console.json \
|
||||
--build-arg APP_VERSION=$(COZYSTACK_VERSION) \
|
||||
--push=$(PUSH) \
|
||||
--label "org.opencontainers.image.source=https://github.com/cozystack/cozystack" \
|
||||
--label "org.opencontainers.image.source=https://github.com/cozystack/cozystack-ui" \
|
||||
--load=$(LOAD)
|
||||
IMAGE="$(REGISTRY)/openapi-ui:$(call settag,$(TAG))@$$(yq e '."containerimage.digest"' images/openapi-ui.json -r)" \
|
||||
yq -i '.openapiUI.image = strenv(IMAGE)' values.yaml
|
||||
rm -f images/openapi-ui.json
|
||||
|
||||
image-openapi-ui-k8s-bff:
|
||||
docker buildx build images/openapi-ui-k8s-bff \
|
||||
--provenance false \
|
||||
--builder=$(BUILDER) \
|
||||
--platform=linux/amd64 \
|
||||
--tag $(REGISTRY)/openapi-ui-k8s-bff:$(call settag,$(TAG)) \
|
||||
--cache-from type=registry,ref=$(REGISTRY)/openapi-ui-k8s-bff:latest \
|
||||
--cache-to type=inline \
|
||||
--metadata-file images/openapi-ui-k8s-bff.json \
|
||||
--push=$(PUSH) \
|
||||
--label "org.opencontainers.image.source=https://github.com/cozystack/cozystack" \
|
||||
--load=$(LOAD)
|
||||
IMAGE="$(REGISTRY)/openapi-ui-k8s-bff:$(call settag,$(TAG))@$$(yq e '."containerimage.digest"' images/openapi-ui-k8s-bff.json -r)" \
|
||||
yq -i '.openapiUIK8sBff.image = strenv(IMAGE)' values.yaml
|
||||
rm -f images/openapi-ui-k8s-bff.json
|
||||
IMAGE="$(REGISTRY)/cozystack-ui:$(call settag,$(TAG))@$$(yq e '."containerimage.digest"' images/console.json -r)" \
|
||||
yq -i '.console.image = strenv(IMAGE)' values.yaml
|
||||
rm -rf .tmp-cozystack-ui images/console.json
|
||||
|
||||
image-token-proxy:
|
||||
docker buildx build images/token-proxy \
|
||||
|
|
@ -65,6 +48,3 @@ image-token-proxy:
|
|||
IMAGE="$(REGISTRY)/token-proxy:$(call settag,$(TAG))@$$(yq e '."containerimage.digest"' images/token-proxy.json -r)" \
|
||||
yq -i '.tokenProxy.image = strenv(IMAGE)' values.yaml
|
||||
rm -f images/token-proxy.json
|
||||
|
||||
update-tenant-text:
|
||||
sed -i 's|\($$tenantText := "\)[^"]\+|\1$(TAG)|' templates/configmap.yaml
|
||||
|
|
|
|||
|
|
@ -1,22 +0,0 @@
|
|||
# imported from https://github.com/PRO-Robotech/openapi-ui-k8s-bff
|
||||
ARG NODE_VERSION=20.18.1
|
||||
FROM node:${NODE_VERSION}-alpine AS builder
|
||||
WORKDIR /src
|
||||
|
||||
# release/1.4.0
|
||||
ARG COMMIT_REF=92e4b618eb9ad17b19827b5a2b7ceab33e8cf534
|
||||
RUN wget -O- https://github.com/PRO-Robotech/openapi-ui-k8s-bff/archive/${COMMIT_REF}.tar.gz | tar xzf - --strip-components=1
|
||||
|
||||
ENV PATH=/src/node_modules/.bin:$PATH
|
||||
RUN npm install
|
||||
RUN npm run build
|
||||
|
||||
FROM node:${NODE_VERSION}-alpine
|
||||
WORKDIR /app
|
||||
COPY --from=builder /src/package*.json /app/
|
||||
COPY --from=builder /src/node_modules /app/node_modules
|
||||
COPY --from=builder /src/src/swagger/swagger-output.json /app/dist/swagger/swagger-output.json
|
||||
COPY --from=builder /src/dist /app/dist
|
||||
EXPOSE 8080
|
||||
USER 1001
|
||||
CMD [ "node", "/app/dist/index.js"]
|
||||
|
|
@ -1,69 +0,0 @@
|
|||
ARG NODE_VERSION=20.18.1
|
||||
|
||||
# openapi-k8s-toolkit
|
||||
# imported from https://github.com/PRO-Robotech/openapi-k8s-toolkit
|
||||
FROM node:${NODE_VERSION}-alpine AS openapi-k8s-toolkit-builder
|
||||
RUN apk add git
|
||||
WORKDIR /src
|
||||
# release/1.4.0
|
||||
ARG COMMIT=d6b9e4ad0d1eb9d3730f7f0c664792c8dda3214d
|
||||
RUN wget -O- https://github.com/PRO-Robotech/openapi-k8s-toolkit/archive/${COMMIT}.tar.gz | tar -xzvf- --strip-components=1
|
||||
|
||||
COPY openapi-k8s-toolkit/patches /patches
|
||||
RUN git apply /patches/*.diff
|
||||
|
||||
RUN npm install
|
||||
RUN npm install --build-from-source @swc/core
|
||||
RUN npm run build
|
||||
|
||||
|
||||
# openapi-ui
|
||||
# imported from https://github.com/PRO-Robotech/openapi-ui
|
||||
FROM node:${NODE_VERSION}-alpine AS builder
|
||||
#RUN apk add git
|
||||
WORKDIR /src
|
||||
|
||||
# release/1.4.0
|
||||
ARG COMMIT_REF=6addca6939264ef2e39801baa88c1460cc1aa53e
|
||||
RUN wget -O- https://github.com/PRO-Robotech/openapi-ui/archive/${COMMIT_REF}.tar.gz | tar xzf - --strip-components=1
|
||||
|
||||
#COPY openapi-ui/patches /patches
|
||||
#RUN git apply /patches/*.diff
|
||||
|
||||
ENV PATH=/src/node_modules/.bin:$PATH
|
||||
|
||||
RUN npm install
|
||||
|
||||
# add patched openapi-k8s-toolkit
|
||||
RUN rm -rf node_modules/@prorobotech/openapi-k8s-toolkit/dist
|
||||
COPY --from=openapi-k8s-toolkit-builder /src/dist node_modules/@prorobotech/openapi-k8s-toolkit/dist
|
||||
|
||||
RUN npm run build
|
||||
|
||||
FROM node:${NODE_VERSION}-alpine AS builder2
|
||||
WORKDIR /src
|
||||
ENV PATH=/src/node_modules/.bin:$PATH
|
||||
|
||||
COPY --from=builder /src/server/package.json ./
|
||||
COPY --from=builder /src/server/package-lock.json ./
|
||||
RUN npm install
|
||||
COPY --from=builder /src/server server
|
||||
COPY --from=builder /src/tsconfig.server.json ./
|
||||
COPY --from=builder /src/build /src/build
|
||||
RUN npm run server:build
|
||||
|
||||
FROM node:${NODE_VERSION}-alpine
|
||||
WORKDIR /app
|
||||
COPY --from=builder2 /src/node_modules /app/node_modules
|
||||
COPY --from=builder2 /src/build /app/build
|
||||
EXPOSE 8080
|
||||
RUN sed -i -e 's|OpenAPI UI|Cozystack|g' build/index.html
|
||||
# Fix Factory component: return null while loading instead of showing "Factory Not Found" 404
|
||||
RUN APP_JS=$(find build -name "App-react.js" -type f | head -1) && \
|
||||
if [ -n "$APP_JS" ]; then \
|
||||
sed -i 's|const { data: factoryData } = useK8sSmartResource({|const { data: factoryData, isLoading: factoryIsLoading } = useK8sSmartResource({|' "$APP_JS" && \
|
||||
sed -i '/Factory Not Found/s/return /return factoryIsLoading ? null : /' "$APP_JS" && \
|
||||
echo "Factory loading patch applied to $APP_JS"; \
|
||||
fi
|
||||
USER 1001
|
||||
CMD ["node", "/app/build/index.js"]
|
||||
|
|
@ -1,17 +0,0 @@
|
|||
diff --git a/src/components/molecules/EnrichedTable/organisms/EnrichedTableProvider/utils.ts b/src/components/molecules/EnrichedTable/organisms/EnrichedTableProvider/utils.ts
|
||||
--- a/src/components/molecules/EnrichedTable/organisms/EnrichedTableProvider/utils.ts
|
||||
+++ b/src/components/molecules/EnrichedTable/organisms/EnrichedTableProvider/utils.ts
|
||||
@@ -185,6 +185,11 @@
|
||||
return `['${escaped}']`
|
||||
})
|
||||
}
|
||||
- const jpQueryResult = jp.query(el, `$${resolvedJsonPath}`)
|
||||
- fieldValue = Array.isArray(jpQueryResult) && jpQueryResult.length === 1 ? jpQueryResult[0] : jpQueryResult
|
||||
+ if (/_flatMap[^\]]+_Key/.test(resolvedJsonPath)) {
|
||||
+ // Placeholder was not resolved (row not yet expanded or key missing) — skip query
|
||||
+ fieldValue = null
|
||||
+ } else {
|
||||
+ const jpQueryResult = jp.query(el, `$${resolvedJsonPath}`)
|
||||
+ fieldValue = Array.isArray(jpQueryResult) && jpQueryResult.length === 1 ? jpQueryResult[0] : jpQueryResult
|
||||
+ }
|
||||
}
|
||||
|
|
@ -1,37 +0,0 @@
|
|||
diff --git a/src/localTypes/formExtensions.ts b/src/localTypes/formExtensions.ts
|
||||
--- a/src/localTypes/formExtensions.ts
|
||||
+++ b/src/localTypes/formExtensions.ts
|
||||
@@ -59,2 +59,4 @@
|
||||
relatedValuePath?: string
|
||||
+ allowEmpty?: boolean
|
||||
+ persistType?: 'str' | 'number' | 'arr' | 'obj'
|
||||
}
|
||||
diff --git a/src/components/molecules/BlackholeForm/molecules/FormListInput/FormListInput.tsx b/src/components/molecules/BlackholeForm/molecules/FormListInput/FormListInput.tsx
|
||||
--- a/src/components/molecules/BlackholeForm/molecules/FormListInput/FormListInput.tsx
|
||||
+++ b/src/components/molecules/BlackholeForm/molecules/FormListInput/FormListInput.tsx
|
||||
@@ -149,3 +149,10 @@
|
||||
}, [relatedPath, form, arrName, fixedName, relatedFieldValue, onValuesChangeCallBack, isTouchedPeristed])
|
||||
|
||||
+ // When allowEmpty is set, auto-persist the field so the BFF preserves empty values
|
||||
+ useEffect(() => {
|
||||
+ if (customProps.allowEmpty) {
|
||||
+ persistedControls.onPersistMark(persistName || name, customProps.persistType ?? 'str')
|
||||
+ }
|
||||
+ }, [customProps.allowEmpty, customProps.persistType, persistedControls, persistName, name])
|
||||
+
|
||||
const uri = prepareTemplate({
|
||||
@@ -267,5 +274,14 @@
|
||||
validateTrigger="onBlur"
|
||||
hasFeedback={designNewLayout ? { icons: feedbackIcons } : true}
|
||||
style={{ flex: 1 }}
|
||||
+ normalize={(value: unknown) => {
|
||||
+ if (customProps.allowEmpty && (value === undefined || value === null)) {
|
||||
+ if (customProps.persistType === 'number') return 0
|
||||
+ if (customProps.persistType === 'arr') return []
|
||||
+ if (customProps.persistType === 'obj') return {}
|
||||
+ return ''
|
||||
+ }
|
||||
+ return value
|
||||
+ }}
|
||||
>
|
||||
<Select
|
||||
|
|
@ -1,29 +0,0 @@
|
|||
diff --git a/src/components/organisms/DynamicComponents/molecules/SecretBase64Plain/SecretBase64Plain.tsx b/src/components/organisms/DynamicComponents/molecules/SecretBase64Plain/SecretBase64Plain.tsx
|
||||
--- a/src/components/organisms/DynamicComponents/molecules/SecretBase64Plain/SecretBase64Plain.tsx
|
||||
+++ b/src/components/organisms/DynamicComponents/molecules/SecretBase64Plain/SecretBase64Plain.tsx
|
||||
@@ -145,6 +145,12 @@
|
||||
<Styled.DisabledInput
|
||||
$hidden={effectiveHidden}
|
||||
onClick={e => handleInputClick(e, effectiveHidden, value)}
|
||||
+ onCopy={e => {
|
||||
+ if (!effectiveHidden) {
|
||||
+ e.preventDefault()
|
||||
+ e.clipboardData?.setData('text/plain', value)
|
||||
+ }
|
||||
+ }}
|
||||
value={shownValue}
|
||||
readOnly
|
||||
/>
|
||||
@@ -161,6 +167,12 @@
|
||||
<Styled.DisabledInput
|
||||
$hidden={effectiveHidden}
|
||||
onClick={e => handleInputClick(e, effectiveHidden, value)}
|
||||
+ onCopy={e => {
|
||||
+ if (!effectiveHidden) {
|
||||
+ e.preventDefault()
|
||||
+ e.clipboardData?.setData('text/plain', value)
|
||||
+ }
|
||||
+ }}
|
||||
value={shownValue}
|
||||
readOnly
|
||||
/>
|
||||
|
|
@ -1,50 +0,0 @@
|
|||
diff --git a/src/components/molecules/EnrichedTable/organisms/EnrichedTable/utils.tsx b/src/components/molecules/EnrichedTable/organisms/EnrichedTable/utils.tsx
|
||||
index 8bcef4d..2551e92 100644
|
||||
--- a/src/components/molecules/EnrichedTable/organisms/EnrichedTable/utils.tsx
|
||||
+++ b/src/components/molecules/EnrichedTable/organisms/EnrichedTable/utils.tsx
|
||||
@@ -22,6 +22,15 @@ import { TableFactory } from '../../molecules'
|
||||
import { ShortenedTextWithTooltip, FilterDropdown, TrimmedTags, TextAlignContainer, TinyButton } from './atoms'
|
||||
import { TInternalDataForControls } from './types'
|
||||
|
||||
+const getPluralForm = (singular: string): string => {
|
||||
+ // If already ends with 's', add 'es'
|
||||
+ if (singular.endsWith('s')) {
|
||||
+ return `${singular}es`
|
||||
+ }
|
||||
+ // Otherwise just add 's'
|
||||
+ return `${singular}s`
|
||||
+}
|
||||
+
|
||||
export const getCellRender = ({
|
||||
value,
|
||||
record,
|
||||
@@ -255,7 +264,7 @@ export const getEnrichedColumnsWithControls = ({
|
||||
key: 'controls',
|
||||
className: 'controls',
|
||||
width: 60,
|
||||
- render: (value: TInternalDataForControls) => {
|
||||
+ render: (value: TInternalDataForControls, record: unknown) => {
|
||||
return (
|
||||
// <TextAlignContainer $align="right" className="hideable">
|
||||
<TextAlignContainer $align="center">
|
||||
@@ -279,10 +288,19 @@ export const getEnrichedColumnsWithControls = ({
|
||||
domEvent.stopPropagation()
|
||||
domEvent.preventDefault()
|
||||
if (key === 'edit') {
|
||||
+ // Special case: redirect tenantmodules from core.cozystack.io to apps.cozystack.io with plural form
|
||||
+ let apiGroupAndVersion = value.apiGroupAndVersion
|
||||
+ let plural = value.plural
|
||||
+ if (apiGroupAndVersion?.startsWith('core.cozystack.io/') && plural === 'tenantmodules') {
|
||||
+ const appsApiVersion = apiGroupAndVersion.replace('core.cozystack.io/', 'apps.cozystack.io/')
|
||||
+ const pluralName = getPluralForm(value.name)
|
||||
+ apiGroupAndVersion = appsApiVersion
|
||||
+ plural = pluralName
|
||||
+ }
|
||||
navigate(
|
||||
`${baseprefix}/${value.cluster}${value.namespace ? `/${value.namespace}` : ''}${
|
||||
value.syntheticProject ? `/${value.syntheticProject}` : ''
|
||||
- }/${value.pathPrefix}/${value.apiGroupAndVersion}/${value.plural}/${value.name}?backlink=${
|
||||
+ }/${value.pathPrefix}/${apiGroupAndVersion}/${plural}/${value.name}?backlink=${
|
||||
value.backlink
|
||||
}`,
|
||||
)
|
||||
|
|
@ -0,0 +1,82 @@
|
|||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: cozy-dashboard-adopt
|
||||
namespace: cozy-dashboard
|
||||
annotations:
|
||||
"helm.sh/hook": pre-upgrade,pre-install
|
||||
"helm.sh/hook-weight": "-10"
|
||||
"helm.sh/hook-delete-policy": hook-succeeded,hook-failed
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: Role
|
||||
metadata:
|
||||
name: cozy-dashboard-adopt
|
||||
namespace: cozy-dashboard
|
||||
annotations:
|
||||
"helm.sh/hook": pre-upgrade,pre-install
|
||||
"helm.sh/hook-weight": "-10"
|
||||
"helm.sh/hook-delete-policy": hook-succeeded,hook-failed
|
||||
rules:
|
||||
- apiGroups: [""]
|
||||
resources: ["configmaps"]
|
||||
resourceNames: ["cozy-dashboard-console-config"]
|
||||
verbs: ["get", "patch"]
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: RoleBinding
|
||||
metadata:
|
||||
name: cozy-dashboard-adopt
|
||||
namespace: cozy-dashboard
|
||||
annotations:
|
||||
"helm.sh/hook": pre-upgrade,pre-install
|
||||
"helm.sh/hook-weight": "-10"
|
||||
"helm.sh/hook-delete-policy": hook-succeeded,hook-failed
|
||||
roleRef:
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: Role
|
||||
name: cozy-dashboard-adopt
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: cozy-dashboard-adopt
|
||||
namespace: cozy-dashboard
|
||||
---
|
||||
apiVersion: batch/v1
|
||||
kind: Job
|
||||
metadata:
|
||||
name: cozy-dashboard-adopt-configmap
|
||||
namespace: cozy-dashboard
|
||||
annotations:
|
||||
"helm.sh/hook": pre-upgrade,pre-install
|
||||
"helm.sh/hook-weight": "-5"
|
||||
"helm.sh/hook-delete-policy": hook-succeeded,hook-failed
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
serviceAccountName: cozy-dashboard-adopt
|
||||
restartPolicy: Never
|
||||
securityContext:
|
||||
runAsNonRoot: true
|
||||
runAsUser: 65534
|
||||
seccompProfile:
|
||||
type: RuntimeDefault
|
||||
containers:
|
||||
- name: adopt
|
||||
image: rancher/kubectl:v1.29.10
|
||||
securityContext:
|
||||
allowPrivilegeEscalation: false
|
||||
capabilities:
|
||||
drop: ["ALL"]
|
||||
command:
|
||||
- /bin/sh
|
||||
- -c
|
||||
- |
|
||||
kubectl annotate configmap cozy-dashboard-console-config \
|
||||
--namespace cozy-dashboard \
|
||||
meta.helm.sh/release-name={{ .Release.Name }} \
|
||||
meta.helm.sh/release-namespace={{ .Release.Namespace }} \
|
||||
--overwrite 2>/dev/null || true
|
||||
kubectl label configmap cozy-dashboard-console-config \
|
||||
--namespace cozy-dashboard \
|
||||
app.kubernetes.io/managed-by=Helm \
|
||||
--overwrite 2>/dev/null || true
|
||||
|
|
@ -1,12 +1,12 @@
|
|||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRoleBinding
|
||||
metadata:
|
||||
name: incloud-web-cluster-view
|
||||
name: cozy-dashboard-cluster-view
|
||||
roleRef:
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: ClusterRole
|
||||
name: view
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: incloud-web-web
|
||||
namespace: incloud-web
|
||||
name: cozy-dashboard-console
|
||||
namespace: {{ .Release.Namespace }}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ apiVersion: rbac.authorization.k8s.io/v1
|
|||
kind: ClusterRoleBinding
|
||||
metadata:
|
||||
annotations: {}
|
||||
name: incloud-web-web-user-edit
|
||||
name: cozystack-dashboard-cluster-admin
|
||||
roleRef:
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: ClusterRole
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
28
packages/system/dashboard/templates/console-rbac.yaml
Normal file
28
packages/system/dashboard/templates/console-rbac.yaml
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: Role
|
||||
metadata:
|
||||
name: cozy-dashboard-console-config-reader
|
||||
namespace: cozy-dashboard
|
||||
rules:
|
||||
- apiGroups:
|
||||
- ""
|
||||
resources:
|
||||
- configmaps
|
||||
resourceNames:
|
||||
- cozy-dashboard-console-config
|
||||
verbs:
|
||||
- get
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: RoleBinding
|
||||
metadata:
|
||||
name: cozy-dashboard-console-config-reader
|
||||
namespace: cozy-dashboard
|
||||
roleRef:
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: Role
|
||||
name: cozy-dashboard-console-config-reader
|
||||
subjects:
|
||||
- apiGroup: rbac.authorization.k8s.io
|
||||
kind: Group
|
||||
name: system:authenticated
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: incloud-web-nginx
|
||||
name: cozy-dashboard-console
|
||||
|
|
@ -1,14 +1,14 @@
|
|||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: incloud-web-nginx
|
||||
name: cozy-dashboard-console
|
||||
spec:
|
||||
ports:
|
||||
- name: nginx-http
|
||||
- name: http
|
||||
port: 8080
|
||||
protocol: TCP
|
||||
targetPort: 8080
|
||||
selector:
|
||||
app.kubernetes.io/instance: incloud-web
|
||||
app.kubernetes.io/name: nginx
|
||||
app.kubernetes.io/instance: cozy-dashboard
|
||||
app.kubernetes.io/name: console
|
||||
type: ClusterIP
|
||||
|
|
@ -1,13 +1,13 @@
|
|||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: incloud-web-nginx
|
||||
name: cozy-dashboard-console
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app.kubernetes.io/instance: incloud-web
|
||||
app.kubernetes.io/name: nginx
|
||||
app.kubernetes.io/instance: cozy-dashboard
|
||||
app.kubernetes.io/name: console
|
||||
strategy:
|
||||
rollingUpdate:
|
||||
maxSurge: 25%
|
||||
|
|
@ -16,10 +16,10 @@ spec:
|
|||
template:
|
||||
metadata:
|
||||
annotations:
|
||||
checksum/config: {{ include (print $.Template.BasePath "/nginx-config.yaml") . | sha256sum }}
|
||||
checksum/config: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }}
|
||||
labels:
|
||||
app.kubernetes.io/instance: incloud-web
|
||||
app.kubernetes.io/name: nginx
|
||||
app.kubernetes.io/instance: cozy-dashboard
|
||||
app.kubernetes.io/name: console
|
||||
spec:
|
||||
affinity:
|
||||
podAntiAffinity:
|
||||
|
|
@ -30,15 +30,15 @@ spec:
|
|||
- key: app.kubernetes.io/name
|
||||
operator: In
|
||||
values:
|
||||
- appSpec
|
||||
- console
|
||||
- key: app.kubernetes.io/instance
|
||||
operator: In
|
||||
values:
|
||||
- incloud-web
|
||||
- cozy-dashboard
|
||||
topologyKey: kubernetes.io/hostname
|
||||
weight: 100
|
||||
containers:
|
||||
- image: nginxinc/nginx-unprivileged:1.29-alpine
|
||||
- image: {{ .Values.console.image | quote }}
|
||||
imagePullPolicy: IfNotPresent
|
||||
livenessProbe:
|
||||
failureThreshold: 3
|
||||
|
|
@ -50,7 +50,14 @@ spec:
|
|||
periodSeconds: 10
|
||||
successThreshold: 1
|
||||
timeoutSeconds: 2
|
||||
name: nginx
|
||||
startupProbe:
|
||||
httpGet:
|
||||
path: /healthcheck
|
||||
port: 8080
|
||||
scheme: HTTP
|
||||
failureThreshold: 30
|
||||
periodSeconds: 2
|
||||
name: console
|
||||
ports:
|
||||
- containerPort: 8080
|
||||
name: http
|
||||
|
|
@ -78,23 +85,13 @@ spec:
|
|||
type: RuntimeDefault
|
||||
terminationMessagePath: /dev/termination-log
|
||||
terminationMessagePolicy: File
|
||||
volumeMounts:
|
||||
- mountPath: /etc/nginx/conf.d/default.conf
|
||||
name: configurationnginxfile
|
||||
subPath: nginx-config
|
||||
dnsPolicy: ClusterFirst
|
||||
enableServiceLinks: false
|
||||
hostIPC: false
|
||||
hostNetwork: false
|
||||
hostPID: false
|
||||
preemptionPolicy: null
|
||||
priorityClassName: system-cluster-critical
|
||||
restartPolicy: Always
|
||||
runtimeClassName: null
|
||||
schedulerName: default-scheduler
|
||||
serviceAccountName: incloud-web-nginx
|
||||
serviceAccountName: cozy-dashboard-console
|
||||
terminationGracePeriodSeconds: 30
|
||||
volumes:
|
||||
- configMap:
|
||||
name: incloud-web-nginx-config
|
||||
name: configurationnginxfile
|
||||
|
|
@ -10,7 +10,7 @@ spec:
|
|||
- subjects:
|
||||
- kind: ServiceAccount
|
||||
serviceAccount:
|
||||
name: incloud-web-web
|
||||
name: cozy-dashboard-console
|
||||
namespace: {{ .Release.Namespace }}
|
||||
resourceRules:
|
||||
- verbs: ["*"]
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ spec:
|
|||
imagePullPolicy: IfNotPresent
|
||||
args:
|
||||
- --provider=oidc
|
||||
- --upstream=http://incloud-web-nginx.{{ .Release.Namespace }}.svc:8080
|
||||
- --upstream=http://cozy-dashboard-console.{{ .Release.Namespace }}.svc:8080
|
||||
- --http-address=0.0.0.0:8000
|
||||
- --redirect-url=https://dashboard.{{ $host }}/oauth2/callback
|
||||
- --oidc-issuer-url=https://keycloak.{{ $host }}/realms/cozy
|
||||
|
|
@ -97,7 +97,7 @@ spec:
|
|||
image: {{ .Values.tokenProxy.image }}
|
||||
imagePullPolicy: IfNotPresent
|
||||
args:
|
||||
- --upstream=http://incloud-web-nginx.{{ .Release.Namespace }}.svc:8080
|
||||
- --upstream=http://cozy-dashboard-console.{{ .Release.Namespace }}.svc:8080
|
||||
- --http-address=0.0.0.0:8000
|
||||
- --cookie-refresh=1h
|
||||
- --cookie-name=kc-access
|
||||
|
|
|
|||
|
|
@ -1,97 +0,0 @@
|
|||
{{- $host := index .Values._cluster "root-host" }}
|
||||
|
||||
apiVersion: v1
|
||||
data:
|
||||
nginx-config: |-
|
||||
map $http_upgrade $connection_upgrade {
|
||||
default upgrade;
|
||||
'' close;
|
||||
}
|
||||
|
||||
server {
|
||||
listen 8080 default_server;
|
||||
listen [::]:8080 default_server;
|
||||
server_name _;
|
||||
|
||||
location ~ ^(/clusterlist|/api/clusters)$ {
|
||||
add_header Content-Type application/json;
|
||||
set $cluster_list '[{"api":"{{ $host }}","baseDomain":"{{ $host }}","description":"dashboard.{{ $host }}","externalDomain":"dashboard.{{ $host }}","name":"default","tenant":"dev"}]';
|
||||
return 200 $cluster_list;
|
||||
}
|
||||
|
||||
location /api/clusters/default {
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection $connection_upgrade;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_set_header Host $host;
|
||||
proxy_read_timeout 86400s;
|
||||
proxy_send_timeout 86400s;
|
||||
|
||||
rewrite /api/clusters/default/(.*) /$1 break;
|
||||
proxy_pass http://incloud-web-nginx.{{ .Release.Namespace }}.svc:8080;
|
||||
}
|
||||
|
||||
location /k8s/clusters/default/ {
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection $connection_upgrade;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_set_header Host $host;
|
||||
proxy_read_timeout 86400s;
|
||||
proxy_send_timeout 86400s;
|
||||
|
||||
rewrite /k8s/clusters/default/(.*) /$1 break;
|
||||
proxy_pass https://kubernetes.default.svc:443;
|
||||
}
|
||||
|
||||
location /k8s {
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection $connection_upgrade;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_set_header Host $host;
|
||||
proxy_read_timeout 86400s;
|
||||
proxy_send_timeout 86400s;
|
||||
|
||||
rewrite /k8s/(.*) /$1 break;
|
||||
proxy_pass https://kubernetes.default.svc:443;
|
||||
}
|
||||
|
||||
location /openapi-bff {
|
||||
proxy_pass http://incloud-web-web.{{ .Release.Namespace }}.svc:64231;
|
||||
}
|
||||
|
||||
|
||||
location /openapi-bff-ws/ {
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection $connection_upgrade;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_set_header Host $host;
|
||||
proxy_read_timeout 86400s;
|
||||
proxy_send_timeout 86400s;
|
||||
|
||||
proxy_pass http://incloud-web-web.{{ .Release.Namespace }}.svc:64231;
|
||||
}
|
||||
|
||||
location = /docs {
|
||||
return 301 https://cozystack.io/docs/;
|
||||
}
|
||||
|
||||
location = / {
|
||||
return 301 https://dashboard.{{ $host }}/openapi-ui;
|
||||
}
|
||||
|
||||
location / {
|
||||
proxy_pass http://incloud-web-web.{{ .Release.Namespace }}.svc:8080;
|
||||
}
|
||||
|
||||
location /healthcheck {
|
||||
access_log off;
|
||||
return 200 "Healthy\n";
|
||||
}
|
||||
}
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: incloud-web-nginx-config
|
||||
|
|
@ -4,6 +4,14 @@ kind: ClusterRole
|
|||
metadata:
|
||||
name: cozystack-dashboard-readonly
|
||||
rules:
|
||||
- apiGroups:
|
||||
- cozystack.io
|
||||
resources:
|
||||
- applicationdefinitions
|
||||
verbs:
|
||||
- get
|
||||
- list
|
||||
- watch
|
||||
- apiGroups:
|
||||
- dashboard.cozystack.io
|
||||
resources:
|
||||
|
|
|
|||
|
|
@ -1,4 +0,0 @@
|
|||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: incloud-web-web
|
||||
|
|
@ -1,18 +0,0 @@
|
|||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: incloud-web-web
|
||||
spec:
|
||||
ports:
|
||||
- name: bff-http
|
||||
port: 64231
|
||||
protocol: TCP
|
||||
targetPort: 64231
|
||||
- name: web-http
|
||||
port: 8080
|
||||
protocol: TCP
|
||||
targetPort: 8080
|
||||
selector:
|
||||
app.kubernetes.io/instance: incloud-web
|
||||
app.kubernetes.io/name: web
|
||||
type: ClusterIP
|
||||
|
|
@ -1,274 +0,0 @@
|
|||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: incloud-web-web
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app.kubernetes.io/instance: incloud-web
|
||||
app.kubernetes.io/name: web
|
||||
strategy:
|
||||
rollingUpdate:
|
||||
maxSurge: 25%
|
||||
maxUnavailable: 25%
|
||||
type: RollingUpdate
|
||||
template:
|
||||
metadata:
|
||||
annotations:
|
||||
checksum/config: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }}
|
||||
labels:
|
||||
app.kubernetes.io/instance: incloud-web
|
||||
app.kubernetes.io/name: web
|
||||
spec:
|
||||
affinity:
|
||||
podAntiAffinity:
|
||||
preferredDuringSchedulingIgnoredDuringExecution:
|
||||
- podAffinityTerm:
|
||||
labelSelector:
|
||||
matchExpressions:
|
||||
- key: app.kubernetes.io/name
|
||||
operator: In
|
||||
values:
|
||||
- appSpec
|
||||
- key: app.kubernetes.io/instance
|
||||
operator: In
|
||||
values:
|
||||
- incloud-web
|
||||
topologyKey: kubernetes.io/hostname
|
||||
weight: 100
|
||||
containers:
|
||||
- env:
|
||||
- name: BASE_API_GROUP
|
||||
value: dashboard.cozystack.io
|
||||
- name: BASE_API_VERSION
|
||||
value: v1alpha1
|
||||
- name: BASE_NAMESPACE_FULL_PATH
|
||||
value: "/apis/core.cozystack.io/v1alpha1/tenantnamespaces"
|
||||
- name: BASE_NAVIGATION_RESOURCE_PLURAL
|
||||
value: navigations
|
||||
- name: BASE_NAVIGATION_RESOURCE_NAME
|
||||
value: navigation
|
||||
- name: BASE_FRONTEND_PREFIX
|
||||
value: /openapi-ui
|
||||
- name: BASE_FACTORY_NAMESPACED_API_KEY
|
||||
value: base-factory-namespaced-api
|
||||
- name: BASE_FACTORY_CLUSTERSCOPED_API_KEY
|
||||
value: base-factory-clusterscoped-api
|
||||
- name: BASE_FACTORY_NAMESPACED_BUILTIN_KEY
|
||||
value: base-factory-namespaced-builtin
|
||||
- name: BASE_FACTORY_CLUSTERSCOPED_BUILTIN_KEY
|
||||
value: base-factory-clusterscoped-builtin
|
||||
- name: BASE_NAMESPACE_FACTORY_KEY
|
||||
value: base-factory-clusterscoped-builtin
|
||||
- name: BASE_ALLOWED_AUTH_HEADERS
|
||||
value: user-agent,accept,content-type,origin,referer,accept-encoding,cookie,authorization
|
||||
- name: LOGGER
|
||||
value: "true"
|
||||
- name: LOGGER_WITH_HEADERS
|
||||
value: "false"
|
||||
- name: PORT
|
||||
value: "64231"
|
||||
image: {{ .Values.openapiUIK8sBff.image | quote }}
|
||||
imagePullPolicy: IfNotPresent
|
||||
livenessProbe:
|
||||
failureThreshold: 3
|
||||
httpGet:
|
||||
path: /healthcheck
|
||||
port: 64231
|
||||
scheme: HTTP
|
||||
initialDelaySeconds: 3
|
||||
periodSeconds: 10
|
||||
successThreshold: 1
|
||||
timeoutSeconds: 2
|
||||
startupProbe:
|
||||
httpGet:
|
||||
path: /healthcheck
|
||||
port: 64231
|
||||
scheme: HTTP
|
||||
failureThreshold: 30
|
||||
periodSeconds: 2
|
||||
name: bff
|
||||
ports:
|
||||
- containerPort: 64231
|
||||
name: http-bff
|
||||
protocol: TCP
|
||||
resources:
|
||||
limits:
|
||||
cpu: 1
|
||||
memory: 1Gi
|
||||
requests:
|
||||
cpu: 100m
|
||||
ephemeral-storage: 50Mi
|
||||
memory: 128Mi
|
||||
securityContext:
|
||||
allowPrivilegeEscalation: false
|
||||
capabilities:
|
||||
add: []
|
||||
drop:
|
||||
- ALL
|
||||
privileged: false
|
||||
readOnlyRootFilesystem: false
|
||||
runAsGroup: 0
|
||||
runAsNonRoot: true
|
||||
runAsUser: 101
|
||||
seccompProfile:
|
||||
type: RuntimeDefault
|
||||
terminationMessagePath: /dev/termination-log
|
||||
terminationMessagePolicy: File
|
||||
- env:
|
||||
- name: BASEPREFIX
|
||||
value: /openapi-ui
|
||||
- name: HIDE_INSIDE
|
||||
value: "true"
|
||||
- name: CUSTOMIZATION_API_GROUP
|
||||
value: dashboard.cozystack.io
|
||||
- name: CUSTOMIZATION_API_VERSION
|
||||
value: v1alpha1
|
||||
- name: CUSTOMIZATION_CFOMAPPING_RESOURCE_NAME
|
||||
value: cfomapping
|
||||
- name: CUSTOMIZATION_CFOMAPPING_RESOURCE_PLURAL
|
||||
value: cfomappings
|
||||
- name: CUSTOMIZATION_CFO_FALLBACK_ID
|
||||
value: ""
|
||||
- name: CUSTOMIZATION_NAVIGATION_RESOURCE_NAME
|
||||
value: navigation
|
||||
- name: CUSTOMIZATION_NAVIGATION_RESOURCE_PLURAL
|
||||
value: navigations
|
||||
- name: CUSTOMIZATION_SIDEBAR_FALLBACK_ID
|
||||
value: ""
|
||||
- name: CUSTOMIZATION_BREADCRUMBS_FALLBACK_ID
|
||||
value: stock-project-api-table
|
||||
- name: INSTANCES_API_GROUP
|
||||
value: dashboard.cozystack.io
|
||||
- name: INSTANCES_API_VERSION
|
||||
value: v1alpha1
|
||||
- name: INSTANCES_PLURAL
|
||||
value: instances
|
||||
- name: MARKETPLACE_KIND
|
||||
value: MarketplacePanel
|
||||
- name: MARKETPLACE_PLURAL
|
||||
value: marketplacepanels
|
||||
- name: NAVIGATE_FROM_CLUSTERLIST
|
||||
value: /openapi-ui/~recordValue~/api-table/core.cozystack.io/v1alpha1/tenantnamespaces
|
||||
- name: PROJECTS_API_GROUP
|
||||
value: core.cozystack.io
|
||||
- name: PROJECTS_API_VERSION
|
||||
value: v1alpha1
|
||||
- name: PROJECTS_PLURAL
|
||||
value: tenantnamespaces
|
||||
- name: CUSTOM_NAMESPACE_API_RESOURCE_API_GROUP
|
||||
value: core.cozystack.io
|
||||
- name: CUSTOM_NAMESPACE_API_RESOURCE_API_VERSION
|
||||
value: v1alpha1
|
||||
- name: CUSTOM_NAMESPACE_API_RESOURCE_PLURAL
|
||||
value: tenantnamespaces
|
||||
- name: BASE_FACTORY_NAMESPACED_API_KEY
|
||||
value: base-factory-namespaced-api
|
||||
- name: BASE_FACTORY_CLUSTERSCOPED_API_KEY
|
||||
value: base-factory-clusterscoped-api
|
||||
- name: BASE_FACTORY_NAMESPACED_BUILTIN_KEY
|
||||
value: base-factory-namespaced-builtin
|
||||
- name: BASE_FACTORY_CLUSTERSCOPED_BUILTIN_KEY
|
||||
value: base-factory-clusterscoped-builtin
|
||||
- name: BASE_NAMESPACE_FACTORY_KEY
|
||||
value: base-factory-clusterscoped-builtin
|
||||
- name: USE_NAMESPACE_NAV
|
||||
value: "true"
|
||||
- name: USE_NEW_NAVIGATION
|
||||
value: "true"
|
||||
- name: HIDE_NAVIGATION
|
||||
value: "true"
|
||||
- name: LOGIN_URL
|
||||
value: "/oauth2/userinfo"
|
||||
- name: LOGOUT_URL
|
||||
value: "/oauth2/sign_out"
|
||||
- name: LOGIN_USERNAME_FIELD
|
||||
value: "preferredUsername"
|
||||
- name: FOOTER_TEXT
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
name: incloud-web-dashboard-config
|
||||
key: FOOTER_TEXT
|
||||
- name: TITLE_TEXT
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
name: incloud-web-dashboard-config
|
||||
key: TITLE_TEXT
|
||||
- name: CUSTOM_TENANT_TEXT
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
name: incloud-web-dashboard-config
|
||||
key: CUSTOM_TENANT_TEXT
|
||||
- name: LOGO_TEXT
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
name: incloud-web-dashboard-config
|
||||
key: LOGO_TEXT
|
||||
- name: CUSTOM_LOGO_SVG
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
name: incloud-web-dashboard-config
|
||||
key: CUSTOM_LOGO_SVG
|
||||
- name: ICON_SVG
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
name: incloud-web-dashboard-config
|
||||
key: ICON_SVG
|
||||
image: {{ .Values.openapiUI.image | quote }}
|
||||
imagePullPolicy: IfNotPresent
|
||||
livenessProbe:
|
||||
failureThreshold: 3
|
||||
httpGet:
|
||||
path: /healthcheck
|
||||
port: 8080
|
||||
scheme: HTTP
|
||||
initialDelaySeconds: 3
|
||||
periodSeconds: 10
|
||||
successThreshold: 1
|
||||
timeoutSeconds: 2
|
||||
startupProbe:
|
||||
httpGet:
|
||||
path: /healthcheck
|
||||
port: 8080
|
||||
scheme: HTTP
|
||||
failureThreshold: 30
|
||||
periodSeconds: 2
|
||||
name: web
|
||||
ports:
|
||||
- containerPort: 8080
|
||||
name: http
|
||||
protocol: TCP
|
||||
resources:
|
||||
limits:
|
||||
cpu: 200m
|
||||
memory: 256Mi
|
||||
requests:
|
||||
cpu: 100m
|
||||
ephemeral-storage: 50Mi
|
||||
memory: 128Mi
|
||||
securityContext:
|
||||
allowPrivilegeEscalation: false
|
||||
capabilities:
|
||||
add: []
|
||||
drop:
|
||||
- ALL
|
||||
privileged: false
|
||||
readOnlyRootFilesystem: false
|
||||
runAsGroup: 0
|
||||
runAsNonRoot: true
|
||||
runAsUser: 101
|
||||
seccompProfile:
|
||||
type: RuntimeDefault
|
||||
terminationMessagePath: /dev/termination-log
|
||||
terminationMessagePolicy: File
|
||||
dnsPolicy: ClusterFirst
|
||||
enableServiceLinks: false
|
||||
hostIPC: false
|
||||
hostNetwork: false
|
||||
hostPID: false
|
||||
priorityClassName: system-cluster-critical
|
||||
restartPolicy: Always
|
||||
schedulerName: default-scheduler
|
||||
serviceAccountName: incloud-web-web
|
||||
terminationGracePeriodSeconds: 30
|
||||
|
|
@ -1,6 +1,4 @@
|
|||
openapiUI:
|
||||
image: ghcr.io/cozystack/cozystack/openapi-ui:v1.3.0@sha256:0fa79c373a62840a617ff1ca1b0e31931c13a6cf7b0bb0ff0dc191f047a465a3
|
||||
openapiUIK8sBff:
|
||||
image: ghcr.io/cozystack/cozystack/openapi-ui-k8s-bff:v1.3.0@sha256:1b3ea6d4c7dbbe6a8def3b2807fffdfab2ac4afc39d7a846e57dd491fa168f92
|
||||
console:
|
||||
image: 999669/cozystack-ui:latest@sha256:c5b0dcfa241603763150188150d56ab58fba1ea820bfdac92c601199057bf9a2
|
||||
tokenProxy:
|
||||
image: ghcr.io/cozystack/cozystack/token-proxy:v1.3.0@sha256:2e280991e07853ea48f97b0a42946afffa10d03d6a83d41099ed83e6ffc94fdc
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue