feat(providers): migrate app deploys to helm charts (#6954)

* feat(providers): migrate app deploys to helm charts

* fix(aiproxy): use sealos-compatible entrypoint command

* fix(providers): use sealos-compatible kubefile commands
This commit is contained in:
jingyang
2026-05-21 16:04:00 +08:00
committed by GitHub
parent ed6556e008
commit 79b3d1f9ed
113 changed files with 3961 additions and 1546 deletions
+7 -2
View File
@@ -1,3 +1,8 @@
FROM scratch
COPY . .
CMD ["bash install.sh"]
USER 65532:65532
COPY charts charts
COPY aiproxy-web-entrypoint.sh aiproxy-web-entrypoint.sh
CMD ["bash aiproxy-web-entrypoint.sh"]
@@ -0,0 +1,94 @@
#!/bin/bash
set -e
RELEASE_NAME=${RELEASE_NAME:-"aiproxy-web"}
RELEASE_NAMESPACE=${RELEASE_NAMESPACE:-"aiproxy-system"}
CHART_PATH=${CHART_PATH:-"./charts/aiproxy"}
HELM_OPTS=${HELM_OPTS:-""}
HELM_OPTIONS=${HELM_OPTIONS:-""}
AUTO_CONFIG_HELM_OPTS=""
get_cm_value() {
local namespace="$1"
local name="$2"
local key="$3"
kubectl get configmap "${name}" -n "${namespace}" -o "jsonpath={.data.${key}}" 2>/dev/null || true
}
get_deploy_env() {
local namespace="$1"
local deployment="$2"
local key="$3"
kubectl get deployment -n "${namespace}" "${deployment}" -o "jsonpath={.spec.template.spec.containers[0].env[?(@.name==\"${key}\")].value}" 2>/dev/null || true
}
add_set_string() {
local key="$1"
local value="$2"
if [ -n "${value}" ]; then
AUTO_CONFIG_HELM_OPTS="${AUTO_CONFIG_HELM_OPTS} --set-string ${key}=${value}"
fi
}
NODE_COUNT=$(kubectl get nodes --no-headers 2>/dev/null | wc -l | tr -d " ")
if [ "${NODE_COUNT}" = "1" ]; then
AUTO_CONFIG_HELM_OPTS="${AUTO_CONFIG_HELM_OPTS} --set replicas=1"
fi
JWT_INTERNAL=${JWT_INTERNAL:-"${jwtInternal:-$(get_cm_value sealos-system sealos-config jwtInternal)}"}
ADMIN_KEY=${ADMIN_KEY:-"${adminKey:-$(get_cm_value aiproxy-system aiproxy-env ADMIN_KEY)}"}
SEALOS_CLOUD_DOMAIN=${SEALOS_CLOUD_DOMAIN:-"${cloudDomain:-$(get_cm_value sealos-system sealos-config cloudDomain)}"}
SEALOS_CLOUD_PORT=${SEALOS_CLOUD_PORT:-"${cloudPort:-$(get_cm_value sealos-system sealos-config cloudPort)}"}
CURRENCY_SYMBOL=${CURRENCY_SYMBOL:-"${currencySymbol:-$(get_deploy_env dbprovider-frontend dbprovider-frontend CURRENCY_SYMBOL)}"}
SUFFIX=${SUFFIX:-"${suffix:-}"}
if [ "${CURRENCY_SYMBOL}" = "usd" ] && [ -z "${SUFFIX}" ]; then
SUFFIX="/en/home"
fi
add_set_string aiproxy.APP_TOKEN_JWT_KEY "${JWT_INTERNAL}"
add_set_string aiproxy.AI_PROXY_BACKEND_KEY "${ADMIN_KEY}"
add_set_string cloudDomain "${SEALOS_CLOUD_DOMAIN}"
add_set_string cloudPort "${SEALOS_CLOUD_PORT}"
add_set_string aiproxy.CURRENCY_SYMBOL "${CURRENCY_SYMBOL}"
add_set_string suffix "${SUFFIX}"
adopt_namespaced_resource() {
local namespace="$1"
local kind="$2"
local name="$3"
if kubectl -n "${namespace}" get "${kind}" "${name}" >/dev/null 2>&1; then
echo "Adopting ${kind} ${namespace}/${name}..."
kubectl -n "${namespace}" label "${kind}" "${name}" app.kubernetes.io/managed-by=Helm --overwrite >/dev/null 2>&1 || true
kubectl -n "${namespace}" annotate "${kind}" "${name}" meta.helm.sh/release-name="${RELEASE_NAME}" meta.helm.sh/release-namespace="${RELEASE_NAMESPACE}" --overwrite >/dev/null 2>&1 || true
fi
}
echo "Checking and adopting existing resources..."
if kubectl get namespace "${RELEASE_NAMESPACE}" >/dev/null 2>&1; then
kubectl label namespace "${RELEASE_NAMESPACE}" app.kubernetes.io/managed-by=Helm --overwrite >/dev/null 2>&1 || true
kubectl annotate namespace "${RELEASE_NAMESPACE}" meta.helm.sh/release-name="${RELEASE_NAME}" meta.helm.sh/release-namespace="${RELEASE_NAMESPACE}" --overwrite >/dev/null 2>&1 || true
adopt_namespaced_resource "${RELEASE_NAMESPACE}" configmap aiproxy-web
adopt_namespaced_resource "${RELEASE_NAMESPACE}" service aiproxy-web
adopt_namespaced_resource "${RELEASE_NAMESPACE}" deployment aiproxy-web
adopt_namespaced_resource "${RELEASE_NAMESPACE}" ingress aiproxy-web
fi
adopt_namespaced_resource app-system apps.app.sealos.io aiproxy
SERVICE_NAME="aiproxy-web"
USER_VALUES_PATH="/root/.sealos/cloud/values/core/${SERVICE_NAME}-values.yaml"
if [ ! -f "${USER_VALUES_PATH}" ]; then
mkdir -p "$(dirname "${USER_VALUES_PATH}")"
cp "./charts/aiproxy/${SERVICE_NAME}-values.yaml" "${USER_VALUES_PATH}"
fi
HELM_ARGS="${AUTO_CONFIG_HELM_OPTS} ${HELM_OPTIONS} ${HELM_OPTS}"
echo "Deploying Helm chart..."
helm upgrade -i "${RELEASE_NAME}" -n "${RELEASE_NAMESPACE}" --create-namespace "${CHART_PATH}" \
-f "./charts/aiproxy/values.yaml" \
-f "${USER_VALUES_PATH}" \
${HELM_ARGS}
@@ -0,0 +1,17 @@
# Custom values for aiproxy web helm chart.
# This file contains user-customizable configurations.
replicas: 2
resources:
requests:
cpu: 50m
memory: 50Mi
limits:
cpu: 500m
memory: 512Mi
aiproxy:
CURRENCY_SYMBOL: ""
IS_INVITATION_ACTIVE: "false"
DOC_URL: "https://sealos.run/docs/guides/ai-proxy"
@@ -1,40 +0,0 @@
#!/bin/bash
timestamp() {
date +"%Y-%m-%d %T"
}
print() {
flag=$(timestamp)
echo -e "\033[1;32m\033[1m INFO [$flag] >> $* \033[0m"
}
warn() {
flag=$(timestamp)
echo -e "\033[33m WARN [$flag] >> $* \033[0m"
}
info() {
flag=$(timestamp)
echo -e "\033[36m INFO [$flag] >> $* \033[0m"
}
#===========================================================================
HELM_OPTS=${HELM_OPTS:-""}
NODE_COUNT=$(kubectl get nodes --no-headers | wc -l)
REPLICA_OPTIONS=""
if [ "$NODE_COUNT" -eq 1 ]; then
REPLICA_OPTIONS="--set replicas=1 "
HELM_OPTS="${HELM_OPTS} ${REPLICA_OPTIONS}"
fi
varJwtInternal=$(kubectl get configmap sealos-config -n sealos-system -o jsonpath='{.data.jwtInternal}')
adminKey=$(kubectl get configmap aiproxy-env -n aiproxy-system -o jsonpath='{.data.ADMIN_KEY}' )
SEALOS_CLOUD_DOMAIN=$(kubectl get configmap sealos-config -n sealos-system -o jsonpath='{.data.cloudDomain}')
SEALOS_CLOUD_PORT=$(kubectl get configmap sealos-config -n sealos-system -o jsonpath='{.data.cloudPort}')
CURRENCY_SYMBOL=$(kubectl get deployment -n dbprovider-frontend dbprovider-frontend -o jsonpath='{.spec.template.spec.containers[0].env[?(@.name=="CURRENCY_SYMBOL")].value}')
if [[ "${CURRENCY_SYMBOL}" == "usd" ]]; then
SUFFIX="/en/home"
fi
helm upgrade -i aiproxy-web -n aiproxy-system charts/aiproxy ${HELM_OPTS} \
--set aiproxy.APP_TOKEN_JWT_KEY=${varJwtInternal} --set aiproxy.AI_PROXY_BACKEND_KEY=${adminKey} \
--set suffix=${SUFFIX} \
--set cloudDomain=${SEALOS_CLOUD_DOMAIN} --set cloudPort=${SEALOS_CLOUD_PORT} --set aiproxy.CURRENCY_SYMBOL=${CURRENCY_SYMBOL} --create-namespace
@@ -3,11 +3,7 @@ FROM scratch
USER 65532:65532
COPY registry registry
COPY manifests manifests
COPY charts charts
COPY cloudserver-frontend-entrypoint.sh cloudserver-frontend-entrypoint.sh
ENV cloudDomain="127.0.0.1.nip.io"
ENV cloudPort=""
ENV certSecretName="wildcard-cert"
ENV lafBaseUrl=""
CMD ["kubectl apply -f manifests"]
CMD ["bash cloudserver-frontend-entrypoint.sh"]
@@ -0,0 +1,6 @@
apiVersion: v2
name: cloudserver-frontend
description: Sealos cloudserver Frontend Helm Chart
type: application
version: 1.0.0
appVersion: "latest"
@@ -0,0 +1,16 @@
# Custom values for cloudserver-frontend helm chart.
# This file contains user-customizable configurations.
replicaCount: 1
resources:
limits:
cpu: 1000m
memory: 1024Mi
requests:
cpu: 10m
memory: 128Mi
cloudserverConfig:
lafBaseUrl: ""
jwtSecretApp: ""
@@ -0,0 +1,84 @@
{{/* Expand the name of the chart. */}}
{{- define "cloudserver-frontend.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
{{- end }}
{{/* Create a default fully qualified app name. */}}
{{- define "cloudserver-frontend.fullname" -}}
{{- if .Values.fullnameOverride }}
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- $name := default .Chart.Name .Values.nameOverride }}
{{- if contains $name .Release.Name }}
{{- .Release.Name | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
{{- end }}
{{- end }}
{{- end }}
{{- define "cloudserver-frontend.chart" -}}
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
{{- end }}
{{- define "cloudserver-frontend.labels" -}}
helm.sh/chart: {{ include "cloudserver-frontend.chart" . }}
{{ include "cloudserver-frontend.selectorLabels" . }}
{{ include "cloudserver-frontend.recommendedLabels" . }}
{{- if .Chart.AppVersion }}
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
{{- end }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- end }}
{{- define "cloudserver-frontend.selectorLabels" -}}
app: {{ include "cloudserver-frontend.fullname" . }}
{{- end }}
{{- define "cloudserver-frontend.recommendedLabels" -}}
app.kubernetes.io/name: {{ include "cloudserver-frontend.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- end }}
{{- define "cloudserver-frontend.scheme" -}}
{{- if eq (toString .Values.cloudserverConfig.disableHttps) "true" -}}http{{- else -}}https{{- end -}}
{{- end }}
{{- define "cloudserver-frontend.port" -}}
{{- $scheme := include "cloudserver-frontend.scheme" . -}}
{{- $port := toString .Values.cloudserverConfig.cloudPort -}}
{{- if eq $scheme "http" -}}
{{- $port = toString .Values.cloudserverConfig.httpPort -}}
{{- end -}}
{{- if or (and (eq $scheme "https") (or (eq $port "") (eq $port "443"))) (and (eq $scheme "http") (or (eq $port "") (eq $port "80"))) -}}
{{- "" -}}
{{- else -}}
{{- $port -}}
{{- end }}
{{- end }}
{{- define "cloudserver-frontend.portSuffix" -}}
{{- $port := include "cloudserver-frontend.port" . -}}
{{- if $port -}}:{{ $port }}{{- end -}}
{{- end }}
{{- define "cloudserver-frontend.portEnv" -}}
{{- $port := include "cloudserver-frontend.port" . -}}
{{- if $port -}}:{{ $port }}{{- end -}}
{{- end }}
{{- define "cloudserver-frontend.cloudOrigin" -}}
{{- include "cloudserver-frontend.scheme" . -}}://{{ .Values.cloudserverConfig.cloudDomain }}{{ include "cloudserver-frontend.portSuffix" . }}
{{- end }}
{{- define "cloudserver-frontend.wildcardCloudOrigin" -}}
{{- include "cloudserver-frontend.scheme" . -}}://*.{{ .Values.cloudserverConfig.cloudDomain }}{{ include "cloudserver-frontend.portSuffix" . }}
{{- end }}
{{- define "cloudserver-frontend.host" -}}
{{- default (printf "cloudserver.%s" .Values.cloudserverConfig.cloudDomain) .Values.ingress.host -}}
{{- end }}
{{- define "cloudserver-frontend.appUrl" -}}
{{- include "cloudserver-frontend.scheme" . -}}://{{ include "cloudserver-frontend.host" . }}{{ include "cloudserver-frontend.portSuffix" . }}
{{- end }}
@@ -6,12 +6,14 @@ metadata:
spec:
data:
desc: cloudserver
url: "https://cloudserver.{{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }}"
icon: "https://cloudserver.{{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }}/logo.svg"
url: {{ include "cloudserver-frontend.appUrl" . | quote }}
icon: {{ printf "%s/logo.svg" (include "cloudserver-frontend.appUrl" .) | quote }}
i18n:
zh:
name: 云主机
zh-Hans:
name: 云主机
menuData:
name: cloudserver
type: iframe
displayType: normal
i18n:
zh:
name: 云主机
@@ -0,0 +1,10 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ include "cloudserver-frontend.fullname" . }}-config
namespace: {{ .Release.Namespace }}
labels:
{{- include "cloudserver-frontend.labels" . | nindent 4 }}
data:
config.yaml: |-
addr: :3000
@@ -0,0 +1,63 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "cloudserver-frontend.fullname" . }}
namespace: {{ .Release.Namespace }}
labels:
{{- include "cloudserver-frontend.labels" . | nindent 4 }}
spec:
replicas: {{ .Values.replicaCount }}
selector:
matchLabels:
{{- include "cloudserver-frontend.selectorLabels" . | nindent 6 }}
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 25%
maxSurge: 25%
template:
metadata:
labels:
{{- include "cloudserver-frontend.labels" . | nindent 8 }}
{{- with .Values.podAnnotations }}
annotations:
{{- toYaml . | nindent 8 }}
{{- end }}
spec:
{{- with .Values.imagePullSecrets }}
imagePullSecrets:
{{- toYaml . | nindent 8 }}
{{- end }}
securityContext:
{{- toYaml .Values.podSecurityContext | nindent 8 }}
containers:
- name: {{ .Chart.Name }}
image: {{ .Values.image | quote }}
imagePullPolicy: {{ .Values.imagePullPolicy }}
{{- if .Values.securityContext }}
securityContext:
{{- toYaml .Values.securityContext | nindent 12 }}
{{- end }}
resources:
{{- toYaml .Values.resources | nindent 12 }}
env:
- name: LAF_BASE_URL
value: {{ .Values.cloudserverConfig.lafBaseUrl | quote }}
- name: JWT_SECRET_APP
value: {{ .Values.cloudserverConfig.jwtSecretApp | quote }}
ports:
- name: http
containerPort: {{ .Values.service.port }}
protocol: TCP
volumeMounts:
- name: cloudserver-frontend-volume
mountPath: /config.yaml
subPath: config.yaml
{{- with .Values.affinity }}
affinity:
{{- toYaml . | nindent 8 }}
{{- end }}
volumes:
- name: cloudserver-frontend-volume
configMap:
name: {{ include "cloudserver-frontend.fullname" . }}-config
@@ -0,0 +1,43 @@
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: {{ include "cloudserver-frontend.fullname" . }}
namespace: {{ .Release.Namespace }}
annotations:
kubernetes.io/ingress.class: {{ .Values.ingress.className | quote }}
nginx.ingress.kubernetes.io/enable-cors: "true"
nginx.ingress.kubernetes.io/cors-allow-methods: "PUT, GET, POST, DELETE, PATCH, OPTIONS"
nginx.ingress.kubernetes.io/cors-allow-origin: "{{ include "cloudserver-frontend.cloudOrigin" . }}, {{ include "cloudserver-frontend.wildcardCloudOrigin" . }}"
nginx.ingress.kubernetes.io/cors-allow-credentials: "true"
nginx.ingress.kubernetes.io/cors-max-age: "600"
nginx.ingress.kubernetes.io/backend-protocol: "HTTP"
nginx.ingress.kubernetes.io/configuration-snippet: |
more_clear_headers "X-Frame-Options:";
more_set_headers "Content-Security-Policy: default-src * blob: data: *.{{ .Values.cloudserverConfig.cloudDomain }}{{ include "cloudserver-frontend.portSuffix" . }} {{ .Values.cloudserverConfig.cloudDomain }}{{ include "cloudserver-frontend.portSuffix" . }}; img-src * data: blob: resource: *.{{ .Values.cloudserverConfig.cloudDomain }}{{ include "cloudserver-frontend.portSuffix" . }} {{ .Values.cloudserverConfig.cloudDomain }}{{ include "cloudserver-frontend.portSuffix" . }}; connect-src * wss: blob: resource:; style-src 'self' 'unsafe-inline' blob: *.{{ .Values.cloudserverConfig.cloudDomain }}{{ include "cloudserver-frontend.portSuffix" . }} {{ .Values.cloudserverConfig.cloudDomain }}{{ include "cloudserver-frontend.portSuffix" . }} resource:; script-src 'self' 'unsafe-inline' 'unsafe-eval' blob: *.{{ .Values.cloudserverConfig.cloudDomain }}{{ include "cloudserver-frontend.portSuffix" . }} {{ .Values.cloudserverConfig.cloudDomain }}{{ include "cloudserver-frontend.portSuffix" . }} resource: *.baidu.com *.bdstatic.com https://js.stripe.com; frame-src 'self' *.{{ .Values.cloudserverConfig.cloudDomain }}{{ include "cloudserver-frontend.portSuffix" . }} {{ .Values.cloudserverConfig.cloudDomain }}{{ include "cloudserver-frontend.portSuffix" . }} mailto: tel: weixin: mtt: *.baidu.com https://js.stripe.com; frame-ancestors 'self' {{ include "cloudserver-frontend.cloudOrigin" . }} {{ include "cloudserver-frontend.wildcardCloudOrigin" . }}";
more_set_headers "X-Xss-Protection: 1; mode=block";
higress.io/response-header-control-remove: X-Frame-Options
higress.io/response-header-control-update: |
Content-Security-Policy "default-src * blob: data: *.{{ .Values.cloudserverConfig.cloudDomain }}{{ include "cloudserver-frontend.portSuffix" . }} {{ .Values.cloudserverConfig.cloudDomain }}{{ include "cloudserver-frontend.portSuffix" . }}; img-src * data: blob: resource: *.{{ .Values.cloudserverConfig.cloudDomain }}{{ include "cloudserver-frontend.portSuffix" . }} {{ .Values.cloudserverConfig.cloudDomain }}{{ include "cloudserver-frontend.portSuffix" . }}; connect-src * wss: blob: resource:; style-src 'self' 'unsafe-inline' blob: *.{{ .Values.cloudserverConfig.cloudDomain }}{{ include "cloudserver-frontend.portSuffix" . }} {{ .Values.cloudserverConfig.cloudDomain }}{{ include "cloudserver-frontend.portSuffix" . }} resource:; script-src 'self' 'unsafe-inline' 'unsafe-eval' blob: *.{{ .Values.cloudserverConfig.cloudDomain }}{{ include "cloudserver-frontend.portSuffix" . }} {{ .Values.cloudserverConfig.cloudDomain }}{{ include "cloudserver-frontend.portSuffix" . }} resource: *.baidu.com *.bdstatic.com https://js.stripe.com; frame-src 'self' *.{{ .Values.cloudserverConfig.cloudDomain }}{{ include "cloudserver-frontend.portSuffix" . }} {{ .Values.cloudserverConfig.cloudDomain }}{{ include "cloudserver-frontend.portSuffix" . }} mailto: tel: weixin: mtt: *.baidu.com https://js.stripe.com; frame-ancestors 'self' {{ include "cloudserver-frontend.cloudOrigin" . }} {{ include "cloudserver-frontend.wildcardCloudOrigin" . }}"
X-Xss-Protection "1; mode=block"
{{- with .Values.ingress.annotations }}
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
ingressClassName: {{ .Values.ingress.className | quote }}
rules:
- host: {{ include "cloudserver-frontend.host" . | quote }}
http:
paths:
- pathType: Prefix
path: /
backend:
service:
name: {{ include "cloudserver-frontend.fullname" . }}
port:
number: {{ .Values.service.port }}
{{- if not (eq (toString .Values.cloudserverConfig.disableHttps) "true") }}
tls:
- hosts:
- {{ include "cloudserver-frontend.host" . | quote }}
secretName: {{ .Values.cloudserverConfig.certSecretName | quote }}
{{- end }}
@@ -0,0 +1,16 @@
apiVersion: v1
kind: Service
metadata:
labels:
{{- include "cloudserver-frontend.labels" . | nindent 4 }}
name: {{ include "cloudserver-frontend.fullname" . }}
namespace: {{ .Release.Namespace }}
spec:
type: {{ .Values.service.type }}
ports:
- name: http
port: {{ .Values.service.port }}
protocol: TCP
targetPort: {{ .Values.service.port }}
selector:
{{- include "cloudserver-frontend.selectorLabels" . | nindent 4 }}
@@ -0,0 +1,52 @@
# Default values for cloudserver-frontend helm chart.
image: ghcr.io/labring/sealos-cloudserver-frontend:latest
imagePullPolicy: Always
imagePullSecrets: []
fullnameOverride: "cloudserver-frontend"
replicaCount: 1
podAnnotations: {}
podLabels: {}
podSecurityContext:
runAsNonRoot: true
runAsUser: 1001
securityContext:
runAsNonRoot: true
runAsUser: 1001
allowPrivilegeEscalation: false
capabilities:
drop:
- "ALL"
service:
type: ClusterIP
port: 3000
ingress:
className: nginx
host: ""
annotations: {}
cloudserverConfig:
cloudDomain: "127.0.0.1.nip.io"
cloudPort: ""
httpPort: ""
disableHttps: false
certSecretName: "wildcard-cert"
lafBaseUrl: ""
jwtSecretApp: ""
resources:
limits:
cpu: 1000m
memory: 1024Mi
requests:
cpu: 10m
memory: 128Mi
affinity: {}
@@ -0,0 +1,89 @@
#!/bin/bash
set -e
RELEASE_NAME=${RELEASE_NAME:-"cloudserver-frontend"}
RELEASE_NAMESPACE=${RELEASE_NAMESPACE:-"cloudserver-frontend"}
CHART_PATH=${CHART_PATH:-"./charts/cloudserver-frontend"}
HELM_OPTS=${HELM_OPTS:-""}
HELM_OPTIONS=${HELM_OPTIONS:-""}
AUTO_CONFIG_HELM_OPTS=""
get_cm_value() {
local namespace="$1"
local name="$2"
local key="$3"
kubectl get configmap "${name}" -n "${namespace}" -o "jsonpath={.data.${key}}" 2>/dev/null || true
}
add_set_string() {
local key="$1"
local value="$2"
if [ -n "${value}" ]; then
AUTO_CONFIG_HELM_OPTS="${AUTO_CONFIG_HELM_OPTS} --set-string ${key}=${value}"
fi
}
SEALOS_CLOUD_DOMAIN=${SEALOS_CLOUD_DOMAIN:-"${cloudDomain:-$(get_cm_value sealos-system sealos-config cloudDomain)}"}
add_set_string cloudserverConfig.cloudDomain "${SEALOS_CLOUD_DOMAIN}"
SEALOS_CLOUD_PORT=${SEALOS_CLOUD_PORT:-"${cloudPort:-$(get_cm_value sealos-system sealos-config cloudPort)}"}
add_set_string cloudserverConfig.cloudPort "${SEALOS_CLOUD_PORT}"
SEALOS_HTTP_PORT=${SEALOS_HTTP_PORT:-"${httpPort:-$(get_cm_value sealos-system sealos-config httpPort)}"}
add_set_string cloudserverConfig.httpPort "${SEALOS_HTTP_PORT}"
SEALOS_DISABLE_HTTPS=${SEALOS_DISABLE_HTTPS:-"${disableHttps:-$(get_cm_value sealos-system sealos-config disableHttps)}"}
add_set_string cloudserverConfig.disableHttps "${SEALOS_DISABLE_HTTPS}"
SEALOS_CERT_SECRET_NAME=${SEALOS_CERT_SECRET_NAME:-"${certSecretName:-$(get_cm_value sealos-system sealos-config certSecretName)}"}
add_set_string cloudserverConfig.certSecretName "${SEALOS_CERT_SECRET_NAME}"
SEALOS_JWT_INTERNAL=${SEALOS_JWT_INTERNAL:-"${jwtInternal:-$(get_cm_value sealos-system sealos-config jwtInternal)}"}
add_set_string cloudserverConfig.jwtSecretApp "${SEALOS_JWT_INTERNAL}"
add_set_string cloudserverConfig.lafBaseUrl "${lafBaseUrl:-}"
adopt_namespaced_resource() {
local namespace="$1"
local kind="$2"
local name="$3"
if kubectl -n "${namespace}" get "${kind}" "${name}" >/dev/null 2>&1; then
echo "Adopting ${kind} ${namespace}/${name}..."
kubectl -n "${namespace}" label "${kind}" "${name}" app.kubernetes.io/managed-by=Helm --overwrite >/dev/null 2>&1 || true
kubectl -n "${namespace}" annotate "${kind}" "${name}" meta.helm.sh/release-name="${RELEASE_NAME}" meta.helm.sh/release-namespace="${RELEASE_NAMESPACE}" --overwrite >/dev/null 2>&1 || true
fi
}
adopt_cluster_resource() {
local kind="$1"
local name="$2"
if kubectl get "${kind}" "${name}" >/dev/null 2>&1; then
echo "Adopting ${kind} ${name}..."
kubectl label "${kind}" "${name}" app.kubernetes.io/managed-by=Helm --overwrite >/dev/null 2>&1 || true
kubectl annotate "${kind}" "${name}" meta.helm.sh/release-name="${RELEASE_NAME}" meta.helm.sh/release-namespace="${RELEASE_NAMESPACE}" --overwrite >/dev/null 2>&1 || true
fi
}
echo "Checking and adopting existing resources..."
if kubectl get namespace "${RELEASE_NAMESPACE}" >/dev/null 2>&1; then
kubectl label namespace "${RELEASE_NAMESPACE}" app.kubernetes.io/managed-by=Helm --overwrite >/dev/null 2>&1 || true
kubectl annotate namespace "${RELEASE_NAMESPACE}" meta.helm.sh/release-name="${RELEASE_NAME}" meta.helm.sh/release-namespace="${RELEASE_NAMESPACE}" --overwrite >/dev/null 2>&1 || true
adopt_namespaced_resource "${RELEASE_NAMESPACE}" configmap cloudserver-frontend-config
adopt_namespaced_resource "${RELEASE_NAMESPACE}" service cloudserver-frontend
adopt_namespaced_resource "${RELEASE_NAMESPACE}" deployment cloudserver-frontend
adopt_namespaced_resource "${RELEASE_NAMESPACE}" ingress cloudserver-frontend
fi
adopt_namespaced_resource app-system apps.app.sealos.io cloudserver
SERVICE_NAME="cloudserver-frontend"
USER_VALUES_PATH="/root/.sealos/cloud/values/core/${SERVICE_NAME}-values.yaml"
if [ ! -f "${USER_VALUES_PATH}" ]; then
mkdir -p "$(dirname "${USER_VALUES_PATH}")"
cp "./charts/cloudserver-frontend/cloudserver-frontend-values.yaml" "${USER_VALUES_PATH}"
fi
HELM_ARGS="${AUTO_CONFIG_HELM_OPTS} ${HELM_OPTIONS} ${HELM_OPTS}"
echo "Deploying Helm chart..."
helm upgrade -i "${RELEASE_NAME}" -n "${RELEASE_NAMESPACE}" --create-namespace "${CHART_PATH}" \
-f "./charts/cloudserver-frontend/values.yaml" \
-f "${USER_VALUES_PATH}" \
${HELM_ARGS}
@@ -1,83 +0,0 @@
apiVersion: v1
kind: Namespace
metadata:
labels:
app: cloudserver-frontend
name: cloudserver-frontend
---
apiVersion: v1
kind: ConfigMap
metadata:
name: cloudserver-frontend-config
namespace: cloudserver-frontend
data:
config.yaml: |-
addr: :3000
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: cloudserver-frontend
namespace: cloudserver-frontend
spec:
replicas: 1
selector:
matchLabels:
app: cloudserver-frontend
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 25%
maxSurge: 25%
template:
metadata:
labels:
app: cloudserver-frontend
spec:
containers:
- name: cloudserver-frontend
env:
- name: LAF_BASE_URL
value: {{ .lafBaseUrl }}
- name: JWT_SECRET_APP
securityContext:
runAsNonRoot: true
runAsUser: 1001
allowPrivilegeEscalation: false
capabilities:
drop:
- 'ALL'
resources:
limits:
cpu: 1000m
memory: 1024Mi
requests:
cpu: 10m
memory: 128Mi
# do not modify this image, it is used for CI/CD
image: ghcr.io/labring/sealos-cloudserver-frontend:latest
imagePullPolicy: Always
volumeMounts:
- name: cloudserver-frontend-volume
mountPath: /config.yaml
subPath: config.yaml
volumes:
- name: cloudserver-frontend-volume
configMap:
name: cloudserver-frontend-config
---
apiVersion: v1
kind: Service
metadata:
labels:
app: cloudserver-frontend
name: cloudserver-frontend
namespace: cloudserver-frontend
spec:
ports:
- name: http
port: 3000
protocol: TCP
targetPort: 3000
selector:
app: cloudserver-frontend
@@ -1,51 +0,0 @@
# Copyright © 2023 sealos.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/enable-cors: "true"
nginx.ingress.kubernetes.io/cors-allow-methods: "PUT, GET, POST, DELETE, PATCH, OPTIONS"
nginx.ingress.kubernetes.io/cors-allow-origin: "https://{{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }}, https://*.{{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }}"
nginx.ingress.kubernetes.io/cors-allow-credentials: "true"
nginx.ingress.kubernetes.io/cors-max-age: "600"
nginx.ingress.kubernetes.io/backend-protocol: "HTTP"
nginx.ingress.kubernetes.io/configuration-snippet: |
more_clear_headers "X-Frame-Options:";
more_set_headers "Content-Security-Policy: default-src * blob: data: *.{{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }} {{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }}; img-src * data: blob: resource: *.{{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }} {{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }}; connect-src * wss: blob: resource:; style-src 'self' 'unsafe-inline' blob: *.{{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }} {{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }} resource:; script-src 'self' 'unsafe-inline' 'unsafe-eval' blob: *.{{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }} {{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }} resource: *.baidu.com *.bdstatic.com https://js.stripe.com; frame-src 'self' *.{{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }} {{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }} mailto: tel: weixin: mtt: *.baidu.com https://js.stripe.com; frame-ancestors 'self' https://{{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }} https://*.{{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }}";
more_set_headers "X-Xss-Protection: 1; mode=block";
higress.io/response-header-control-remove: X-Frame-Options
higress.io/response-header-control-update: |
Content-Security-Policy "default-src * blob: data: *.{{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }} {{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }}; img-src * data: blob: resource: *.{{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }} {{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }}; connect-src * wss: blob: resource:; style-src 'self' 'unsafe-inline' blob: *.{{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }} {{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }} resource:; script-src 'self' 'unsafe-inline' 'unsafe-eval' blob: *.{{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }} {{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }} resource: *.baidu.com *.bdstatic.com https://js.stripe.com; frame-src 'self' *.{{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }} {{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }} mailto: tel: weixin: mtt: *.baidu.com https://js.stripe.com; frame-ancestors 'self' https://{{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }} https://*.{{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }}"
X-Xss-Protection "1; mode=block"
name: cloudserver-frontend
namespace: cloudserver-frontend
spec:
rules:
- host: cloudserver.{{ .cloudDomain }}
http:
paths:
- pathType: Prefix
path: /
backend:
service:
name: cloudserver-frontend
port:
number: 3000
tls:
- hosts:
- cloudserver.{{ .cloudDomain }}
secretName: {{ .certSecretName }}
@@ -4,5 +4,6 @@ USER 65532:65532
COPY registry registry
COPY charts charts
COPY costcenter-frontend-entrypoint.sh costcenter-frontend-entrypoint.sh
CMD ["./costcenter-frontend-entrypoint.sh"]
CMD ["bash costcenter-frontend-entrypoint.sh"]
@@ -9,6 +9,8 @@ fullnameOverride: "costcenter-frontend"
podAnnotations: {}
podLabels: {}
replicaCount: 1
podSecurityContext:
runAsNonRoot: true
runAsUser: 1001
@@ -23,11 +25,46 @@ service:
type: ClusterIP
port: 3000
resources:
limits:
cpu: 1000m
memory: 2048Mi
requests:
cpu: 10m
memory: 128Mi
# Costcenter frontend configuration
# Note: jwtInternal is auto-configured by entrypoint.sh from sealos-config ConfigMap
# For business configurations (transfer, invoice, recharge, etc.), see costcenter-frontend-values.yaml
costcenterConfig:
jwtInternal: "" # Auto-injected by entrypoint script
transferEnabled: true
currencyType: "shellCoin"
invoice:
enabled: false
feiShuBotURL: ""
aliSms:
endpoint: ""
accessKeyID: ""
accessKeySecret: ""
templateCode: ""
signName: ""
invoiceCompletedTemplateCode: ""
mongo:
uri: ""
recharge:
enabled: false
payMethods:
wechat:
enabled: false
alipay:
enabled: false
stripe:
enabled: false
publicKey: ""
components:
accountService:
url: "http://account-service.account-system.svc:2333"
# Affinity for pod anti-affinity
affinity:
+3 -9
View File
@@ -3,13 +3,7 @@ FROM scratch
USER 65532:65532
COPY registry registry
COPY manifests manifests
COPY charts charts
COPY cronjob-frontend-entrypoint.sh cronjob-frontend-entrypoint.sh
ENV cloudDomain="127.0.0.1.nip.io"
ENV cloudPort=""
ENV certSecretName="wildcard-cert"
ENV SUCCESSFUL_JOBS_HISTORY_LIMIT="3"
ENV FAILED_JOBS_HISTORY_LIMIT="3"
CMD ["kubectl apply -f manifests"]
CMD ["bash cronjob-frontend-entrypoint.sh"]
@@ -0,0 +1,6 @@
apiVersion: v2
name: cronjob-frontend
description: Sealos CronJob Frontend Helm Chart
type: application
version: 1.0.0
appVersion: "latest"
@@ -0,0 +1,18 @@
# Custom values for cronjob-frontend helm chart.
# This file contains user-customizable configurations.
replicaCount: 1
resources:
limits:
cpu: 1000m
memory: 1024Mi
requests:
cpu: 10m
memory: 128Mi
cronjobConfig:
successfulJobsHistoryLimit: 3
failedJobsHistoryLimit: 3
podCpuMilliCores: 50
podMemoryMiB: 64
@@ -0,0 +1,84 @@
{{/* Expand the name of the chart. */}}
{{- define "cronjob-frontend.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
{{- end }}
{{/* Create a default fully qualified app name. */}}
{{- define "cronjob-frontend.fullname" -}}
{{- if .Values.fullnameOverride }}
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- $name := default .Chart.Name .Values.nameOverride }}
{{- if contains $name .Release.Name }}
{{- .Release.Name | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
{{- end }}
{{- end }}
{{- end }}
{{- define "cronjob-frontend.chart" -}}
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
{{- end }}
{{- define "cronjob-frontend.labels" -}}
helm.sh/chart: {{ include "cronjob-frontend.chart" . }}
{{ include "cronjob-frontend.selectorLabels" . }}
{{ include "cronjob-frontend.recommendedLabels" . }}
{{- if .Chart.AppVersion }}
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
{{- end }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- end }}
{{- define "cronjob-frontend.selectorLabels" -}}
app: {{ include "cronjob-frontend.fullname" . }}
{{- end }}
{{- define "cronjob-frontend.recommendedLabels" -}}
app.kubernetes.io/name: {{ include "cronjob-frontend.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- end }}
{{- define "cronjob-frontend.scheme" -}}
{{- if eq (toString .Values.cronjobConfig.disableHttps) "true" -}}http{{- else -}}https{{- end -}}
{{- end }}
{{- define "cronjob-frontend.port" -}}
{{- $scheme := include "cronjob-frontend.scheme" . -}}
{{- $port := toString .Values.cronjobConfig.cloudPort -}}
{{- if eq $scheme "http" -}}
{{- $port = toString .Values.cronjobConfig.httpPort -}}
{{- end -}}
{{- if or (and (eq $scheme "https") (or (eq $port "") (eq $port "443"))) (and (eq $scheme "http") (or (eq $port "") (eq $port "80"))) -}}
{{- "" -}}
{{- else -}}
{{- $port -}}
{{- end }}
{{- end }}
{{- define "cronjob-frontend.portSuffix" -}}
{{- $port := include "cronjob-frontend.port" . -}}
{{- if $port -}}:{{ $port }}{{- end -}}
{{- end }}
{{- define "cronjob-frontend.portEnv" -}}
{{- $port := include "cronjob-frontend.port" . -}}
{{- if $port -}}:{{ $port }}{{- end -}}
{{- end }}
{{- define "cronjob-frontend.cloudOrigin" -}}
{{- include "cronjob-frontend.scheme" . -}}://{{ .Values.cronjobConfig.cloudDomain }}{{ include "cronjob-frontend.portSuffix" . }}
{{- end }}
{{- define "cronjob-frontend.wildcardCloudOrigin" -}}
{{- include "cronjob-frontend.scheme" . -}}://*.{{ .Values.cronjobConfig.cloudDomain }}{{ include "cronjob-frontend.portSuffix" . }}
{{- end }}
{{- define "cronjob-frontend.host" -}}
{{- default (printf "cronjob.%s" .Values.cronjobConfig.cloudDomain) .Values.ingress.host -}}
{{- end }}
{{- define "cronjob-frontend.appUrl" -}}
{{- include "cronjob-frontend.scheme" . -}}://{{ include "cronjob-frontend.host" . }}{{ include "cronjob-frontend.portSuffix" . }}
{{- end }}
@@ -6,14 +6,14 @@ metadata:
spec:
data:
desc: CronJob
url: "https://cronjob.{{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }}"
icon: "https://cronjob.{{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }}/logo.svg"
menuData:
name: CronJob
type: iframe
displayType: normal
url: {{ include "cronjob-frontend.appUrl" . | quote }}
icon: {{ printf "%s/logo.svg" (include "cronjob-frontend.appUrl" .) | quote }}
i18n:
zh:
name: 定时任务
zh-Hans:
name: 定时任务
menuData:
name: CronJob
type: iframe
displayType: normal
@@ -0,0 +1,22 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ include "cronjob-frontend.fullname" . }}-config
namespace: {{ .Release.Namespace }}
labels:
{{- include "cronjob-frontend.labels" . | nindent 4 }}
data:
config.yaml: |-
cloud:
domain: {{ .Values.cronjobConfig.cloudDomain | quote }}
desktopDomain: {{ .Values.cronjobConfig.cloudDomain | quote }}
cronjob:
components:
applaunchpad:
url: {{ printf "https://applaunchpad.%s%s" .Values.cronjobConfig.cloudDomain (include "cronjob-frontend.portSuffix" .) | quote }}
podResources:
cpuMilliCores: {{ .Values.cronjobConfig.podCpuMilliCores }}
memoryMiB: {{ .Values.cronjobConfig.podMemoryMiB }}
jobHistory:
successfulLimit: {{ .Values.cronjobConfig.successfulJobsHistoryLimit }}
failedLimit: {{ .Values.cronjobConfig.failedJobsHistoryLimit }}
@@ -0,0 +1,67 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "cronjob-frontend.fullname" . }}
namespace: {{ .Release.Namespace }}
labels:
{{- include "cronjob-frontend.labels" . | nindent 4 }}
spec:
replicas: {{ .Values.replicaCount }}
selector:
matchLabels:
{{- include "cronjob-frontend.selectorLabels" . | nindent 6 }}
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 25%
maxSurge: 25%
template:
metadata:
labels:
{{- include "cronjob-frontend.labels" . | nindent 8 }}
{{- with .Values.podAnnotations }}
annotations:
{{- toYaml . | nindent 8 }}
{{- end }}
spec:
{{- with .Values.imagePullSecrets }}
imagePullSecrets:
{{- toYaml . | nindent 8 }}
{{- end }}
securityContext:
{{- toYaml .Values.podSecurityContext | nindent 8 }}
containers:
- name: {{ .Chart.Name }}
image: {{ .Values.image | quote }}
imagePullPolicy: {{ .Values.imagePullPolicy }}
{{- if .Values.securityContext }}
securityContext:
{{- toYaml .Values.securityContext | nindent 12 }}
{{- end }}
resources:
{{- toYaml .Values.resources | nindent 12 }}
env:
- name: SEALOS_DOMAIN
value: {{ .Values.cronjobConfig.cloudDomain | quote }}
- name: APPLAUNCHPAD_URL
value: {{ printf "applaunchpad.%s" .Values.cronjobConfig.cloudDomain | quote }}
- name: SUCCESSFUL_JOBS_HISTORY_LIMIT
value: {{ .Values.cronjobConfig.successfulJobsHistoryLimit | quote }}
- name: FAILED_JOBS_HISTORY_LIMIT
value: {{ .Values.cronjobConfig.failedJobsHistoryLimit | quote }}
ports:
- name: http
containerPort: {{ .Values.service.port }}
protocol: TCP
volumeMounts:
- name: cronjob-frontend-volume
mountPath: /app/data/config.yaml
subPath: config.yaml
{{- with .Values.affinity }}
affinity:
{{- toYaml . | nindent 8 }}
{{- end }}
volumes:
- name: cronjob-frontend-volume
configMap:
name: {{ include "cronjob-frontend.fullname" . }}-config
@@ -0,0 +1,43 @@
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: {{ include "cronjob-frontend.fullname" . }}
namespace: {{ .Release.Namespace }}
annotations:
kubernetes.io/ingress.class: {{ .Values.ingress.className | quote }}
nginx.ingress.kubernetes.io/enable-cors: "true"
nginx.ingress.kubernetes.io/cors-allow-methods: "PUT, GET, POST, DELETE, PATCH, OPTIONS"
nginx.ingress.kubernetes.io/cors-allow-origin: "{{ include "cronjob-frontend.cloudOrigin" . }}, {{ include "cronjob-frontend.wildcardCloudOrigin" . }}"
nginx.ingress.kubernetes.io/cors-allow-credentials: "true"
nginx.ingress.kubernetes.io/cors-max-age: "600"
nginx.ingress.kubernetes.io/backend-protocol: "HTTP"
nginx.ingress.kubernetes.io/configuration-snippet: |
more_clear_headers "X-Frame-Options:";
more_set_headers "Content-Security-Policy: default-src * blob: data: *.{{ .Values.cronjobConfig.cloudDomain }}{{ include "cronjob-frontend.portSuffix" . }} {{ .Values.cronjobConfig.cloudDomain }}{{ include "cronjob-frontend.portSuffix" . }}; img-src * data: blob: resource: *.{{ .Values.cronjobConfig.cloudDomain }}{{ include "cronjob-frontend.portSuffix" . }} {{ .Values.cronjobConfig.cloudDomain }}{{ include "cronjob-frontend.portSuffix" . }}; connect-src * wss: blob: resource:; style-src 'self' 'unsafe-inline' blob: *.{{ .Values.cronjobConfig.cloudDomain }}{{ include "cronjob-frontend.portSuffix" . }} {{ .Values.cronjobConfig.cloudDomain }}{{ include "cronjob-frontend.portSuffix" . }} resource:; script-src 'self' 'unsafe-inline' 'unsafe-eval' blob: *.{{ .Values.cronjobConfig.cloudDomain }}{{ include "cronjob-frontend.portSuffix" . }} {{ .Values.cronjobConfig.cloudDomain }}{{ include "cronjob-frontend.portSuffix" . }} resource: *.baidu.com *.bdstatic.com https://js.stripe.com; frame-src 'self' *.{{ .Values.cronjobConfig.cloudDomain }}{{ include "cronjob-frontend.portSuffix" . }} {{ .Values.cronjobConfig.cloudDomain }}{{ include "cronjob-frontend.portSuffix" . }} mailto: tel: weixin: mtt: *.baidu.com https://js.stripe.com; frame-ancestors 'self' {{ include "cronjob-frontend.cloudOrigin" . }} {{ include "cronjob-frontend.wildcardCloudOrigin" . }}";
more_set_headers "X-Xss-Protection: 1; mode=block";
higress.io/response-header-control-remove: X-Frame-Options
higress.io/response-header-control-update: |
Content-Security-Policy "default-src * blob: data: *.{{ .Values.cronjobConfig.cloudDomain }}{{ include "cronjob-frontend.portSuffix" . }} {{ .Values.cronjobConfig.cloudDomain }}{{ include "cronjob-frontend.portSuffix" . }}; img-src * data: blob: resource: *.{{ .Values.cronjobConfig.cloudDomain }}{{ include "cronjob-frontend.portSuffix" . }} {{ .Values.cronjobConfig.cloudDomain }}{{ include "cronjob-frontend.portSuffix" . }}; connect-src * wss: blob: resource:; style-src 'self' 'unsafe-inline' blob: *.{{ .Values.cronjobConfig.cloudDomain }}{{ include "cronjob-frontend.portSuffix" . }} {{ .Values.cronjobConfig.cloudDomain }}{{ include "cronjob-frontend.portSuffix" . }} resource:; script-src 'self' 'unsafe-inline' 'unsafe-eval' blob: *.{{ .Values.cronjobConfig.cloudDomain }}{{ include "cronjob-frontend.portSuffix" . }} {{ .Values.cronjobConfig.cloudDomain }}{{ include "cronjob-frontend.portSuffix" . }} resource: *.baidu.com *.bdstatic.com https://js.stripe.com; frame-src 'self' *.{{ .Values.cronjobConfig.cloudDomain }}{{ include "cronjob-frontend.portSuffix" . }} {{ .Values.cronjobConfig.cloudDomain }}{{ include "cronjob-frontend.portSuffix" . }} mailto: tel: weixin: mtt: *.baidu.com https://js.stripe.com; frame-ancestors 'self' {{ include "cronjob-frontend.cloudOrigin" . }} {{ include "cronjob-frontend.wildcardCloudOrigin" . }}"
X-Xss-Protection "1; mode=block"
{{- with .Values.ingress.annotations }}
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
ingressClassName: {{ .Values.ingress.className | quote }}
rules:
- host: {{ include "cronjob-frontend.host" . | quote }}
http:
paths:
- pathType: Prefix
path: /
backend:
service:
name: {{ include "cronjob-frontend.fullname" . }}
port:
number: {{ .Values.service.port }}
{{- if not (eq (toString .Values.cronjobConfig.disableHttps) "true") }}
tls:
- hosts:
- {{ include "cronjob-frontend.host" . | quote }}
secretName: {{ .Values.cronjobConfig.certSecretName | quote }}
{{- end }}
@@ -0,0 +1,16 @@
apiVersion: v1
kind: Service
metadata:
labels:
{{- include "cronjob-frontend.labels" . | nindent 4 }}
name: {{ include "cronjob-frontend.fullname" . }}
namespace: {{ .Release.Namespace }}
spec:
type: {{ .Values.service.type }}
ports:
- name: http
port: {{ .Values.service.port }}
protocol: TCP
targetPort: {{ .Values.service.port }}
selector:
{{- include "cronjob-frontend.selectorLabels" . | nindent 4 }}
@@ -0,0 +1,65 @@
# Default values for cronjob-frontend helm chart.
image: ghcr.io/labring/sealos-cronjob-frontend:latest
imagePullPolicy: Always
imagePullSecrets: []
fullnameOverride: "cronjob-frontend"
replicaCount: 1
podAnnotations: {}
podLabels: {}
podSecurityContext:
runAsNonRoot: true
runAsUser: 1001
securityContext:
runAsNonRoot: true
runAsUser: 1001
allowPrivilegeEscalation: false
capabilities:
drop:
- "ALL"
service:
type: ClusterIP
port: 3000
ingress:
className: nginx
host: ""
annotations: {}
cronjobConfig:
cloudDomain: "127.0.0.1.nip.io"
cloudPort: ""
httpPort: ""
disableHttps: false
certSecretName: "wildcard-cert"
successfulJobsHistoryLimit: 3
failedJobsHistoryLimit: 3
podCpuMilliCores: 50
podMemoryMiB: 64
resources:
limits:
cpu: 1000m
memory: 1024Mi
requests:
cpu: 10m
memory: 128Mi
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchExpressions:
- key: "app"
operator: In
values:
- cronjob-frontend
topologyKey: "kubernetes.io/hostname"
@@ -0,0 +1,90 @@
#!/bin/bash
set -e
RELEASE_NAME=${RELEASE_NAME:-"cronjob-frontend"}
RELEASE_NAMESPACE=${RELEASE_NAMESPACE:-"cronjob-frontend"}
CHART_PATH=${CHART_PATH:-"./charts/cronjob-frontend"}
HELM_OPTS=${HELM_OPTS:-""}
HELM_OPTIONS=${HELM_OPTIONS:-""}
AUTO_CONFIG_HELM_OPTS=""
get_cm_value() {
local namespace="$1"
local name="$2"
local key="$3"
kubectl get configmap "${name}" -n "${namespace}" -o "jsonpath={.data.${key}}" 2>/dev/null || true
}
add_set_string() {
local key="$1"
local value="$2"
if [ -n "${value}" ]; then
AUTO_CONFIG_HELM_OPTS="${AUTO_CONFIG_HELM_OPTS} --set-string ${key}=${value}"
fi
}
SEALOS_CLOUD_DOMAIN=${SEALOS_CLOUD_DOMAIN:-"${cloudDomain:-$(get_cm_value sealos-system sealos-config cloudDomain)}"}
add_set_string cronjobConfig.cloudDomain "${SEALOS_CLOUD_DOMAIN}"
SEALOS_CLOUD_PORT=${SEALOS_CLOUD_PORT:-"${cloudPort:-$(get_cm_value sealos-system sealos-config cloudPort)}"}
add_set_string cronjobConfig.cloudPort "${SEALOS_CLOUD_PORT}"
SEALOS_HTTP_PORT=${SEALOS_HTTP_PORT:-"${httpPort:-$(get_cm_value sealos-system sealos-config httpPort)}"}
add_set_string cronjobConfig.httpPort "${SEALOS_HTTP_PORT}"
SEALOS_DISABLE_HTTPS=${SEALOS_DISABLE_HTTPS:-"${disableHttps:-$(get_cm_value sealos-system sealos-config disableHttps)}"}
add_set_string cronjobConfig.disableHttps "${SEALOS_DISABLE_HTTPS}"
SEALOS_CERT_SECRET_NAME=${SEALOS_CERT_SECRET_NAME:-"${certSecretName:-$(get_cm_value sealos-system sealos-config certSecretName)}"}
add_set_string cronjobConfig.certSecretName "${SEALOS_CERT_SECRET_NAME}"
add_set_string cronjobConfig.successfulJobsHistoryLimit "${successfulJobsHistoryLimit:-}"
add_set_string cronjobConfig.failedJobsHistoryLimit "${failedJobsHistoryLimit:-}"
add_set_string cronjobConfig.podCpuMilliCores "${podCpuMilliCores:-}"
add_set_string cronjobConfig.podMemoryMiB "${podMemoryMiB:-}"
adopt_namespaced_resource() {
local namespace="$1"
local kind="$2"
local name="$3"
if kubectl -n "${namespace}" get "${kind}" "${name}" >/dev/null 2>&1; then
echo "Adopting ${kind} ${namespace}/${name}..."
kubectl -n "${namespace}" label "${kind}" "${name}" app.kubernetes.io/managed-by=Helm --overwrite >/dev/null 2>&1 || true
kubectl -n "${namespace}" annotate "${kind}" "${name}" meta.helm.sh/release-name="${RELEASE_NAME}" meta.helm.sh/release-namespace="${RELEASE_NAMESPACE}" --overwrite >/dev/null 2>&1 || true
fi
}
adopt_cluster_resource() {
local kind="$1"
local name="$2"
if kubectl get "${kind}" "${name}" >/dev/null 2>&1; then
echo "Adopting ${kind} ${name}..."
kubectl label "${kind}" "${name}" app.kubernetes.io/managed-by=Helm --overwrite >/dev/null 2>&1 || true
kubectl annotate "${kind}" "${name}" meta.helm.sh/release-name="${RELEASE_NAME}" meta.helm.sh/release-namespace="${RELEASE_NAMESPACE}" --overwrite >/dev/null 2>&1 || true
fi
}
echo "Checking and adopting existing resources..."
if kubectl get namespace "${RELEASE_NAMESPACE}" >/dev/null 2>&1; then
kubectl label namespace "${RELEASE_NAMESPACE}" app.kubernetes.io/managed-by=Helm --overwrite >/dev/null 2>&1 || true
kubectl annotate namespace "${RELEASE_NAMESPACE}" meta.helm.sh/release-name="${RELEASE_NAME}" meta.helm.sh/release-namespace="${RELEASE_NAMESPACE}" --overwrite >/dev/null 2>&1 || true
adopt_namespaced_resource "${RELEASE_NAMESPACE}" configmap cronjob-frontend-config
adopt_namespaced_resource "${RELEASE_NAMESPACE}" service cronjob-frontend
adopt_namespaced_resource "${RELEASE_NAMESPACE}" deployment cronjob-frontend
adopt_namespaced_resource "${RELEASE_NAMESPACE}" ingress cronjob-frontend
fi
adopt_namespaced_resource app-system apps.app.sealos.io cronjob
SERVICE_NAME="cronjob-frontend"
USER_VALUES_PATH="/root/.sealos/cloud/values/core/${SERVICE_NAME}-values.yaml"
if [ ! -f "${USER_VALUES_PATH}" ]; then
mkdir -p "$(dirname "${USER_VALUES_PATH}")"
cp "./charts/cronjob-frontend/cronjob-frontend-values.yaml" "${USER_VALUES_PATH}"
fi
HELM_ARGS="${AUTO_CONFIG_HELM_OPTS} ${HELM_OPTIONS} ${HELM_OPTS}"
echo "Deploying Helm chart..."
helm upgrade -i "${RELEASE_NAME}" -n "${RELEASE_NAMESPACE}" --create-namespace "${CHART_PATH}" \
-f "./charts/cronjob-frontend/values.yaml" \
-f "${USER_VALUES_PATH}" \
${HELM_ARGS}
@@ -1,100 +0,0 @@
apiVersion: v1
kind: Namespace
metadata:
labels:
app: cronjob-frontend
name: cronjob-frontend
---
apiVersion: v1
kind: ConfigMap
metadata:
name: cronjob-frontend-config
namespace: cronjob-frontend
data:
config.yaml: |-
addr: :3000
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: cronjob-frontend
namespace: cronjob-frontend
spec:
replicas: 1
selector:
matchLabels:
app: cronjob-frontend
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 25%
maxSurge: 25%
template:
metadata:
labels:
app: cronjob-frontend
spec:
containers:
- name: cronjob-frontend
env:
- name: SEALOS_DOMAIN
value: {{ .cloudDomain }}
- name: APPLAUNCHPAD_URL
value: applaunchpad.{{ .cloudDomain }}
- name: SUCCESSFUL_JOBS_HISTORY_LIMIT
value: "{{ .SUCCESSFUL_JOBS_HISTORY_LIMIT }}"
- name: FAILED_JOBS_HISTORY_LIMIT
value: "{{ .FAILED_JOBS_HISTORY_LIMIT }}"
securityContext:
runAsNonRoot: true
runAsUser: 1001
allowPrivilegeEscalation: false
capabilities:
drop:
- 'ALL'
resources:
limits:
cpu: 1000m
memory: 1024Mi
requests:
cpu: 10m
memory: 128Mi
# do not modify this image, it is used for CI/CD
image: ghcr.io/labring/sealos-cronjob-frontend:latest
imagePullPolicy: Always
volumeMounts:
- name: cronjob-frontend-volume
mountPath: /config.yaml
subPath: config.yaml
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchExpressions:
- key: "app"
operator: In
values:
- cronjob-frontend
topologyKey: "kubernetes.io/hostname"
volumes:
- name: cronjob-frontend-volume
configMap:
name: cronjob-frontend-config
---
apiVersion: v1
kind: Service
metadata:
labels:
app: cronjob-frontend
name: cronjob-frontend
namespace: cronjob-frontend
spec:
ports:
- name: http
port: 3000
protocol: TCP
targetPort: 3000
selector:
app: cronjob-frontend
@@ -1,51 +0,0 @@
# Copyright © 2023 sealos.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/enable-cors: "true"
nginx.ingress.kubernetes.io/cors-allow-methods: "PUT, GET, POST, DELETE, PATCH, OPTIONS"
nginx.ingress.kubernetes.io/cors-allow-origin: "https://{{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }}, https://*.{{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }}"
nginx.ingress.kubernetes.io/cors-allow-credentials: "true"
nginx.ingress.kubernetes.io/cors-max-age: "600"
nginx.ingress.kubernetes.io/backend-protocol: "HTTP"
nginx.ingress.kubernetes.io/configuration-snippet: |
more_clear_headers "X-Frame-Options:";
more_set_headers "Content-Security-Policy: default-src * blob: data: *.{{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }} {{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }}; img-src * data: blob: resource: *.{{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }} {{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }}; connect-src * wss: blob: resource:; style-src 'self' 'unsafe-inline' blob: *.{{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }} {{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }} resource:; script-src 'self' 'unsafe-inline' 'unsafe-eval' blob: *.{{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }} {{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }} resource: *.baidu.com *.bdstatic.com https://js.stripe.com; frame-src 'self' *.{{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }} {{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }} mailto: tel: weixin: mtt: *.baidu.com https://js.stripe.com; frame-ancestors 'self' https://{{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }} https://*.{{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }}";
more_set_headers "X-Xss-Protection: 1; mode=block";
higress.io/response-header-control-remove: X-Frame-Options
higress.io/response-header-control-update: |
Content-Security-Policy "default-src * blob: data: *.{{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }} {{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }}; img-src * data: blob: resource: *.{{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }} {{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }}; connect-src * wss: blob: resource:; style-src 'self' 'unsafe-inline' blob: *.{{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }} {{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }} resource:; script-src 'self' 'unsafe-inline' 'unsafe-eval' blob: *.{{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }} {{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }} resource: *.baidu.com *.bdstatic.com https://js.stripe.com; frame-src 'self' *.{{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }} {{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }} mailto: tel: weixin: mtt: *.baidu.com https://js.stripe.com; frame-ancestors 'self' https://{{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }} https://*.{{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }}"
X-Xss-Protection "1; mode=block"
name: cronjob-frontend
namespace: cronjob-frontend
spec:
rules:
- host: cronjob.{{ .cloudDomain }}
http:
paths:
- pathType: Prefix
path: /
backend:
service:
name: cronjob-frontend
port:
number: 3000
tls:
- hosts:
- cronjob.{{ .cloudDomain }}
secretName: {{ .certSecretName }}
+3 -16
View File
@@ -3,20 +3,7 @@ FROM scratch
USER 65532:65532
COPY registry registry
COPY manifests manifests
COPY charts charts
COPY dbprovider-frontend-entrypoint.sh dbprovider-frontend-entrypoint.sh
ENV cloudDomain="127.0.0.1.nip.io"
ENV cloudPort=""
ENV certSecretName="wildcard-cert"
ENV monitorUrl="http://database-monitor.sealos.svc.cluster.local:9090"
ENV minioUrl=""
ENV minioAccessKey=""
ENV minioSecretKey=""
ENV minioPort=""
ENV migrateFileImage=""
ENV minioBucketName=""
ENV guideEnabled="true"
ENV billingUrl="http://account-service.account-system.svc:2333"
ENV vlogsBaseUrl="http://service-vlogs.sealos.svc.cluster.local:8428"
CMD ["kubectl apply -f manifests"]
CMD ["bash dbprovider-frontend-entrypoint.sh"]
@@ -0,0 +1,6 @@
apiVersion: v2
name: dbprovider-frontend
description: Sealos Database Frontend Helm Chart
type: application
version: 1.0.0
appVersion: "latest"
@@ -0,0 +1,47 @@
# Custom values for dbprovider-frontend helm chart.
# This file contains user-customizable configurations.
replicaCount: 1
resources:
limits:
cpu: 2000m
memory: 2048Mi
requests:
cpu: 10m
memory: 128Mi
dbproviderConfig:
monitorUrl: "http://database-monitor.sealos.svc.cluster.local:9090"
minioUrl: ""
minioAccessKey: ""
minioSecretKey: ""
minioPort: 9000
minioUseSSL: false
minioBucketName: "file-migration"
migrateFileFetchFileImage: "quay.io/minio/mc:latest"
migrateFileImportDataImage: "sealos.hub:5000/db-import-client:latest"
guideEnabled: true
billingUrl: "http://account-service.account-system.svc:2333"
billingSecret: ""
alertingUrl: "http://database-alert-service.sealos.svc.cluster.local:8000"
alertingSecret: ""
vlogsBaseUrl: "http://service-vlogs.sealos.svc.cluster.local:8428"
migrationJobCPURequirement: 2000
migrationJobMemoryRequirement: 4096
dumpImportJobCPURequirement: 2000
dumpImportJobMemoryRequirement: 4096
backupJobCPURequirement: 300
backupJobMemoryRequirement: 256
backupEnabled: false
showDocument: true
managedDbEnabled: false
fileImportEnabled: false
currencySymbol: "shellCoin"
forcedStorageClassName: ""
storageMaxSize: 300
customScripts: []
eventAnalysisEnabled: false
eventAnalysisUrl: "https://fastgpt.run/api/openapi"
eventAnalysisModelId: "6455c433f437e55c638e630c"
eventAnalysisFastGPTKey: ""
@@ -0,0 +1,84 @@
{{/* Expand the name of the chart. */}}
{{- define "dbprovider-frontend.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
{{- end }}
{{/* Create a default fully qualified app name. */}}
{{- define "dbprovider-frontend.fullname" -}}
{{- if .Values.fullnameOverride }}
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- $name := default .Chart.Name .Values.nameOverride }}
{{- if contains $name .Release.Name }}
{{- .Release.Name | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
{{- end }}
{{- end }}
{{- end }}
{{- define "dbprovider-frontend.chart" -}}
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
{{- end }}
{{- define "dbprovider-frontend.labels" -}}
helm.sh/chart: {{ include "dbprovider-frontend.chart" . }}
{{ include "dbprovider-frontend.selectorLabels" . }}
{{ include "dbprovider-frontend.recommendedLabels" . }}
{{- if .Chart.AppVersion }}
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
{{- end }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- end }}
{{- define "dbprovider-frontend.selectorLabels" -}}
app: {{ include "dbprovider-frontend.fullname" . }}
{{- end }}
{{- define "dbprovider-frontend.recommendedLabels" -}}
app.kubernetes.io/name: {{ include "dbprovider-frontend.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- end }}
{{- define "dbprovider-frontend.scheme" -}}
{{- if eq (toString .Values.dbproviderConfig.disableHttps) "true" -}}http{{- else -}}https{{- end -}}
{{- end }}
{{- define "dbprovider-frontend.port" -}}
{{- $scheme := include "dbprovider-frontend.scheme" . -}}
{{- $port := toString .Values.dbproviderConfig.cloudPort -}}
{{- if eq $scheme "http" -}}
{{- $port = toString .Values.dbproviderConfig.httpPort -}}
{{- end -}}
{{- if or (and (eq $scheme "https") (or (eq $port "") (eq $port "443"))) (and (eq $scheme "http") (or (eq $port "") (eq $port "80"))) -}}
{{- "" -}}
{{- else -}}
{{- $port -}}
{{- end }}
{{- end }}
{{- define "dbprovider-frontend.portSuffix" -}}
{{- $port := include "dbprovider-frontend.port" . -}}
{{- if $port -}}:{{ $port }}{{- end -}}
{{- end }}
{{- define "dbprovider-frontend.portEnv" -}}
{{- $port := include "dbprovider-frontend.port" . -}}
{{- if $port -}}:{{ $port }}{{- end -}}
{{- end }}
{{- define "dbprovider-frontend.cloudOrigin" -}}
{{- include "dbprovider-frontend.scheme" . -}}://{{ .Values.dbproviderConfig.cloudDomain }}{{ include "dbprovider-frontend.portSuffix" . }}
{{- end }}
{{- define "dbprovider-frontend.wildcardCloudOrigin" -}}
{{- include "dbprovider-frontend.scheme" . -}}://*.{{ .Values.dbproviderConfig.cloudDomain }}{{ include "dbprovider-frontend.portSuffix" . }}
{{- end }}
{{- define "dbprovider-frontend.host" -}}
{{- default (printf "dbprovider.%s" .Values.dbproviderConfig.cloudDomain) .Values.ingress.host -}}
{{- end }}
{{- define "dbprovider-frontend.appUrl" -}}
{{- include "dbprovider-frontend.scheme" . -}}://{{ include "dbprovider-frontend.host" . }}{{ include "dbprovider-frontend.portSuffix" . }}
{{- end }}
@@ -6,8 +6,8 @@ metadata:
spec:
data:
desc: Database
url: "https://dbprovider.{{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }}"
icon: "https://dbprovider.{{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }}/logo.svg"
url: {{ include "dbprovider-frontend.appUrl" . | quote }}
icon: {{ printf "%s/logo.svg" (include "dbprovider-frontend.appUrl" .) | quote }}
i18n:
zh:
name: 数据库
@@ -0,0 +1,58 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ include "dbprovider-frontend.fullname" . }}-config
namespace: {{ .Release.Namespace }}
labels:
{{- include "dbprovider-frontend.labels" . | nindent 4 }}
data:
config.yaml: |-
cloud:
domain: {{ .Values.dbproviderConfig.cloudDomain | quote }}
desktopDomain: {{ .Values.dbproviderConfig.cloudDomain | quote }}
dbprovider:
features:
guide: {{ .Values.dbproviderConfig.guideEnabled }}
showDocument: {{ .Values.dbproviderConfig.showDocument }}
fileImport: {{ .Values.dbproviderConfig.fileImportEnabled }}
ui:
currencySymbol: {{ .Values.dbproviderConfig.currencySymbol | quote }}
customScripts:
{{- toYaml .Values.dbproviderConfig.customScripts | nindent 10 }}
storage:
forcedClassName: {{ if .Values.dbproviderConfig.forcedStorageClassName }}{{ .Values.dbproviderConfig.forcedStorageClassName | quote }}{{ else }}null{{ end }}
maxSize: {{ .Values.dbproviderConfig.storageMaxSize }}
components:
monitoring:
url: {{ .Values.dbproviderConfig.monitorUrl | quote }}
alerting:
url: {{ .Values.dbproviderConfig.alertingUrl | quote }}
secret: {{ .Values.dbproviderConfig.alertingSecret | quote }}
billing:
url: {{ .Values.dbproviderConfig.billingUrl | quote }}
secret: {{ .Values.dbproviderConfig.billingSecret | quote }}
logging:
url: {{ .Values.dbproviderConfig.vlogsBaseUrl | quote }}
storage:
url: {{ .Values.dbproviderConfig.minioUrl | quote }}
port: {{ .Values.dbproviderConfig.minioPort }}
useSSL: {{ .Values.dbproviderConfig.minioUseSSL }}
bucketName: {{ .Values.dbproviderConfig.minioBucketName | quote }}
accessKey: {{ .Values.dbproviderConfig.minioAccessKey | quote }}
secretKey: {{ .Values.dbproviderConfig.minioSecretKey | quote }}
eventAnalysis:
enabled: {{ .Values.dbproviderConfig.eventAnalysisEnabled }}
url: {{ .Values.dbproviderConfig.eventAnalysisUrl | quote }}
modelId: {{ .Values.dbproviderConfig.eventAnalysisModelId | quote }}
fastGPTKey: {{ .Values.dbproviderConfig.eventAnalysisFastGPTKey | quote }}
migration:
fetchFileImage: {{ .Values.dbproviderConfig.migrateFileFetchFileImage | quote }}
importDataImage: {{ .Values.dbproviderConfig.migrateFileImportDataImage | quote }}
jobCpuMillicores: {{ .Values.dbproviderConfig.migrationJobCPURequirement }}
jobMemoryMiB: {{ .Values.dbproviderConfig.migrationJobMemoryRequirement }}
dumpImportCpuMillicores: {{ .Values.dbproviderConfig.dumpImportJobCPURequirement }}
dumpImportMemoryMiB: {{ .Values.dbproviderConfig.dumpImportJobMemoryRequirement }}
backup:
enabled: {{ .Values.dbproviderConfig.backupEnabled }}
jobCpuMillicores: {{ .Values.dbproviderConfig.backupJobCPURequirement }}
jobMemoryMiB: {{ .Values.dbproviderConfig.backupJobMemoryRequirement }}
@@ -0,0 +1,108 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "dbprovider-frontend.fullname" . }}
namespace: {{ .Release.Namespace }}
labels:
{{- include "dbprovider-frontend.labels" . | nindent 4 }}
spec:
replicas: {{ .Values.replicaCount }}
selector:
matchLabels:
{{- include "dbprovider-frontend.selectorLabels" . | nindent 6 }}
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 25%
maxSurge: 25%
template:
metadata:
labels:
{{- include "dbprovider-frontend.labels" . | nindent 8 }}
{{- with .Values.podAnnotations }}
annotations:
{{- toYaml . | nindent 8 }}
{{- end }}
spec:
{{- with .Values.imagePullSecrets }}
imagePullSecrets:
{{- toYaml . | nindent 8 }}
{{- end }}
securityContext:
{{- toYaml .Values.podSecurityContext | nindent 8 }}
serviceAccountName: cluster-version-reader
containers:
- name: {{ .Chart.Name }}
image: {{ .Values.image | quote }}
imagePullPolicy: {{ .Values.imagePullPolicy }}
{{- if .Values.securityContext }}
securityContext:
{{- toYaml .Values.securityContext | nindent 12 }}
{{- end }}
resources:
{{- toYaml .Values.resources | nindent 12 }}
env:
- name: SEALOS_DOMAIN
value: {{ .Values.dbproviderConfig.cloudDomain | quote }}
- name: DESKTOP_DOMAIN
value: {{ .Values.dbproviderConfig.cloudDomain | quote }}
- name: SEALOS_PORT
value: {{ include "dbprovider-frontend.portEnv" . | quote }}
- name: MONITOR_URL
value: {{ .Values.dbproviderConfig.monitorUrl | quote }}
- name: MINIO_URL
value: {{ .Values.dbproviderConfig.minioUrl | quote }}
- name: MINIO_ACCESS_KEY
value: {{ .Values.dbproviderConfig.minioAccessKey | quote }}
- name: MINIO_SECRET_KEY
value: {{ .Values.dbproviderConfig.minioSecretKey | quote }}
- name: MIGRATE_FILE_FETCH_FILE_IMAGE
value: {{ .Values.dbproviderConfig.migrateFileFetchFileImage | quote }}
- name: MIGRATE_FILE_IMPORT_DATA_IMAGE
value: {{ .Values.dbproviderConfig.migrateFileImportDataImage | quote }}
- name: MINIO_PORT
value: {{ .Values.dbproviderConfig.minioPort | quote }}
- name: MINIO_BUCKET_NAME
value: {{ .Values.dbproviderConfig.minioBucketName | quote }}
- name: BACKUP_ENABLED
value: {{ .Values.dbproviderConfig.backupEnabled | quote }}
- name: SHOW_DOCUMENT
value: {{ .Values.dbproviderConfig.showDocument | quote }}
- name: GUIDE_ENABLED
value: {{ .Values.dbproviderConfig.guideEnabled | quote }}
- name: BILLING_URL
value: {{ .Values.dbproviderConfig.billingUrl | quote }}
- name: MANAGED_DB_ENABLED
value: {{ .Values.dbproviderConfig.managedDbEnabled | quote }}
- name: VLOGS_BASE_URL
value: {{ .Values.dbproviderConfig.vlogsBaseUrl | quote }}
- name: MIGRATION_JOB_CPU_REQUIREMENT
value: {{ .Values.dbproviderConfig.migrationJobCPURequirement | quote }}
- name: MIGRATION_JOB_MEMORY_REQUIREMENT
value: {{ .Values.dbproviderConfig.migrationJobMemoryRequirement | quote }}
- name: DUMPIMPORT_JOB_CPU_REQUIREMENT
value: {{ .Values.dbproviderConfig.dumpImportJobCPURequirement | quote }}
- name: DUMPIMPORT_JOB_MEMORY_REQUIREMENT
value: {{ .Values.dbproviderConfig.dumpImportJobMemoryRequirement | quote }}
- name: BACKUP_JOB_CPU_REQUIREMENT
value: {{ .Values.dbproviderConfig.backupJobCPURequirement | quote }}
- name: BACKUP_JOB_MEMORY_REQUIREMENT
value: {{ .Values.dbproviderConfig.backupJobMemoryRequirement | quote }}
- name: CURRENCY_SYMBOL
value: {{ .Values.dbproviderConfig.currencySymbol | quote }}
ports:
- name: http
containerPort: {{ .Values.service.port }}
protocol: TCP
volumeMounts:
- name: dbprovider-frontend-volume
mountPath: /app/data/config.yaml
subPath: config.yaml
{{- with .Values.affinity }}
affinity:
{{- toYaml . | nindent 8 }}
{{- end }}
volumes:
- name: dbprovider-frontend-volume
configMap:
name: {{ include "dbprovider-frontend.fullname" . }}-config
@@ -0,0 +1,43 @@
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: {{ include "dbprovider-frontend.fullname" . }}
namespace: {{ .Release.Namespace }}
annotations:
kubernetes.io/ingress.class: {{ .Values.ingress.className | quote }}
nginx.ingress.kubernetes.io/enable-cors: "true"
nginx.ingress.kubernetes.io/cors-allow-methods: "PUT, GET, POST, DELETE, PATCH, OPTIONS"
nginx.ingress.kubernetes.io/cors-allow-origin: "{{ include "dbprovider-frontend.cloudOrigin" . }}, {{ include "dbprovider-frontend.wildcardCloudOrigin" . }}"
nginx.ingress.kubernetes.io/cors-allow-credentials: "true"
nginx.ingress.kubernetes.io/cors-max-age: "600"
nginx.ingress.kubernetes.io/backend-protocol: "HTTP"
nginx.ingress.kubernetes.io/configuration-snippet: |
more_clear_headers "X-Frame-Options:";
more_set_headers "Content-Security-Policy: default-src * blob: data: *.{{ .Values.dbproviderConfig.cloudDomain }}{{ include "dbprovider-frontend.portSuffix" . }} {{ .Values.dbproviderConfig.cloudDomain }}{{ include "dbprovider-frontend.portSuffix" . }}; img-src * data: blob: resource: *.{{ .Values.dbproviderConfig.cloudDomain }}{{ include "dbprovider-frontend.portSuffix" . }} {{ .Values.dbproviderConfig.cloudDomain }}{{ include "dbprovider-frontend.portSuffix" . }}; connect-src * wss: blob: resource:; style-src 'self' 'unsafe-inline' blob: *.{{ .Values.dbproviderConfig.cloudDomain }}{{ include "dbprovider-frontend.portSuffix" . }} {{ .Values.dbproviderConfig.cloudDomain }}{{ include "dbprovider-frontend.portSuffix" . }} resource:; script-src 'self' 'unsafe-inline' 'unsafe-eval' blob: *.{{ .Values.dbproviderConfig.cloudDomain }}{{ include "dbprovider-frontend.portSuffix" . }} {{ .Values.dbproviderConfig.cloudDomain }}{{ include "dbprovider-frontend.portSuffix" . }} resource: *.baidu.com *.bdstatic.com https://js.stripe.com; frame-src 'self' *.{{ .Values.dbproviderConfig.cloudDomain }}{{ include "dbprovider-frontend.portSuffix" . }} {{ .Values.dbproviderConfig.cloudDomain }}{{ include "dbprovider-frontend.portSuffix" . }} mailto: tel: weixin: mtt: *.baidu.com https://js.stripe.com; frame-ancestors 'self' {{ include "dbprovider-frontend.cloudOrigin" . }} {{ include "dbprovider-frontend.wildcardCloudOrigin" . }}";
more_set_headers "X-Xss-Protection: 1; mode=block";
higress.io/response-header-control-remove: X-Frame-Options
higress.io/response-header-control-update: |
Content-Security-Policy "default-src * blob: data: *.{{ .Values.dbproviderConfig.cloudDomain }}{{ include "dbprovider-frontend.portSuffix" . }} {{ .Values.dbproviderConfig.cloudDomain }}{{ include "dbprovider-frontend.portSuffix" . }}; img-src * data: blob: resource: *.{{ .Values.dbproviderConfig.cloudDomain }}{{ include "dbprovider-frontend.portSuffix" . }} {{ .Values.dbproviderConfig.cloudDomain }}{{ include "dbprovider-frontend.portSuffix" . }}; connect-src * wss: blob: resource:; style-src 'self' 'unsafe-inline' blob: *.{{ .Values.dbproviderConfig.cloudDomain }}{{ include "dbprovider-frontend.portSuffix" . }} {{ .Values.dbproviderConfig.cloudDomain }}{{ include "dbprovider-frontend.portSuffix" . }} resource:; script-src 'self' 'unsafe-inline' 'unsafe-eval' blob: *.{{ .Values.dbproviderConfig.cloudDomain }}{{ include "dbprovider-frontend.portSuffix" . }} {{ .Values.dbproviderConfig.cloudDomain }}{{ include "dbprovider-frontend.portSuffix" . }} resource: *.baidu.com *.bdstatic.com https://js.stripe.com; frame-src 'self' *.{{ .Values.dbproviderConfig.cloudDomain }}{{ include "dbprovider-frontend.portSuffix" . }} {{ .Values.dbproviderConfig.cloudDomain }}{{ include "dbprovider-frontend.portSuffix" . }} mailto: tel: weixin: mtt: *.baidu.com https://js.stripe.com; frame-ancestors 'self' {{ include "dbprovider-frontend.cloudOrigin" . }} {{ include "dbprovider-frontend.wildcardCloudOrigin" . }}"
X-Xss-Protection "1; mode=block"
{{- with .Values.ingress.annotations }}
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
ingressClassName: {{ .Values.ingress.className | quote }}
rules:
- host: {{ include "dbprovider-frontend.host" . | quote }}
http:
paths:
- pathType: Prefix
path: /
backend:
service:
name: {{ include "dbprovider-frontend.fullname" . }}
port:
number: {{ .Values.service.port }}
{{- if not (eq (toString .Values.dbproviderConfig.disableHttps) "true") }}
tls:
- hosts:
- {{ include "dbprovider-frontend.host" . | quote }}
secretName: {{ .Values.dbproviderConfig.certSecretName | quote }}
{{- end }}
@@ -0,0 +1,42 @@
apiVersion: v1
kind: ServiceAccount
metadata:
name: cluster-version-reader
namespace: {{ .Release.Namespace }}
labels:
{{- include "dbprovider-frontend.labels" . | nindent 4 }}
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: cluster-version-reader
rules:
- apiGroups: ["extensions.kubeblocks.io"]
resources: ["addons"]
verbs: ["get", "watch", "list"]
- apiGroups: ["apps.kubeblocks.io"]
resources: ["clusterversions"]
verbs: ["get", "watch", "list"]
- apiGroups: ["dataprotection.kubeblocks.io"]
resources: ["backuprepos"]
verbs: ["get", "watch", "list"]
- apiGroups: ["apps.kubeblocks.io"]
resources: ["componentversions"]
verbs: ["get", "watch", "list"]
- apiGroups: ["app.sealos.io"]
resources: ["apps"]
resourceNames: ["dataflow"]
verbs: ["get"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: cluster-version-reader-rolebinding
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-version-reader
subjects:
- kind: ServiceAccount
name: cluster-version-reader
namespace: {{ .Release.Namespace }}
@@ -0,0 +1,16 @@
apiVersion: v1
kind: Service
metadata:
labels:
{{- include "dbprovider-frontend.labels" . | nindent 4 }}
name: {{ include "dbprovider-frontend.fullname" . }}
namespace: {{ .Release.Namespace }}
spec:
type: {{ .Values.service.type }}
ports:
- name: http
port: {{ .Values.service.port }}
protocol: TCP
targetPort: {{ .Values.service.port }}
selector:
{{- include "dbprovider-frontend.selectorLabels" . | nindent 4 }}
@@ -0,0 +1,94 @@
# Default values for dbprovider-frontend helm chart.
image: ghcr.io/labring/sealos-dbprovider-frontend:latest
imagePullPolicy: Always
imagePullSecrets: []
fullnameOverride: "dbprovider-frontend"
replicaCount: 1
podAnnotations: {}
podLabels: {}
podSecurityContext:
runAsNonRoot: true
runAsUser: 1001
securityContext:
runAsNonRoot: true
runAsUser: 1001
allowPrivilegeEscalation: false
capabilities:
drop:
- "ALL"
service:
type: ClusterIP
port: 3000
ingress:
className: nginx
host: ""
annotations: {}
dbproviderConfig:
cloudDomain: "127.0.0.1.nip.io"
cloudPort: ""
httpPort: ""
disableHttps: false
certSecretName: "wildcard-cert"
monitorUrl: "http://database-monitor.sealos.svc.cluster.local:9090"
minioUrl: ""
minioAccessKey: ""
minioSecretKey: ""
minioPort: 9000
minioUseSSL: false
minioBucketName: "file-migration"
migrateFileFetchFileImage: "quay.io/minio/mc:latest"
migrateFileImportDataImage: "sealos.hub:5000/db-import-client:latest"
guideEnabled: true
billingUrl: "http://account-service.account-system.svc:2333"
billingSecret: ""
alertingUrl: "http://database-alert-service.sealos.svc.cluster.local:8000"
alertingSecret: ""
vlogsBaseUrl: "http://service-vlogs.sealos.svc.cluster.local:8428"
migrationJobCPURequirement: 2000
migrationJobMemoryRequirement: 4096
dumpImportJobCPURequirement: 2000
dumpImportJobMemoryRequirement: 4096
backupJobCPURequirement: 300
backupJobMemoryRequirement: 256
backupEnabled: false
showDocument: true
managedDbEnabled: false
fileImportEnabled: false
currencySymbol: "shellCoin"
forcedStorageClassName: ""
storageMaxSize: 300
customScripts: []
eventAnalysisEnabled: false
eventAnalysisUrl: "https://fastgpt.run/api/openapi"
eventAnalysisModelId: "6455c433f437e55c638e630c"
eventAnalysisFastGPTKey: ""
resources:
limits:
cpu: 2000m
memory: 2048Mi
requests:
cpu: 10m
memory: 128Mi
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchExpressions:
- key: "app"
operator: In
values:
- dbprovider-frontend
topologyKey: "kubernetes.io/hostname"
@@ -0,0 +1,121 @@
#!/bin/bash
set -e
RELEASE_NAME=${RELEASE_NAME:-"dbprovider-frontend"}
RELEASE_NAMESPACE=${RELEASE_NAMESPACE:-"dbprovider-frontend"}
CHART_PATH=${CHART_PATH:-"./charts/dbprovider-frontend"}
HELM_OPTS=${HELM_OPTS:-""}
HELM_OPTIONS=${HELM_OPTIONS:-""}
AUTO_CONFIG_HELM_OPTS=""
get_cm_value() {
local namespace="$1"
local name="$2"
local key="$3"
kubectl get configmap "${name}" -n "${namespace}" -o "jsonpath={.data.${key}}" 2>/dev/null || true
}
add_set_string() {
local key="$1"
local value="$2"
if [ -n "${value}" ]; then
AUTO_CONFIG_HELM_OPTS="${AUTO_CONFIG_HELM_OPTS} --set-string ${key}=${value}"
fi
}
SEALOS_CLOUD_DOMAIN=${SEALOS_CLOUD_DOMAIN:-"${cloudDomain:-$(get_cm_value sealos-system sealos-config cloudDomain)}"}
add_set_string dbproviderConfig.cloudDomain "${SEALOS_CLOUD_DOMAIN}"
SEALOS_CLOUD_PORT=${SEALOS_CLOUD_PORT:-"${cloudPort:-$(get_cm_value sealos-system sealos-config cloudPort)}"}
add_set_string dbproviderConfig.cloudPort "${SEALOS_CLOUD_PORT}"
SEALOS_HTTP_PORT=${SEALOS_HTTP_PORT:-"${httpPort:-$(get_cm_value sealos-system sealos-config httpPort)}"}
add_set_string dbproviderConfig.httpPort "${SEALOS_HTTP_PORT}"
SEALOS_DISABLE_HTTPS=${SEALOS_DISABLE_HTTPS:-"${disableHttps:-$(get_cm_value sealos-system sealos-config disableHttps)}"}
add_set_string dbproviderConfig.disableHttps "${SEALOS_DISABLE_HTTPS}"
SEALOS_CERT_SECRET_NAME=${SEALOS_CERT_SECRET_NAME:-"${certSecretName:-$(get_cm_value sealos-system sealos-config certSecretName)}"}
add_set_string dbproviderConfig.certSecretName "${SEALOS_CERT_SECRET_NAME}"
add_set_string dbproviderConfig.monitorUrl "${monitorUrl:-}"
add_set_string dbproviderConfig.minioUrl "${minioUrl:-}"
add_set_string dbproviderConfig.minioAccessKey "${minioAccessKey:-}"
add_set_string dbproviderConfig.minioSecretKey "${minioSecretKey:-}"
add_set_string dbproviderConfig.minioPort "${minioPort:-}"
add_set_string dbproviderConfig.minioUseSSL "${minioUseSSL:-}"
add_set_string dbproviderConfig.minioBucketName "${minioBucketName:-}"
add_set_string dbproviderConfig.migrateFileFetchFileImage "${migrateFileFetchFileImage:-}"
add_set_string dbproviderConfig.migrateFileImportDataImage "${migrateFileImportDataImage:-}"
add_set_string dbproviderConfig.guideEnabled "${guideEnabled:-}"
add_set_string dbproviderConfig.billingUrl "${billingUrl:-}"
add_set_string dbproviderConfig.billingSecret "${billingSecret:-}"
add_set_string dbproviderConfig.alertingUrl "${alertingUrl:-}"
add_set_string dbproviderConfig.alertingSecret "${alertingSecret:-}"
add_set_string dbproviderConfig.vlogsBaseUrl "${vlogsBaseUrl:-}"
add_set_string dbproviderConfig.migrationJobCPURequirement "${migrationJobCPURequirement:-}"
add_set_string dbproviderConfig.migrationJobMemoryRequirement "${migrationJobMemoryRequirement:-}"
add_set_string dbproviderConfig.dumpImportJobCPURequirement "${dumpImportJobCPURequirement:-}"
add_set_string dbproviderConfig.dumpImportJobMemoryRequirement "${dumpImportJobMemoryRequirement:-}"
add_set_string dbproviderConfig.backupJobCPURequirement "${backupJobCPURequirement:-}"
add_set_string dbproviderConfig.backupJobMemoryRequirement "${backupJobMemoryRequirement:-}"
add_set_string dbproviderConfig.backupEnabled "${backupEnabled:-}"
add_set_string dbproviderConfig.showDocument "${showDocument:-}"
add_set_string dbproviderConfig.managedDbEnabled "${managedDbEnabled:-}"
add_set_string dbproviderConfig.fileImportEnabled "${fileImportEnabled:-}"
add_set_string dbproviderConfig.currencySymbol "${currencySymbol:-}"
add_set_string dbproviderConfig.forcedStorageClassName "${forcedStorageClassName:-}"
add_set_string dbproviderConfig.storageMaxSize "${storageMaxSize:-}"
add_set_string dbproviderConfig.customScripts "${customScripts:-}"
add_set_string dbproviderConfig.eventAnalysisEnabled "${eventAnalysisEnabled:-}"
add_set_string dbproviderConfig.eventAnalysisUrl "${eventAnalysisUrl:-}"
add_set_string dbproviderConfig.eventAnalysisModelId "${eventAnalysisModelId:-}"
add_set_string dbproviderConfig.eventAnalysisFastGPTKey "${eventAnalysisFastGPTKey:-}"
adopt_namespaced_resource() {
local namespace="$1"
local kind="$2"
local name="$3"
if kubectl -n "${namespace}" get "${kind}" "${name}" >/dev/null 2>&1; then
echo "Adopting ${kind} ${namespace}/${name}..."
kubectl -n "${namespace}" label "${kind}" "${name}" app.kubernetes.io/managed-by=Helm --overwrite >/dev/null 2>&1 || true
kubectl -n "${namespace}" annotate "${kind}" "${name}" meta.helm.sh/release-name="${RELEASE_NAME}" meta.helm.sh/release-namespace="${RELEASE_NAMESPACE}" --overwrite >/dev/null 2>&1 || true
fi
}
adopt_cluster_resource() {
local kind="$1"
local name="$2"
if kubectl get "${kind}" "${name}" >/dev/null 2>&1; then
echo "Adopting ${kind} ${name}..."
kubectl label "${kind}" "${name}" app.kubernetes.io/managed-by=Helm --overwrite >/dev/null 2>&1 || true
kubectl annotate "${kind}" "${name}" meta.helm.sh/release-name="${RELEASE_NAME}" meta.helm.sh/release-namespace="${RELEASE_NAMESPACE}" --overwrite >/dev/null 2>&1 || true
fi
}
echo "Checking and adopting existing resources..."
if kubectl get namespace "${RELEASE_NAMESPACE}" >/dev/null 2>&1; then
kubectl label namespace "${RELEASE_NAMESPACE}" app.kubernetes.io/managed-by=Helm --overwrite >/dev/null 2>&1 || true
kubectl annotate namespace "${RELEASE_NAMESPACE}" meta.helm.sh/release-name="${RELEASE_NAME}" meta.helm.sh/release-namespace="${RELEASE_NAMESPACE}" --overwrite >/dev/null 2>&1 || true
adopt_namespaced_resource "${RELEASE_NAMESPACE}" serviceaccount cluster-version-reader
adopt_namespaced_resource "${RELEASE_NAMESPACE}" configmap dbprovider-frontend-config
adopt_namespaced_resource "${RELEASE_NAMESPACE}" service dbprovider-frontend
adopt_namespaced_resource "${RELEASE_NAMESPACE}" deployment dbprovider-frontend
adopt_namespaced_resource "${RELEASE_NAMESPACE}" ingress dbprovider-frontend
fi
adopt_namespaced_resource app-system apps.app.sealos.io dbprovider
adopt_cluster_resource clusterrole cluster-version-reader
adopt_cluster_resource clusterrolebinding cluster-version-reader-rolebinding
SERVICE_NAME="dbprovider-frontend"
USER_VALUES_PATH="/root/.sealos/cloud/values/core/${SERVICE_NAME}-values.yaml"
if [ ! -f "${USER_VALUES_PATH}" ]; then
mkdir -p "$(dirname "${USER_VALUES_PATH}")"
cp "./charts/dbprovider-frontend/dbprovider-frontend-values.yaml" "${USER_VALUES_PATH}"
fi
HELM_ARGS="${AUTO_CONFIG_HELM_OPTS} ${HELM_OPTIONS} ${HELM_OPTS}"
echo "Deploying Helm chart..."
helm upgrade -i "${RELEASE_NAME}" -n "${RELEASE_NAMESPACE}" --create-namespace "${CHART_PATH}" \
-f "./charts/dbprovider-frontend/values.yaml" \
-f "${USER_VALUES_PATH}" \
${HELM_ARGS}
@@ -1,139 +0,0 @@
apiVersion: v1
kind: Namespace
metadata:
labels:
app: dbprovider-frontend
name: dbprovider-frontend
---
apiVersion: v1
kind: ConfigMap
metadata:
name: dbprovider-frontend-config
namespace: dbprovider-frontend
data:
config.yaml: |-
addr: :3000
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: dbprovider-frontend
namespace: dbprovider-frontend
spec:
replicas: 1
selector:
matchLabels:
app: dbprovider-frontend
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 25%
maxSurge: 25%
template:
metadata:
labels:
app: dbprovider-frontend
spec:
serviceAccountName: cluster-version-reader
containers:
- name: dbprovider-frontend
env:
- name: SEALOS_DOMAIN
value: {{ .cloudDomain }}
- name: DESKTOP_DOMAIN
value: {{ .cloudDomain }}
- name: SEALOS_PORT
value: "{{ if .cloudPort }}:{{ .cloudPort }}{{ end }}"
- name: MONITOR_URL
value: {{ .monitorUrl }}
- name: MINIO_URL
value: {{ .minioUrl }}
- name: MINIO_ACCESS_KEY
value: {{ .minioAccessKey }}
- name: MINIO_SECRET_KEY
value: {{ .minioSecretKey }}
- name: MIGRATE_FILE_FETCH_FILE_IMAGE
value: {{ .migrateFileFetchFileImage }}
- name: MIGRATE_FILE_IMPORT_DATA_IMAGE
value: {{ .migrateFileImportDataImage }}
- name: MINIO_PORT
value: '{{ .minioPort }}'
- name: MINIO_BUCKET_NAME
value: {{ .minioBucketName }}
- name: BACKUP_ENABLED
value: "false"
- name: SHOW_DOCUMENT
value: "true"
- name: GUIDE_ENABLED
value: "{{ .guideEnabled }}"
- name: BILLING_URL
value: {{ .billingUrl }}
- name: MANAGED_DB_ENABLED
value: "false"
- name: VLOGS_BASE_URL
value: {{ .vlogsBaseUrl }}
- name: MIGRATION_JOB_CPU_REQUIREMENT
value: {{ .migrationJobCPURequirement }}
- name: MIGRATION_JOB_MEMORY_REQUIREMENT
value: {{ .migrationJobMemoryRequirement }}
- name: DUMPIMPORT_JOB_CPU_REQUIREMENT
value: {{ .dumpImportJobCPURequirement }}
- name: DUMPIMPORT_JOB_MEMORY_REQUIREMENT
value: {{ .dumpImportJobMemoryRequirement }}
- name: BACKUP_JOB_CPU_REQUIREMENT
value: {{ .backupJobCPURequirement }}
- name: BACKUP_JOB_MEMORY_REQUIREMENT
value: {{ .backupJobMemoryRequirement }}
securityContext:
runAsNonRoot: true
runAsUser: 1001
allowPrivilegeEscalation: false
capabilities:
drop:
- 'ALL'
resources:
limits:
cpu: 2000m
memory: 2048Mi
requests:
cpu: 10m
memory: 128Mi
# do not modify this image, it is used for CI/CD
image: ghcr.io/labring/sealos-dbprovider-frontend:latest
imagePullPolicy: Always
volumeMounts:
- name: dbprovider-frontend-volume
mountPath: /config.yaml
subPath: config.yaml
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchExpressions:
- key: "app"
operator: In
values:
- dbprovider-frontend
topologyKey: "kubernetes.io/hostname"
volumes:
- name: dbprovider-frontend-volume
configMap:
name: dbprovider-frontend-config
---
apiVersion: v1
kind: Service
metadata:
labels:
app: dbprovider-frontend
name: dbprovider-frontend
namespace: dbprovider-frontend
spec:
ports:
- name: http
port: 3000
protocol: TCP
targetPort: 3000
selector:
app: dbprovider-frontend
@@ -1,31 +0,0 @@
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/configuration-snippet: |
more_clear_headers "X-Frame-Options:";
more_set_headers "Content-Security-Policy: default-src * blob: data: *.{{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }} {{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }}; img-src * data: blob: resource: *.{{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }} {{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }}; connect-src * wss: blob: resource:; style-src 'self' 'unsafe-inline' blob: *.{{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }} {{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }} resource:; script-src 'self' 'unsafe-inline' 'unsafe-eval' blob: *.{{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }} {{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }} resource: *.baidu.com *.bdstatic.com; frame-src 'self' {{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }} mailto: tel: weixin: mtt: *.baidu.com; frame-ancestors 'self' https://{{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }} https://*.{{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }}";
more_set_headers "X-Xss-Protection: 1; mode=block";
higress.io/response-header-control-remove: X-Frame-Options
higress.io/response-header-control-update: |
Content-Security-Policy "default-src * blob: data: *.{{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }} {{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }}; img-src * data: blob: resource: *.{{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }} {{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }}; connect-src * wss: blob: resource:; style-src 'self' 'unsafe-inline' blob: *.{{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }} {{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }} resource:; script-src 'self' 'unsafe-inline' 'unsafe-eval' blob: *.{{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }} {{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }} resource: *.baidu.com *.bdstatic.com; frame-src 'self' {{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }} mailto: tel: weixin: mtt: *.baidu.com; frame-ancestors 'self' https://{{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }} https://*.{{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }}"
X-Xss-Protection "1; mode=block"
name: dbprovider-frontend
namespace: dbprovider-frontend
spec:
rules:
- host: dbprovider.{{ .cloudDomain }}
http:
paths:
- pathType: Prefix
path: /
backend:
service:
name: dbprovider-frontend
port:
number: 3000
tls:
- hosts:
- dbprovider.{{ .cloudDomain }}
secretName: {{ .certSecretName }}
@@ -1,40 +0,0 @@
apiVersion: v1
kind: ServiceAccount
metadata:
name: cluster-version-reader
namespace: dbprovider-frontend
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: cluster-version-reader
rules:
- apiGroups: [ 'extensions.kubeblocks.io' ]
resources: [ 'addons' ]
verbs: [ 'get', 'watch', 'list' ]
- apiGroups: ['apps.kubeblocks.io']
resources: ['clusterversions']
verbs: ['get', 'watch', 'list']
- apiGroups: ['dataprotection.kubeblocks.io']
resources: ['backuprepos']
verbs: ['get', 'watch', 'list']
- apiGroups: ['apps.kubeblocks.io']
resources: ['componentversions']
verbs: ['get', 'watch', 'list']
- apiGroups: ['app.sealos.io']
resources: ['apps']
resourceNames: ['dataflow']
verbs: ['get']
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: cluster-version-reader-rolebinding
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-version-reader
subjects:
- kind: ServiceAccount
name: cluster-version-reader
namespace: dbprovider-frontend
+3 -7
View File
@@ -3,11 +3,7 @@ FROM scratch
USER 65532:65532
COPY registry registry
COPY manifests manifests
COPY charts charts
COPY devbox-frontend-entrypoint.sh devbox-frontend-entrypoint.sh
ENV cloudDomain="127.0.0.1.nip.io"
ENV cloudPort=""
ENV certSecretName="wildcard-cert"
ENV registryAddr="sealos.hub:5000"
CMD ["kubectl apply -f manifests"]
CMD ["bash devbox-frontend-entrypoint.sh"]
@@ -0,0 +1,6 @@
apiVersion: v2
name: devbox-frontend
description: Sealos DevBox Frontend Helm Chart
type: application
version: 1.0.0
appVersion: "latest"
@@ -0,0 +1,41 @@
# Custom values for devbox-frontend helm chart.
# This file contains user-customizable configurations.
replicaCount: 1
resources:
limits:
cpu: 2000m
memory: 2048Mi
requests:
cpu: 100m
memory: 128Mi
devboxConfig:
databaseUrl: ""
databaseProvider: "cockroachdb"
tlsRejectUnauthorized: "1"
sshDomain: ""
registryAddr: "sealos.hub:5000"
monitorUrl: "http://launchpad-monitor.sealos.svc.cluster.local:8428"
accountUrl: "http://account-service.account-system.svc.cluster.local:2333"
rootRuntimeNamespace: "devbox-system"
currencySymbol: "usd"
gpuEnable: false
storageLimit: "10Gi"
runtimeClassName: "devbox-runtime"
retagSvcUrl: "http://devbox-service.devbox-system.svc.cluster.local:8092"
jwtSecret: ""
regionUid: ""
enableImportFeature: false
enableWebideFeature: false
enableAdvancedConfig: false
cpuSlideMarkList: "1,2,4,8,16"
memorySlideMarkList: "2,4,8,16,32"
devboxDomainChallengeSecret: "default-dev-secret-change-in-production"
nfsStorageClassName: "nfs-csi"
customScripts: "[]"
documentUrlZh: "https://sealos.run/docs/overview/intro"
documentUrlEn: "https://sealos.io/docs/overview/intro"
privacyUrlZh: "https://sealos.run/docs/msa/privacy-policy"
privacyUrlEn: "https://sealos.io/docs/msa/privacy-policy"
@@ -0,0 +1,84 @@
{{/* Expand the name of the chart. */}}
{{- define "devbox-frontend.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
{{- end }}
{{/* Create a default fully qualified app name. */}}
{{- define "devbox-frontend.fullname" -}}
{{- if .Values.fullnameOverride }}
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- $name := default .Chart.Name .Values.nameOverride }}
{{- if contains $name .Release.Name }}
{{- .Release.Name | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
{{- end }}
{{- end }}
{{- end }}
{{- define "devbox-frontend.chart" -}}
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
{{- end }}
{{- define "devbox-frontend.labels" -}}
helm.sh/chart: {{ include "devbox-frontend.chart" . }}
{{ include "devbox-frontend.selectorLabels" . }}
{{ include "devbox-frontend.recommendedLabels" . }}
{{- if .Chart.AppVersion }}
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
{{- end }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- end }}
{{- define "devbox-frontend.selectorLabels" -}}
app: {{ include "devbox-frontend.fullname" . }}
{{- end }}
{{- define "devbox-frontend.recommendedLabels" -}}
app.kubernetes.io/name: {{ include "devbox-frontend.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- end }}
{{- define "devbox-frontend.scheme" -}}
{{- if eq (toString .Values.devboxConfig.disableHttps) "true" -}}http{{- else -}}https{{- end -}}
{{- end }}
{{- define "devbox-frontend.port" -}}
{{- $scheme := include "devbox-frontend.scheme" . -}}
{{- $port := toString .Values.devboxConfig.cloudPort -}}
{{- if eq $scheme "http" -}}
{{- $port = toString .Values.devboxConfig.httpPort -}}
{{- end -}}
{{- if or (and (eq $scheme "https") (or (eq $port "") (eq $port "443"))) (and (eq $scheme "http") (or (eq $port "") (eq $port "80"))) -}}
{{- "" -}}
{{- else -}}
{{- $port -}}
{{- end }}
{{- end }}
{{- define "devbox-frontend.portSuffix" -}}
{{- $port := include "devbox-frontend.port" . -}}
{{- if $port -}}:{{ $port }}{{- end -}}
{{- end }}
{{- define "devbox-frontend.portEnv" -}}
{{- $port := include "devbox-frontend.port" . -}}
{{- if $port -}}:{{ $port }}{{- end -}}
{{- end }}
{{- define "devbox-frontend.cloudOrigin" -}}
{{- include "devbox-frontend.scheme" . -}}://{{ .Values.devboxConfig.cloudDomain }}{{ include "devbox-frontend.portSuffix" . }}
{{- end }}
{{- define "devbox-frontend.wildcardCloudOrigin" -}}
{{- include "devbox-frontend.scheme" . -}}://*.{{ .Values.devboxConfig.cloudDomain }}{{ include "devbox-frontend.portSuffix" . }}
{{- end }}
{{- define "devbox-frontend.host" -}}
{{- default (printf "devbox.%s" .Values.devboxConfig.cloudDomain) .Values.ingress.host -}}
{{- end }}
{{- define "devbox-frontend.appUrl" -}}
{{- include "devbox-frontend.scheme" . -}}://{{ include "devbox-frontend.host" . }}{{ include "devbox-frontend.portSuffix" . }}
{{- end }}
@@ -6,13 +6,14 @@ metadata:
spec:
data:
desc: DevBox
url: 'https://devbox.{{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }}'
icon: 'https://devbox.{{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }}/logo.svg'
url: {{ include "devbox-frontend.appUrl" . | quote }}
icon: {{ printf "%s/logo.svg" (include "devbox-frontend.appUrl" .) | quote }}
i18n:
zh:
name: DevBox
zh-Hans:
name: DevBox
menuData:
name: DevBox
type: iframe
displayType: normal
@@ -0,0 +1,19 @@
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
kubernetes.io/ingress.class: {{ .Values.ingress.className | quote }}
name: devbox-challenge
namespace: {{ .Release.Namespace }}
spec:
rules:
- host: ""
http:
paths:
- backend:
service:
name: {{ include "devbox-frontend.fullname" . }}
port:
number: {{ .Values.service.port }}
path: /api/.well-known/devbox-domain-challenge
pathType: Prefix
@@ -0,0 +1,10 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ include "devbox-frontend.fullname" . }}-config
namespace: {{ .Release.Namespace }}
labels:
{{- include "devbox-frontend.labels" . | nindent 4 }}
data:
config.yaml: |-
addr: :3000
@@ -0,0 +1,156 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "devbox-frontend.fullname" . }}
namespace: {{ .Release.Namespace }}
labels:
{{- include "devbox-frontend.labels" . | nindent 4 }}
spec:
replicas: {{ .Values.replicaCount }}
selector:
matchLabels:
{{- include "devbox-frontend.selectorLabels" . | nindent 6 }}
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 25%
maxSurge: 25%
template:
metadata:
labels:
{{- include "devbox-frontend.labels" . | nindent 8 }}
{{- with .Values.podAnnotations }}
annotations:
{{- toYaml . | nindent 8 }}
{{- end }}
spec:
{{- with .Values.imagePullSecrets }}
imagePullSecrets:
{{- toYaml . | nindent 8 }}
{{- end }}
securityContext:
{{- toYaml .Values.podSecurityContext | nindent 8 }}
initContainers:
- name: devbox-frontend-init
image: {{ .Values.image | quote }}
imagePullPolicy: {{ .Values.imagePullPolicy }}
env:
- name: DATABASE_URL
value: {{ .Values.devboxConfig.databaseUrl | quote }}
- name: DATABASE_PROVIDER
value: {{ .Values.devboxConfig.databaseProvider | quote }}
command:
- sh
- -c
args:
- |-
cd /app/providers/devbox
DB_PROVIDER="${DATABASE_PROVIDER:-cockroachdb}"
SCHEMA_PATH="./prisma/cockroach/schema.prisma"
if [ "$DB_PROVIDER" = "postgresql" ] || [ "$DB_PROVIDER" = "postgres" ] || [ "$DB_PROVIDER" = "pg" ]; then
SCHEMA_PATH="./prisma/postgresql/schema.prisma"
HAS_UUID_FN=$(psql "$DATABASE_URL" -tAc "SELECT 1 FROM pg_proc WHERE proname='gen_random_uuid' LIMIT 1;")
if [ "$HAS_UUID_FN" != "1" ]; then
psql "$DATABASE_URL" -v ON_ERROR_STOP=1 -c 'CREATE OR REPLACE FUNCTION public.gen_random_uuid() RETURNS uuid LANGUAGE SQL VOLATILE AS $func$ SELECT md5(random()::text || clock_timestamp()::text || txid_current()::text)::uuid; $func$;'
fi
MIGRATION="20260125094114_add_template_repository_kind"
HAS_MIGRATION=$(psql "$DATABASE_URL" -tAc "SELECT 1 FROM _prisma_migrations WHERE migration_name='${MIGRATION}' AND rolled_back_at IS NULL LIMIT 1;")
if [ "$HAS_MIGRATION" = "1" ]; then
prisma migrate deploy --schema "$SCHEMA_PATH"
exit 0
fi
HAS_ENUM=$(psql "$DATABASE_URL" -tAc "SELECT 1 FROM pg_enum e JOIN pg_type t ON t.oid = e.enumtypid WHERE t.typname IN ('TemplateRepositoryKind','template_repository_kind') AND e.enumlabel = 'SERVICE' LIMIT 1;")
if [ "$HAS_ENUM" = "1" ]; then
prisma migrate resolve --schema "$SCHEMA_PATH" --applied "$MIGRATION"
fi
fi
prisma migrate deploy --schema "$SCHEMA_PATH"
containers:
- name: {{ .Chart.Name }}
image: {{ .Values.image | quote }}
imagePullPolicy: {{ .Values.imagePullPolicy }}
{{- if .Values.securityContext }}
securityContext:
{{- toYaml .Values.securityContext | nindent 12 }}
{{- end }}
resources:
{{- toYaml .Values.resources | nindent 12 }}
env:
- name: NODE_TLS_REJECT_UNAUTHORIZED
value: {{ .Values.devboxConfig.tlsRejectUnauthorized | quote }}
- name: DOCUMENT_URL_ZH
value: {{ .Values.devboxConfig.documentUrlZh | quote }}
- name: DOCUMENT_URL_EN
value: {{ .Values.devboxConfig.documentUrlEn | quote }}
- name: PRIVACY_URL_ZH
value: {{ .Values.devboxConfig.privacyUrlZh | quote }}
- name: PRIVACY_URL_EN
value: {{ .Values.devboxConfig.privacyUrlEn | quote }}
- name: SEALOS_DOMAIN
value: {{ .Values.devboxConfig.cloudDomain | quote }}
- name: SSH_DOMAIN
value: {{ .Values.devboxConfig.sshDomain | quote }}
- name: INGRESS_SECRET
value: {{ .Values.devboxConfig.certSecretName | quote }}
- name: REGISTRY_ADDR
value: {{ .Values.devboxConfig.registryAddr | quote }}
- name: DEVBOX_AFFINITY_ENABLE
value: {{ "true" | quote }}
- name: MONITOR_URL
value: {{ .Values.devboxConfig.monitorUrl | quote }}
- name: ACCOUNT_URL
value: {{ .Values.devboxConfig.accountUrl | quote }}
- name: ROOT_RUNTIME_NAMESPACE
value: {{ .Values.devboxConfig.rootRuntimeNamespace | quote }}
- name: INGRESS_DOMAIN
value: {{ .Values.devboxConfig.cloudDomain | quote }}
- name: CURRENCY_SYMBOL
value: {{ .Values.devboxConfig.currencySymbol | quote }}
- name: GPU_ENABLE
value: {{ .Values.devboxConfig.gpuEnable | quote }}
- name: STORAGE_LIMIT
value: {{ .Values.devboxConfig.storageLimit | quote }}
- name: DEVBOX_RUNTIME_CLASS_NAME
value: {{ .Values.devboxConfig.runtimeClassName | quote }}
- name: RETAG_SVC_URL
value: {{ .Values.devboxConfig.retagSvcUrl | quote }}
- name: JWT_SECRET
value: {{ .Values.devboxConfig.jwtSecret | quote }}
- name: REGION_UID
value: {{ .Values.devboxConfig.regionUid | quote }}
- name: DATABASE_URL
value: {{ .Values.devboxConfig.databaseUrl | quote }}
- name: DATABASE_PROVIDER
value: {{ .Values.devboxConfig.databaseProvider | quote }}
- name: ENABLE_IMPORT_FEATURE
value: {{ .Values.devboxConfig.enableImportFeature | quote }}
- name: ENABLE_WEBIDE_FEATURE
value: {{ .Values.devboxConfig.enableWebideFeature | quote }}
- name: ENABLE_ADVANCED_CONFIG
value: {{ .Values.devboxConfig.enableAdvancedConfig | quote }}
- name: CPU_SLIDE_MARK_LIST
value: {{ .Values.devboxConfig.cpuSlideMarkList | quote }}
- name: MEMORY_SLIDE_MARK_LIST
value: {{ .Values.devboxConfig.memorySlideMarkList | quote }}
- name: DEVBOX_DOMAIN_CHALLENGE_SECRET
value: {{ .Values.devboxConfig.devboxDomainChallengeSecret | quote }}
- name: NFS_STORAGE_CLASS_NAME
value: {{ .Values.devboxConfig.nfsStorageClassName | quote }}
- name: CUSTOM_SCRIPTS
value: {{ .Values.devboxConfig.customScripts | quote }}
ports:
- name: http
containerPort: {{ .Values.service.port }}
protocol: TCP
volumeMounts:
- name: devbox-frontend-volume
mountPath: /config.yaml
subPath: config.yaml
{{- with .Values.affinity }}
affinity:
{{- toYaml . | nindent 8 }}
{{- end }}
volumes:
- name: devbox-frontend-volume
configMap:
name: {{ include "devbox-frontend.fullname" . }}-config
@@ -0,0 +1,43 @@
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: {{ include "devbox-frontend.fullname" . }}
namespace: {{ .Release.Namespace }}
annotations:
kubernetes.io/ingress.class: {{ .Values.ingress.className | quote }}
nginx.ingress.kubernetes.io/enable-cors: "true"
nginx.ingress.kubernetes.io/cors-allow-methods: "PUT, GET, POST, DELETE, PATCH, OPTIONS"
nginx.ingress.kubernetes.io/cors-allow-origin: "{{ include "devbox-frontend.cloudOrigin" . }}, {{ include "devbox-frontend.wildcardCloudOrigin" . }}"
nginx.ingress.kubernetes.io/cors-allow-credentials: "true"
nginx.ingress.kubernetes.io/cors-max-age: "600"
nginx.ingress.kubernetes.io/backend-protocol: "HTTP"
nginx.ingress.kubernetes.io/configuration-snippet: |
more_clear_headers "X-Frame-Options:";
more_set_headers "Content-Security-Policy: default-src * blob: data: *.{{ .Values.devboxConfig.cloudDomain }}{{ include "devbox-frontend.portSuffix" . }} {{ .Values.devboxConfig.cloudDomain }}{{ include "devbox-frontend.portSuffix" . }}; img-src * data: blob: resource: *.{{ .Values.devboxConfig.cloudDomain }}{{ include "devbox-frontend.portSuffix" . }} {{ .Values.devboxConfig.cloudDomain }}{{ include "devbox-frontend.portSuffix" . }}; connect-src * wss: blob: resource:; style-src 'self' 'unsafe-inline' blob: *.{{ .Values.devboxConfig.cloudDomain }}{{ include "devbox-frontend.portSuffix" . }} {{ .Values.devboxConfig.cloudDomain }}{{ include "devbox-frontend.portSuffix" . }} resource:; script-src 'self' 'unsafe-inline' 'unsafe-eval' blob: *.{{ .Values.devboxConfig.cloudDomain }}{{ include "devbox-frontend.portSuffix" . }} {{ .Values.devboxConfig.cloudDomain }}{{ include "devbox-frontend.portSuffix" . }} resource: *.baidu.com *.bdstatic.com https://js.stripe.com; frame-src 'self' *.{{ .Values.devboxConfig.cloudDomain }}{{ include "devbox-frontend.portSuffix" . }} {{ .Values.devboxConfig.cloudDomain }}{{ include "devbox-frontend.portSuffix" . }} mailto: tel: weixin: mtt: *.baidu.com https://js.stripe.com; frame-ancestors 'self' {{ include "devbox-frontend.cloudOrigin" . }} {{ include "devbox-frontend.wildcardCloudOrigin" . }}";
more_set_headers "X-Xss-Protection: 1; mode=block";
higress.io/response-header-control-remove: X-Frame-Options
higress.io/response-header-control-update: |
Content-Security-Policy "default-src * blob: data: *.{{ .Values.devboxConfig.cloudDomain }}{{ include "devbox-frontend.portSuffix" . }} {{ .Values.devboxConfig.cloudDomain }}{{ include "devbox-frontend.portSuffix" . }}; img-src * data: blob: resource: *.{{ .Values.devboxConfig.cloudDomain }}{{ include "devbox-frontend.portSuffix" . }} {{ .Values.devboxConfig.cloudDomain }}{{ include "devbox-frontend.portSuffix" . }}; connect-src * wss: blob: resource:; style-src 'self' 'unsafe-inline' blob: *.{{ .Values.devboxConfig.cloudDomain }}{{ include "devbox-frontend.portSuffix" . }} {{ .Values.devboxConfig.cloudDomain }}{{ include "devbox-frontend.portSuffix" . }} resource:; script-src 'self' 'unsafe-inline' 'unsafe-eval' blob: *.{{ .Values.devboxConfig.cloudDomain }}{{ include "devbox-frontend.portSuffix" . }} {{ .Values.devboxConfig.cloudDomain }}{{ include "devbox-frontend.portSuffix" . }} resource: *.baidu.com *.bdstatic.com https://js.stripe.com; frame-src 'self' *.{{ .Values.devboxConfig.cloudDomain }}{{ include "devbox-frontend.portSuffix" . }} {{ .Values.devboxConfig.cloudDomain }}{{ include "devbox-frontend.portSuffix" . }} mailto: tel: weixin: mtt: *.baidu.com https://js.stripe.com; frame-ancestors 'self' {{ include "devbox-frontend.cloudOrigin" . }} {{ include "devbox-frontend.wildcardCloudOrigin" . }}"
X-Xss-Protection "1; mode=block"
{{- with .Values.ingress.annotations }}
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
ingressClassName: {{ .Values.ingress.className | quote }}
rules:
- host: {{ include "devbox-frontend.host" . | quote }}
http:
paths:
- pathType: Prefix
path: /
backend:
service:
name: {{ include "devbox-frontend.fullname" . }}
port:
number: {{ .Values.service.port }}
{{- if not (eq (toString .Values.devboxConfig.disableHttps) "true") }}
tls:
- hosts:
- {{ include "devbox-frontend.host" . | quote }}
secretName: {{ .Values.devboxConfig.certSecretName | quote }}
{{- end }}
@@ -0,0 +1,16 @@
apiVersion: v1
kind: Service
metadata:
labels:
{{- include "devbox-frontend.labels" . | nindent 4 }}
name: {{ include "devbox-frontend.fullname" . }}
namespace: {{ .Release.Namespace }}
spec:
type: {{ .Values.service.type }}
ports:
- name: http
port: {{ .Values.service.port }}
protocol: TCP
targetPort: {{ .Values.service.port }}
selector:
{{- include "devbox-frontend.selectorLabels" . | nindent 4 }}
@@ -0,0 +1,88 @@
# Default values for devbox-frontend helm chart.
image: ghcr.io/labring/sealos-devbox-frontend:latest
imagePullPolicy: Always
imagePullSecrets: []
fullnameOverride: "devbox-frontend"
replicaCount: 1
podAnnotations: {}
podLabels: {}
podSecurityContext:
runAsNonRoot: true
runAsUser: 1001
securityContext:
runAsNonRoot: true
runAsUser: 1001
allowPrivilegeEscalation: false
capabilities:
drop:
- "ALL"
service:
type: ClusterIP
port: 3000
ingress:
className: nginx
host: ""
annotations: {}
devboxConfig:
cloudDomain: "127.0.0.1.nip.io"
cloudPort: ""
httpPort: ""
disableHttps: false
certSecretName: "wildcard-cert"
databaseUrl: ""
databaseProvider: "cockroachdb"
tlsRejectUnauthorized: "1"
sshDomain: ""
registryAddr: "sealos.hub:5000"
monitorUrl: "http://launchpad-monitor.sealos.svc.cluster.local:8428"
accountUrl: "http://account-service.account-system.svc.cluster.local:2333"
rootRuntimeNamespace: "devbox-system"
currencySymbol: "usd"
gpuEnable: false
storageLimit: "10Gi"
runtimeClassName: "devbox-runtime"
retagSvcUrl: "http://devbox-service.devbox-system.svc.cluster.local:8092"
jwtSecret: ""
regionUid: ""
enableImportFeature: false
enableWebideFeature: false
enableAdvancedConfig: false
cpuSlideMarkList: "1,2,4,8,16"
memorySlideMarkList: "2,4,8,16,32"
devboxDomainChallengeSecret: "default-dev-secret-change-in-production"
nfsStorageClassName: "nfs-csi"
customScripts: "[]"
documentUrlZh: "https://sealos.run/docs/overview/intro"
documentUrlEn: "https://sealos.io/docs/overview/intro"
privacyUrlZh: "https://sealos.run/docs/msa/privacy-policy"
privacyUrlEn: "https://sealos.io/docs/msa/privacy-policy"
resources:
limits:
cpu: 2000m
memory: 2048Mi
requests:
cpu: 100m
memory: 128Mi
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchExpressions:
- key: "app"
operator: In
values:
- devbox-frontend
topologyKey: "kubernetes.io/hostname"
@@ -0,0 +1,117 @@
#!/bin/bash
set -e
RELEASE_NAME=${RELEASE_NAME:-"devbox-frontend"}
RELEASE_NAMESPACE=${RELEASE_NAMESPACE:-"devbox-frontend"}
CHART_PATH=${CHART_PATH:-"./charts/devbox-frontend"}
HELM_OPTS=${HELM_OPTS:-""}
HELM_OPTIONS=${HELM_OPTIONS:-""}
AUTO_CONFIG_HELM_OPTS=""
get_cm_value() {
local namespace="$1"
local name="$2"
local key="$3"
kubectl get configmap "${name}" -n "${namespace}" -o "jsonpath={.data.${key}}" 2>/dev/null || true
}
add_set_string() {
local key="$1"
local value="$2"
if [ -n "${value}" ]; then
AUTO_CONFIG_HELM_OPTS="${AUTO_CONFIG_HELM_OPTS} --set-string ${key}=${value}"
fi
}
SEALOS_CLOUD_DOMAIN=${SEALOS_CLOUD_DOMAIN:-"${cloudDomain:-$(get_cm_value sealos-system sealos-config cloudDomain)}"}
add_set_string devboxConfig.cloudDomain "${SEALOS_CLOUD_DOMAIN}"
SEALOS_CLOUD_PORT=${SEALOS_CLOUD_PORT:-"${cloudPort:-$(get_cm_value sealos-system sealos-config cloudPort)}"}
add_set_string devboxConfig.cloudPort "${SEALOS_CLOUD_PORT}"
SEALOS_HTTP_PORT=${SEALOS_HTTP_PORT:-"${httpPort:-$(get_cm_value sealos-system sealos-config httpPort)}"}
add_set_string devboxConfig.httpPort "${SEALOS_HTTP_PORT}"
SEALOS_DISABLE_HTTPS=${SEALOS_DISABLE_HTTPS:-"${disableHttps:-$(get_cm_value sealos-system sealos-config disableHttps)}"}
add_set_string devboxConfig.disableHttps "${SEALOS_DISABLE_HTTPS}"
SEALOS_CERT_SECRET_NAME=${SEALOS_CERT_SECRET_NAME:-"${certSecretName:-$(get_cm_value sealos-system sealos-config certSecretName)}"}
add_set_string devboxConfig.certSecretName "${SEALOS_CERT_SECRET_NAME}"
SEALOS_DATABASE_GLOBAL_COCKROACHDB_URI=${SEALOS_DATABASE_GLOBAL_COCKROACHDB_URI:-"${databaseGlobalCockroachdbURI:-$(get_cm_value sealos-system sealos-config databaseGlobalCockroachdbURI)}"}
add_set_string devboxConfig.databaseUrl "${SEALOS_DATABASE_GLOBAL_COCKROACHDB_URI}"
SEALOS_JWT_INTERNAL=${SEALOS_JWT_INTERNAL:-"${jwtInternal:-$(get_cm_value sealos-system sealos-config jwtInternal)}"}
add_set_string devboxConfig.jwtSecret "${SEALOS_JWT_INTERNAL}"
SEALOS_REGION_UID=${SEALOS_REGION_UID:-"${regionUid:-${regionUID:-$(get_cm_value sealos-system sealos-config regionUID)}}"}
add_set_string devboxConfig.regionUid "${SEALOS_REGION_UID}"
add_set_string devboxConfig.databaseProvider "${databaseProvider:-}"
add_set_string devboxConfig.tlsRejectUnauthorized "${tlsRejectUnauthorized:-}"
add_set_string devboxConfig.sshDomain "${sshDomain:-}"
add_set_string devboxConfig.registryAddr "${registryAddr:-}"
add_set_string devboxConfig.monitorUrl "${monitorUrl:-}"
add_set_string devboxConfig.accountUrl "${accountUrl:-}"
add_set_string devboxConfig.rootRuntimeNamespace "${rootRuntimeNamespace:-}"
add_set_string devboxConfig.currencySymbol "${currencySymbol:-}"
add_set_string devboxConfig.gpuEnable "${gpuEnable:-}"
add_set_string devboxConfig.storageLimit "${storageLimit:-}"
add_set_string devboxConfig.runtimeClassName "${runtimeClassName:-}"
add_set_string devboxConfig.retagSvcUrl "${retagSvcUrl:-}"
add_set_string devboxConfig.enableImportFeature "${enableImportFeature:-}"
add_set_string devboxConfig.enableWebideFeature "${enableWebideFeature:-}"
add_set_string devboxConfig.enableAdvancedConfig "${enableAdvancedConfig:-}"
add_set_string devboxConfig.cpuSlideMarkList "${cpuSlideMarkList:-}"
add_set_string devboxConfig.memorySlideMarkList "${memorySlideMarkList:-}"
add_set_string devboxConfig.devboxDomainChallengeSecret "${devboxDomainChallengeSecret:-}"
add_set_string devboxConfig.nfsStorageClassName "${nfsStorageClassName:-}"
add_set_string devboxConfig.customScripts "${customScripts:-}"
add_set_string devboxConfig.documentUrlZh "${documentUrlZh:-}"
add_set_string devboxConfig.documentUrlEn "${documentUrlEn:-}"
add_set_string devboxConfig.privacyUrlZh "${privacyUrlZh:-}"
add_set_string devboxConfig.privacyUrlEn "${privacyUrlEn:-}"
adopt_namespaced_resource() {
local namespace="$1"
local kind="$2"
local name="$3"
if kubectl -n "${namespace}" get "${kind}" "${name}" >/dev/null 2>&1; then
echo "Adopting ${kind} ${namespace}/${name}..."
kubectl -n "${namespace}" label "${kind}" "${name}" app.kubernetes.io/managed-by=Helm --overwrite >/dev/null 2>&1 || true
kubectl -n "${namespace}" annotate "${kind}" "${name}" meta.helm.sh/release-name="${RELEASE_NAME}" meta.helm.sh/release-namespace="${RELEASE_NAMESPACE}" --overwrite >/dev/null 2>&1 || true
fi
}
adopt_cluster_resource() {
local kind="$1"
local name="$2"
if kubectl get "${kind}" "${name}" >/dev/null 2>&1; then
echo "Adopting ${kind} ${name}..."
kubectl label "${kind}" "${name}" app.kubernetes.io/managed-by=Helm --overwrite >/dev/null 2>&1 || true
kubectl annotate "${kind}" "${name}" meta.helm.sh/release-name="${RELEASE_NAME}" meta.helm.sh/release-namespace="${RELEASE_NAMESPACE}" --overwrite >/dev/null 2>&1 || true
fi
}
echo "Checking and adopting existing resources..."
if kubectl get namespace "${RELEASE_NAMESPACE}" >/dev/null 2>&1; then
kubectl label namespace "${RELEASE_NAMESPACE}" app.kubernetes.io/managed-by=Helm --overwrite >/dev/null 2>&1 || true
kubectl annotate namespace "${RELEASE_NAMESPACE}" meta.helm.sh/release-name="${RELEASE_NAME}" meta.helm.sh/release-namespace="${RELEASE_NAMESPACE}" --overwrite >/dev/null 2>&1 || true
adopt_namespaced_resource "${RELEASE_NAMESPACE}" configmap devbox-frontend-config
adopt_namespaced_resource "${RELEASE_NAMESPACE}" service devbox-frontend
adopt_namespaced_resource "${RELEASE_NAMESPACE}" deployment devbox-frontend
adopt_namespaced_resource "${RELEASE_NAMESPACE}" ingress devbox-frontend
adopt_namespaced_resource "${RELEASE_NAMESPACE}" ingress devbox-challenge
fi
adopt_namespaced_resource app-system apps.app.sealos.io devbox
SERVICE_NAME="devbox-frontend"
USER_VALUES_PATH="/root/.sealos/cloud/values/core/${SERVICE_NAME}-values.yaml"
if [ ! -f "${USER_VALUES_PATH}" ]; then
mkdir -p "$(dirname "${USER_VALUES_PATH}")"
cp "./charts/devbox-frontend/devbox-frontend-values.yaml" "${USER_VALUES_PATH}"
fi
HELM_ARGS="${AUTO_CONFIG_HELM_OPTS} ${HELM_OPTIONS} ${HELM_OPTS}"
echo "Deploying Helm chart..."
helm upgrade -i "${RELEASE_NAME}" -n "${RELEASE_NAMESPACE}" --create-namespace "${CHART_PATH}" \
-f "./charts/devbox-frontend/values.yaml" \
-f "${USER_VALUES_PATH}" \
${HELM_ARGS}
@@ -1,189 +0,0 @@
apiVersion: v1
kind: Namespace
metadata:
labels:
app: devbox-frontend
name: devbox-frontend
---
apiVersion: v1
kind: ConfigMap
metadata:
name: devbox-frontend-config
namespace: devbox-frontend
data:
config.yaml: |-
addr: :3000
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: devbox-frontend
namespace: devbox-frontend
spec:
replicas: 1
selector:
matchLabels:
app: devbox-frontend
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 25%
maxSurge: 25%
template:
metadata:
labels:
app: devbox-frontend
spec:
initContainers:
- name: devbox-frontend-init
image: ghcr.io/labring/sealos-devbox-frontend:latest
imagePullPolicy: Always
env:
- name: DATABASE_URL
value: {{ .databaseUrl }} # -nsealos cm desktop-frontend-config ->database->global + devbox
- name: DATABASE_PROVIDER
value: "{{ default "cockroachdb" .databaseProvider }}"
command:
- sh
- -c
args:
- |-
cd /app/providers/devbox
DB_PROVIDER="${DATABASE_PROVIDER:-cockroachdb}"
SCHEMA_PATH="./prisma/cockroach/schema.prisma"
if [ "$DB_PROVIDER" = "postgresql" ] || [ "$DB_PROVIDER" = "postgres" ] || [ "$DB_PROVIDER" = "pg" ]; then
SCHEMA_PATH="./prisma/postgresql/schema.prisma"
HAS_UUID_FN=$(psql "$DATABASE_URL" -tAc "SELECT 1 FROM pg_proc WHERE proname='gen_random_uuid' LIMIT 1;")
if [ "$HAS_UUID_FN" != "1" ]; then
psql "$DATABASE_URL" -v ON_ERROR_STOP=1 -c 'CREATE OR REPLACE FUNCTION public.gen_random_uuid() RETURNS uuid LANGUAGE SQL VOLATILE AS $func$ SELECT md5(random()::text || clock_timestamp()::text || txid_current()::text)::uuid; $func$;'
fi
MIGRATION="20260125094114_add_template_repository_kind"
HAS_MIGRATION=$(psql "$DATABASE_URL" -tAc "SELECT 1 FROM _prisma_migrations WHERE migration_name='${MIGRATION}' AND rolled_back_at IS NULL LIMIT 1;")
if [ "$HAS_MIGRATION" = "1" ]; then
prisma migrate deploy --schema "$SCHEMA_PATH"
exit 0
fi
HAS_ENUM=$(psql "$DATABASE_URL" -tAc "SELECT 1 FROM pg_enum e JOIN pg_type t ON t.oid = e.enumtypid WHERE t.typname IN ('TemplateRepositoryKind','template_repository_kind') AND e.enumlabel = 'SERVICE' LIMIT 1;")
if [ "$HAS_ENUM" = "1" ]; then
prisma migrate resolve --schema "$SCHEMA_PATH" --applied "$MIGRATION"
fi
fi
prisma migrate deploy --schema "$SCHEMA_PATH"
containers:
- name: devbox-frontend
env:
- name: NODE_TLS_REJECT_UNAUTHORIZED
value: "{{ default "1" .tlsRejectUnauthorized }}"
- name: DOCUMENT_URL_ZH
value: https://sealos.run/docs/overview/intro
- name: DOCUMENT_URL_EN
value: https://sealos.io/docs/overview/intro
- name: PRIVACY_URL_ZH
value: https://sealos.run/docs/msa/privacy-policy
- name: PRIVACY_URL_EN
value: https://sealos.io/docs/msa/privacy-policy
- name: SEALOS_DOMAIN
value: {{ .cloudDomain }}
- name: SSH_DOMAIN
value: {{ default "" .sshDomain }}
- name: INGRESS_SECRET
value: wildcard-cert
- name: REGISTRY_ADDR
value: {{ .registryAddr }}
- name: DEVBOX_AFFINITY_ENABLE
value: 'true'
- name: MONITOR_URL
value: http://launchpad-monitor.sealos.svc.cluster.local:8428
- name: ACCOUNT_URL
value: http://account-service.account-system.svc.cluster.local:2333
- name: ROOT_RUNTIME_NAMESPACE
value: devbox-system
- name: INGRESS_DOMAIN
value: {{ .cloudDomain }}
- name: CURRENCY_SYMBOL
value: usd # 'shellCoin' | 'cny' | 'usd'
- name: GPU_ENABLE
value: 'false'
- name: STORAGE_LIMIT
value: 10Gi # default is 10Gi
- name: DEVBOX_RUNTIME_CLASS_NAME
value: devbox-runtime
- name: RETAG_SVC_URL
value: http://devbox-service.devbox-system.svc.cluster.local:8092
- name: JWT_SECRET
value: {{ .jwtSecret }} # -nsealos cm desktop-frontend-config ->jwt->Internal
- name: REGION_UID
value: {{ .regionUid }} # -nsealos cm desktop-frontend-config ->regionUid
- name: DATABASE_URL
value: {{ .databaseUrl }} # -nsealos cm desktop-frontend-config ->database->global + devbox
- name: DATABASE_PROVIDER
value: "{{ default "cockroachdb" .databaseProvider }}"
- name: ENABLE_IMPORT_FEATURE
value: 'false'
- name: ENABLE_WEBIDE_FEATURE
value: 'false'
- name: ENABLE_ADVANCED_CONFIG
value: 'false'
- name: CPU_SLIDE_MARK_LIST
value: '1,2,4,8,16'
- name: MEMORY_SLIDE_MARK_LIST
value: '2,4,8,16,32'
- name: DEVBOX_DOMAIN_CHALLENGE_SECRET
value: {{ .devboxDomainChallengeSecret }}
- name: NFS_STORAGE_CLASS_NAME
value: {{ default "nfs-csi" .nfsStorageClassName }}
- name: CUSTOM_SCRIPTS
value: '{{ default "[]" .customScripts }}'
securityContext:
runAsNonRoot: true
runAsUser: 1001
allowPrivilegeEscalation: false
capabilities:
drop:
- 'ALL'
resources:
limits:
cpu: 2000m
memory: 2048Mi
requests:
cpu: 100m
memory: 128Mi
# do not modify this image, it is used for CI/CD
image: ghcr.io/labring/sealos-devbox-frontend:latest
imagePullPolicy: Always
volumeMounts:
- name: devbox-frontend-volume
mountPath: /config.yaml
subPath: config.yaml
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchExpressions:
- key: 'app'
operator: In
values:
- devbox-frontend
topologyKey: 'kubernetes.io/hostname'
volumes:
- name: devbox-frontend-volume
configMap:
name: devbox-frontend-config
---
apiVersion: v1
kind: Service
metadata:
labels:
app: devbox-frontend
name: devbox-frontend
namespace: devbox-frontend
spec:
ports:
- name: http
port: 3000
protocol: TCP
targetPort: 3000
selector:
app: devbox-frontend
@@ -1,51 +0,0 @@
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/configuration-snippet: |
more_clear_headers "X-Frame-Options:";
more_set_headers "Content-Security-Policy: default-src * blob: data: *.{{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }} {{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }}; img-src * data: blob: resource: *.{{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }} {{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }}; connect-src * wss: blob: resource:; style-src 'self' 'unsafe-inline' blob: *.{{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }} {{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }} resource:; script-src 'self' 'unsafe-inline' 'unsafe-eval' blob: *.{{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }} {{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }} resource: *.baidu.com *.bdstatic.com; frame-src 'self' {{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }} mailto: tel: weixin: mtt: *.baidu.com; frame-ancestors 'self' https://{{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }} https://*.{{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }}";
more_set_headers "X-Xss-Protection: 1; mode=block";
higress.io/response-header-control-remove: X-Frame-Options
higress.io/response-header-control-update: |
Content-Security-Policy "default-src * blob: data: *.{{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }} {{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }}; img-src * data: blob: resource: *.{{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }} {{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }}; connect-src * wss: blob: resource:; style-src 'self' 'unsafe-inline' blob: *.{{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }} {{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }} resource:; script-src 'self' 'unsafe-inline' 'unsafe-eval' blob: *.{{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }} {{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }} resource: *.baidu.com *.bdstatic.com; frame-src 'self' {{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }} mailto: tel: weixin: mtt: *.baidu.com; frame-ancestors 'self' https://{{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }} https://*.{{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }}"
X-Xss-Protection "1; mode=block"
name: devbox-frontend
namespace: devbox-frontend
spec:
rules:
- host: devbox.{{ .cloudDomain }}
http:
paths:
- pathType: Prefix
path: /
backend:
service:
name: devbox-frontend
port:
number: 3000
tls:
- hosts:
- devbox.{{ .cloudDomain }}
secretName: {{ .certSecretName }} # wildcard-cert
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
kubernetes.io/ingress.class: nginx
name: devbox-challenge
namespace: devbox-frontend
spec:
rules:
- host: ""
http:
paths:
- backend:
service:
name: devbox-frontend
port:
number: 3000
path: /api/.well-known/devbox-domain-challenge
pathType: Prefix
+3 -7
View File
@@ -3,11 +3,7 @@ FROM scratch
USER 65532:65532
COPY registry registry
COPY manifests manifests
COPY charts charts
COPY invite-frontend-entrypoint.sh invite-frontend-entrypoint.sh
ENV cloudDomain="127.0.0.1.nip.io"
ENV cloudPort=""
ENV certSecretName="wildcard-cert"
ENV lafBaseUrl=""
CMD ["kubectl apply -f manifests"]
CMD ["bash invite-frontend-entrypoint.sh"]
@@ -0,0 +1,6 @@
apiVersion: v2
name: invite-frontend
description: Sealos invite Frontend Helm Chart
type: application
version: 1.0.0
appVersion: "latest"
@@ -0,0 +1,16 @@
# Custom values for invite-frontend helm chart.
# This file contains user-customizable configurations.
replicaCount: 1
resources:
limits:
cpu: 1000m
memory: 1024Mi
requests:
cpu: 10m
memory: 128Mi
inviteConfig:
lafBaseUrl: ""
giftRatio: "0.1"
@@ -0,0 +1,84 @@
{{/* Expand the name of the chart. */}}
{{- define "invite-frontend.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
{{- end }}
{{/* Create a default fully qualified app name. */}}
{{- define "invite-frontend.fullname" -}}
{{- if .Values.fullnameOverride }}
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- $name := default .Chart.Name .Values.nameOverride }}
{{- if contains $name .Release.Name }}
{{- .Release.Name | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
{{- end }}
{{- end }}
{{- end }}
{{- define "invite-frontend.chart" -}}
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
{{- end }}
{{- define "invite-frontend.labels" -}}
helm.sh/chart: {{ include "invite-frontend.chart" . }}
{{ include "invite-frontend.selectorLabels" . }}
{{ include "invite-frontend.recommendedLabels" . }}
{{- if .Chart.AppVersion }}
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
{{- end }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- end }}
{{- define "invite-frontend.selectorLabels" -}}
app: {{ include "invite-frontend.fullname" . }}
{{- end }}
{{- define "invite-frontend.recommendedLabels" -}}
app.kubernetes.io/name: {{ include "invite-frontend.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- end }}
{{- define "invite-frontend.scheme" -}}
{{- if eq (toString .Values.inviteConfig.disableHttps) "true" -}}http{{- else -}}https{{- end -}}
{{- end }}
{{- define "invite-frontend.port" -}}
{{- $scheme := include "invite-frontend.scheme" . -}}
{{- $port := toString .Values.inviteConfig.cloudPort -}}
{{- if eq $scheme "http" -}}
{{- $port = toString .Values.inviteConfig.httpPort -}}
{{- end -}}
{{- if or (and (eq $scheme "https") (or (eq $port "") (eq $port "443"))) (and (eq $scheme "http") (or (eq $port "") (eq $port "80"))) -}}
{{- "" -}}
{{- else -}}
{{- $port -}}
{{- end }}
{{- end }}
{{- define "invite-frontend.portSuffix" -}}
{{- $port := include "invite-frontend.port" . -}}
{{- if $port -}}:{{ $port }}{{- end -}}
{{- end }}
{{- define "invite-frontend.portEnv" -}}
{{- $port := include "invite-frontend.port" . -}}
{{- if $port -}}:{{ $port }}{{- end -}}
{{- end }}
{{- define "invite-frontend.cloudOrigin" -}}
{{- include "invite-frontend.scheme" . -}}://{{ .Values.inviteConfig.cloudDomain }}{{ include "invite-frontend.portSuffix" . }}
{{- end }}
{{- define "invite-frontend.wildcardCloudOrigin" -}}
{{- include "invite-frontend.scheme" . -}}://*.{{ .Values.inviteConfig.cloudDomain }}{{ include "invite-frontend.portSuffix" . }}
{{- end }}
{{- define "invite-frontend.host" -}}
{{- default (printf "invite.%s" .Values.inviteConfig.cloudDomain) .Values.ingress.host -}}
{{- end }}
{{- define "invite-frontend.appUrl" -}}
{{- include "invite-frontend.scheme" . -}}://{{ include "invite-frontend.host" . }}{{ include "invite-frontend.portSuffix" . }}
{{- end }}
@@ -6,12 +6,14 @@ metadata:
spec:
data:
desc: invite
url: "https://invite.{{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }}"
icon: "https://invite.{{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }}/logo.svg"
url: {{ include "invite-frontend.appUrl" . | quote }}
icon: {{ printf "%s/logo.svg" (include "invite-frontend.appUrl" .) | quote }}
i18n:
zh:
name: 邀请注册
zh-Hans:
name: 邀请注册
menuData:
name: invite
type: iframe
displayType: normal
i18n:
zh:
name: 邀请注册
@@ -0,0 +1,10 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ include "invite-frontend.fullname" . }}-config
namespace: {{ .Release.Namespace }}
labels:
{{- include "invite-frontend.labels" . | nindent 4 }}
data:
config.yaml: |-
addr: :3000
@@ -0,0 +1,65 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "invite-frontend.fullname" . }}
namespace: {{ .Release.Namespace }}
labels:
{{- include "invite-frontend.labels" . | nindent 4 }}
spec:
replicas: {{ .Values.replicaCount }}
selector:
matchLabels:
{{- include "invite-frontend.selectorLabels" . | nindent 6 }}
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 25%
maxSurge: 25%
template:
metadata:
labels:
{{- include "invite-frontend.labels" . | nindent 8 }}
{{- with .Values.podAnnotations }}
annotations:
{{- toYaml . | nindent 8 }}
{{- end }}
spec:
{{- with .Values.imagePullSecrets }}
imagePullSecrets:
{{- toYaml . | nindent 8 }}
{{- end }}
securityContext:
{{- toYaml .Values.podSecurityContext | nindent 8 }}
containers:
- name: {{ .Chart.Name }}
image: {{ .Values.image | quote }}
imagePullPolicy: {{ .Values.imagePullPolicy }}
{{- if .Values.securityContext }}
securityContext:
{{- toYaml .Values.securityContext | nindent 12 }}
{{- end }}
resources:
{{- toYaml .Values.resources | nindent 12 }}
env:
- name: SEALOS_DOMAIN
value: {{ .Values.inviteConfig.cloudDomain | quote }}
- name: LAF_BASE_URL
value: {{ .Values.inviteConfig.lafBaseUrl | quote }}
- name: GIFT_RATIO
value: {{ .Values.inviteConfig.giftRatio | quote }}
ports:
- name: http
containerPort: {{ .Values.service.port }}
protocol: TCP
volumeMounts:
- name: invite-frontend-volume
mountPath: /config.yaml
subPath: config.yaml
{{- with .Values.affinity }}
affinity:
{{- toYaml . | nindent 8 }}
{{- end }}
volumes:
- name: invite-frontend-volume
configMap:
name: {{ include "invite-frontend.fullname" . }}-config
@@ -0,0 +1,43 @@
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: {{ include "invite-frontend.fullname" . }}
namespace: {{ .Release.Namespace }}
annotations:
kubernetes.io/ingress.class: {{ .Values.ingress.className | quote }}
nginx.ingress.kubernetes.io/enable-cors: "true"
nginx.ingress.kubernetes.io/cors-allow-methods: "PUT, GET, POST, DELETE, PATCH, OPTIONS"
nginx.ingress.kubernetes.io/cors-allow-origin: "{{ include "invite-frontend.cloudOrigin" . }}, {{ include "invite-frontend.wildcardCloudOrigin" . }}"
nginx.ingress.kubernetes.io/cors-allow-credentials: "true"
nginx.ingress.kubernetes.io/cors-max-age: "600"
nginx.ingress.kubernetes.io/backend-protocol: "HTTP"
nginx.ingress.kubernetes.io/configuration-snippet: |
more_clear_headers "X-Frame-Options:";
more_set_headers "Content-Security-Policy: default-src * blob: data: *.{{ .Values.inviteConfig.cloudDomain }}{{ include "invite-frontend.portSuffix" . }} {{ .Values.inviteConfig.cloudDomain }}{{ include "invite-frontend.portSuffix" . }}; img-src * data: blob: resource: *.{{ .Values.inviteConfig.cloudDomain }}{{ include "invite-frontend.portSuffix" . }} {{ .Values.inviteConfig.cloudDomain }}{{ include "invite-frontend.portSuffix" . }}; connect-src * wss: blob: resource:; style-src 'self' 'unsafe-inline' blob: *.{{ .Values.inviteConfig.cloudDomain }}{{ include "invite-frontend.portSuffix" . }} {{ .Values.inviteConfig.cloudDomain }}{{ include "invite-frontend.portSuffix" . }} resource:; script-src 'self' 'unsafe-inline' 'unsafe-eval' blob: *.{{ .Values.inviteConfig.cloudDomain }}{{ include "invite-frontend.portSuffix" . }} {{ .Values.inviteConfig.cloudDomain }}{{ include "invite-frontend.portSuffix" . }} resource: *.baidu.com *.bdstatic.com https://js.stripe.com; frame-src 'self' *.{{ .Values.inviteConfig.cloudDomain }}{{ include "invite-frontend.portSuffix" . }} {{ .Values.inviteConfig.cloudDomain }}{{ include "invite-frontend.portSuffix" . }} mailto: tel: weixin: mtt: *.baidu.com https://js.stripe.com; frame-ancestors 'self' {{ include "invite-frontend.cloudOrigin" . }} {{ include "invite-frontend.wildcardCloudOrigin" . }}";
more_set_headers "X-Xss-Protection: 1; mode=block";
higress.io/response-header-control-remove: X-Frame-Options
higress.io/response-header-control-update: |
Content-Security-Policy "default-src * blob: data: *.{{ .Values.inviteConfig.cloudDomain }}{{ include "invite-frontend.portSuffix" . }} {{ .Values.inviteConfig.cloudDomain }}{{ include "invite-frontend.portSuffix" . }}; img-src * data: blob: resource: *.{{ .Values.inviteConfig.cloudDomain }}{{ include "invite-frontend.portSuffix" . }} {{ .Values.inviteConfig.cloudDomain }}{{ include "invite-frontend.portSuffix" . }}; connect-src * wss: blob: resource:; style-src 'self' 'unsafe-inline' blob: *.{{ .Values.inviteConfig.cloudDomain }}{{ include "invite-frontend.portSuffix" . }} {{ .Values.inviteConfig.cloudDomain }}{{ include "invite-frontend.portSuffix" . }} resource:; script-src 'self' 'unsafe-inline' 'unsafe-eval' blob: *.{{ .Values.inviteConfig.cloudDomain }}{{ include "invite-frontend.portSuffix" . }} {{ .Values.inviteConfig.cloudDomain }}{{ include "invite-frontend.portSuffix" . }} resource: *.baidu.com *.bdstatic.com https://js.stripe.com; frame-src 'self' *.{{ .Values.inviteConfig.cloudDomain }}{{ include "invite-frontend.portSuffix" . }} {{ .Values.inviteConfig.cloudDomain }}{{ include "invite-frontend.portSuffix" . }} mailto: tel: weixin: mtt: *.baidu.com https://js.stripe.com; frame-ancestors 'self' {{ include "invite-frontend.cloudOrigin" . }} {{ include "invite-frontend.wildcardCloudOrigin" . }}"
X-Xss-Protection "1; mode=block"
{{- with .Values.ingress.annotations }}
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
ingressClassName: {{ .Values.ingress.className | quote }}
rules:
- host: {{ include "invite-frontend.host" . | quote }}
http:
paths:
- pathType: Prefix
path: /
backend:
service:
name: {{ include "invite-frontend.fullname" . }}
port:
number: {{ .Values.service.port }}
{{- if not (eq (toString .Values.inviteConfig.disableHttps) "true") }}
tls:
- hosts:
- {{ include "invite-frontend.host" . | quote }}
secretName: {{ .Values.inviteConfig.certSecretName | quote }}
{{- end }}
@@ -0,0 +1,16 @@
apiVersion: v1
kind: Service
metadata:
labels:
{{- include "invite-frontend.labels" . | nindent 4 }}
name: {{ include "invite-frontend.fullname" . }}
namespace: {{ .Release.Namespace }}
spec:
type: {{ .Values.service.type }}
ports:
- name: http
port: {{ .Values.service.port }}
protocol: TCP
targetPort: {{ .Values.service.port }}
selector:
{{- include "invite-frontend.selectorLabels" . | nindent 4 }}
@@ -0,0 +1,52 @@
# Default values for invite-frontend helm chart.
image: ghcr.io/labring/sealos-invite-frontend:latest
imagePullPolicy: Always
imagePullSecrets: []
fullnameOverride: "invite-frontend"
replicaCount: 1
podAnnotations: {}
podLabels: {}
podSecurityContext:
runAsNonRoot: true
runAsUser: 1001
securityContext:
runAsNonRoot: true
runAsUser: 1001
allowPrivilegeEscalation: false
capabilities:
drop:
- "ALL"
service:
type: ClusterIP
port: 3000
ingress:
className: nginx
host: ""
annotations: {}
inviteConfig:
cloudDomain: "127.0.0.1.nip.io"
cloudPort: ""
httpPort: ""
disableHttps: false
certSecretName: "wildcard-cert"
lafBaseUrl: ""
giftRatio: "0.1"
resources:
limits:
cpu: 1000m
memory: 1024Mi
requests:
cpu: 10m
memory: 128Mi
affinity: {}
@@ -0,0 +1,88 @@
#!/bin/bash
set -e
RELEASE_NAME=${RELEASE_NAME:-"invite-frontend"}
RELEASE_NAMESPACE=${RELEASE_NAMESPACE:-"invite-frontend"}
CHART_PATH=${CHART_PATH:-"./charts/invite-frontend"}
HELM_OPTS=${HELM_OPTS:-""}
HELM_OPTIONS=${HELM_OPTIONS:-""}
AUTO_CONFIG_HELM_OPTS=""
get_cm_value() {
local namespace="$1"
local name="$2"
local key="$3"
kubectl get configmap "${name}" -n "${namespace}" -o "jsonpath={.data.${key}}" 2>/dev/null || true
}
add_set_string() {
local key="$1"
local value="$2"
if [ -n "${value}" ]; then
AUTO_CONFIG_HELM_OPTS="${AUTO_CONFIG_HELM_OPTS} --set-string ${key}=${value}"
fi
}
SEALOS_CLOUD_DOMAIN=${SEALOS_CLOUD_DOMAIN:-"${cloudDomain:-$(get_cm_value sealos-system sealos-config cloudDomain)}"}
add_set_string inviteConfig.cloudDomain "${SEALOS_CLOUD_DOMAIN}"
SEALOS_CLOUD_PORT=${SEALOS_CLOUD_PORT:-"${cloudPort:-$(get_cm_value sealos-system sealos-config cloudPort)}"}
add_set_string inviteConfig.cloudPort "${SEALOS_CLOUD_PORT}"
SEALOS_HTTP_PORT=${SEALOS_HTTP_PORT:-"${httpPort:-$(get_cm_value sealos-system sealos-config httpPort)}"}
add_set_string inviteConfig.httpPort "${SEALOS_HTTP_PORT}"
SEALOS_DISABLE_HTTPS=${SEALOS_DISABLE_HTTPS:-"${disableHttps:-$(get_cm_value sealos-system sealos-config disableHttps)}"}
add_set_string inviteConfig.disableHttps "${SEALOS_DISABLE_HTTPS}"
SEALOS_CERT_SECRET_NAME=${SEALOS_CERT_SECRET_NAME:-"${certSecretName:-$(get_cm_value sealos-system sealos-config certSecretName)}"}
add_set_string inviteConfig.certSecretName "${SEALOS_CERT_SECRET_NAME}"
add_set_string inviteConfig.lafBaseUrl "${lafBaseUrl:-}"
add_set_string inviteConfig.giftRatio "${giftRatio:-}"
adopt_namespaced_resource() {
local namespace="$1"
local kind="$2"
local name="$3"
if kubectl -n "${namespace}" get "${kind}" "${name}" >/dev/null 2>&1; then
echo "Adopting ${kind} ${namespace}/${name}..."
kubectl -n "${namespace}" label "${kind}" "${name}" app.kubernetes.io/managed-by=Helm --overwrite >/dev/null 2>&1 || true
kubectl -n "${namespace}" annotate "${kind}" "${name}" meta.helm.sh/release-name="${RELEASE_NAME}" meta.helm.sh/release-namespace="${RELEASE_NAMESPACE}" --overwrite >/dev/null 2>&1 || true
fi
}
adopt_cluster_resource() {
local kind="$1"
local name="$2"
if kubectl get "${kind}" "${name}" >/dev/null 2>&1; then
echo "Adopting ${kind} ${name}..."
kubectl label "${kind}" "${name}" app.kubernetes.io/managed-by=Helm --overwrite >/dev/null 2>&1 || true
kubectl annotate "${kind}" "${name}" meta.helm.sh/release-name="${RELEASE_NAME}" meta.helm.sh/release-namespace="${RELEASE_NAMESPACE}" --overwrite >/dev/null 2>&1 || true
fi
}
echo "Checking and adopting existing resources..."
if kubectl get namespace "${RELEASE_NAMESPACE}" >/dev/null 2>&1; then
kubectl label namespace "${RELEASE_NAMESPACE}" app.kubernetes.io/managed-by=Helm --overwrite >/dev/null 2>&1 || true
kubectl annotate namespace "${RELEASE_NAMESPACE}" meta.helm.sh/release-name="${RELEASE_NAME}" meta.helm.sh/release-namespace="${RELEASE_NAMESPACE}" --overwrite >/dev/null 2>&1 || true
adopt_namespaced_resource "${RELEASE_NAMESPACE}" configmap invite-frontend-config
adopt_namespaced_resource "${RELEASE_NAMESPACE}" service invite-frontend
adopt_namespaced_resource "${RELEASE_NAMESPACE}" deployment invite-frontend
adopt_namespaced_resource "${RELEASE_NAMESPACE}" ingress invite-frontend
fi
adopt_namespaced_resource app-system apps.app.sealos.io invite
SERVICE_NAME="invite-frontend"
USER_VALUES_PATH="/root/.sealos/cloud/values/core/${SERVICE_NAME}-values.yaml"
if [ ! -f "${USER_VALUES_PATH}" ]; then
mkdir -p "$(dirname "${USER_VALUES_PATH}")"
cp "./charts/invite-frontend/invite-frontend-values.yaml" "${USER_VALUES_PATH}"
fi
HELM_ARGS="${AUTO_CONFIG_HELM_OPTS} ${HELM_OPTIONS} ${HELM_OPTS}"
echo "Deploying Helm chart..."
helm upgrade -i "${RELEASE_NAME}" -n "${RELEASE_NAMESPACE}" --create-namespace "${CHART_PATH}" \
-f "./charts/invite-frontend/values.yaml" \
-f "${USER_VALUES_PATH}" \
${HELM_ARGS}
@@ -1,86 +0,0 @@
apiVersion: v1
kind: Namespace
metadata:
labels:
app: invite-frontend
name: invite-frontend
---
apiVersion: v1
kind: ConfigMap
metadata:
name: invite-frontend-config
namespace: invite-frontend
data:
config.yaml: |-
addr: :3000
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: invite-frontend
namespace: invite-frontend
spec:
replicas: 1
selector:
matchLabels:
app: invite-frontend
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 25%
maxSurge: 25%
template:
metadata:
labels:
app: invite-frontend
spec:
containers:
- name: invite-frontend
env:
- name: SEALOS_DOMAIN
value: {{ .cloudDomain }}
- name: LAF_BASE_URL
value: {{ .lafBaseUrl }}
- name: GIFT_RATIO
value: "0.1"
securityContext:
runAsNonRoot: true
runAsUser: 1001
allowPrivilegeEscalation: false
capabilities:
drop:
- 'ALL'
resources:
limits:
cpu: 1000m
memory: 1024Mi
requests:
cpu: 10m
memory: 128Mi
# do not modify this image, it is used for CI/CD
image: ghcr.io/labring/sealos-invite-frontend:latest
imagePullPolicy: Always
volumeMounts:
- name: invite-frontend-volume
mountPath: /config.yaml
subPath: config.yaml
volumes:
- name: invite-frontend-volume
configMap:
name: invite-frontend-config
---
apiVersion: v1
kind: Service
metadata:
labels:
app: invite-frontend
name: invite-frontend
namespace: invite-frontend
spec:
ports:
- name: http
port: 3000
protocol: TCP
targetPort: 3000
selector:
app: invite-frontend
@@ -1,51 +0,0 @@
# Copyright © 2023 sealos.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/enable-cors: "true"
nginx.ingress.kubernetes.io/cors-allow-methods: "PUT, GET, POST, DELETE, PATCH, OPTIONS"
nginx.ingress.kubernetes.io/cors-allow-origin: "https://{{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }}, https://*.{{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }}"
nginx.ingress.kubernetes.io/cors-allow-credentials: "true"
nginx.ingress.kubernetes.io/cors-max-age: "600"
nginx.ingress.kubernetes.io/backend-protocol: "HTTP"
nginx.ingress.kubernetes.io/configuration-snippet: |
more_clear_headers "X-Frame-Options:";
more_set_headers "Content-Security-Policy: default-src * blob: data: *.{{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }} {{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }}; img-src * data: blob: resource: *.{{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }} {{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }}; connect-src * wss: blob: resource:; style-src 'self' 'unsafe-inline' blob: *.{{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }} {{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }} resource:; script-src 'self' 'unsafe-inline' 'unsafe-eval' blob: *.{{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }} {{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }} resource: *.baidu.com *.bdstatic.com https://js.stripe.com; frame-src 'self' *.{{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }} {{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }} mailto: tel: weixin: mtt: *.baidu.com https://js.stripe.com; frame-ancestors 'self' https://{{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }} https://*.{{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }}";
more_set_headers "X-Xss-Protection: 1; mode=block";
higress.io/response-header-control-remove: X-Frame-Options
higress.io/response-header-control-update: |
Content-Security-Policy "default-src * blob: data: *.{{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }} {{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }}; img-src * data: blob: resource: *.{{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }} {{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }}; connect-src * wss: blob: resource:; style-src 'self' 'unsafe-inline' blob: *.{{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }} {{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }} resource:; script-src 'self' 'unsafe-inline' 'unsafe-eval' blob: *.{{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }} {{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }} resource: *.baidu.com *.bdstatic.com https://js.stripe.com; frame-src 'self' *.{{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }} {{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }} mailto: tel: weixin: mtt: *.baidu.com https://js.stripe.com; frame-ancestors 'self' https://{{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }} https://*.{{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }}"
X-Xss-Protection "1; mode=block"
name: invite-frontend
namespace: invite-frontend
spec:
rules:
- host: invite.{{ .cloudDomain }}
http:
paths:
- pathType: Prefix
path: /
backend:
service:
name: invite-frontend
port:
number: 3000
tls:
- hosts:
- invite.{{ .cloudDomain }}
secretName: {{ .certSecretName }}
+3 -6
View File
@@ -2,11 +2,8 @@ FROM scratch
USER 65532:65532
COPY manifests manifests
COPY registry registry
COPY charts charts
COPY kubepanel-frontend-entrypoint.sh kubepanel-frontend-entrypoint.sh
ENV cloudDomain="127.0.0.1.nip.io"
ENV cloudPort=""
ENV certSecretName="wildcard-cert"
CMD ["kubectl apply -f manifests"]
CMD ["bash kubepanel-frontend-entrypoint.sh"]
@@ -0,0 +1,6 @@
apiVersion: v2
name: kubepanel-frontend
description: Sealos Kube Panel Frontend Helm Chart
type: application
version: 1.0.0
appVersion: "latest"
@@ -0,0 +1,14 @@
# Custom values for kubepanel-frontend helm chart.
# This file contains user-customizable configurations.
replicaCount: 1
resources:
limits:
cpu: 1000m
memory: 1024Mi
requests:
cpu: 10m
memory: 128Mi
kubepanelConfig:
@@ -0,0 +1,84 @@
{{/* Expand the name of the chart. */}}
{{- define "kubepanel-frontend.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
{{- end }}
{{/* Create a default fully qualified app name. */}}
{{- define "kubepanel-frontend.fullname" -}}
{{- if .Values.fullnameOverride }}
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- $name := default .Chart.Name .Values.nameOverride }}
{{- if contains $name .Release.Name }}
{{- .Release.Name | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
{{- end }}
{{- end }}
{{- end }}
{{- define "kubepanel-frontend.chart" -}}
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
{{- end }}
{{- define "kubepanel-frontend.labels" -}}
helm.sh/chart: {{ include "kubepanel-frontend.chart" . }}
{{ include "kubepanel-frontend.selectorLabels" . }}
{{ include "kubepanel-frontend.recommendedLabels" . }}
{{- if .Chart.AppVersion }}
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
{{- end }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- end }}
{{- define "kubepanel-frontend.selectorLabels" -}}
app: {{ include "kubepanel-frontend.fullname" . }}
{{- end }}
{{- define "kubepanel-frontend.recommendedLabels" -}}
app.kubernetes.io/name: {{ include "kubepanel-frontend.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- end }}
{{- define "kubepanel-frontend.scheme" -}}
{{- if eq (toString .Values.kubepanelConfig.disableHttps) "true" -}}http{{- else -}}https{{- end -}}
{{- end }}
{{- define "kubepanel-frontend.port" -}}
{{- $scheme := include "kubepanel-frontend.scheme" . -}}
{{- $port := toString .Values.kubepanelConfig.cloudPort -}}
{{- if eq $scheme "http" -}}
{{- $port = toString .Values.kubepanelConfig.httpPort -}}
{{- end -}}
{{- if or (and (eq $scheme "https") (or (eq $port "") (eq $port "443"))) (and (eq $scheme "http") (or (eq $port "") (eq $port "80"))) -}}
{{- "" -}}
{{- else -}}
{{- $port -}}
{{- end }}
{{- end }}
{{- define "kubepanel-frontend.portSuffix" -}}
{{- $port := include "kubepanel-frontend.port" . -}}
{{- if $port -}}:{{ $port }}{{- end -}}
{{- end }}
{{- define "kubepanel-frontend.portEnv" -}}
{{- $port := include "kubepanel-frontend.port" . -}}
{{- if $port -}}:{{ $port }}{{- end -}}
{{- end }}
{{- define "kubepanel-frontend.cloudOrigin" -}}
{{- include "kubepanel-frontend.scheme" . -}}://{{ .Values.kubepanelConfig.cloudDomain }}{{ include "kubepanel-frontend.portSuffix" . }}
{{- end }}
{{- define "kubepanel-frontend.wildcardCloudOrigin" -}}
{{- include "kubepanel-frontend.scheme" . -}}://*.{{ .Values.kubepanelConfig.cloudDomain }}{{ include "kubepanel-frontend.portSuffix" . }}
{{- end }}
{{- define "kubepanel-frontend.host" -}}
{{- default (printf "kubepanel.%s" .Values.kubepanelConfig.cloudDomain) .Values.ingress.host -}}
{{- end }}
{{- define "kubepanel-frontend.appUrl" -}}
{{- include "kubepanel-frontend.scheme" . -}}://{{ include "kubepanel-frontend.host" . }}{{ include "kubepanel-frontend.portSuffix" . }}
{{- end }}
@@ -6,8 +6,8 @@ metadata:
spec:
data:
desc: Kube Panel
url: "https://kubepanel.{{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }}"
icon: "https://kubepanel.{{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }}/logo.svg"
url: {{ include "kubepanel-frontend.appUrl" . | quote }}
icon: {{ printf "%s/logo.svg" (include "kubepanel-frontend.appUrl" .) | quote }}
i18n:
zh:
name: 资源监控
@@ -0,0 +1,10 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ include "kubepanel-frontend.fullname" . }}-config
namespace: {{ .Release.Namespace }}
labels:
{{- include "kubepanel-frontend.labels" . | nindent 4 }}
data:
config.yaml: |-
addr: :3000
@@ -0,0 +1,63 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "kubepanel-frontend.fullname" . }}
namespace: {{ .Release.Namespace }}
labels:
{{- include "kubepanel-frontend.labels" . | nindent 4 }}
spec:
replicas: {{ .Values.replicaCount }}
selector:
matchLabels:
{{- include "kubepanel-frontend.selectorLabels" . | nindent 6 }}
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 25%
maxSurge: 25%
template:
metadata:
labels:
{{- include "kubepanel-frontend.labels" . | nindent 8 }}
{{- with .Values.podAnnotations }}
annotations:
{{- toYaml . | nindent 8 }}
{{- end }}
spec:
{{- with .Values.imagePullSecrets }}
imagePullSecrets:
{{- toYaml . | nindent 8 }}
{{- end }}
securityContext:
{{- toYaml .Values.podSecurityContext | nindent 8 }}
containers:
- name: {{ .Chart.Name }}
image: {{ .Values.image | quote }}
imagePullPolicy: {{ .Values.imagePullPolicy }}
{{- if .Values.securityContext }}
securityContext:
{{- toYaml .Values.securityContext | nindent 12 }}
{{- end }}
resources:
{{- toYaml .Values.resources | nindent 12 }}
env:
- name: SEALOS_DOMAIN
value: {{ .Values.kubepanelConfig.cloudDomain | quote }}
- name: SEALOS_PORT
value: {{ include "kubepanel-frontend.portEnv" . | quote }}
ports:
- name: http
containerPort: {{ .Values.service.port }}
protocol: TCP
volumeMounts:
- name: kubepanel-frontend-volume
mountPath: /config.yaml
subPath: config.yaml
{{- with .Values.affinity }}
affinity:
{{- toYaml . | nindent 8 }}
{{- end }}
volumes:
- name: kubepanel-frontend-volume
configMap:
name: {{ include "kubepanel-frontend.fullname" . }}-config
@@ -0,0 +1,43 @@
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: {{ include "kubepanel-frontend.fullname" . }}
namespace: {{ .Release.Namespace }}
annotations:
kubernetes.io/ingress.class: {{ .Values.ingress.className | quote }}
nginx.ingress.kubernetes.io/enable-cors: "true"
nginx.ingress.kubernetes.io/cors-allow-methods: "PUT, GET, POST, DELETE, PATCH, OPTIONS"
nginx.ingress.kubernetes.io/cors-allow-origin: "{{ include "kubepanel-frontend.cloudOrigin" . }}, {{ include "kubepanel-frontend.wildcardCloudOrigin" . }}"
nginx.ingress.kubernetes.io/cors-allow-credentials: "true"
nginx.ingress.kubernetes.io/cors-max-age: "600"
nginx.ingress.kubernetes.io/backend-protocol: "HTTP"
nginx.ingress.kubernetes.io/configuration-snippet: |
more_clear_headers "X-Frame-Options:";
more_set_headers "Content-Security-Policy: default-src * blob: data: *.{{ .Values.kubepanelConfig.cloudDomain }}{{ include "kubepanel-frontend.portSuffix" . }} {{ .Values.kubepanelConfig.cloudDomain }}{{ include "kubepanel-frontend.portSuffix" . }}; img-src * data: blob: resource: *.{{ .Values.kubepanelConfig.cloudDomain }}{{ include "kubepanel-frontend.portSuffix" . }} {{ .Values.kubepanelConfig.cloudDomain }}{{ include "kubepanel-frontend.portSuffix" . }}; connect-src * wss: blob: resource:; style-src 'self' 'unsafe-inline' blob: *.{{ .Values.kubepanelConfig.cloudDomain }}{{ include "kubepanel-frontend.portSuffix" . }} {{ .Values.kubepanelConfig.cloudDomain }}{{ include "kubepanel-frontend.portSuffix" . }} resource:; script-src 'self' 'unsafe-inline' 'unsafe-eval' blob: *.{{ .Values.kubepanelConfig.cloudDomain }}{{ include "kubepanel-frontend.portSuffix" . }} {{ .Values.kubepanelConfig.cloudDomain }}{{ include "kubepanel-frontend.portSuffix" . }} resource: *.baidu.com *.bdstatic.com https://js.stripe.com; frame-src 'self' *.{{ .Values.kubepanelConfig.cloudDomain }}{{ include "kubepanel-frontend.portSuffix" . }} {{ .Values.kubepanelConfig.cloudDomain }}{{ include "kubepanel-frontend.portSuffix" . }} mailto: tel: weixin: mtt: *.baidu.com https://js.stripe.com; frame-ancestors 'self' {{ include "kubepanel-frontend.cloudOrigin" . }} {{ include "kubepanel-frontend.wildcardCloudOrigin" . }}";
more_set_headers "X-Xss-Protection: 1; mode=block";
higress.io/response-header-control-remove: X-Frame-Options
higress.io/response-header-control-update: |
Content-Security-Policy "default-src * blob: data: *.{{ .Values.kubepanelConfig.cloudDomain }}{{ include "kubepanel-frontend.portSuffix" . }} {{ .Values.kubepanelConfig.cloudDomain }}{{ include "kubepanel-frontend.portSuffix" . }}; img-src * data: blob: resource: *.{{ .Values.kubepanelConfig.cloudDomain }}{{ include "kubepanel-frontend.portSuffix" . }} {{ .Values.kubepanelConfig.cloudDomain }}{{ include "kubepanel-frontend.portSuffix" . }}; connect-src * wss: blob: resource:; style-src 'self' 'unsafe-inline' blob: *.{{ .Values.kubepanelConfig.cloudDomain }}{{ include "kubepanel-frontend.portSuffix" . }} {{ .Values.kubepanelConfig.cloudDomain }}{{ include "kubepanel-frontend.portSuffix" . }} resource:; script-src 'self' 'unsafe-inline' 'unsafe-eval' blob: *.{{ .Values.kubepanelConfig.cloudDomain }}{{ include "kubepanel-frontend.portSuffix" . }} {{ .Values.kubepanelConfig.cloudDomain }}{{ include "kubepanel-frontend.portSuffix" . }} resource: *.baidu.com *.bdstatic.com https://js.stripe.com; frame-src 'self' *.{{ .Values.kubepanelConfig.cloudDomain }}{{ include "kubepanel-frontend.portSuffix" . }} {{ .Values.kubepanelConfig.cloudDomain }}{{ include "kubepanel-frontend.portSuffix" . }} mailto: tel: weixin: mtt: *.baidu.com https://js.stripe.com; frame-ancestors 'self' {{ include "kubepanel-frontend.cloudOrigin" . }} {{ include "kubepanel-frontend.wildcardCloudOrigin" . }}"
X-Xss-Protection "1; mode=block"
{{- with .Values.ingress.annotations }}
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
ingressClassName: {{ .Values.ingress.className | quote }}
rules:
- host: {{ include "kubepanel-frontend.host" . | quote }}
http:
paths:
- pathType: Prefix
path: /
backend:
service:
name: {{ include "kubepanel-frontend.fullname" . }}
port:
number: {{ .Values.service.port }}
{{- if not (eq (toString .Values.kubepanelConfig.disableHttps) "true") }}
tls:
- hosts:
- {{ include "kubepanel-frontend.host" . | quote }}
secretName: {{ .Values.kubepanelConfig.certSecretName | quote }}
{{- end }}
@@ -0,0 +1,16 @@
apiVersion: v1
kind: Service
metadata:
labels:
{{- include "kubepanel-frontend.labels" . | nindent 4 }}
name: {{ include "kubepanel-frontend.fullname" . }}
namespace: {{ .Release.Namespace }}
spec:
type: {{ .Values.service.type }}
ports:
- name: http
port: {{ .Values.service.port }}
protocol: TCP
targetPort: {{ .Values.service.port }}
selector:
{{- include "kubepanel-frontend.selectorLabels" . | nindent 4 }}
@@ -0,0 +1,61 @@
# Default values for kubepanel-frontend helm chart.
image: ghcr.io/labring/sealos-kubepanel-frontend:latest
imagePullPolicy: Always
imagePullSecrets: []
fullnameOverride: "kubepanel-frontend"
replicaCount: 1
podAnnotations: {}
podLabels: {}
podSecurityContext:
runAsNonRoot: true
runAsUser: 1001
securityContext:
runAsNonRoot: true
runAsUser: 1001
allowPrivilegeEscalation: false
capabilities:
drop:
- "ALL"
service:
type: ClusterIP
port: 3000
ingress:
className: nginx
host: ""
annotations: {}
kubepanelConfig:
cloudDomain: "127.0.0.1.nip.io"
cloudPort: ""
httpPort: ""
disableHttps: false
certSecretName: "wildcard-cert"
resources:
limits:
cpu: 1000m
memory: 1024Mi
requests:
cpu: 10m
memory: 128Mi
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchExpressions:
- key: "app"
operator: In
values:
- kubepanel-frontend
topologyKey: "kubernetes.io/hostname"
@@ -0,0 +1,87 @@
#!/bin/bash
set -e
RELEASE_NAME=${RELEASE_NAME:-"kubepanel-frontend"}
RELEASE_NAMESPACE=${RELEASE_NAMESPACE:-"kubepanel-frontend"}
CHART_PATH=${CHART_PATH:-"./charts/kubepanel-frontend"}
HELM_OPTS=${HELM_OPTS:-""}
HELM_OPTIONS=${HELM_OPTIONS:-""}
AUTO_CONFIG_HELM_OPTS=""
get_cm_value() {
local namespace="$1"
local name="$2"
local key="$3"
kubectl get configmap "${name}" -n "${namespace}" -o "jsonpath={.data.${key}}" 2>/dev/null || true
}
add_set_string() {
local key="$1"
local value="$2"
if [ -n "${value}" ]; then
AUTO_CONFIG_HELM_OPTS="${AUTO_CONFIG_HELM_OPTS} --set-string ${key}=${value}"
fi
}
SEALOS_CLOUD_DOMAIN=${SEALOS_CLOUD_DOMAIN:-"${cloudDomain:-$(get_cm_value sealos-system sealos-config cloudDomain)}"}
add_set_string kubepanelConfig.cloudDomain "${SEALOS_CLOUD_DOMAIN}"
SEALOS_CLOUD_PORT=${SEALOS_CLOUD_PORT:-"${cloudPort:-$(get_cm_value sealos-system sealos-config cloudPort)}"}
add_set_string kubepanelConfig.cloudPort "${SEALOS_CLOUD_PORT}"
SEALOS_HTTP_PORT=${SEALOS_HTTP_PORT:-"${httpPort:-$(get_cm_value sealos-system sealos-config httpPort)}"}
add_set_string kubepanelConfig.httpPort "${SEALOS_HTTP_PORT}"
SEALOS_DISABLE_HTTPS=${SEALOS_DISABLE_HTTPS:-"${disableHttps:-$(get_cm_value sealos-system sealos-config disableHttps)}"}
add_set_string kubepanelConfig.disableHttps "${SEALOS_DISABLE_HTTPS}"
SEALOS_CERT_SECRET_NAME=${SEALOS_CERT_SECRET_NAME:-"${certSecretName:-$(get_cm_value sealos-system sealos-config certSecretName)}"}
add_set_string kubepanelConfig.certSecretName "${SEALOS_CERT_SECRET_NAME}"
adopt_namespaced_resource() {
local namespace="$1"
local kind="$2"
local name="$3"
if kubectl -n "${namespace}" get "${kind}" "${name}" >/dev/null 2>&1; then
echo "Adopting ${kind} ${namespace}/${name}..."
kubectl -n "${namespace}" label "${kind}" "${name}" app.kubernetes.io/managed-by=Helm --overwrite >/dev/null 2>&1 || true
kubectl -n "${namespace}" annotate "${kind}" "${name}" meta.helm.sh/release-name="${RELEASE_NAME}" meta.helm.sh/release-namespace="${RELEASE_NAMESPACE}" --overwrite >/dev/null 2>&1 || true
fi
}
adopt_cluster_resource() {
local kind="$1"
local name="$2"
if kubectl get "${kind}" "${name}" >/dev/null 2>&1; then
echo "Adopting ${kind} ${name}..."
kubectl label "${kind}" "${name}" app.kubernetes.io/managed-by=Helm --overwrite >/dev/null 2>&1 || true
kubectl annotate "${kind}" "${name}" meta.helm.sh/release-name="${RELEASE_NAME}" meta.helm.sh/release-namespace="${RELEASE_NAMESPACE}" --overwrite >/dev/null 2>&1 || true
fi
}
echo "Checking and adopting existing resources..."
if kubectl get namespace "${RELEASE_NAMESPACE}" >/dev/null 2>&1; then
kubectl label namespace "${RELEASE_NAMESPACE}" app.kubernetes.io/managed-by=Helm --overwrite >/dev/null 2>&1 || true
kubectl annotate namespace "${RELEASE_NAMESPACE}" meta.helm.sh/release-name="${RELEASE_NAME}" meta.helm.sh/release-namespace="${RELEASE_NAMESPACE}" --overwrite >/dev/null 2>&1 || true
adopt_namespaced_resource "${RELEASE_NAMESPACE}" configmap kubepanel-frontend-config
adopt_namespaced_resource "${RELEASE_NAMESPACE}" service kubepanel-frontend
adopt_namespaced_resource "${RELEASE_NAMESPACE}" deployment kubepanel-frontend
adopt_namespaced_resource "${RELEASE_NAMESPACE}" ingress kubepanel-frontend
fi
adopt_namespaced_resource app-system apps.app.sealos.io kubepanel
SERVICE_NAME="kubepanel-frontend"
USER_VALUES_PATH="/root/.sealos/cloud/values/core/${SERVICE_NAME}-values.yaml"
if [ ! -f "${USER_VALUES_PATH}" ]; then
mkdir -p "$(dirname "${USER_VALUES_PATH}")"
cp "./charts/kubepanel-frontend/kubepanel-frontend-values.yaml" "${USER_VALUES_PATH}"
fi
HELM_ARGS="${AUTO_CONFIG_HELM_OPTS} ${HELM_OPTIONS} ${HELM_OPTS}"
echo "Deploying Helm chart..."
helm upgrade -i "${RELEASE_NAME}" -n "${RELEASE_NAMESPACE}" --create-namespace "${CHART_PATH}" \
-f "./charts/kubepanel-frontend/values.yaml" \
-f "${USER_VALUES_PATH}" \
${HELM_ARGS}
@@ -1,96 +0,0 @@
apiVersion: v1
kind: Namespace
metadata:
labels:
app: kubepanel-frontend
name: kubepanel-frontend
---
apiVersion: v1
kind: ConfigMap
metadata:
name: kubepanel-frontend-config
namespace: kubepanel-frontend
data:
config.yaml: |-
addr: :3000
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: kubepanel-frontend
namespace: kubepanel-frontend
spec:
replicas: 1
selector:
matchLabels:
app: kubepanel-frontend
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 25%
maxSurge: 25%
template:
metadata:
labels:
app: kubepanel-frontend
spec:
containers:
- name: kubepanel-frontend
env:
- name: SEALOS_DOMAIN
value: {{ .cloudDomain }}
- name: SEALOS_PORT
value: "{{ if .cloudPort }}:{{ .cloudPort }}{{ end }}"
securityContext:
runAsNonRoot: true
runAsUser: 1001
allowPrivilegeEscalation: false
capabilities:
drop:
- 'ALL'
resources:
limits:
cpu: 1000m
memory: 1024Mi
requests:
cpu: 10m
memory: 128Mi
# do not modify this image, it is used for CI/CD
image: ghcr.io/labring/sealos-kubepanel-frontend:latest
imagePullPolicy: Always
volumeMounts:
- name: kubepanel-frontend-volume
mountPath: /config.yaml
subPath: config.yaml
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchExpressions:
- key: "app"
operator: In
values:
- kubepanel-frontend
topologyKey: "kubernetes.io/hostname"
volumes:
- name: kubepanel-frontend-volume
configMap:
name: kubepanel-frontend-config
---
apiVersion: v1
kind: Service
metadata:
labels:
app: kubepanel-frontend
name: kubepanel-frontend
namespace: kubepanel-frontend
spec:
ports:
- name: http
port: 3000
protocol: TCP
targetPort: 3000
selector:
app: kubepanel-frontend
@@ -1,45 +0,0 @@
# Copyright © 2022 sealos.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/configuration-snippet: |
more_clear_headers "X-Frame-Options:";
more_set_headers "Content-Security-Policy: default-src * blob: data: *.{{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }} {{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }}; img-src * data: blob: resource: *.{{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }} {{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }}; connect-src * wss: blob: resource:; style-src 'self' 'unsafe-inline' blob: *.{{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }} {{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }} resource:; script-src 'self' 'unsafe-inline' 'unsafe-eval' blob: *.{{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }} {{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }} resource: *.baidu.com *.bdstatic.com; frame-src 'self' *.{{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }} {{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }} mailto: tel: weixin: mtt: *.baidu.com; frame-ancestors 'self' https://{{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }} https://*.{{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }}";
more_set_headers "X-Xss-Protection: 1; mode=block";
higress.io/response-header-control-remove: X-Frame-Options
higress.io/response-header-control-update: |
Content-Security-Policy "default-src * blob: data: *.{{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }} {{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }}; img-src * data: blob: resource: *.{{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }} {{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }}; connect-src * wss: blob: resource:; style-src 'self' 'unsafe-inline' blob: *.{{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }} {{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }} resource:; script-src 'self' 'unsafe-inline' 'unsafe-eval' blob: *.{{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }} {{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }} resource: *.baidu.com *.bdstatic.com; frame-src 'self' *.{{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }} {{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }} mailto: tel: weixin: mtt: *.baidu.com; frame-ancestors 'self' https://{{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }} https://*.{{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }}"
X-Xss-Protection "1; mode=block"
name: kubepanel-frontend
namespace: kubepanel-frontend
spec:
rules:
- host: kubepanel.{{ .cloudDomain }}
http:
paths:
- pathType: Prefix
path: /
backend:
service:
name: kubepanel-frontend
port:
number: 3000
tls:
- hosts:
- kubepanel.{{ .cloudDomain }}
secretName: {{ .certSecretName }}
@@ -3,9 +3,7 @@ FROM scratch
USER 65532:65532
COPY registry registry
COPY manifests manifests
COPY charts charts
COPY object-storage-frontend-entrypoint.sh object-storage-frontend-entrypoint.sh
ENV cloudDomain=${cloudDomain:-"127.0.0.1.nip.io"}
ENV cloudPort=${cloudPort:-"443"}
CMD ["kubectl apply -f manifests/deploy.yaml"]
CMD ["bash object-storage-frontend-entrypoint.sh"]
@@ -0,0 +1,6 @@
apiVersion: v2
name: objectstorage-frontend
description: Sealos Object Storage Frontend Helm Chart
type: application
version: 1.0.0
appVersion: "latest"
@@ -0,0 +1,24 @@
# Custom values for objectstorage-frontend helm chart.
# This file contains user-customizable configurations.
replicaCount: 1
resources:
limits:
cpu: 2000m
memory: 2048Mi
requests:
cpu: 10m
memory: 128Mi
objectstorageConfig:
monitorUrl: "http://object-storage-monitor.objectstorage-system.svc.cluster.local:9090/q"
billingUrl: ""
billingSecret: ""
appLaunchpadUrl: "http://applaunchpad-frontend.applaunchpad-frontend.svc.cluster.local:3000/api/v1alpha"
appTokenJwtKey: ""
hostingPodCpuMilliCores: 200
hostingPodMemoryMiB: 128
hostingAppNamePrefix: "static-host"
hostingNetworkProtocol: "HTTP"
hostingNetworkPort: 80
@@ -0,0 +1,84 @@
{{/* Expand the name of the chart. */}}
{{- define "objectstorage-frontend.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
{{- end }}
{{/* Create a default fully qualified app name. */}}
{{- define "objectstorage-frontend.fullname" -}}
{{- if .Values.fullnameOverride }}
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- $name := default .Chart.Name .Values.nameOverride }}
{{- if contains $name .Release.Name }}
{{- .Release.Name | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
{{- end }}
{{- end }}
{{- end }}
{{- define "objectstorage-frontend.chart" -}}
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
{{- end }}
{{- define "objectstorage-frontend.labels" -}}
helm.sh/chart: {{ include "objectstorage-frontend.chart" . }}
{{ include "objectstorage-frontend.selectorLabels" . }}
{{ include "objectstorage-frontend.recommendedLabels" . }}
{{- if .Chart.AppVersion }}
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
{{- end }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- end }}
{{- define "objectstorage-frontend.selectorLabels" -}}
app: {{ include "objectstorage-frontend.fullname" . }}
{{- end }}
{{- define "objectstorage-frontend.recommendedLabels" -}}
app.kubernetes.io/name: {{ include "objectstorage-frontend.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- end }}
{{- define "objectstorage-frontend.scheme" -}}
{{- if eq (toString .Values.objectstorageConfig.disableHttps) "true" -}}http{{- else -}}https{{- end -}}
{{- end }}
{{- define "objectstorage-frontend.port" -}}
{{- $scheme := include "objectstorage-frontend.scheme" . -}}
{{- $port := toString .Values.objectstorageConfig.cloudPort -}}
{{- if eq $scheme "http" -}}
{{- $port = toString .Values.objectstorageConfig.httpPort -}}
{{- end -}}
{{- if or (and (eq $scheme "https") (or (eq $port "") (eq $port "443"))) (and (eq $scheme "http") (or (eq $port "") (eq $port "80"))) -}}
{{- "" -}}
{{- else -}}
{{- $port -}}
{{- end }}
{{- end }}
{{- define "objectstorage-frontend.portSuffix" -}}
{{- $port := include "objectstorage-frontend.port" . -}}
{{- if $port -}}:{{ $port }}{{- end -}}
{{- end }}
{{- define "objectstorage-frontend.portEnv" -}}
{{- $port := include "objectstorage-frontend.port" . -}}
{{- if $port -}}:{{ $port }}{{- end -}}
{{- end }}
{{- define "objectstorage-frontend.cloudOrigin" -}}
{{- include "objectstorage-frontend.scheme" . -}}://{{ .Values.objectstorageConfig.cloudDomain }}{{ include "objectstorage-frontend.portSuffix" . }}
{{- end }}
{{- define "objectstorage-frontend.wildcardCloudOrigin" -}}
{{- include "objectstorage-frontend.scheme" . -}}://*.{{ .Values.objectstorageConfig.cloudDomain }}{{ include "objectstorage-frontend.portSuffix" . }}
{{- end }}
{{- define "objectstorage-frontend.host" -}}
{{- default (printf "objectstorage.%s" .Values.objectstorageConfig.cloudDomain) .Values.ingress.host -}}
{{- end }}
{{- define "objectstorage-frontend.appUrl" -}}
{{- include "objectstorage-frontend.scheme" . -}}://{{ include "objectstorage-frontend.host" . }}{{ include "objectstorage-frontend.portSuffix" . }}
{{- end }}
@@ -0,0 +1,19 @@
apiVersion: app.sealos.io/v1
kind: App
metadata:
name: objectstorage
namespace: app-system
spec:
data:
desc: object storage
url: {{ include "objectstorage-frontend.appUrl" . | quote }}
icon: {{ printf "%s/logo.svg" (include "objectstorage-frontend.appUrl" .) | quote }}
i18n:
zh:
name: 对象存储
zh-Hans:
name: 对象存储
menuData:
name: Object Storage
type: iframe
displayType: normal
@@ -0,0 +1,30 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ include "objectstorage-frontend.fullname" . }}-config
namespace: {{ .Release.Namespace }}
labels:
{{- include "objectstorage-frontend.labels" . | nindent 4 }}
data:
config.yaml: |-
cloud:
domain: {{ .Values.objectstorageConfig.cloudDomain | quote }}
port: {{ default 443 .Values.objectstorageConfig.cloudPort }}
objectStorage:
resources:
hostingPodCpuMilliCores: {{ .Values.objectstorageConfig.hostingPodCpuMilliCores }}
hostingPodMemoryMiB: {{ .Values.objectstorageConfig.hostingPodMemoryMiB }}
components:
monitoring:
url: {{ .Values.objectstorageConfig.monitorUrl | quote }}
billing:
url: {{ .Values.objectstorageConfig.billingUrl | quote }}
secret: {{ .Values.objectstorageConfig.billingSecret | quote }}
appLaunchpad:
url: {{ .Values.objectstorageConfig.appLaunchpadUrl | quote }}
realName:
appTokenJwtKey: {{ .Values.objectstorageConfig.appTokenJwtKey | quote }}
hosting:
appNamePrefix: {{ .Values.objectstorageConfig.hostingAppNamePrefix | quote }}
networkProtocol: {{ .Values.objectstorageConfig.hostingNetworkProtocol | quote }}
networkPort: {{ .Values.objectstorageConfig.hostingNetworkPort }}
@@ -0,0 +1,64 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "objectstorage-frontend.fullname" . }}
namespace: {{ .Release.Namespace }}
labels:
{{- include "objectstorage-frontend.labels" . | nindent 4 }}
spec:
replicas: {{ .Values.replicaCount }}
revisionHistoryLimit: 1
selector:
matchLabels:
{{- include "objectstorage-frontend.selectorLabels" . | nindent 6 }}
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 1
maxSurge: 0
template:
metadata:
labels:
{{- include "objectstorage-frontend.labels" . | nindent 8 }}
{{- with .Values.podAnnotations }}
annotations:
{{- toYaml . | nindent 8 }}
{{- end }}
spec:
{{- with .Values.imagePullSecrets }}
imagePullSecrets:
{{- toYaml . | nindent 8 }}
{{- end }}
securityContext:
{{- toYaml .Values.podSecurityContext | nindent 8 }}
containers:
- name: {{ .Chart.Name }}
image: {{ .Values.image | quote }}
imagePullPolicy: {{ .Values.imagePullPolicy }}
{{- if .Values.securityContext }}
securityContext:
{{- toYaml .Values.securityContext | nindent 12 }}
{{- end }}
resources:
{{- toYaml .Values.resources | nindent 12 }}
env:
- name: MONITOR_URL
value: {{ .Values.objectstorageConfig.monitorUrl | quote }}
- name: APP_LAUNCHPAD_URL
value: {{ .Values.objectstorageConfig.appLaunchpadUrl | quote }}
ports:
- name: http
containerPort: {{ .Values.service.port }}
protocol: TCP
volumeMounts:
- name: object-storage-frontend-volume
mountPath: /app/data/config.yaml
subPath: config.yaml
{{- with .Values.affinity }}
affinity:
{{- toYaml . | nindent 8 }}
{{- end }}
volumes:
- name: object-storage-frontend-volume
configMap:
name: {{ include "objectstorage-frontend.fullname" . }}-config
@@ -0,0 +1,37 @@
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: {{ include "objectstorage-frontend.fullname" . }}
namespace: {{ .Release.Namespace }}
annotations:
kubernetes.io/ingress.class: {{ .Values.ingress.className | quote }}
nginx.ingress.kubernetes.io/configuration-snippet: |
if ($request_uri ~* \.(js|css|gif|jpe?g|png)) {
expires 30d;
add_header Cache-Control "public";
}
nginx.ingress.kubernetes.io/proxy-body-size: 3g
nginx.ingress.kubernetes.io/proxy-next-upstream-timeout: "180"
nginx.ingress.kubernetes.io/proxy-send-timeout: "180"
{{- with .Values.ingress.annotations }}
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
ingressClassName: {{ .Values.ingress.className | quote }}
rules:
- host: {{ include "objectstorage-frontend.host" . | quote }}
http:
paths:
- pathType: Prefix
path: /
backend:
service:
name: {{ include "objectstorage-frontend.fullname" . }}
port:
number: {{ .Values.service.port }}
{{- if not (eq (toString .Values.objectstorageConfig.disableHttps) "true") }}
tls:
- hosts:
- {{ include "objectstorage-frontend.host" . | quote }}
secretName: {{ .Values.objectstorageConfig.certSecretName | quote }}
{{- end }}
@@ -0,0 +1,16 @@
apiVersion: v1
kind: Service
metadata:
labels:
{{- include "objectstorage-frontend.labels" . | nindent 4 }}
name: {{ include "objectstorage-frontend.fullname" . }}
namespace: {{ .Release.Namespace }}
spec:
type: {{ .Values.service.type }}
ports:
- name: http
port: {{ .Values.service.port }}
protocol: TCP
targetPort: {{ .Values.service.port }}
selector:
{{- include "objectstorage-frontend.selectorLabels" . | nindent 4 }}
@@ -0,0 +1,71 @@
# Default values for objectstorage-frontend helm chart.
image: ghcr.io/labring/sealos-objectstorage-frontend:latest
imagePullPolicy: Always
imagePullSecrets: []
fullnameOverride: "object-storage-frontend"
replicaCount: 1
podAnnotations: {}
podLabels: {}
podSecurityContext:
runAsNonRoot: true
runAsUser: 1001
securityContext:
runAsNonRoot: true
runAsUser: 1001
allowPrivilegeEscalation: false
capabilities:
drop:
- "ALL"
service:
type: ClusterIP
port: 3000
ingress:
className: nginx
host: ""
annotations: {}
objectstorageConfig:
cloudDomain: "127.0.0.1.nip.io"
cloudPort: ""
httpPort: ""
disableHttps: false
certSecretName: "wildcard-cert"
monitorUrl: "http://object-storage-monitor.objectstorage-system.svc.cluster.local:9090/q"
billingUrl: ""
billingSecret: ""
appLaunchpadUrl: "http://applaunchpad-frontend.applaunchpad-frontend.svc.cluster.local:3000/api/v1alpha"
appTokenJwtKey: ""
hostingPodCpuMilliCores: 200
hostingPodMemoryMiB: 128
hostingAppNamePrefix: "static-host"
hostingNetworkProtocol: "HTTP"
hostingNetworkPort: 80
resources:
limits:
cpu: 2000m
memory: 2048Mi
requests:
cpu: 10m
memory: 128Mi
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchExpressions:
- key: "app"
operator: In
values:
- object-storage-frontend
topologyKey: "kubernetes.io/hostname"
@@ -1,128 +0,0 @@
apiVersion: v1
kind: Namespace
metadata:
name: objectstorage-frontend
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: object-storage-frontend
namespace: objectstorage-frontend
labels:
app: object-storage-frontend
spec:
replicas: 1
revisionHistoryLimit: 1
selector:
matchLabels:
app: object-storage-frontend
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 1
maxSurge: 0
template:
metadata:
labels:
app: object-storage-frontend
spec:
containers:
- name: object-storage-frontend
image: ghcr.io/labring/sealos-objectstorage-frontend:latest
ports:
- containerPort: 3000
protocol: TCP
env:
- name: MONITOR_URL
value: http://object-storage-monitor.objectstorage-system.svc.cluster.local:9090/q
- name: APP_LAUNCHPAD_URL
value: http://applaunchpad-frontend.applaunchpad-frontend.svc.cluster.local:3000/api/v1alpha
resources:
limits:
cpu: 2000m
memory: 2048Mi
requests:
cpu: 10m
memory: 128Mi
imagePullPolicy: Always
volumeMounts: []
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchExpressions:
- key: "app"
operator: In
values:
- object-storage-frontend
topologyKey: "kubernetes.io/hostname"
volumes: []
---
apiVersion: v1
kind: Service
metadata:
name: object-storage-frontend
namespace: objectstorage-frontend
labels:
app: object-storage-frontend
spec:
ports:
- port: 3000
targetPort: 3000
protocol: TCP
selector:
app: object-storage-frontend
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/configuration-snippet: |
if ($request_uri ~* \.(js|css|gif|jpe?g|png)) {
expires 30d;
add_header Cache-Control "public";
}
nginx.ingress.kubernetes.io/proxy-body-size: 3g
nginx.ingress.kubernetes.io/proxy-next-upstream-timeout: '180'
nginx.ingress.kubernetes.io/proxy-send-timeout: '180'
name: object-storage-frontend
namespace: objectstorage-frontend
spec:
rules:
- host: objectstorage.{{ .cloudDomain }}
http:
paths:
- backend:
service:
name: object-storage-frontend
port:
number: 3000
path: /
pathType: Prefix
tls:
- hosts:
- objectstorage.{{ .cloudDomain }}
secretName: wildcard-cert
---
apiVersion: app.sealos.io/v1
kind: App
metadata:
name: objectstorage
namespace: app-system
spec:
data:
desc: object storage
url: https://objectstorage.{{ .cloudDomain }}:{{ .cloudPort }}
displayType: normal
i18n:
zh:
name: 对象存储
zh-Hans:
name: 对象存储
icon: https://objectstorage.{{ .cloudDomain }}:{{ .cloudPort }}/logo.svg
menuData:
name: Object Storage
type: iframe
@@ -0,0 +1,97 @@
#!/bin/bash
set -e
RELEASE_NAME=${RELEASE_NAME:-"object-storage-frontend"}
RELEASE_NAMESPACE=${RELEASE_NAMESPACE:-"objectstorage-frontend"}
CHART_PATH=${CHART_PATH:-"./charts/objectstorage-frontend"}
HELM_OPTS=${HELM_OPTS:-""}
HELM_OPTIONS=${HELM_OPTIONS:-""}
AUTO_CONFIG_HELM_OPTS=""
get_cm_value() {
local namespace="$1"
local name="$2"
local key="$3"
kubectl get configmap "${name}" -n "${namespace}" -o "jsonpath={.data.${key}}" 2>/dev/null || true
}
add_set_string() {
local key="$1"
local value="$2"
if [ -n "${value}" ]; then
AUTO_CONFIG_HELM_OPTS="${AUTO_CONFIG_HELM_OPTS} --set-string ${key}=${value}"
fi
}
SEALOS_CLOUD_DOMAIN=${SEALOS_CLOUD_DOMAIN:-"${cloudDomain:-$(get_cm_value sealos-system sealos-config cloudDomain)}"}
add_set_string objectstorageConfig.cloudDomain "${SEALOS_CLOUD_DOMAIN}"
SEALOS_CLOUD_PORT=${SEALOS_CLOUD_PORT:-"${cloudPort:-$(get_cm_value sealos-system sealos-config cloudPort)}"}
add_set_string objectstorageConfig.cloudPort "${SEALOS_CLOUD_PORT}"
SEALOS_HTTP_PORT=${SEALOS_HTTP_PORT:-"${httpPort:-$(get_cm_value sealos-system sealos-config httpPort)}"}
add_set_string objectstorageConfig.httpPort "${SEALOS_HTTP_PORT}"
SEALOS_DISABLE_HTTPS=${SEALOS_DISABLE_HTTPS:-"${disableHttps:-$(get_cm_value sealos-system sealos-config disableHttps)}"}
add_set_string objectstorageConfig.disableHttps "${SEALOS_DISABLE_HTTPS}"
SEALOS_CERT_SECRET_NAME=${SEALOS_CERT_SECRET_NAME:-"${certSecretName:-$(get_cm_value sealos-system sealos-config certSecretName)}"}
add_set_string objectstorageConfig.certSecretName "${SEALOS_CERT_SECRET_NAME}"
SEALOS_JWT_INTERNAL=${SEALOS_JWT_INTERNAL:-"${jwtInternal:-$(get_cm_value sealos-system sealos-config jwtInternal)}"}
add_set_string objectstorageConfig.appTokenJwtKey "${SEALOS_JWT_INTERNAL}"
add_set_string objectstorageConfig.monitorUrl "${monitorUrl:-}"
add_set_string objectstorageConfig.billingUrl "${billingUrl:-}"
add_set_string objectstorageConfig.billingSecret "${billingSecret:-}"
add_set_string objectstorageConfig.appLaunchpadUrl "${appLaunchpadUrl:-}"
add_set_string objectstorageConfig.hostingPodCpuMilliCores "${hostingPodCpuMilliCores:-}"
add_set_string objectstorageConfig.hostingPodMemoryMiB "${hostingPodMemoryMiB:-}"
add_set_string objectstorageConfig.hostingAppNamePrefix "${hostingAppNamePrefix:-}"
add_set_string objectstorageConfig.hostingNetworkProtocol "${hostingNetworkProtocol:-}"
add_set_string objectstorageConfig.hostingNetworkPort "${hostingNetworkPort:-}"
adopt_namespaced_resource() {
local namespace="$1"
local kind="$2"
local name="$3"
if kubectl -n "${namespace}" get "${kind}" "${name}" >/dev/null 2>&1; then
echo "Adopting ${kind} ${namespace}/${name}..."
kubectl -n "${namespace}" label "${kind}" "${name}" app.kubernetes.io/managed-by=Helm --overwrite >/dev/null 2>&1 || true
kubectl -n "${namespace}" annotate "${kind}" "${name}" meta.helm.sh/release-name="${RELEASE_NAME}" meta.helm.sh/release-namespace="${RELEASE_NAMESPACE}" --overwrite >/dev/null 2>&1 || true
fi
}
adopt_cluster_resource() {
local kind="$1"
local name="$2"
if kubectl get "${kind}" "${name}" >/dev/null 2>&1; then
echo "Adopting ${kind} ${name}..."
kubectl label "${kind}" "${name}" app.kubernetes.io/managed-by=Helm --overwrite >/dev/null 2>&1 || true
kubectl annotate "${kind}" "${name}" meta.helm.sh/release-name="${RELEASE_NAME}" meta.helm.sh/release-namespace="${RELEASE_NAMESPACE}" --overwrite >/dev/null 2>&1 || true
fi
}
echo "Checking and adopting existing resources..."
if kubectl get namespace "${RELEASE_NAMESPACE}" >/dev/null 2>&1; then
kubectl label namespace "${RELEASE_NAMESPACE}" app.kubernetes.io/managed-by=Helm --overwrite >/dev/null 2>&1 || true
kubectl annotate namespace "${RELEASE_NAMESPACE}" meta.helm.sh/release-name="${RELEASE_NAME}" meta.helm.sh/release-namespace="${RELEASE_NAMESPACE}" --overwrite >/dev/null 2>&1 || true
adopt_namespaced_resource "${RELEASE_NAMESPACE}" configmap object-storage-frontend-config
adopt_namespaced_resource "${RELEASE_NAMESPACE}" service object-storage-frontend
adopt_namespaced_resource "${RELEASE_NAMESPACE}" deployment object-storage-frontend
adopt_namespaced_resource "${RELEASE_NAMESPACE}" ingress object-storage-frontend
fi
adopt_namespaced_resource app-system apps.app.sealos.io objectstorage
SERVICE_NAME="object-storage-frontend"
USER_VALUES_PATH="/root/.sealos/cloud/values/core/${SERVICE_NAME}-values.yaml"
if [ ! -f "${USER_VALUES_PATH}" ]; then
mkdir -p "$(dirname "${USER_VALUES_PATH}")"
cp "./charts/objectstorage-frontend/object-storage-frontend-values.yaml" "${USER_VALUES_PATH}"
fi
HELM_ARGS="${AUTO_CONFIG_HELM_OPTS} ${HELM_OPTIONS} ${HELM_OPTS}"
echo "Deploying Helm chart..."
helm upgrade -i "${RELEASE_NAME}" -n "${RELEASE_NAMESPACE}" --create-namespace "${CHART_PATH}" \
-f "./charts/objectstorage-frontend/values.yaml" \
-f "${USER_VALUES_PATH}" \
${HELM_ARGS}
+3 -13
View File
@@ -3,17 +3,7 @@ FROM scratch
USER 65532:65532
COPY registry registry
COPY manifests manifests
COPY charts charts
COPY template-frontend-entrypoint.sh template-frontend-entrypoint.sh
ENV cloudDomain="127.0.0.1.nip.io"
ENV cloudPort=""
ENV userDomain=""
ENV certSecretName="wildcard-cert"
ENV templateRepoUrl="https://github.com/labring-actions/templates"
ENV templateRepoBranch="main"
ENV templateRepoPath="templates"
ENV guideEnabled="true"
ENV billingUrl="http://account-service.account-system.svc:2333"
ENV enableReadmeFetch="true"
CMD ["kubectl apply -f manifests"]
CMD ["bash template-frontend-entrypoint.sh"]

Some files were not shown because too many files have changed in this diff Show More