Merge branch 'main' into feature/appstore
This commit is contained in:
8
Makefile
8
Makefile
@@ -733,6 +733,7 @@ backend-debug: go-check generate-backend $(EXECUTABLE)-debug
|
|||||||
$(EXECUTABLE)-debug: $(GO_SOURCES) $(TAGS_PREREQ)
|
$(EXECUTABLE)-debug: $(GO_SOURCES) $(TAGS_PREREQ)
|
||||||
CGO_CFLAGS="$(CGO_CFLAGS)" $(GO) build $(GOFLAGS) $(EXTRA_GOFLAGS) -tags '$(TAGS)' -ldflags '$(LDFLAGS)' -o $@
|
CGO_CFLAGS="$(CGO_CFLAGS)" $(GO) build $(GOFLAGS) $(EXTRA_GOFLAGS) -tags '$(TAGS)' -ldflags '$(LDFLAGS)' -o $@
|
||||||
|
|
||||||
|
|
||||||
.PHONY: frontend
|
.PHONY: frontend
|
||||||
frontend: $(WEBPACK_DEST) ## build frontend files
|
frontend: $(WEBPACK_DEST) ## build frontend files
|
||||||
|
|
||||||
@@ -969,6 +970,13 @@ docker:
|
|||||||
# support also build args docker build --build-arg GITEA_VERSION=v1.2.3 --build-arg TAGS="bindata sqlite sqlite_unlock_notify" .
|
# support also build args docker build --build-arg GITEA_VERSION=v1.2.3 --build-arg TAGS="bindata sqlite sqlite_unlock_notify" .
|
||||||
|
|
||||||
# This endif closes the if at the top of the file
|
# This endif closes the if at the top of the file
|
||||||
|
|
||||||
|
# 添加一个新目标,用于构建 controller-manager
|
||||||
|
.PHONY: controller-manager
|
||||||
|
controller-manager: go-check
|
||||||
|
@echo "Building controller-manager..."
|
||||||
|
CGO_CFLAGS="$(CGO_CFLAGS)" $(GO) build $(GOFLAGS) $(EXTRA_GOFLAGS) -tags '$(TAGS)' -ldflags '-s -w $(LDFLAGS)' -o controller-manager modules/k8s/cmd/controller-manager/controller-manager.go
|
||||||
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# Disable parallel execution because it would break some targets that don't
|
# Disable parallel execution because it would break some targets that don't
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ if [ ! -f ${GITEA_CUSTOM}/conf/app.ini ]; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# Substitute the environment variables in the template
|
# Substitute the environment variables in the template
|
||||||
APP_NAME=${APP_NAME:-"Gitea: Git with a cup of tea"} \
|
APP_NAME=${APP_NAME:-"DevStar: The Last Mile of Al for R&D"} \
|
||||||
RUN_MODE=${RUN_MODE:-"prod"} \
|
RUN_MODE=${RUN_MODE:-"prod"} \
|
||||||
DOMAIN=${DOMAIN:-"localhost"} \
|
DOMAIN=${DOMAIN:-"localhost"} \
|
||||||
SSH_DOMAIN=${SSH_DOMAIN:-"localhost"} \
|
SSH_DOMAIN=${SSH_DOMAIN:-"localhost"} \
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ if [ ! -f ${GITEA_APP_INI} ]; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# Substitute the environment variables in the template
|
# Substitute the environment variables in the template
|
||||||
APP_NAME=${APP_NAME:-"Gitea: Git with a cup of tea"} \
|
APP_NAME=${APP_NAME:-"DevStar: The Last Mile of Al for R&D"} \
|
||||||
RUN_MODE=${RUN_MODE:-"prod"} \
|
RUN_MODE=${RUN_MODE:-"prod"} \
|
||||||
RUN_USER=${USER:-"git"} \
|
RUN_USER=${USER:-"git"} \
|
||||||
SSH_DOMAIN=${SSH_DOMAIN:-"localhost"} \
|
SSH_DOMAIN=${SSH_DOMAIN:-"localhost"} \
|
||||||
|
|||||||
280
docs/devcontainer-local-k8s.md
Normal file
280
docs/devcontainer-local-k8s.md
Normal file
@@ -0,0 +1,280 @@
|
|||||||
|
## DevContainer(Kubernetes + Istio)本地运行
|
||||||
|
|
||||||
|
仅保留三点:Istio 1.27.1 安装、app.ini 手动配置、安装 Devcontainer CRD(内嵌 YAML)。
|
||||||
|
|
||||||
|
### 1) 安装 Istio 1.27.1(指定版本)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ISTIO_VER=1.27.1
|
||||||
|
curl -L https://istio.io/downloadIstio | ISTIO_VERSION=${ISTIO_VER} sh -
|
||||||
|
export PATH="$PWD/istio-${ISTIO_VER}/bin:$PATH"
|
||||||
|
|
||||||
|
istioctl x precheck
|
||||||
|
istioctl install -y --set profile=default
|
||||||
|
|
||||||
|
kubectl -n istio-system get svc istio-ingressgateway -o wide
|
||||||
|
```
|
||||||
|
|
||||||
|
说明:本项目 WebTerminal 使用 HTTP/80,经 `istio-ingressgateway` 进入,无需立刻配置 HTTPS。
|
||||||
|
|
||||||
|
### 2) 本地 app.ini 手动配置(非helm安装的 devstar 不会自动写入)
|
||||||
|
|
||||||
|
文件:`devstar/custom/conf/app.ini`
|
||||||
|
|
||||||
|
```ini
|
||||||
|
|
||||||
|
[devstar.devcontainer]
|
||||||
|
NAMESPACE = default # 创建的devcontainer所在的命名空间
|
||||||
|
HOST = 192.168.23.138 # 和[server].DOMAIN一致
|
||||||
|
```
|
||||||
|
|
||||||
|
保存后重启后端以加载配置。
|
||||||
|
|
||||||
|
### 3) 安装 Devcontainer CRD(内嵌 YAML,可直接 apply)
|
||||||
|
|
||||||
|
可直接复制以下清单,通过标准输入安装:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
kubectl apply -f - <<'YAML'
|
||||||
|
---
|
||||||
|
apiVersion: apiextensions.k8s.io/v1
|
||||||
|
kind: CustomResourceDefinition
|
||||||
|
metadata:
|
||||||
|
annotations:
|
||||||
|
controller-gen.kubebuilder.io/version: v0.16.1
|
||||||
|
name: devcontainerapps.devcontainer.devstar.cn
|
||||||
|
spec:
|
||||||
|
group: devcontainer.devstar.cn
|
||||||
|
names:
|
||||||
|
kind: DevcontainerApp
|
||||||
|
listKind: DevcontainerAppList
|
||||||
|
plural: devcontainerapps
|
||||||
|
singular: devcontainerapp
|
||||||
|
scope: Namespaced
|
||||||
|
versions:
|
||||||
|
- name: v1
|
||||||
|
schema:
|
||||||
|
openAPIV3Schema:
|
||||||
|
description: DevcontainerApp is the Schema for the devcontainerapps API
|
||||||
|
properties:
|
||||||
|
apiVersion:
|
||||||
|
description: |-
|
||||||
|
APIVersion defines the versioned schema of this representation of an object.
|
||||||
|
Servers should convert recognized schemas to the latest internal value, and
|
||||||
|
may reject unrecognized values.
|
||||||
|
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
|
||||||
|
type: string
|
||||||
|
kind:
|
||||||
|
description: |-
|
||||||
|
Kind is a string value representing the REST resource this object represents.
|
||||||
|
Servers may infer this from the endpoint the client submits requests to.
|
||||||
|
Cannot be updated.
|
||||||
|
In CamelCase.
|
||||||
|
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
|
||||||
|
type: string
|
||||||
|
metadata:
|
||||||
|
type: object
|
||||||
|
spec:
|
||||||
|
description: DevcontainerAppSpec defines the desired state of DevcontainerApp
|
||||||
|
properties:
|
||||||
|
failedJobsHistoryLimit:
|
||||||
|
description: |-
|
||||||
|
The number of failed finished jobs to retain.
|
||||||
|
This is a pointer to distinguish between explicit zero and not specified.
|
||||||
|
format: int32
|
||||||
|
minimum: 0
|
||||||
|
type: integer
|
||||||
|
service:
|
||||||
|
description: ServiceSpec specifies Service for DevContainer
|
||||||
|
properties:
|
||||||
|
extraPorts:
|
||||||
|
description: ExtraPorts 定义额外的端口配置
|
||||||
|
items:
|
||||||
|
description: ExtraPortSpec 定义额外端口配置
|
||||||
|
properties:
|
||||||
|
containerPort:
|
||||||
|
description: ContainerPort 是容器内的端口号
|
||||||
|
maximum: 65535
|
||||||
|
minimum: 1
|
||||||
|
type: integer
|
||||||
|
name:
|
||||||
|
description: Name 是端口的名称
|
||||||
|
type: string
|
||||||
|
servicePort:
|
||||||
|
description: ServicePort 是服务暴露的端口号
|
||||||
|
maximum: 65535
|
||||||
|
minimum: 1
|
||||||
|
type: integer
|
||||||
|
required:
|
||||||
|
- containerPort
|
||||||
|
- servicePort
|
||||||
|
type: object
|
||||||
|
type: array
|
||||||
|
nodePort:
|
||||||
|
maximum: 32767
|
||||||
|
minimum: 30000
|
||||||
|
type: integer
|
||||||
|
servicePort:
|
||||||
|
minimum: 1
|
||||||
|
type: integer
|
||||||
|
type: object
|
||||||
|
startingDeadlineSeconds:
|
||||||
|
description: |-
|
||||||
|
Optional deadline in seconds for starting the job if it misses scheduled
|
||||||
|
time for any reason. Missed jobs executions will be counted as failed ones.
|
||||||
|
format: int64
|
||||||
|
minimum: 0
|
||||||
|
type: integer
|
||||||
|
statefulset:
|
||||||
|
description: StatefulSetSpec specifies StatefulSet for DevContainer
|
||||||
|
properties:
|
||||||
|
command:
|
||||||
|
items:
|
||||||
|
type: string
|
||||||
|
type: array
|
||||||
|
containerPort:
|
||||||
|
minimum: 1
|
||||||
|
type: integer
|
||||||
|
gitRepositoryURL:
|
||||||
|
type: string
|
||||||
|
image:
|
||||||
|
type: string
|
||||||
|
sshPublicKeyList:
|
||||||
|
description: 至少包含一个 SSH Public Key 才能通过校验规则
|
||||||
|
items:
|
||||||
|
type: string
|
||||||
|
minItems: 1
|
||||||
|
type: array
|
||||||
|
required:
|
||||||
|
- command
|
||||||
|
- gitRepositoryURL
|
||||||
|
- image
|
||||||
|
- sshPublicKeyList
|
||||||
|
type: object
|
||||||
|
successfulJobsHistoryLimit:
|
||||||
|
description: |-
|
||||||
|
The number of successful finished jobs to retain.
|
||||||
|
This is a pointer to distinguish between explicit zero and not specified.
|
||||||
|
format: int32
|
||||||
|
minimum: 0
|
||||||
|
type: integer
|
||||||
|
suspend:
|
||||||
|
description: |-
|
||||||
|
This flag tells the controller to suspend subsequent executions, it does
|
||||||
|
not apply to already started executions. Defaults to false.
|
||||||
|
type: boolean
|
||||||
|
required:
|
||||||
|
- statefulset
|
||||||
|
type: object
|
||||||
|
status:
|
||||||
|
description: DevcontainerAppStatus defines the observed state of DevcontainerApp
|
||||||
|
properties:
|
||||||
|
active:
|
||||||
|
description: A list of pointers to currently running jobs.
|
||||||
|
items:
|
||||||
|
description: ObjectReference contains enough information to let
|
||||||
|
you inspect or modify the referred object.
|
||||||
|
properties:
|
||||||
|
apiVersion:
|
||||||
|
description: API version of the referent.
|
||||||
|
type: string
|
||||||
|
fieldPath:
|
||||||
|
description: |-
|
||||||
|
If referring to a piece of an object instead of an entire object, this string
|
||||||
|
should contain a valid JSON/Go field access statement, such as desiredState.manifest.containers[2].
|
||||||
|
For example, if the object reference is to a container within a pod, this would take on a value like:
|
||||||
|
"spec.containers{name}" (where "name" refers to the name of the container that triggered
|
||||||
|
the event) or if no container name is specified "spec.containers[2]" (container with
|
||||||
|
index 2 in this pod). This syntax is chosen only to have some well-defined way of
|
||||||
|
referencing a part of an object.
|
||||||
|
type: string
|
||||||
|
kind:
|
||||||
|
description: |-
|
||||||
|
Kind of the referent.
|
||||||
|
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
|
||||||
|
type: string
|
||||||
|
name:
|
||||||
|
description: |-
|
||||||
|
Name of the referent.
|
||||||
|
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||||
|
type: string
|
||||||
|
namespace:
|
||||||
|
description: |-
|
||||||
|
Namespace of the referent.
|
||||||
|
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/
|
||||||
|
type: string
|
||||||
|
resourceVersion:
|
||||||
|
description: |-
|
||||||
|
Specific resourceVersion to which this reference is made, if any.
|
||||||
|
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency
|
||||||
|
type: string
|
||||||
|
uid:
|
||||||
|
description: |-
|
||||||
|
UID of the referent.
|
||||||
|
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids
|
||||||
|
type: string
|
||||||
|
type: object
|
||||||
|
x-kubernetes-map-type: atomic
|
||||||
|
type: array
|
||||||
|
extraPortsAssigned:
|
||||||
|
description: ExtraPortsAssigned 存储额外端口映射的 NodePort
|
||||||
|
items:
|
||||||
|
description: ExtraPortAssigned 定义已分配的额外端口信息
|
||||||
|
properties:
|
||||||
|
containerPort:
|
||||||
|
description: ContainerPort 是容器内的端口号
|
||||||
|
type: integer
|
||||||
|
name:
|
||||||
|
description: Name 是端口的名称
|
||||||
|
type: string
|
||||||
|
nodePort:
|
||||||
|
description: NodePort 是 Kubernetes 分配的 NodePort
|
||||||
|
type: integer
|
||||||
|
servicePort:
|
||||||
|
description: ServicePort 是服务暴露的端口号
|
||||||
|
type: integer
|
||||||
|
required:
|
||||||
|
- containerPort
|
||||||
|
- nodePort
|
||||||
|
- servicePort
|
||||||
|
type: object
|
||||||
|
type: array
|
||||||
|
lastScheduleTime:
|
||||||
|
description: Information when was the last time the job was successfully
|
||||||
|
scheduled.
|
||||||
|
format: date-time
|
||||||
|
type: string
|
||||||
|
nodePortAssigned:
|
||||||
|
description: NodePortAssigned 存储 DevcontainerApp CRD调度后集群分配的 NodePort
|
||||||
|
type: integer
|
||||||
|
ready:
|
||||||
|
description: Ready 标识 DevcontainerApp 管理的 Pod 的 Readiness Probe 是否达到就绪状态
|
||||||
|
type: boolean
|
||||||
|
type: object
|
||||||
|
type: object
|
||||||
|
served: true
|
||||||
|
storage: true
|
||||||
|
subresources:
|
||||||
|
status: {}
|
||||||
|
YAML
|
||||||
|
```
|
||||||
|
|
||||||
|
验证 CRD:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
kubectl get crd devcontainerapps.devcontainer.devstar.cn -o wide
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4) 编译与运行 controller-manager(必需)
|
||||||
|
|
||||||
|
controller-manager 负责监听 `DevcontainerApp` CR,并创建/更新/删除底层 K8s 资源(StatefulSet、Service 等),并回写 `Status.Ready` 等状态。仅安装 CRD 不会触发任何实际资源变更,必须运行 controller-manager 才会生效。
|
||||||
|
|
||||||
|
- 在主目录编译并运行:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd /home/psx/devstar-main
|
||||||
|
make controller-manager
|
||||||
|
./controller-manager
|
||||||
|
# 观察日志:应能看到 Reconcile 日志;创建 DevcontainerApp 后会创建 sts/svc
|
||||||
|
```
|
||||||
|
|
||||||
100
go.mod
100
go.mod
@@ -96,6 +96,8 @@ require (
|
|||||||
github.com/nektos/act v0.2.63
|
github.com/nektos/act v0.2.63
|
||||||
github.com/niklasfasching/go-org v1.8.0
|
github.com/niklasfasching/go-org v1.8.0
|
||||||
github.com/olivere/elastic/v7 v7.0.32
|
github.com/olivere/elastic/v7 v7.0.32
|
||||||
|
github.com/onsi/ginkgo/v2 v2.22.0
|
||||||
|
github.com/onsi/gomega v1.36.1
|
||||||
github.com/opencontainers/go-digest v1.0.0
|
github.com/opencontainers/go-digest v1.0.0
|
||||||
github.com/opencontainers/image-spec v1.1.1
|
github.com/opencontainers/image-spec v1.1.1
|
||||||
github.com/pkg/errors v0.9.1
|
github.com/pkg/errors v0.9.1
|
||||||
@@ -107,7 +109,7 @@ require (
|
|||||||
github.com/santhosh-tekuri/jsonschema/v5 v5.3.1
|
github.com/santhosh-tekuri/jsonschema/v5 v5.3.1
|
||||||
github.com/sassoftware/go-rpmutils v0.4.0
|
github.com/sassoftware/go-rpmutils v0.4.0
|
||||||
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3
|
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3
|
||||||
github.com/spf13/cobra v1.8.1
|
github.com/spf13/cobra v1.9.1
|
||||||
github.com/spf13/pflag v1.0.6
|
github.com/spf13/pflag v1.0.6
|
||||||
github.com/stretchr/testify v1.10.0
|
github.com/stretchr/testify v1.10.0
|
||||||
github.com/syndtr/goleveldb v1.0.0
|
github.com/syndtr/goleveldb v1.0.0
|
||||||
@@ -129,52 +131,75 @@ require (
|
|||||||
golang.org/x/sync v0.15.0
|
golang.org/x/sync v0.15.0
|
||||||
golang.org/x/sys v0.33.0
|
golang.org/x/sys v0.33.0
|
||||||
golang.org/x/text v0.26.0
|
golang.org/x/text v0.26.0
|
||||||
google.golang.org/grpc v1.72.0
|
google.golang.org/grpc v1.72.1
|
||||||
google.golang.org/protobuf v1.36.6
|
google.golang.org/protobuf v1.36.6
|
||||||
gopkg.in/ini.v1 v1.67.0
|
gopkg.in/ini.v1 v1.67.0
|
||||||
gopkg.in/yaml.v3 v3.0.1
|
gopkg.in/yaml.v3 v3.0.1
|
||||||
istio.io/api v1.26.3
|
istio.io/api v1.27.2
|
||||||
istio.io/client-go v1.26.3
|
istio.io/client-go v1.27.2
|
||||||
k8s.io/api v0.33.3
|
k8s.io/api v0.34.1
|
||||||
k8s.io/apimachinery v0.33.3
|
k8s.io/apimachinery v0.34.1
|
||||||
k8s.io/client-go v0.33.3
|
k8s.io/client-go v0.34.1
|
||||||
k8s.io/component-base v0.33.3
|
k8s.io/component-base v0.34.1
|
||||||
k8s.io/klog/v2 v2.130.1
|
k8s.io/klog/v2 v2.130.1
|
||||||
|
k8s.io/kubectl v0.34.1
|
||||||
mvdan.cc/xurls/v2 v2.6.0
|
mvdan.cc/xurls/v2 v2.6.0
|
||||||
sigs.k8s.io/controller-runtime v0.21.0
|
sigs.k8s.io/controller-runtime v0.22.3
|
||||||
|
sigs.k8s.io/yaml v1.6.0
|
||||||
strk.kbt.io/projects/go/libravatar v0.0.0-20191008002943-06d1c002b251
|
strk.kbt.io/projects/go/libravatar v0.0.0-20191008002943-06d1c002b251
|
||||||
xorm.io/builder v0.3.13
|
xorm.io/builder v0.3.13
|
||||||
xorm.io/xorm v1.3.9
|
xorm.io/xorm v1.3.9
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
cel.dev/expr v0.24.0 // indirect
|
||||||
github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c // indirect
|
github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c // indirect
|
||||||
github.com/distribution/reference v0.5.0 // indirect
|
github.com/antlr4-go/antlr/v4 v4.13.0 // indirect
|
||||||
|
github.com/blang/semver/v4 v4.0.0 // indirect
|
||||||
|
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
|
||||||
|
github.com/distribution/reference v0.6.0 // indirect
|
||||||
github.com/docker/distribution v2.8.3+incompatible // indirect
|
github.com/docker/distribution v2.8.3+incompatible // indirect
|
||||||
github.com/docker/go-units v0.5.0 // indirect
|
github.com/docker/go-units v0.5.0 // indirect
|
||||||
github.com/emicklei/go-restful/v3 v3.11.0 // indirect
|
github.com/emicklei/go-restful/v3 v3.12.2 // indirect
|
||||||
|
github.com/evanphx/json-patch/v5 v5.9.11 // indirect
|
||||||
|
github.com/felixge/httpsnoop v1.0.4 // indirect
|
||||||
github.com/go-logr/logr v1.4.2 // indirect
|
github.com/go-logr/logr v1.4.2 // indirect
|
||||||
|
github.com/go-logr/stdr v1.2.2 // indirect
|
||||||
|
github.com/go-logr/zapr v1.3.0 // indirect
|
||||||
github.com/go-openapi/jsonpointer v0.21.0 // indirect
|
github.com/go-openapi/jsonpointer v0.21.0 // indirect
|
||||||
github.com/go-openapi/jsonreference v0.20.2 // indirect
|
github.com/go-openapi/jsonreference v0.20.2 // indirect
|
||||||
github.com/go-openapi/swag v0.23.0 // indirect
|
github.com/go-openapi/swag v0.23.0 // indirect
|
||||||
|
github.com/go-task/slim-sprig/v3 v3.0.0 // indirect
|
||||||
github.com/gogo/protobuf v1.3.2 // indirect
|
github.com/gogo/protobuf v1.3.2 // indirect
|
||||||
github.com/google/gnostic-models v0.6.9 // indirect
|
github.com/google/cel-go v0.26.0 // indirect
|
||||||
|
github.com/google/gnostic-models v0.7.0 // indirect
|
||||||
github.com/google/go-cmp v0.7.0 // indirect
|
github.com/google/go-cmp v0.7.0 // indirect
|
||||||
|
github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674 // indirect
|
||||||
|
github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3 // indirect
|
||||||
|
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||||
|
github.com/moby/spdystream v0.5.0 // indirect
|
||||||
|
github.com/moby/term v0.5.0 // indirect
|
||||||
github.com/morikuni/aec v1.0.0 // indirect
|
github.com/morikuni/aec v1.0.0 // indirect
|
||||||
|
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f // indirect
|
||||||
|
go.yaml.in/yaml/v2 v2.4.2 // indirect
|
||||||
|
go.yaml.in/yaml/v3 v3.0.4 // indirect
|
||||||
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 // indirect
|
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 // indirect
|
||||||
golang.org/x/term v0.32.0 // indirect
|
golang.org/x/term v0.32.0 // indirect
|
||||||
|
gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect
|
||||||
|
google.golang.org/genproto/googleapis/api v0.0.0-20250324211829-b45e905df463 // indirect
|
||||||
gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect
|
gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect
|
||||||
gopkg.in/inf.v0 v0.9.1 // indirect
|
gopkg.in/inf.v0 v0.9.1 // indirect
|
||||||
k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff // indirect
|
k8s.io/apiextensions-apiserver v0.34.1 // indirect
|
||||||
k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 // indirect
|
k8s.io/apiserver v0.34.1 // indirect
|
||||||
sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 // indirect
|
k8s.io/kube-openapi v0.0.0-20250710124328-f3f2b991d03b // indirect
|
||||||
|
k8s.io/utils v0.0.0-20250604170112-4c0f3b243397 // indirect
|
||||||
|
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.2 // indirect
|
||||||
|
sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 // indirect
|
||||||
sigs.k8s.io/randfill v1.0.0 // indirect
|
sigs.k8s.io/randfill v1.0.0 // indirect
|
||||||
sigs.k8s.io/structured-merge-diff/v4 v4.6.0 // indirect
|
sigs.k8s.io/structured-merge-diff/v6 v6.3.0 // indirect
|
||||||
sigs.k8s.io/yaml v1.4.0 // indirect
|
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
cel.dev/expr v0.20.0 // indirect
|
|
||||||
cloud.google.com/go/compute/metadata v0.6.0 // indirect
|
cloud.google.com/go/compute/metadata v0.6.0 // indirect
|
||||||
dario.cat/mergo v1.0.1 // indirect
|
dario.cat/mergo v1.0.1 // indirect
|
||||||
filippo.io/edwards25519 v1.1.0 // indirect
|
filippo.io/edwards25519 v1.1.0 // indirect
|
||||||
@@ -187,7 +212,6 @@ require (
|
|||||||
github.com/andybalholm/brotli v1.1.1 // indirect
|
github.com/andybalholm/brotli v1.1.1 // indirect
|
||||||
github.com/andybalholm/cascadia v1.3.3 // indirect
|
github.com/andybalholm/cascadia v1.3.3 // indirect
|
||||||
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be // indirect
|
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be // indirect
|
||||||
github.com/antlr4-go/antlr/v4 v4.13.0 // indirect
|
|
||||||
github.com/aws/aws-sdk-go-v2 v1.36.3 // indirect
|
github.com/aws/aws-sdk-go-v2 v1.36.3 // indirect
|
||||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.34 // indirect
|
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.34 // indirect
|
||||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.34 // indirect
|
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.34 // indirect
|
||||||
@@ -195,7 +219,6 @@ require (
|
|||||||
github.com/aymerick/douceur v0.2.0 // indirect
|
github.com/aymerick/douceur v0.2.0 // indirect
|
||||||
github.com/beorn7/perks v1.0.1 // indirect
|
github.com/beorn7/perks v1.0.1 // indirect
|
||||||
github.com/bits-and-blooms/bitset v1.22.0 // indirect
|
github.com/bits-and-blooms/bitset v1.22.0 // indirect
|
||||||
github.com/blang/semver/v4 v4.0.0 // indirect
|
|
||||||
github.com/blevesearch/bleve_index_api v1.2.8 // indirect
|
github.com/blevesearch/bleve_index_api v1.2.8 // indirect
|
||||||
github.com/blevesearch/geo v0.2.0 // indirect
|
github.com/blevesearch/geo v0.2.0 // indirect
|
||||||
github.com/blevesearch/go-faiss v1.0.25 // indirect
|
github.com/blevesearch/go-faiss v1.0.25 // indirect
|
||||||
@@ -217,7 +240,6 @@ require (
|
|||||||
github.com/boombuler/barcode v1.0.2 // indirect
|
github.com/boombuler/barcode v1.0.2 // indirect
|
||||||
github.com/bradfitz/gomemcache v0.0.0-20250403215159-8d39553ac7cf // indirect
|
github.com/bradfitz/gomemcache v0.0.0-20250403215159-8d39553ac7cf // indirect
|
||||||
github.com/caddyserver/zerossl v0.1.3 // indirect
|
github.com/caddyserver/zerossl v0.1.3 // indirect
|
||||||
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
|
|
||||||
github.com/cention-sany/utf7 v0.0.0-20170124080048-26cad61bd60a // indirect
|
github.com/cention-sany/utf7 v0.0.0-20170124080048-26cad61bd60a // indirect
|
||||||
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||||
github.com/clbanning/mxj/v2 v2.7.0 // indirect
|
github.com/clbanning/mxj/v2 v2.7.0 // indirect
|
||||||
@@ -225,7 +247,7 @@ require (
|
|||||||
github.com/couchbase/go-couchbase v0.1.1 // indirect
|
github.com/couchbase/go-couchbase v0.1.1 // indirect
|
||||||
github.com/couchbase/gomemcached v0.3.3 // indirect
|
github.com/couchbase/gomemcached v0.3.3 // indirect
|
||||||
github.com/couchbase/goutils v0.1.2 // indirect
|
github.com/couchbase/goutils v0.1.2 // indirect
|
||||||
github.com/cpuguy83/go-md2man/v2 v2.0.5 // indirect
|
github.com/cpuguy83/go-md2man/v2 v2.0.6 // indirect
|
||||||
github.com/cyphar/filepath-securejoin v0.4.1 // indirect
|
github.com/cyphar/filepath-securejoin v0.4.1 // indirect
|
||||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
|
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
|
||||||
github.com/davidmz/go-pageant v1.0.2 // indirect
|
github.com/davidmz/go-pageant v1.0.2 // indirect
|
||||||
@@ -233,10 +255,8 @@ require (
|
|||||||
github.com/dlclark/regexp2 v1.11.5 // indirect
|
github.com/dlclark/regexp2 v1.11.5 // indirect
|
||||||
github.com/docker/docker v24.0.9+incompatible
|
github.com/docker/docker v24.0.9+incompatible
|
||||||
github.com/emersion/go-sasl v0.0.0-20241020182733-b788ff22d5a6 // indirect
|
github.com/emersion/go-sasl v0.0.0-20241020182733-b788ff22d5a6 // indirect
|
||||||
github.com/evanphx/json-patch/v5 v5.9.11 // indirect
|
|
||||||
github.com/fatih/color v1.18.0 // indirect
|
github.com/fatih/color v1.18.0 // indirect
|
||||||
github.com/felixge/httpsnoop v1.0.4 // indirect
|
github.com/fxamacker/cbor/v2 v2.9.0 // indirect
|
||||||
github.com/fxamacker/cbor/v2 v2.8.0 // indirect
|
|
||||||
github.com/git-lfs/pktline v0.0.0-20230103162542-ca444d533ef1 // indirect
|
github.com/git-lfs/pktline v0.0.0-20230103162542-ca444d533ef1 // indirect
|
||||||
github.com/go-ap/errors v0.0.0-20250409143711-5686c11ae650 // indirect
|
github.com/go-ap/errors v0.0.0-20250409143711-5686c11ae650 // indirect
|
||||||
github.com/go-asn1-ber/asn1-ber v1.5.8-0.20250403174932-29230038a667 // indirect
|
github.com/go-asn1-ber/asn1-ber v1.5.8-0.20250403174932-29230038a667 // indirect
|
||||||
@@ -244,7 +264,6 @@ require (
|
|||||||
github.com/go-fed/httpsig v1.1.1-0.20201223112313-55836744818e // indirect
|
github.com/go-fed/httpsig v1.1.1-0.20201223112313-55836744818e // indirect
|
||||||
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect
|
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect
|
||||||
github.com/go-ini/ini v1.67.0 // indirect
|
github.com/go-ini/ini v1.67.0 // indirect
|
||||||
github.com/go-logr/stdr v1.2.2 // indirect
|
|
||||||
github.com/go-webauthn/x v0.1.20 // indirect
|
github.com/go-webauthn/x v0.1.20 // indirect
|
||||||
github.com/goccy/go-json v0.10.5 // indirect
|
github.com/goccy/go-json v0.10.5 // indirect
|
||||||
github.com/golang-jwt/jwt/v4 v4.5.2 // indirect
|
github.com/golang-jwt/jwt/v4 v4.5.2 // indirect
|
||||||
@@ -254,19 +273,16 @@ require (
|
|||||||
github.com/golang/protobuf v1.5.4 // indirect
|
github.com/golang/protobuf v1.5.4 // indirect
|
||||||
github.com/golang/snappy v1.0.0 // indirect
|
github.com/golang/snappy v1.0.0 // indirect
|
||||||
github.com/google/btree v1.1.3 // indirect
|
github.com/google/btree v1.1.3 // indirect
|
||||||
github.com/google/cel-go v0.23.2 // indirect
|
|
||||||
github.com/google/flatbuffers v25.2.10+incompatible // indirect
|
github.com/google/flatbuffers v25.2.10+incompatible // indirect
|
||||||
github.com/google/go-querystring v1.1.0 // indirect
|
github.com/google/go-querystring v1.1.0 // indirect
|
||||||
github.com/google/go-tpm v0.9.3 // indirect
|
github.com/google/go-tpm v0.9.3 // indirect
|
||||||
github.com/gorilla/css v1.0.1 // indirect
|
github.com/gorilla/css v1.0.1 // indirect
|
||||||
github.com/gorilla/mux v1.8.1 // indirect
|
github.com/gorilla/mux v1.8.1 // indirect
|
||||||
github.com/gorilla/securecookie v1.1.2 // indirect
|
github.com/gorilla/securecookie v1.1.2 // indirect
|
||||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.24.0 // indirect
|
|
||||||
github.com/hashicorp/errwrap v1.1.0 // indirect
|
github.com/hashicorp/errwrap v1.1.0 // indirect
|
||||||
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
|
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
|
||||||
github.com/hashicorp/go-multierror v1.1.1 // indirect
|
github.com/hashicorp/go-multierror v1.1.1 // indirect
|
||||||
github.com/hashicorp/go-retryablehttp v0.7.7 // indirect
|
github.com/hashicorp/go-retryablehttp v0.7.7 // indirect
|
||||||
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
|
||||||
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
|
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
|
||||||
github.com/josharian/intern v1.0.0 // indirect
|
github.com/josharian/intern v1.0.0 // indirect
|
||||||
github.com/kevinburke/ssh_config v1.2.0 // indirect
|
github.com/kevinburke/ssh_config v1.2.0 // indirect
|
||||||
@@ -282,9 +298,8 @@ require (
|
|||||||
github.com/minio/crc64nvme v1.0.1 // indirect
|
github.com/minio/crc64nvme v1.0.1 // indirect
|
||||||
github.com/minio/md5-simd v1.1.2 // indirect
|
github.com/minio/md5-simd v1.1.2 // indirect
|
||||||
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
||||||
github.com/moby/term v0.5.0 // indirect
|
|
||||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee // indirect
|
||||||
github.com/mrjones/oauth v0.0.0-20190623134757-126b35219450 // indirect
|
github.com/mrjones/oauth v0.0.0-20190623134757-126b35219450 // indirect
|
||||||
github.com/mschoch/smat v0.2.0 // indirect
|
github.com/mschoch/smat v0.2.0 // indirect
|
||||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
|
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
|
||||||
@@ -315,16 +330,16 @@ require (
|
|||||||
github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 // indirect
|
github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 // indirect
|
||||||
github.com/zeebo/assert v1.3.0 // indirect
|
github.com/zeebo/assert v1.3.0 // indirect
|
||||||
github.com/zeebo/blake3 v0.2.4 // indirect
|
github.com/zeebo/blake3 v0.2.4 // indirect
|
||||||
go.etcd.io/bbolt v1.4.0 // indirect
|
go.etcd.io/bbolt v1.4.2 // indirect
|
||||||
go.opentelemetry.io/auto/sdk v1.1.0 // indirect
|
go.opentelemetry.io/auto/sdk v1.1.0 // indirect
|
||||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.58.0 // indirect
|
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.58.0 // indirect
|
||||||
go.opentelemetry.io/otel v1.34.0 // indirect
|
go.opentelemetry.io/otel v1.35.0 // indirect
|
||||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.33.0 // indirect
|
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.34.0 // indirect
|
||||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.33.0 // indirect
|
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.34.0 // indirect
|
||||||
go.opentelemetry.io/otel/metric v1.34.0 // indirect
|
go.opentelemetry.io/otel/metric v1.35.0 // indirect
|
||||||
go.opentelemetry.io/otel/sdk v1.34.0 // indirect
|
go.opentelemetry.io/otel/sdk v1.34.0 // indirect
|
||||||
go.opentelemetry.io/otel/trace v1.34.0 // indirect
|
go.opentelemetry.io/otel/trace v1.35.0 // indirect
|
||||||
go.opentelemetry.io/proto/otlp v1.4.0 // indirect
|
go.opentelemetry.io/proto/otlp v1.5.0 // indirect
|
||||||
go.uber.org/atomic v1.11.0 // indirect
|
go.uber.org/atomic v1.11.0 // indirect
|
||||||
go.uber.org/multierr v1.11.0 // indirect
|
go.uber.org/multierr v1.11.0 // indirect
|
||||||
go.uber.org/zap v1.27.0 // indirect
|
go.uber.org/zap v1.27.0 // indirect
|
||||||
@@ -332,14 +347,9 @@ require (
|
|||||||
golang.org/x/mod v0.25.0 // indirect
|
golang.org/x/mod v0.25.0 // indirect
|
||||||
golang.org/x/time v0.11.0 // indirect
|
golang.org/x/time v0.11.0 // indirect
|
||||||
golang.org/x/tools v0.33.0 // indirect
|
golang.org/x/tools v0.33.0 // indirect
|
||||||
gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect
|
|
||||||
google.golang.org/genproto/googleapis/api v0.0.0-20250324211829-b45e905df463 // indirect
|
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250422160041-2d3770c4ea7f // indirect
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20250422160041-2d3770c4ea7f // indirect
|
||||||
gopkg.in/warnings.v0 v0.1.2 // indirect
|
gopkg.in/warnings.v0 v0.1.2 // indirect
|
||||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||||
k8s.io/apiextensions-apiserver v0.33.0 // indirect
|
|
||||||
k8s.io/apiserver v0.33.0 // indirect
|
|
||||||
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.2 // indirect
|
|
||||||
)
|
)
|
||||||
|
|
||||||
replace github.com/hashicorp/go-version => github.com/6543/go-version v1.3.1
|
replace github.com/hashicorp/go-version => github.com/6543/go-version v1.3.1
|
||||||
@@ -361,3 +371,7 @@ exclude github.com/gofrs/uuid v4.0.0+incompatible
|
|||||||
exclude github.com/goccy/go-json v0.4.11
|
exclude github.com/goccy/go-json v0.4.11
|
||||||
|
|
||||||
exclude github.com/satori/go.uuid v1.2.0
|
exclude github.com/satori/go.uuid v1.2.0
|
||||||
|
|
||||||
|
replace github.com/docker/distribution => github.com/distribution/distribution v2.8.3+incompatible
|
||||||
|
|
||||||
|
replace github.com/distribution/reference => github.com/distribution/reference v0.5.0
|
||||||
|
|||||||
144
go.sum
144
go.sum
@@ -1,5 +1,5 @@
|
|||||||
cel.dev/expr v0.20.0 h1:OunBvVCfvpWlt4dN7zg3FM6TDkzOePe1+foGJ9AXeeI=
|
cel.dev/expr v0.24.0 h1:56OvJKSH3hDGL0ml5uSxZmz3/3Pq4tJ+fb1unVLAFcY=
|
||||||
cel.dev/expr v0.20.0/go.mod h1:MrpN08Q+lEBs+bGYdLxxHkZoUSsCp0nSKTs0nTymJgw=
|
cel.dev/expr v0.24.0/go.mod h1:hLPLo1W4QUmuYdA72RBX06QTs6MXw941piREPl3Yfiw=
|
||||||
cloud.google.com/go/compute/metadata v0.6.0 h1:A6hENjEsCDtC1k8byVsgwvVcioamEHvZ4j01OwKxG9I=
|
cloud.google.com/go/compute/metadata v0.6.0 h1:A6hENjEsCDtC1k8byVsgwvVcioamEHvZ4j01OwKxG9I=
|
||||||
cloud.google.com/go/compute/metadata v0.6.0/go.mod h1:FjyFAW1MW0C203CEOMDTu3Dk1FlqW3Rga40jzHL4hfg=
|
cloud.google.com/go/compute/metadata v0.6.0/go.mod h1:FjyFAW1MW0C203CEOMDTu3Dk1FlqW3Rga40jzHL4hfg=
|
||||||
code.gitea.io/actions-proto-go v0.4.1 h1:l0EYhjsgpUe/1VABo2eK7zcoNX2W44WOnb0MSLrKfls=
|
code.gitea.io/actions-proto-go v0.4.1 h1:l0EYhjsgpUe/1VABo2eK7zcoNX2W44WOnb0MSLrKfls=
|
||||||
@@ -233,9 +233,8 @@ github.com/couchbase/goutils v0.1.2 h1:gWr8B6XNWPIhfalHNog3qQKfGiYyh4K4VhO3P2o9B
|
|||||||
github.com/couchbase/goutils v0.1.2/go.mod h1:h89Ek/tiOxxqjz30nPPlwZdQbdB8BwgnuBxeoUe/ViE=
|
github.com/couchbase/goutils v0.1.2/go.mod h1:h89Ek/tiOxxqjz30nPPlwZdQbdB8BwgnuBxeoUe/ViE=
|
||||||
github.com/couchbase/moss v0.1.0/go.mod h1:9MaHIaRuy9pvLPUJxB8sh8OrLfyDczECVL37grCIubs=
|
github.com/couchbase/moss v0.1.0/go.mod h1:9MaHIaRuy9pvLPUJxB8sh8OrLfyDczECVL37grCIubs=
|
||||||
github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE=
|
github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE=
|
||||||
github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
github.com/cpuguy83/go-md2man/v2 v2.0.6 h1:XJtiaUW6dEEqVuZiMTn1ldk455QWwEIsMIJlo5vtkx0=
|
||||||
github.com/cpuguy83/go-md2man/v2 v2.0.5 h1:ZtcqGrnekaHpVLArFSe4HK5DoKx1T0rq2DwVB0alcyc=
|
github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
|
||||||
github.com/cpuguy83/go-md2man/v2 v2.0.5/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
|
||||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||||
github.com/creack/pty v1.1.21 h1:1/QdRyBaHHJP61QkWMXlOIBfsgdDeeKfK8SYVUWJKf0=
|
github.com/creack/pty v1.1.21 h1:1/QdRyBaHHJP61QkWMXlOIBfsgdDeeKfK8SYVUWJKf0=
|
||||||
github.com/creack/pty v1.1.21/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4=
|
github.com/creack/pty v1.1.21/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4=
|
||||||
@@ -251,6 +250,8 @@ github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/r
|
|||||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
|
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
|
||||||
github.com/dimiro1/reply v0.0.0-20200315094148-d0136a4c9e21 h1:PdsjTl0Cg+ZJgOx/CFV5NNgO1ThTreqdgKYiDCMHJwA=
|
github.com/dimiro1/reply v0.0.0-20200315094148-d0136a4c9e21 h1:PdsjTl0Cg+ZJgOx/CFV5NNgO1ThTreqdgKYiDCMHJwA=
|
||||||
github.com/dimiro1/reply v0.0.0-20200315094148-d0136a4c9e21/go.mod h1:xJvkyD6Y2rZapGvPJLYo9dyx1s5dxBEDPa8T3YTuOk0=
|
github.com/dimiro1/reply v0.0.0-20200315094148-d0136a4c9e21/go.mod h1:xJvkyD6Y2rZapGvPJLYo9dyx1s5dxBEDPa8T3YTuOk0=
|
||||||
|
github.com/distribution/distribution v2.8.3+incompatible h1:RlpEXBLq/WPXYvBYMDAmBX/SnhD67qwtvW/DzKc8pAo=
|
||||||
|
github.com/distribution/distribution v2.8.3+incompatible/go.mod h1:EgLm2NgWtdKgzF9NpMzUKgzmR7AMmb0VQi2B+ZzDRjc=
|
||||||
github.com/distribution/reference v0.5.0 h1:/FUIFXtfc/x2gpa5/VGfiGLuOIdYa1t65IKK2OFGvA0=
|
github.com/distribution/reference v0.5.0 h1:/FUIFXtfc/x2gpa5/VGfiGLuOIdYa1t65IKK2OFGvA0=
|
||||||
github.com/distribution/reference v0.5.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E=
|
github.com/distribution/reference v0.5.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E=
|
||||||
github.com/djherbis/buffer v1.1.0/go.mod h1:VwN8VdFkMY0DCALdY8o00d3IZ6Amz/UNVMWcSaJT44o=
|
github.com/djherbis/buffer v1.1.0/go.mod h1:VwN8VdFkMY0DCALdY8o00d3IZ6Amz/UNVMWcSaJT44o=
|
||||||
@@ -263,8 +264,6 @@ github.com/dlclark/regexp2 v1.4.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55k
|
|||||||
github.com/dlclark/regexp2 v1.7.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
|
github.com/dlclark/regexp2 v1.7.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
|
||||||
github.com/dlclark/regexp2 v1.11.5 h1:Q/sSnsKerHeCkc/jSTNq1oCm7KiVgUMZRDUoRu0JQZQ=
|
github.com/dlclark/regexp2 v1.11.5 h1:Q/sSnsKerHeCkc/jSTNq1oCm7KiVgUMZRDUoRu0JQZQ=
|
||||||
github.com/dlclark/regexp2 v1.11.5/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
|
github.com/dlclark/regexp2 v1.11.5/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
|
||||||
github.com/docker/distribution v2.8.3+incompatible h1:AtKxIZ36LoNK51+Z6RpzLpddBirtxJnzDrHLEKxTAYk=
|
|
||||||
github.com/docker/distribution v2.8.3+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
|
|
||||||
github.com/docker/docker v24.0.9+incompatible h1:HPGzNmwfLZWdxHqK9/II92pyi1EpYKsAqcl4G0Of9v0=
|
github.com/docker/docker v24.0.9+incompatible h1:HPGzNmwfLZWdxHqK9/II92pyi1EpYKsAqcl4G0Of9v0=
|
||||||
github.com/docker/docker v24.0.9+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
github.com/docker/docker v24.0.9+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
||||||
github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ=
|
github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ=
|
||||||
@@ -289,8 +288,8 @@ github.com/emersion/go-sasl v0.0.0-20200509203442-7bfe0ed36a21/go.mod h1:iL2twTe
|
|||||||
github.com/emersion/go-sasl v0.0.0-20241020182733-b788ff22d5a6 h1:oP4q0fw+fOSWn3DfFi4EXdT+B+gTtzx8GC9xsc26Znk=
|
github.com/emersion/go-sasl v0.0.0-20241020182733-b788ff22d5a6 h1:oP4q0fw+fOSWn3DfFi4EXdT+B+gTtzx8GC9xsc26Znk=
|
||||||
github.com/emersion/go-sasl v0.0.0-20241020182733-b788ff22d5a6/go.mod h1:iL2twTeMvZnrg54ZoPDNfJaJaqy0xIQFuBdrLsmspwQ=
|
github.com/emersion/go-sasl v0.0.0-20241020182733-b788ff22d5a6/go.mod h1:iL2twTeMvZnrg54ZoPDNfJaJaqy0xIQFuBdrLsmspwQ=
|
||||||
github.com/emersion/go-textwrapper v0.0.0-20200911093747-65d896831594/go.mod h1:aqO8z8wPrjkscevZJFVE1wXJrLpC5LtJG7fqLOsPb2U=
|
github.com/emersion/go-textwrapper v0.0.0-20200911093747-65d896831594/go.mod h1:aqO8z8wPrjkscevZJFVE1wXJrLpC5LtJG7fqLOsPb2U=
|
||||||
github.com/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxERmMY4rD+g=
|
github.com/emicklei/go-restful/v3 v3.12.2 h1:DhwDP0vY3k8ZzE0RunuJy8GhNpPL6zqLkDf9B/a0/xU=
|
||||||
github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
|
github.com/emicklei/go-restful/v3 v3.12.2/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
|
||||||
github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc=
|
github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc=
|
||||||
github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ=
|
github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ=
|
||||||
github.com/ethantkoenig/rupture v1.0.1 h1:6aAXghmvtnngMgQzy7SMGdicMvkV86V4n9fT0meE5E4=
|
github.com/ethantkoenig/rupture v1.0.1 h1:6aAXghmvtnngMgQzy7SMGdicMvkV86V4n9fT0meE5E4=
|
||||||
@@ -311,8 +310,8 @@ github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMo
|
|||||||
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
||||||
github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k=
|
github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k=
|
||||||
github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
|
github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
|
||||||
github.com/fxamacker/cbor/v2 v2.8.0 h1:fFtUGXUzXPHTIUdne5+zzMPTfffl3RD5qYnkY40vtxU=
|
github.com/fxamacker/cbor/v2 v2.9.0 h1:NpKPmjDBgUfBms6tr6JZkTHtfFGcMKsw3eGcmD/sapM=
|
||||||
github.com/fxamacker/cbor/v2 v2.8.0/go.mod h1:vM4b+DJCtHn+zz7h3FFp/hDAI9WNWCsZj23V5ytsSxQ=
|
github.com/fxamacker/cbor/v2 v2.9.0/go.mod h1:vM4b+DJCtHn+zz7h3FFp/hDAI9WNWCsZj23V5ytsSxQ=
|
||||||
github.com/git-lfs/pktline v0.0.0-20230103162542-ca444d533ef1 h1:mtDjlmloH7ytdblogrMz1/8Hqua1y8B4ID+bh3rvod0=
|
github.com/git-lfs/pktline v0.0.0-20230103162542-ca444d533ef1 h1:mtDjlmloH7ytdblogrMz1/8Hqua1y8B4ID+bh3rvod0=
|
||||||
github.com/git-lfs/pktline v0.0.0-20230103162542-ca444d533ef1/go.mod h1:fenKRzpXDjNpsIBhuhUzvjCKlDjKam0boRAenTE0Q6A=
|
github.com/git-lfs/pktline v0.0.0-20230103162542-ca444d533ef1/go.mod h1:fenKRzpXDjNpsIBhuhUzvjCKlDjKam0boRAenTE0Q6A=
|
||||||
github.com/gliderlabs/ssh v0.3.8 h1:a4YXD1V7xMF9g5nTkdfnja3Sxy1PVDCj1Zg4Wb8vY6c=
|
github.com/gliderlabs/ssh v0.3.8 h1:a4YXD1V7xMF9g5nTkdfnja3Sxy1PVDCj1Zg4Wb8vY6c=
|
||||||
@@ -379,7 +378,6 @@ github.com/go-redsync/redsync/v4 v4.13.0 h1:49X6GJfnbLGaIpBBREM/zA4uIMDXKAh1NDkv
|
|||||||
github.com/go-redsync/redsync/v4 v4.13.0/go.mod h1:HMW4Q224GZQz6x1Xc7040Yfgacukdzu7ifTDAKiyErQ=
|
github.com/go-redsync/redsync/v4 v4.13.0/go.mod h1:HMW4Q224GZQz6x1Xc7040Yfgacukdzu7ifTDAKiyErQ=
|
||||||
github.com/go-sql-driver/mysql v1.9.2 h1:4cNKDYQ1I84SXslGddlsrMhc8k4LeDVj6Ad6WRjiHuU=
|
github.com/go-sql-driver/mysql v1.9.2 h1:4cNKDYQ1I84SXslGddlsrMhc8k4LeDVj6Ad6WRjiHuU=
|
||||||
github.com/go-sql-driver/mysql v1.9.2/go.mod h1:qn46aNg1333BRMNU69Lq93t8du/dwxI64Gl8i5p1WMU=
|
github.com/go-sql-driver/mysql v1.9.2/go.mod h1:qn46aNg1333BRMNU69Lq93t8du/dwxI64Gl8i5p1WMU=
|
||||||
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 h1:p104kn46Q8WdvHunIJ9dAyjPVtrBPhSr3KT2yUst43I=
|
|
||||||
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
|
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
|
||||||
github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI=
|
github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI=
|
||||||
github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=
|
github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=
|
||||||
@@ -432,19 +430,18 @@ github.com/gomodule/redigo v1.8.9 h1:Sl3u+2BI/kk+VEatbj0scLdrFhjPmbxOc1myhDP41ws
|
|||||||
github.com/gomodule/redigo v1.8.9/go.mod h1:7ArFNvsTjH8GMMzB4uy1snslv2BwmginuMs06a1uzZE=
|
github.com/gomodule/redigo v1.8.9/go.mod h1:7ArFNvsTjH8GMMzB4uy1snslv2BwmginuMs06a1uzZE=
|
||||||
github.com/google/btree v1.1.3 h1:CVpQJjYgC4VbzxeGVHfvZrv1ctoYCAI8vbl07Fcxlyg=
|
github.com/google/btree v1.1.3 h1:CVpQJjYgC4VbzxeGVHfvZrv1ctoYCAI8vbl07Fcxlyg=
|
||||||
github.com/google/btree v1.1.3/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4=
|
github.com/google/btree v1.1.3/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4=
|
||||||
github.com/google/cel-go v0.23.2 h1:UdEe3CvQh3Nv+E/j9r1Y//WO0K0cSyD7/y0bzyLIMI4=
|
github.com/google/cel-go v0.26.0 h1:DPGjXackMpJWH680oGY4lZhYjIameYmR+/6RBdDGmaI=
|
||||||
github.com/google/cel-go v0.23.2/go.mod h1:52Pb6QsDbC5kvgxvZhiL9QX1oZEkcUF/ZqaPx1J5Wwo=
|
github.com/google/cel-go v0.26.0/go.mod h1:A9O8OU9rdvrK5MQyrqfIxo1a0u4g3sF8KB6PUIaryMM=
|
||||||
github.com/google/flatbuffers v24.3.25+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8=
|
github.com/google/flatbuffers v24.3.25+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8=
|
||||||
github.com/google/flatbuffers v25.2.10+incompatible h1:F3vclr7C3HpB1k9mxCGRMXq6FdUalZ6H/pNX4FP1v0Q=
|
github.com/google/flatbuffers v25.2.10+incompatible h1:F3vclr7C3HpB1k9mxCGRMXq6FdUalZ6H/pNX4FP1v0Q=
|
||||||
github.com/google/flatbuffers v25.2.10+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8=
|
github.com/google/flatbuffers v25.2.10+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8=
|
||||||
github.com/google/gnostic-models v0.6.9 h1:MU/8wDLif2qCXZmzncUQ/BOfxWfthHi63KqpoNbWqVw=
|
github.com/google/gnostic-models v0.7.0 h1:qwTtogB15McXDaNqTZdzPJRHvaVJlAl+HVQnLmJEJxo=
|
||||||
github.com/google/gnostic-models v0.6.9/go.mod h1:CiWsm0s6BSQd1hRn8/QmxqB6BesYcbSZxsz9b0KuDBw=
|
github.com/google/gnostic-models v0.7.0/go.mod h1:whL5G0m6dmc5cPxKc5bdKdEN3UjI7OUGxBlw57miDrQ=
|
||||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||||
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||||
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
|
||||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||||
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
||||||
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
||||||
@@ -484,8 +481,10 @@ github.com/gorilla/securecookie v1.1.2/go.mod h1:NfCASbcHqRSY+3a8tlWJwsQap2VX5pw
|
|||||||
github.com/gorilla/sessions v1.2.0/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM=
|
github.com/gorilla/sessions v1.2.0/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM=
|
||||||
github.com/gorilla/sessions v1.4.0 h1:kpIYOp/oi6MG/p5PgxApU8srsSw9tuFbt46Lt7auzqQ=
|
github.com/gorilla/sessions v1.4.0 h1:kpIYOp/oi6MG/p5PgxApU8srsSw9tuFbt46Lt7auzqQ=
|
||||||
github.com/gorilla/sessions v1.4.0/go.mod h1:FLWm50oby91+hl7p/wRxDth9bWSuk0qVL2emc7lT5ik=
|
github.com/gorilla/sessions v1.4.0/go.mod h1:FLWm50oby91+hl7p/wRxDth9bWSuk0qVL2emc7lT5ik=
|
||||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.24.0 h1:TmHmbvxPmaegwhDubVz0lICL0J5Ka2vwTzhoePEXsGE=
|
github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674 h1:JeSE6pjso5THxAzdVpqr6/geYxZytqFMBCOtn/ujyeo=
|
||||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.24.0/go.mod h1:qztMSjm835F2bXf+5HKAPIS5qsmQDqZna/PgVt4rWtI=
|
github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674/go.mod h1:r4w70xmWCQKmi1ONH4KIaBptdivuRPyosB9RmPlGEwA=
|
||||||
|
github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3 h1:5ZPtiqj0JL5oKWmcsq4VMaAW5ukBEgSGXEN89zeH1Jo=
|
||||||
|
github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3/go.mod h1:ndYquD05frm2vACXE1nsccT4oJzjhw2arTS2cpUD1PI=
|
||||||
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||||
github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I=
|
github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I=
|
||||||
github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||||
@@ -609,13 +608,16 @@ github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrk
|
|||||||
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||||
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
|
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
|
||||||
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||||
|
github.com/moby/spdystream v0.5.0 h1:7r0J1Si3QO/kjRitvSLVVFUjxMEb/YLj6S9FF62JBCU=
|
||||||
|
github.com/moby/spdystream v0.5.0/go.mod h1:xBAYlnt/ay+11ShkdFKNAG7LsyK/tmNBVvVOwrfMgdI=
|
||||||
github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0=
|
github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0=
|
||||||
github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y=
|
github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y=
|
||||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
|
||||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||||
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
|
|
||||||
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
||||||
|
github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee h1:W5t00kpgFdJifH4BDsTlE89Zl93FEloxaWZfGcifgq8=
|
||||||
|
github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
||||||
github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A=
|
github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A=
|
||||||
github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc=
|
github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc=
|
||||||
github.com/mrjones/oauth v0.0.0-20190623134757-126b35219450 h1:j2kD3MT1z4PXCiUllUJF9mWUESr9TWKS7iEKsQ/IipM=
|
github.com/mrjones/oauth v0.0.0-20190623134757-126b35219450 h1:j2kD3MT1z4PXCiUllUJF9mWUESr9TWKS7iEKsQ/IipM=
|
||||||
@@ -627,6 +629,8 @@ github.com/msteinert/pam v1.2.0 h1:mYfjlvN2KYs2Pb9G6nb/1f/nPfAttT/Jee5Sq9r3bGE=
|
|||||||
github.com/msteinert/pam v1.2.0/go.mod h1:d2n0DCUK8rGecChV3JzvmsDjOY4R7AYbsNxAT+ftQl0=
|
github.com/msteinert/pam v1.2.0/go.mod h1:d2n0DCUK8rGecChV3JzvmsDjOY4R7AYbsNxAT+ftQl0=
|
||||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
|
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
|
||||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
|
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
|
||||||
|
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f h1:y5//uYreIhSUg3J1GEMiLbxo1LJaP8RfCpH6pymGZus=
|
||||||
|
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw=
|
||||||
github.com/niklasfasching/go-org v1.8.0 h1:WyGLaajLLp8JbQzkmapZ1y0MOzKuKV47HkZRloi+HGY=
|
github.com/niklasfasching/go-org v1.8.0 h1:WyGLaajLLp8JbQzkmapZ1y0MOzKuKV47HkZRloi+HGY=
|
||||||
github.com/niklasfasching/go-org v1.8.0/go.mod h1:e2A9zJs7cdONrEGs3gvxCcaAEpwwPNPG7csDpXckMNg=
|
github.com/niklasfasching/go-org v1.8.0/go.mod h1:e2A9zJs7cdONrEGs3gvxCcaAEpwwPNPG7csDpXckMNg=
|
||||||
github.com/nwaples/rardecode v1.1.0/go.mod h1:5DzqNKiOdpKKBH87u8VlvAnPZMXcGRhxWkRpHbbfGS0=
|
github.com/nwaples/rardecode v1.1.0/go.mod h1:5DzqNKiOdpKKBH87u8VlvAnPZMXcGRhxWkRpHbbfGS0=
|
||||||
@@ -731,11 +735,10 @@ github.com/smartystreets/goconvey v0.0.0-20190731233626-505e41936337/go.mod h1:s
|
|||||||
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
|
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
|
||||||
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
|
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
|
||||||
github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU=
|
github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU=
|
||||||
github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM=
|
github.com/spf13/cobra v1.9.1 h1:CXSaggrXdbHK9CF+8ywj8Amf7PBRmPCOJugH954Nnlo=
|
||||||
github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y=
|
github.com/spf13/cobra v1.9.1/go.mod h1:nDyEzZ8ogv936Cinf6g1RU9MRY64Ir93oCnqb9wxYW0=
|
||||||
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
|
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
|
||||||
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||||
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
|
||||||
github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o=
|
github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o=
|
||||||
github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||||
github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s=
|
github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s=
|
||||||
@@ -823,28 +826,28 @@ github.com/zeebo/pcg v1.0.1/go.mod h1:09F0S9iiKrwn9rlI5yjLkmrug154/YRW6KnnXVDM/l
|
|||||||
gitlab.com/gitlab-org/api/client-go v0.127.0 h1:8xnxcNKGF2gDazEoMs+hOZfOspSSw8D0vAoWhQk9U+U=
|
gitlab.com/gitlab-org/api/client-go v0.127.0 h1:8xnxcNKGF2gDazEoMs+hOZfOspSSw8D0vAoWhQk9U+U=
|
||||||
gitlab.com/gitlab-org/api/client-go v0.127.0/go.mod h1:bYC6fPORKSmtuPRyD9Z2rtbAjE7UeNatu2VWHRf4/LE=
|
gitlab.com/gitlab-org/api/client-go v0.127.0/go.mod h1:bYC6fPORKSmtuPRyD9Z2rtbAjE7UeNatu2VWHRf4/LE=
|
||||||
go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ=
|
go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ=
|
||||||
go.etcd.io/bbolt v1.4.0 h1:TU77id3TnN/zKr7CO/uk+fBCwF2jGcMuw2B/FMAzYIk=
|
go.etcd.io/bbolt v1.4.2 h1:IrUHp260R8c+zYx/Tm8QZr04CX+qWS5PGfPdevhdm1I=
|
||||||
go.etcd.io/bbolt v1.4.0/go.mod h1:AsD+OCi/qPN1giOX1aiLAha3o1U8rAz65bvN4j0sRuk=
|
go.etcd.io/bbolt v1.4.2/go.mod h1:Is8rSHO/b4f3XigBC0lL0+4FwAQv3HXEEIgFMuKHceM=
|
||||||
go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
|
go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
|
||||||
go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
|
go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
|
||||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.58.0 h1:yd02MEjBdJkG3uabWP9apV+OuWRIXGDuJEUJbOHmCFU=
|
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.58.0 h1:yd02MEjBdJkG3uabWP9apV+OuWRIXGDuJEUJbOHmCFU=
|
||||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.58.0/go.mod h1:umTcuxiv1n/s/S6/c2AT/g2CQ7u5C59sHDNmfSwgz7Q=
|
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.58.0/go.mod h1:umTcuxiv1n/s/S6/c2AT/g2CQ7u5C59sHDNmfSwgz7Q=
|
||||||
go.opentelemetry.io/otel v1.34.0 h1:zRLXxLCgL1WyKsPVrgbSdMN4c0FMkDAskSTQP+0hdUY=
|
go.opentelemetry.io/otel v1.35.0 h1:xKWKPxrxB6OtMCbmMY021CqC45J+3Onta9MqjhnusiQ=
|
||||||
go.opentelemetry.io/otel v1.34.0/go.mod h1:OWFPOQ+h4G8xpyjgqo4SxJYdDQ/qmRH+wivy7zzx9oI=
|
go.opentelemetry.io/otel v1.35.0/go.mod h1:UEqy8Zp11hpkUrL73gSlELM0DupHoiq72dR+Zqel/+Y=
|
||||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.33.0 h1:Vh5HayB/0HHfOQA7Ctx69E/Y/DcQSMPpKANYVMQ7fBA=
|
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.34.0 h1:OeNbIYk/2C15ckl7glBlOBp5+WlYsOElzTNmiPW/x60=
|
||||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.33.0/go.mod h1:cpgtDBaqD/6ok/UG0jT15/uKjAY8mRA53diogHBg3UI=
|
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.34.0/go.mod h1:7Bept48yIeqxP2OZ9/AqIpYS94h2or0aB4FypJTc8ZM=
|
||||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.33.0 h1:5pojmb1U1AogINhN3SurB+zm/nIcusopeBNp42f45QM=
|
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.34.0 h1:tgJ0uaNS4c98WRNUEx5U3aDlrDOI5Rs+1Vifcw4DJ8U=
|
||||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.33.0/go.mod h1:57gTHJSE5S1tqg+EKsLPlTWhpHMsWlVmer+LA926XiA=
|
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.34.0/go.mod h1:U7HYyW0zt/a9x5J1Kjs+r1f/d4ZHnYFclhYY2+YbeoE=
|
||||||
go.opentelemetry.io/otel/metric v1.34.0 h1:+eTR3U0MyfWjRDhmFMxe2SsW64QrZ84AOhvqS7Y+PoQ=
|
go.opentelemetry.io/otel/metric v1.35.0 h1:0znxYu2SNyuMSQT4Y9WDWej0VpcsxkuklLa4/siN90M=
|
||||||
go.opentelemetry.io/otel/metric v1.34.0/go.mod h1:CEDrp0fy2D0MvkXE+dPV7cMi8tWZwX3dmaIhwPOaqHE=
|
go.opentelemetry.io/otel/metric v1.35.0/go.mod h1:nKVFgxBZ2fReX6IlyW28MgZojkoAkJGaE8CpgeAU3oE=
|
||||||
go.opentelemetry.io/otel/sdk v1.34.0 h1:95zS4k/2GOy069d321O8jWgYsW3MzVV+KuSPKp7Wr1A=
|
go.opentelemetry.io/otel/sdk v1.34.0 h1:95zS4k/2GOy069d321O8jWgYsW3MzVV+KuSPKp7Wr1A=
|
||||||
go.opentelemetry.io/otel/sdk v1.34.0/go.mod h1:0e/pNiaMAqaykJGKbi+tSjWfNNHMTxoC9qANsCzbyxU=
|
go.opentelemetry.io/otel/sdk v1.34.0/go.mod h1:0e/pNiaMAqaykJGKbi+tSjWfNNHMTxoC9qANsCzbyxU=
|
||||||
go.opentelemetry.io/otel/sdk/metric v1.34.0 h1:5CeK9ujjbFVL5c1PhLuStg1wxA7vQv7ce1EK0Gyvahk=
|
go.opentelemetry.io/otel/sdk/metric v1.34.0 h1:5CeK9ujjbFVL5c1PhLuStg1wxA7vQv7ce1EK0Gyvahk=
|
||||||
go.opentelemetry.io/otel/sdk/metric v1.34.0/go.mod h1:jQ/r8Ze28zRKoNRdkjCZxfs6YvBTG1+YIqyFVFYec5w=
|
go.opentelemetry.io/otel/sdk/metric v1.34.0/go.mod h1:jQ/r8Ze28zRKoNRdkjCZxfs6YvBTG1+YIqyFVFYec5w=
|
||||||
go.opentelemetry.io/otel/trace v1.34.0 h1:+ouXS2V8Rd4hp4580a8q23bg0azF2nI8cqLYnC8mh/k=
|
go.opentelemetry.io/otel/trace v1.35.0 h1:dPpEfJu1sDIqruz7BHFG3c7528f6ddfSWfFDVt/xgMs=
|
||||||
go.opentelemetry.io/otel/trace v1.34.0/go.mod h1:Svm7lSjQD7kG7KJ/MUHPVXSDGz2OX4h0M2jHBhmSfRE=
|
go.opentelemetry.io/otel/trace v1.35.0/go.mod h1:WUk7DtFp1Aw2MkvqGdwiXYDZZNvA/1J8o6xRXLrIkyc=
|
||||||
go.opentelemetry.io/proto/otlp v1.4.0 h1:TA9WRvW6zMwP+Ssb6fLoUIuirti1gGbP28GcKG1jgeg=
|
go.opentelemetry.io/proto/otlp v1.5.0 h1:xJvq7gMzB31/d406fB8U5CBdyQGw4P399D1aQWU/3i4=
|
||||||
go.opentelemetry.io/proto/otlp v1.4.0/go.mod h1:PPBWZIP98o2ElSqI35IHfu7hIhSwvc5N38Jw8pXuGFY=
|
go.opentelemetry.io/proto/otlp v1.5.0/go.mod h1:keN8WnHxOy8PG0rQZjJJ5A2ebUoafqWp0eVQ4yIXvJ4=
|
||||||
go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
|
go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
|
||||||
go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE=
|
go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE=
|
||||||
go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=
|
go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=
|
||||||
@@ -856,6 +859,10 @@ go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
|
|||||||
go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
|
go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
|
||||||
go.uber.org/zap/exp v0.3.0 h1:6JYzdifzYkGmTdRR59oYH+Ng7k49H9qVpWwNSsGJj3U=
|
go.uber.org/zap/exp v0.3.0 h1:6JYzdifzYkGmTdRR59oYH+Ng7k49H9qVpWwNSsGJj3U=
|
||||||
go.uber.org/zap/exp v0.3.0/go.mod h1:5I384qq7XGxYyByIhHm6jg5CHkGY0nsTfbDLgDDlgJQ=
|
go.uber.org/zap/exp v0.3.0/go.mod h1:5I384qq7XGxYyByIhHm6jg5CHkGY0nsTfbDLgDDlgJQ=
|
||||||
|
go.yaml.in/yaml/v2 v2.4.2 h1:DzmwEr2rDGHl7lsFgAHxmNz/1NlQ7xLIrlN2h5d1eGI=
|
||||||
|
go.yaml.in/yaml/v2 v2.4.2/go.mod h1:081UH+NErpNdqlCXm3TtEran0rJZGxAYx9hb/ELlsPU=
|
||||||
|
go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc=
|
||||||
|
go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=
|
||||||
golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
@@ -1009,8 +1016,8 @@ google.golang.org/genproto/googleapis/api v0.0.0-20250324211829-b45e905df463 h1:
|
|||||||
google.golang.org/genproto/googleapis/api v0.0.0-20250324211829-b45e905df463/go.mod h1:U90ffi8eUL9MwPcrJylN5+Mk2v3vuPDptd5yyNUiRR8=
|
google.golang.org/genproto/googleapis/api v0.0.0-20250324211829-b45e905df463/go.mod h1:U90ffi8eUL9MwPcrJylN5+Mk2v3vuPDptd5yyNUiRR8=
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250422160041-2d3770c4ea7f h1:N/PrbTw4kdkqNRzVfWPrBekzLuarFREcbFOiOLkXon4=
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20250422160041-2d3770c4ea7f h1:N/PrbTw4kdkqNRzVfWPrBekzLuarFREcbFOiOLkXon4=
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250422160041-2d3770c4ea7f/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A=
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20250422160041-2d3770c4ea7f/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A=
|
||||||
google.golang.org/grpc v1.72.0 h1:S7UkcVa60b5AAQTaO6ZKamFp1zMZSU0fGDK2WZLbBnM=
|
google.golang.org/grpc v1.72.1 h1:HR03wO6eyZ7lknl75XlxABNVLLFc2PAb6mHlYh756mA=
|
||||||
google.golang.org/grpc v1.72.0/go.mod h1:wH5Aktxcg25y1I3w7H69nHfXdOG3UiadoBtjh3izSDM=
|
google.golang.org/grpc v1.72.1/go.mod h1:wH5Aktxcg25y1I3w7H69nHfXdOG3UiadoBtjh3izSDM=
|
||||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||||
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
||||||
@@ -1049,28 +1056,30 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
|||||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
gotest.tools/v3 v3.5.1 h1:EENdUnS3pdur5nybKYIh2Vfgc8IUNBjxDPSjtiJcOzU=
|
gotest.tools/v3 v3.5.1 h1:EENdUnS3pdur5nybKYIh2Vfgc8IUNBjxDPSjtiJcOzU=
|
||||||
gotest.tools/v3 v3.5.1/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU=
|
gotest.tools/v3 v3.5.1/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU=
|
||||||
istio.io/api v1.26.3 h1:/TiA7bJi24yBQSgpLy5vHhFkobf4DWS1L+CuUxNk4os=
|
istio.io/api v1.27.2 h1:t0m2EAT+LWGA/jSvsyxEhGQoIQYdXD5sJG7tQ9OtQk0=
|
||||||
istio.io/api v1.26.3/go.mod h1:DTVGH6CLXj5W8FF9JUD3Tis78iRgT1WeuAnxfTz21Wg=
|
istio.io/api v1.27.2/go.mod h1:DTVGH6CLXj5W8FF9JUD3Tis78iRgT1WeuAnxfTz21Wg=
|
||||||
istio.io/client-go v1.26.3 h1:ryF4+Nyz5wDO4mVCzXcm2W+fqbnekY88Z36hTcv5fnw=
|
istio.io/client-go v1.27.2 h1:4IsF7UAdV5Yg0iq6ONyWZpjFr3z2ahkIbLWyzOHCAwA=
|
||||||
istio.io/client-go v1.26.3/go.mod h1:u2p5L7UvjNswrrlHZ+QMlUOjERK2sXputywzyNhtTMg=
|
istio.io/client-go v1.27.2/go.mod h1:zgT5R1USl6rwYK1eb2kisPuiji05TQJE7CQHU253iAg=
|
||||||
k8s.io/api v0.33.3 h1:SRd5t//hhkI1buzxb288fy2xvjubstenEKL9K51KBI8=
|
k8s.io/api v0.34.1 h1:jC+153630BMdlFukegoEL8E/yT7aLyQkIVuwhmwDgJM=
|
||||||
k8s.io/api v0.33.3/go.mod h1:01Y/iLUjNBM3TAvypct7DIj0M0NIZc+PzAHCIo0CYGE=
|
k8s.io/api v0.34.1/go.mod h1:SB80FxFtXn5/gwzCoN6QCtPD7Vbu5w2n1S0J5gFfTYk=
|
||||||
k8s.io/apiextensions-apiserver v0.33.0 h1:d2qpYL7Mngbsc1taA4IjJPRJ9ilnsXIrndH+r9IimOs=
|
k8s.io/apiextensions-apiserver v0.34.1 h1:NNPBva8FNAPt1iSVwIE0FsdrVriRXMsaWFMqJbII2CI=
|
||||||
k8s.io/apiextensions-apiserver v0.33.0/go.mod h1:VeJ8u9dEEN+tbETo+lFkwaaZPg6uFKLGj5vyNEwwSzc=
|
k8s.io/apiextensions-apiserver v0.34.1/go.mod h1:hP9Rld3zF5Ay2Of3BeEpLAToP+l4s5UlxiHfqRaRcMc=
|
||||||
k8s.io/apimachinery v0.33.3 h1:4ZSrmNa0c/ZpZJhAgRdcsFcZOw1PQU1bALVQ0B3I5LA=
|
k8s.io/apimachinery v0.34.1 h1:dTlxFls/eikpJxmAC7MVE8oOeP1zryV7iRyIjB0gky4=
|
||||||
k8s.io/apimachinery v0.33.3/go.mod h1:BHW0YOu7n22fFv/JkYOEfkUYNRN0fj0BlvMFWA7b+SM=
|
k8s.io/apimachinery v0.34.1/go.mod h1:/GwIlEcWuTX9zKIg2mbw0LRFIsXwrfoVxn+ef0X13lw=
|
||||||
k8s.io/apiserver v0.33.0 h1:QqcM6c+qEEjkOODHppFXRiw/cE2zP85704YrQ9YaBbc=
|
k8s.io/apiserver v0.34.1 h1:U3JBGdgANK3dfFcyknWde1G6X1F4bg7PXuvlqt8lITA=
|
||||||
k8s.io/apiserver v0.33.0/go.mod h1:EixYOit0YTxt8zrO2kBU7ixAtxFce9gKGq367nFmqI8=
|
k8s.io/apiserver v0.34.1/go.mod h1:eOOc9nrVqlBI1AFCvVzsob0OxtPZUCPiUJL45JOTBG0=
|
||||||
k8s.io/client-go v0.33.3 h1:M5AfDnKfYmVJif92ngN532gFqakcGi6RvaOF16efrpA=
|
k8s.io/client-go v0.34.1 h1:ZUPJKgXsnKwVwmKKdPfw4tB58+7/Ik3CrjOEhsiZ7mY=
|
||||||
k8s.io/client-go v0.33.3/go.mod h1:luqKBQggEf3shbxHY4uVENAxrDISLOarxpTKMiUuujg=
|
k8s.io/client-go v0.34.1/go.mod h1:kA8v0FP+tk6sZA0yKLRG67LWjqufAoSHA2xVGKw9Of8=
|
||||||
k8s.io/component-base v0.33.3 h1:mlAuyJqyPlKZM7FyaoM/LcunZaaY353RXiOd2+B5tGA=
|
k8s.io/component-base v0.34.1 h1:v7xFgG+ONhytZNFpIz5/kecwD+sUhVE6HU7qQUiRM4A=
|
||||||
k8s.io/component-base v0.33.3/go.mod h1:ktBVsBzkI3imDuxYXmVxZ2zxJnYTZ4HAsVj9iF09qp4=
|
k8s.io/component-base v0.34.1/go.mod h1:mknCpLlTSKHzAQJJnnHVKqjxR7gBeHRv0rPXA7gdtQ0=
|
||||||
k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk=
|
k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk=
|
||||||
k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
|
k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
|
||||||
k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff h1:/usPimJzUKKu+m+TE36gUyGcf03XZEP0ZIKgKj35LS4=
|
k8s.io/kube-openapi v0.0.0-20250710124328-f3f2b991d03b h1:MloQ9/bdJyIu9lb1PzujOPolHyvO06MXG5TUIj2mNAA=
|
||||||
k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff/go.mod h1:5jIi+8yX4RIb8wk3XwBo5Pq2ccx4FP10ohkbSKCZoK8=
|
k8s.io/kube-openapi v0.0.0-20250710124328-f3f2b991d03b/go.mod h1:UZ2yyWbFTpuhSbFhv24aGNOdoRdJZgsIObGBUaYVsts=
|
||||||
k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 h1:M3sRQVHv7vB20Xc2ybTt7ODCeFj6JSWYFzOFnYeS6Ro=
|
k8s.io/kubectl v0.34.1 h1:1qP1oqT5Xc93K+H8J7ecpBjaz511gan89KO9Vbsh/OI=
|
||||||
k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
|
k8s.io/kubectl v0.34.1/go.mod h1:JRYlhJpGPyk3dEmJ+BuBiOB9/dAvnrALJEiY/C5qa6A=
|
||||||
|
k8s.io/utils v0.0.0-20250604170112-4c0f3b243397 h1:hwvWFiBzdWw1FhfY1FooPn3kzWuJ8tmbZBHi4zVsl1Y=
|
||||||
|
k8s.io/utils v0.0.0-20250604170112-4c0f3b243397/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
|
||||||
lukechampine.com/uint128 v1.2.0 h1:mBi/5l91vocEN8otkC5bDLhi2KdCticRiwbdB0O+rjI=
|
lukechampine.com/uint128 v1.2.0 h1:mBi/5l91vocEN8otkC5bDLhi2KdCticRiwbdB0O+rjI=
|
||||||
lukechampine.com/uint128 v1.2.0/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk=
|
lukechampine.com/uint128 v1.2.0/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk=
|
||||||
modernc.org/cc/v3 v3.40.0 h1:P3g79IUS/93SYhtoeaHW+kRCIrYaxJ27MFPv+7kaTOw=
|
modernc.org/cc/v3 v3.40.0 h1:P3g79IUS/93SYhtoeaHW+kRCIrYaxJ27MFPv+7kaTOw=
|
||||||
@@ -1097,17 +1106,16 @@ pgregory.net/rapid v0.4.2 h1:lsi9jhvZTYvzVpeG93WWgimPRmiJQfGFRNTEZh1dtY0=
|
|||||||
pgregory.net/rapid v0.4.2/go.mod h1:UYpPVyjFHzYBGHIxLFoupi8vwk6rXNzRY9OMvVxFIOU=
|
pgregory.net/rapid v0.4.2/go.mod h1:UYpPVyjFHzYBGHIxLFoupi8vwk6rXNzRY9OMvVxFIOU=
|
||||||
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.2 h1:jpcvIRr3GLoUoEKRkHKSmGjxb6lWwrBlJsXc+eUYQHM=
|
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.2 h1:jpcvIRr3GLoUoEKRkHKSmGjxb6lWwrBlJsXc+eUYQHM=
|
||||||
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.2/go.mod h1:Ve9uj1L+deCXFrPOk1LpFXqTg7LCFzFso6PA48q/XZw=
|
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.2/go.mod h1:Ve9uj1L+deCXFrPOk1LpFXqTg7LCFzFso6PA48q/XZw=
|
||||||
sigs.k8s.io/controller-runtime v0.21.0 h1:CYfjpEuicjUecRk+KAeyYh+ouUBn4llGyDYytIGcJS8=
|
sigs.k8s.io/controller-runtime v0.22.3 h1:I7mfqz/a/WdmDCEnXmSPm8/b/yRTy6JsKKENTijTq8Y=
|
||||||
sigs.k8s.io/controller-runtime v0.21.0/go.mod h1:OSg14+F65eWqIu4DceX7k/+QRAbTTvxeQSNSOQpukWM=
|
sigs.k8s.io/controller-runtime v0.22.3/go.mod h1:+QX1XUpTXN4mLoblf4tqr5CQcyHPAki2HLXqQMY6vh8=
|
||||||
sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 h1:/Rv+M11QRah1itp8VhT6HoVx1Ray9eB4DBr+K+/sCJ8=
|
sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 h1:gBQPwqORJ8d8/YNZWEjoZs7npUVDpVXUUOFfW6CgAqE=
|
||||||
sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3/go.mod h1:18nIHnGi6636UCz6m8i4DhaJ65T6EruyzmoQqI2BVDo=
|
sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8/go.mod h1:mdzfpAEoE6DHQEN0uh9ZbOCuHbLK5wOm7dK4ctXE9Tg=
|
||||||
sigs.k8s.io/randfill v0.0.0-20250304075658-069ef1bbf016/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY=
|
|
||||||
sigs.k8s.io/randfill v1.0.0 h1:JfjMILfT8A6RbawdsK2JXGBR5AQVfd+9TbzrlneTyrU=
|
sigs.k8s.io/randfill v1.0.0 h1:JfjMILfT8A6RbawdsK2JXGBR5AQVfd+9TbzrlneTyrU=
|
||||||
sigs.k8s.io/randfill v1.0.0/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY=
|
sigs.k8s.io/randfill v1.0.0/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY=
|
||||||
sigs.k8s.io/structured-merge-diff/v4 v4.6.0 h1:IUA9nvMmnKWcj5jl84xn+T5MnlZKThmUW1TdblaLVAc=
|
sigs.k8s.io/structured-merge-diff/v6 v6.3.0 h1:jTijUJbW353oVOd9oTlifJqOGEkUw2jB/fXCbTiQEco=
|
||||||
sigs.k8s.io/structured-merge-diff/v4 v4.6.0/go.mod h1:dDy58f92j70zLsuZVuUX5Wp9vtxXpaZnkPGWeqDfCps=
|
sigs.k8s.io/structured-merge-diff/v6 v6.3.0/go.mod h1:M3W8sfWvn2HhQDIbGWj3S099YozAsymCo/wrT5ohRUE=
|
||||||
sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E=
|
sigs.k8s.io/yaml v1.6.0 h1:G8fkbMSAFqgEFgh4b1wmtzDnioxFCUgTZhlbj5P9QYs=
|
||||||
sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY=
|
sigs.k8s.io/yaml v1.6.0/go.mod h1:796bPqUfzR/0jLAl6XjHl3Ck7MiyVv8dbTdyT3/pMf4=
|
||||||
strk.kbt.io/projects/go/libravatar v0.0.0-20191008002943-06d1c002b251 h1:mUcz5b3FJbP5Cvdq7Khzn6J9OCUQJaBwgBkCR+MOwSs=
|
strk.kbt.io/projects/go/libravatar v0.0.0-20191008002943-06d1c002b251 h1:mUcz5b3FJbP5Cvdq7Khzn6J9OCUQJaBwgBkCR+MOwSs=
|
||||||
strk.kbt.io/projects/go/libravatar v0.0.0-20191008002943-06d1c002b251/go.mod h1:FJGmPh3vz9jSos1L/F91iAgnC/aejc0wIIrF2ZwJxdY=
|
strk.kbt.io/projects/go/libravatar v0.0.0-20191008002943-06d1c002b251/go.mod h1:FJGmPh3vz9jSos1L/F91iAgnC/aejc0wIIrF2ZwJxdY=
|
||||||
xorm.io/builder v0.3.13 h1:a3jmiVVL19psGeXx8GIurTp7p0IIgqeDmwhcR6BAOAo=
|
xorm.io/builder v0.3.13 h1:a3jmiVVL19psGeXx8GIurTp7p0IIgqeDmwhcR6BAOAo=
|
||||||
|
|||||||
@@ -125,6 +125,7 @@ type User struct {
|
|||||||
AllowImportLocal bool // Allow migrate repository by local path
|
AllowImportLocal bool // Allow migrate repository by local path
|
||||||
AllowCreateOrganization bool `xorm:"DEFAULT true"`
|
AllowCreateOrganization bool `xorm:"DEFAULT true"`
|
||||||
AllowCreateDevcontainer bool `xorm:"DEFAULT false"`
|
AllowCreateDevcontainer bool `xorm:"DEFAULT false"`
|
||||||
|
AllowCreateActRunner bool `xorm:"DEFAULT false"`
|
||||||
|
|
||||||
// true: the user is not allowed to log in Web UI. Git/SSH access could still be allowed (please refer to Git/SSH access related code/documents)
|
// true: the user is not allowed to log in Web UI. Git/SSH access could still be allowed (please refer to Git/SSH access related code/documents)
|
||||||
ProhibitLogin bool `xorm:"NOT NULL DEFAULT false"`
|
ProhibitLogin bool `xorm:"NOT NULL DEFAULT false"`
|
||||||
@@ -274,6 +275,11 @@ func (u *User) CanCreateDevcontainer() bool {
|
|||||||
return u.AllowCreateDevcontainer
|
return u.AllowCreateDevcontainer
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CanCreateActrunner returns true if user can create organisation.
|
||||||
|
func (u *User) CanCreateActrunner() bool {
|
||||||
|
return u.AllowCreateActRunner
|
||||||
|
}
|
||||||
|
|
||||||
// CanEditGitHook returns true if user can edit Git hooks.
|
// CanEditGitHook returns true if user can edit Git hooks.
|
||||||
func (u *User) CanEditGitHook() bool {
|
func (u *User) CanEditGitHook() bool {
|
||||||
return !setting.DisableGitHooks && (u.IsAdmin || u.AllowGitHook)
|
return !setting.DisableGitHooks && (u.IsAdmin || u.AllowGitHook)
|
||||||
@@ -640,6 +646,7 @@ type CreateUserOverwriteOptions struct {
|
|||||||
Visibility *structs.VisibleType
|
Visibility *structs.VisibleType
|
||||||
AllowCreateOrganization optional.Option[bool]
|
AllowCreateOrganization optional.Option[bool]
|
||||||
AllowCreateDevcontainer optional.Option[bool]
|
AllowCreateDevcontainer optional.Option[bool]
|
||||||
|
AllowCreateActRunner optional.Option[bool]
|
||||||
EmailNotificationsPreference *string
|
EmailNotificationsPreference *string
|
||||||
MaxRepoCreation *int
|
MaxRepoCreation *int
|
||||||
Theme *string
|
Theme *string
|
||||||
@@ -668,6 +675,7 @@ func createUser(ctx context.Context, u *User, meta *Meta, createdByAdmin bool, o
|
|||||||
u.Visibility = setting.Service.DefaultUserVisibilityMode
|
u.Visibility = setting.Service.DefaultUserVisibilityMode
|
||||||
u.AllowCreateOrganization = setting.Service.DefaultAllowCreateOrganization && !setting.Admin.DisableRegularOrgCreation
|
u.AllowCreateOrganization = setting.Service.DefaultAllowCreateOrganization && !setting.Admin.DisableRegularOrgCreation
|
||||||
u.AllowCreateDevcontainer = setting.Service.DefaultAllowCreateDevcontainer
|
u.AllowCreateDevcontainer = setting.Service.DefaultAllowCreateDevcontainer
|
||||||
|
u.AllowCreateActRunner = setting.Service.DefaultAllowCreateActRunner
|
||||||
u.EmailNotificationsPreference = setting.Admin.DefaultEmailNotification
|
u.EmailNotificationsPreference = setting.Admin.DefaultEmailNotification
|
||||||
u.MaxRepoCreation = -1
|
u.MaxRepoCreation = -1
|
||||||
u.Theme = setting.UI.DefaultTheme
|
u.Theme = setting.UI.DefaultTheme
|
||||||
|
|||||||
@@ -59,6 +59,7 @@ func NewActionsUser() *User {
|
|||||||
Type: UserTypeBot,
|
Type: UserTypeBot,
|
||||||
AllowCreateOrganization: true,
|
AllowCreateOrganization: true,
|
||||||
AllowCreateDevcontainer: false,
|
AllowCreateDevcontainer: false,
|
||||||
|
AllowCreateActRunner: false,
|
||||||
Visibility: structs.VisibleTypePublic,
|
Visibility: structs.VisibleTypePublic,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,3 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) Mengning Software. 2025. All rights reserved.
|
|
||||||
* Authors: DevStar Team, panshuxiao
|
|
||||||
* Create: 2025-11-19
|
|
||||||
* Description: Application CRD Go type definitions.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Copyright 2025.
|
Copyright 2025.
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,84 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2024.
|
||||||
|
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package devcontainer
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
. "github.com/onsi/ginkgo/v2"
|
||||||
|
. "github.com/onsi/gomega"
|
||||||
|
"k8s.io/apimachinery/pkg/api/errors"
|
||||||
|
"k8s.io/apimachinery/pkg/types"
|
||||||
|
"sigs.k8s.io/controller-runtime/pkg/reconcile"
|
||||||
|
|
||||||
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
|
||||||
|
devcontainerv1 "code.gitea.io/gitea/modules/k8s/api/devcontainer/v1"
|
||||||
|
)
|
||||||
|
|
||||||
|
var _ = Describe("DevcontainerApp Controller", func() {
|
||||||
|
Context("When reconciling a resource", func() {
|
||||||
|
const resourceName = "test-resource"
|
||||||
|
|
||||||
|
ctx := context.Background()
|
||||||
|
|
||||||
|
typeNamespacedName := types.NamespacedName{
|
||||||
|
Name: resourceName,
|
||||||
|
Namespace: "default", // TODO(user):Modify as needed
|
||||||
|
}
|
||||||
|
devcontainerapp := &devcontainerv1.DevcontainerApp{}
|
||||||
|
|
||||||
|
BeforeEach(func() {
|
||||||
|
By("creating the custom resource for the Kind DevcontainerApp")
|
||||||
|
err := k8sClient.Get(ctx, typeNamespacedName, devcontainerapp)
|
||||||
|
if err != nil && errors.IsNotFound(err) {
|
||||||
|
resource := &devcontainerv1.DevcontainerApp{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: resourceName,
|
||||||
|
Namespace: "default",
|
||||||
|
},
|
||||||
|
// TODO(user): Specify other spec details if needed.
|
||||||
|
}
|
||||||
|
Expect(k8sClient.Create(ctx, resource)).To(Succeed())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
AfterEach(func() {
|
||||||
|
// TODO(user): Cleanup logic after each test, like removing the resource instance.
|
||||||
|
resource := &devcontainerv1.DevcontainerApp{}
|
||||||
|
err := k8sClient.Get(ctx, typeNamespacedName, resource)
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
|
By("Cleanup the specific resource instance DevcontainerApp")
|
||||||
|
Expect(k8sClient.Delete(ctx, resource)).To(Succeed())
|
||||||
|
})
|
||||||
|
It("should successfully reconcile the resource", func() {
|
||||||
|
By("Reconciling the created resource")
|
||||||
|
controllerReconciler := &DevcontainerAppReconciler{
|
||||||
|
Client: k8sClient,
|
||||||
|
Scheme: k8sClient.Scheme(),
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err := controllerReconciler.Reconcile(ctx, reconcile.Request{
|
||||||
|
NamespacedName: typeNamespacedName,
|
||||||
|
})
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
// TODO(user): Add more specific assertions depending on your controller's reconciliation logic.
|
||||||
|
// Example: If you expect a certain status condition after reconciliation, verify it here.
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
96
modules/k8s/controller/devcontainer/suite_test.go
Normal file
96
modules/k8s/controller/devcontainer/suite_test.go
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2024.
|
||||||
|
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package devcontainer
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"path/filepath"
|
||||||
|
"runtime"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
. "github.com/onsi/ginkgo/v2"
|
||||||
|
. "github.com/onsi/gomega"
|
||||||
|
|
||||||
|
"k8s.io/client-go/kubernetes/scheme"
|
||||||
|
"k8s.io/client-go/rest"
|
||||||
|
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||||
|
"sigs.k8s.io/controller-runtime/pkg/envtest"
|
||||||
|
logf "sigs.k8s.io/controller-runtime/pkg/log"
|
||||||
|
"sigs.k8s.io/controller-runtime/pkg/log/zap"
|
||||||
|
|
||||||
|
devcontainerv1 "code.gitea.io/gitea/modules/k8s/api/devcontainer/v1"
|
||||||
|
// +kubebuilder:scaffold:imports
|
||||||
|
)
|
||||||
|
|
||||||
|
// These tests use Ginkgo (BDD-style Go testing framework). Refer to
|
||||||
|
// http://onsi.github.io/ginkgo/ to learn more about Ginkgo.
|
||||||
|
|
||||||
|
var cfg *rest.Config
|
||||||
|
var k8sClient client.Client
|
||||||
|
var testEnv *envtest.Environment
|
||||||
|
var ctx context.Context
|
||||||
|
var cancel context.CancelFunc
|
||||||
|
|
||||||
|
func TestControllers(t *testing.T) {
|
||||||
|
RegisterFailHandler(Fail)
|
||||||
|
|
||||||
|
RunSpecs(t, "Controller Suite")
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ = BeforeSuite(func() {
|
||||||
|
logf.SetLogger(zap.New(zap.WriteTo(GinkgoWriter), zap.UseDevMode(true)))
|
||||||
|
|
||||||
|
ctx, cancel = context.WithCancel(context.TODO())
|
||||||
|
|
||||||
|
By("bootstrapping test environment")
|
||||||
|
testEnv = &envtest.Environment{
|
||||||
|
CRDDirectoryPaths: []string{filepath.Join("..", "..", "config", "crd", "bases")},
|
||||||
|
ErrorIfCRDPathMissing: true,
|
||||||
|
|
||||||
|
// The BinaryAssetsDirectory is only required if you want to run the tests directly
|
||||||
|
// without call the makefile target test. If not informed it will look for the
|
||||||
|
// default path defined in controller-runtime which is /usr/local/kubebuilder/.
|
||||||
|
// Note that you must have the required binaries setup under the bin directory to perform
|
||||||
|
// the tests directly. When we run make test it will be setup and used automatically.
|
||||||
|
BinaryAssetsDirectory: filepath.Join("..", "..", "bin", "k8s",
|
||||||
|
fmt.Sprintf("1.31.0-%s-%s", runtime.GOOS, runtime.GOARCH)),
|
||||||
|
}
|
||||||
|
|
||||||
|
var err error
|
||||||
|
// cfg is defined in this file globally.
|
||||||
|
cfg, err = testEnv.Start()
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
Expect(cfg).NotTo(BeNil())
|
||||||
|
|
||||||
|
err = devcontainerv1.AddToScheme(scheme.Scheme)
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
|
// +kubebuilder:scaffold:scheme
|
||||||
|
|
||||||
|
k8sClient, err = client.New(cfg, client.Options{Scheme: scheme.Scheme})
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
Expect(k8sClient).NotTo(BeNil())
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
var _ = AfterSuite(func() {
|
||||||
|
By("tearing down the test environment")
|
||||||
|
cancel()
|
||||||
|
err := testEnv.Stop()
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
})
|
||||||
10
modules/k8s/controller/options/options.go
Normal file
10
modules/k8s/controller/options/options.go
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
/*
|
||||||
|
* Please refer to the LICENSE file in the root directory of the project.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package options
|
||||||
|
|
||||||
|
// Options 包含所有控制器可能需要的选项
|
||||||
|
type Options struct {
|
||||||
|
// 可以根据实际需求扩展更多选项
|
||||||
|
}
|
||||||
@@ -17,9 +17,7 @@ import (
|
|||||||
"code.gitea.io/gitea/modules/setting"
|
"code.gitea.io/gitea/modules/setting"
|
||||||
|
|
||||||
k8s_api_v1 "code.gitea.io/gitea/modules/k8s/api/devcontainer/v1"
|
k8s_api_v1 "code.gitea.io/gitea/modules/k8s/api/devcontainer/v1"
|
||||||
|
k8sErrors "code.gitea.io/gitea/modules/k8s/errors"
|
||||||
devcontainer_errors "code.gitea.io/gitea/modules/k8s/errors"
|
|
||||||
devcontainer_k8s_agent_modules_errors "code.gitea.io/gitea/modules/k8s/errors"
|
|
||||||
apimachinery_api_metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
apimachinery_api_metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
apimachinery_apis_v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
apimachinery_apis_v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
apimachinery_apis_v1_unstructured "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
apimachinery_apis_v1_unstructured "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||||
@@ -181,7 +179,7 @@ func GetDevcontainer(ctx context.Context, client dynamic_client.Interface, opts
|
|||||||
|
|
||||||
// 0. 检查参数
|
// 0. 检查参数
|
||||||
if ctx == nil || opts == nil || len(opts.Namespace) == 0 || len(opts.Name) == 0 {
|
if ctx == nil || opts == nil || len(opts.Namespace) == 0 || len(opts.Name) == 0 {
|
||||||
return nil, devcontainer_errors.ErrIllegalDevcontainerParameters{
|
return nil, k8sErrors.ErrIllegalDevcontainerParameters{
|
||||||
FieldList: []string{"ctx", "opts", "opts.Name", "opts.Namespace"},
|
FieldList: []string{"ctx", "opts", "opts.Name", "opts.Namespace"},
|
||||||
Message: "cannot be nil",
|
Message: "cannot be nil",
|
||||||
}
|
}
|
||||||
@@ -190,7 +188,7 @@ func GetDevcontainer(ctx context.Context, client dynamic_client.Interface, opts
|
|||||||
// 1. 获取 k8s CRD 资源 DevcontainerApp
|
// 1. 获取 k8s CRD 资源 DevcontainerApp
|
||||||
devcontainerUnstructured, err := client.Resource(groupVersionResource).Namespace(opts.Namespace).Get(ctx, opts.Name, opts.GetOptions)
|
devcontainerUnstructured, err := client.Resource(groupVersionResource).Namespace(opts.Namespace).Get(ctx, opts.Name, opts.GetOptions)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, devcontainer_errors.ErrOperateDevcontainer{
|
return nil, k8sErrors.ErrOperateDevcontainer{
|
||||||
Action: "Get DevcontainerApp thru k8s API Server",
|
Action: "Get DevcontainerApp thru k8s API Server",
|
||||||
Message: err.Error(),
|
Message: err.Error(),
|
||||||
}
|
}
|
||||||
@@ -200,7 +198,7 @@ func GetDevcontainer(ctx context.Context, client dynamic_client.Interface, opts
|
|||||||
devcontainerApp := &k8s_api_v1.DevcontainerApp{}
|
devcontainerApp := &k8s_api_v1.DevcontainerApp{}
|
||||||
err = apimachinery_runtime_utils.DefaultUnstructuredConverter.FromUnstructured(devcontainerUnstructured.Object, &devcontainerApp)
|
err = apimachinery_runtime_utils.DefaultUnstructuredConverter.FromUnstructured(devcontainerUnstructured.Object, &devcontainerApp)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, devcontainer_errors.ErrOperateDevcontainer{
|
return nil, k8sErrors.ErrOperateDevcontainer{
|
||||||
Action: "Convert k8s API Server unstructured response into DevcontainerApp",
|
Action: "Convert k8s API Server unstructured response into DevcontainerApp",
|
||||||
Message: err.Error(),
|
Message: err.Error(),
|
||||||
}
|
}
|
||||||
@@ -210,7 +208,7 @@ func GetDevcontainer(ctx context.Context, client dynamic_client.Interface, opts
|
|||||||
if !IsK8sDevcontainerStatusReady(&devcontainerApp.Status) {
|
if !IsK8sDevcontainerStatusReady(&devcontainerApp.Status) {
|
||||||
// 3.1 检查 Wait 参数,若用户不需要阻塞式等待,直接返回 “DevContainer 未就绪” 错误
|
// 3.1 检查 Wait 参数,若用户不需要阻塞式等待,直接返回 “DevContainer 未就绪” 错误
|
||||||
if opts.Wait == false {
|
if opts.Wait == false {
|
||||||
return nil, devcontainer_errors.ErrK8sDevcontainerNotReady{
|
return nil, k8sErrors.ErrK8sDevcontainerNotReady{
|
||||||
Name: opts.Name,
|
Name: opts.Name,
|
||||||
Namespace: opts.Namespace,
|
Namespace: opts.Namespace,
|
||||||
Wait: opts.Wait,
|
Wait: opts.Wait,
|
||||||
@@ -220,7 +218,7 @@ func GetDevcontainer(ctx context.Context, client dynamic_client.Interface, opts
|
|||||||
// 3.2 执行阻塞式等待
|
// 3.2 执行阻塞式等待
|
||||||
devcontainerStatusVO, err := waitUntilDevcontainerReadyWithTimeout(ctx, client, opts)
|
devcontainerStatusVO, err := waitUntilDevcontainerReadyWithTimeout(ctx, client, opts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, devcontainer_errors.ErrOperateDevcontainer{
|
return nil, k8sErrors.ErrOperateDevcontainer{
|
||||||
Action: "wait for k8s DevContainer to be ready",
|
Action: "wait for k8s DevContainer to be ready",
|
||||||
Message: err.Error(),
|
Message: err.Error(),
|
||||||
}
|
}
|
||||||
@@ -238,21 +236,21 @@ func waitUntilDevcontainerReadyWithTimeout(ctx context.Context, client dynamic_c
|
|||||||
|
|
||||||
// 0. 检查参数
|
// 0. 检查参数
|
||||||
if ctx == nil || client == nil || opts == nil || len(opts.Name) == 0 || len(opts.Namespace) == 0 {
|
if ctx == nil || client == nil || opts == nil || len(opts.Name) == 0 || len(opts.Namespace) == 0 {
|
||||||
return nil, devcontainer_errors.ErrIllegalDevcontainerParameters{
|
return nil, k8sErrors.ErrIllegalDevcontainerParameters{
|
||||||
FieldList: []string{"ctx", "client", "opts", "opts.Name", "opts.Namespace"},
|
FieldList: []string{"ctx", "client", "opts", "opts.Name", "opts.Namespace"},
|
||||||
Message: "could not be nil",
|
Message: "could not be nil",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 1. 注册 watcher 监听 DevContainer Status 变化
|
// 1. 注册 watcher 监听 DevContainer Status 变化
|
||||||
watcherTimeoutSeconds := setting.DevContainerConfig.TimeoutSeconds
|
watcherTimeoutSeconds := int64(120)
|
||||||
watcher, err := client.Resource(groupVersionResource).Namespace(opts.Namespace).Watch(ctx, apimachinery_apis_v1.ListOptions{
|
watcher, err := client.Resource(groupVersionResource).Namespace(opts.Namespace).Watch(ctx, apimachinery_apis_v1.ListOptions{
|
||||||
FieldSelector: fmt.Sprintf("metadata.name=%s", opts.Name),
|
FieldSelector: fmt.Sprintf("metadata.name=%s", opts.Name),
|
||||||
Watch: true,
|
Watch: true,
|
||||||
TimeoutSeconds: &watcherTimeoutSeconds,
|
TimeoutSeconds: &watcherTimeoutSeconds,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, devcontainer_errors.ErrOperateDevcontainer{
|
return nil, k8sErrors.ErrOperateDevcontainer{
|
||||||
Action: "register watcher of DevContainer Readiness",
|
Action: "register watcher of DevContainer Readiness",
|
||||||
Message: err.Error(),
|
Message: err.Error(),
|
||||||
}
|
}
|
||||||
@@ -288,7 +286,7 @@ func waitUntilDevcontainerReadyWithTimeout(ctx context.Context, client dynamic_c
|
|||||||
// 2.3 监听 DevcontainerApp ERROR 事件,返回报错信息
|
// 2.3 监听 DevcontainerApp ERROR 事件,返回报错信息
|
||||||
apimachineryApiMetav1Status, ok := event.Object.(*apimachinery_api_metav1.Status)
|
apimachineryApiMetav1Status, ok := event.Object.(*apimachinery_api_metav1.Status)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, devcontainer_errors.ErrOperateDevcontainer{
|
return nil, k8sErrors.ErrOperateDevcontainer{
|
||||||
Action: fmt.Sprintf("wait for Devcontainer '%s' in namespace '%s' to be ready", opts.Name, opts.Namespace),
|
Action: fmt.Sprintf("wait for Devcontainer '%s' in namespace '%s' to be ready", opts.Name, opts.Namespace),
|
||||||
Message: fmt.Sprintf("An error occurred in k8s CRD DevcontainerApp Watcher: \n"+
|
Message: fmt.Sprintf("An error occurred in k8s CRD DevcontainerApp Watcher: \n"+
|
||||||
" Code: %v (status = %v)\n"+
|
" Code: %v (status = %v)\n"+
|
||||||
@@ -303,7 +301,7 @@ func waitUntilDevcontainerReadyWithTimeout(ctx context.Context, client dynamic_c
|
|||||||
}
|
}
|
||||||
case apimachinery_watch.Deleted:
|
case apimachinery_watch.Deleted:
|
||||||
// 2.4 监听 DevcontainerApp DELETED 事件,返回报错信息
|
// 2.4 监听 DevcontainerApp DELETED 事件,返回报错信息
|
||||||
return nil, devcontainer_errors.ErrOperateDevcontainer{
|
return nil, k8sErrors.ErrOperateDevcontainer{
|
||||||
Action: fmt.Sprintf("Open DevContainer '%s' in namespace '%s'", opts.Name, opts.Namespace),
|
Action: fmt.Sprintf("Open DevContainer '%s' in namespace '%s'", opts.Name, opts.Namespace),
|
||||||
Message: fmt.Sprintf("'%s' of Kind DevcontainerApp has been Deleted", opts.Name),
|
Message: fmt.Sprintf("'%s' of Kind DevcontainerApp has been Deleted", opts.Name),
|
||||||
}
|
}
|
||||||
@@ -311,7 +309,7 @@ func waitUntilDevcontainerReadyWithTimeout(ctx context.Context, client dynamic_c
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 3. k8s CRD DevcontainerApp Watcher 超时关闭处理:直接返回超时错误
|
// 3. k8s CRD DevcontainerApp Watcher 超时关闭处理:直接返回超时错误
|
||||||
return nil, devcontainer_errors.ErrOpenDevcontainerTimeout{
|
return nil, k8sErrors.ErrOpenDevcontainerTimeout{
|
||||||
Name: opts.Name,
|
Name: opts.Name,
|
||||||
Namespace: opts.Namespace,
|
Namespace: opts.Namespace,
|
||||||
TimeoutSeconds: setting.DevContainerConfig.TimeoutSeconds,
|
TimeoutSeconds: setting.DevContainerConfig.TimeoutSeconds,
|
||||||
@@ -357,7 +355,7 @@ func CreateDevcontainer(ctx context.Context, client dynamic_client.Interface, op
|
|||||||
jsonData, err := json.Marshal(devcontainerApp)
|
jsonData, err := json.Marshal(devcontainerApp)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("Failed to marshal DevcontainerApp to JSON: %v", err)
|
log.Error("Failed to marshal DevcontainerApp to JSON: %v", err)
|
||||||
return nil, devcontainer_k8s_agent_modules_errors.ErrOperateDevcontainer{
|
return nil, k8sErrors.ErrOperateDevcontainer{
|
||||||
Action: "Marshal JSON",
|
Action: "Marshal JSON",
|
||||||
Message: err.Error(),
|
Message: err.Error(),
|
||||||
}
|
}
|
||||||
@@ -371,7 +369,7 @@ func CreateDevcontainer(ctx context.Context, client dynamic_client.Interface, op
|
|||||||
err = unstructuredObj.UnmarshalJSON(jsonData)
|
err = unstructuredObj.UnmarshalJSON(jsonData)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("Failed to unmarshal JSON to Unstructured: %v", err)
|
log.Error("Failed to unmarshal JSON to Unstructured: %v", err)
|
||||||
return nil, devcontainer_k8s_agent_modules_errors.ErrOperateDevcontainer{
|
return nil, k8sErrors.ErrOperateDevcontainer{
|
||||||
Action: "Unmarshal JSON to Unstructured",
|
Action: "Unmarshal JSON to Unstructured",
|
||||||
Message: err.Error(),
|
Message: err.Error(),
|
||||||
}
|
}
|
||||||
@@ -386,7 +384,7 @@ func CreateDevcontainer(ctx context.Context, client dynamic_client.Interface, op
|
|||||||
result, err := client.Resource(groupVersionResource).Namespace(opts.Namespace).Create(ctx, unstructuredObj, opts.CreateOptions)
|
result, err := client.Resource(groupVersionResource).Namespace(opts.Namespace).Create(ctx, unstructuredObj, opts.CreateOptions)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("Failed to create DevcontainerApp: %v", err)
|
log.Error("Failed to create DevcontainerApp: %v", err)
|
||||||
return nil, devcontainer_k8s_agent_modules_errors.ErrOperateDevcontainer{
|
return nil, k8sErrors.ErrOperateDevcontainer{
|
||||||
Action: "create DevContainer via Dynamic Client",
|
Action: "create DevContainer via Dynamic Client",
|
||||||
Message: err.Error(),
|
Message: err.Error(),
|
||||||
}
|
}
|
||||||
@@ -398,7 +396,7 @@ func CreateDevcontainer(ctx context.Context, client dynamic_client.Interface, op
|
|||||||
resultJSON, err := result.MarshalJSON()
|
resultJSON, err := result.MarshalJSON()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("Failed to marshal result to JSON: %v", err)
|
log.Error("Failed to marshal result to JSON: %v", err)
|
||||||
return nil, devcontainer_k8s_agent_modules_errors.ErrOperateDevcontainer{
|
return nil, k8sErrors.ErrOperateDevcontainer{
|
||||||
Action: "Marshal result JSON",
|
Action: "Marshal result JSON",
|
||||||
Message: err.Error(),
|
Message: err.Error(),
|
||||||
}
|
}
|
||||||
@@ -407,7 +405,7 @@ func CreateDevcontainer(ctx context.Context, client dynamic_client.Interface, op
|
|||||||
createdDevcontainer := &k8s_api_v1.DevcontainerApp{}
|
createdDevcontainer := &k8s_api_v1.DevcontainerApp{}
|
||||||
if err := json.Unmarshal(resultJSON, createdDevcontainer); err != nil {
|
if err := json.Unmarshal(resultJSON, createdDevcontainer); err != nil {
|
||||||
log.Error("Failed to unmarshal result JSON: %v", err)
|
log.Error("Failed to unmarshal result JSON: %v", err)
|
||||||
return nil, devcontainer_k8s_agent_modules_errors.ErrOperateDevcontainer{
|
return nil, k8sErrors.ErrOperateDevcontainer{
|
||||||
Action: "Unmarshal result JSON",
|
Action: "Unmarshal result JSON",
|
||||||
Message: err.Error(),
|
Message: err.Error(),
|
||||||
}
|
}
|
||||||
@@ -418,7 +416,7 @@ func CreateDevcontainer(ctx context.Context, client dynamic_client.Interface, op
|
|||||||
|
|
||||||
func DeleteDevcontainer(ctx context.Context, client dynamic_client.Interface, opts *DeleteDevcontainerOptions) error {
|
func DeleteDevcontainer(ctx context.Context, client dynamic_client.Interface, opts *DeleteDevcontainerOptions) error {
|
||||||
if ctx == nil || opts == nil || len(opts.Namespace) == 0 || len(opts.Name) == 0 {
|
if ctx == nil || opts == nil || len(opts.Namespace) == 0 || len(opts.Name) == 0 {
|
||||||
return devcontainer_errors.ErrIllegalDevcontainerParameters{
|
return k8sErrors.ErrIllegalDevcontainerParameters{
|
||||||
FieldList: []string{"ctx", "opts", "opts.Name", "opts.Namespace"},
|
FieldList: []string{"ctx", "opts", "opts.Name", "opts.Namespace"},
|
||||||
Message: "cannot be nil",
|
Message: "cannot be nil",
|
||||||
}
|
}
|
||||||
@@ -427,7 +425,7 @@ func DeleteDevcontainer(ctx context.Context, client dynamic_client.Interface, op
|
|||||||
err := client.Resource(groupVersionResource).Namespace(opts.Namespace).Delete(ctx, opts.Name, opts.DeleteOptions)
|
err := client.Resource(groupVersionResource).Namespace(opts.Namespace).Delete(ctx, opts.Name, opts.DeleteOptions)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Warn("Failed to delete DevcontainerApp '%s' in namespace '%s': %s", opts.Name, opts.Namespace, err.Error())
|
log.Warn("Failed to delete DevcontainerApp '%s' in namespace '%s': %s", opts.Name, opts.Namespace, err.Error())
|
||||||
return devcontainer_errors.ErrOperateDevcontainer{
|
return k8sErrors.ErrOperateDevcontainer{
|
||||||
Action: fmt.Sprintf("delete devcontainer '%s' in namespace '%s'", opts.Name, opts.Namespace),
|
Action: fmt.Sprintf("delete devcontainer '%s' in namespace '%s'", opts.Name, opts.Namespace),
|
||||||
Message: err.Error(),
|
Message: err.Error(),
|
||||||
}
|
}
|
||||||
@@ -439,7 +437,7 @@ func DeleteDevcontainer(ctx context.Context, client dynamic_client.Interface, op
|
|||||||
func ListDevcontainers(ctx context.Context, client dynamic_client.Interface, opts *ListDevcontainersOptions) (*k8s_api_v1.DevcontainerAppList, error) {
|
func ListDevcontainers(ctx context.Context, client dynamic_client.Interface, opts *ListDevcontainersOptions) (*k8s_api_v1.DevcontainerAppList, error) {
|
||||||
|
|
||||||
if ctx == nil || opts == nil || len(opts.Namespace) == 0 {
|
if ctx == nil || opts == nil || len(opts.Namespace) == 0 {
|
||||||
return nil, devcontainer_errors.ErrIllegalDevcontainerParameters{
|
return nil, k8sErrors.ErrIllegalDevcontainerParameters{
|
||||||
FieldList: []string{"ctx", "namespace"},
|
FieldList: []string{"ctx", "namespace"},
|
||||||
Message: "cannot be empty",
|
Message: "cannot be empty",
|
||||||
}
|
}
|
||||||
@@ -447,7 +445,7 @@ func ListDevcontainers(ctx context.Context, client dynamic_client.Interface, opt
|
|||||||
|
|
||||||
list, err := client.Resource(groupVersionResource).Namespace(opts.Namespace).List(ctx, opts.ListOptions)
|
list, err := client.Resource(groupVersionResource).Namespace(opts.Namespace).List(ctx, opts.ListOptions)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, devcontainer_errors.ErrOperateDevcontainer{
|
return nil, k8sErrors.ErrOperateDevcontainer{
|
||||||
Action: fmt.Sprintf("List Devcontainer in namespace '%s'", opts.Namespace),
|
Action: fmt.Sprintf("List Devcontainer in namespace '%s'", opts.Namespace),
|
||||||
Message: err.Error(),
|
Message: err.Error(),
|
||||||
}
|
}
|
||||||
@@ -455,14 +453,14 @@ func ListDevcontainers(ctx context.Context, client dynamic_client.Interface, opt
|
|||||||
// JSON 反序列化为 DevcontainerAppList
|
// JSON 反序列化为 DevcontainerAppList
|
||||||
jsonData, err := list.MarshalJSON()
|
jsonData, err := list.MarshalJSON()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, devcontainer_errors.ErrOperateDevcontainer{
|
return nil, k8sErrors.ErrOperateDevcontainer{
|
||||||
Action: "verify JSON data of Devcontainer List",
|
Action: "verify JSON data of Devcontainer List",
|
||||||
Message: err.Error(),
|
Message: err.Error(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
devcontainerList := &k8s_api_v1.DevcontainerAppList{}
|
devcontainerList := &k8s_api_v1.DevcontainerAppList{}
|
||||||
if err := json.Unmarshal(jsonData, devcontainerList); err != nil {
|
if err := json.Unmarshal(jsonData, devcontainerList); err != nil {
|
||||||
return nil, devcontainer_errors.ErrOperateDevcontainer{
|
return nil, k8sErrors.ErrOperateDevcontainer{
|
||||||
Action: "deserialize Devcontainer List data",
|
Action: "deserialize Devcontainer List data",
|
||||||
Message: err.Error(),
|
Message: err.Error(),
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -72,6 +72,7 @@ var Service = struct {
|
|||||||
DefaultKeepEmailPrivate bool
|
DefaultKeepEmailPrivate bool
|
||||||
DefaultAllowCreateOrganization bool
|
DefaultAllowCreateOrganization bool
|
||||||
DefaultAllowCreateDevcontainer bool
|
DefaultAllowCreateDevcontainer bool
|
||||||
|
DefaultAllowCreateActRunner bool
|
||||||
DefaultUserIsRestricted bool
|
DefaultUserIsRestricted bool
|
||||||
EnableTimetracking bool
|
EnableTimetracking bool
|
||||||
DefaultEnableTimetracking bool
|
DefaultEnableTimetracking bool
|
||||||
@@ -207,6 +208,7 @@ func loadServiceFrom(rootCfg ConfigProvider) {
|
|||||||
Service.DefaultKeepEmailPrivate = sec.Key("DEFAULT_KEEP_EMAIL_PRIVATE").MustBool()
|
Service.DefaultKeepEmailPrivate = sec.Key("DEFAULT_KEEP_EMAIL_PRIVATE").MustBool()
|
||||||
Service.DefaultAllowCreateOrganization = sec.Key("DEFAULT_ALLOW_CREATE_ORGANIZATION").MustBool(true)
|
Service.DefaultAllowCreateOrganization = sec.Key("DEFAULT_ALLOW_CREATE_ORGANIZATION").MustBool(true)
|
||||||
Service.DefaultAllowCreateDevcontainer = sec.Key("DEFAULT_ALLOW_CREATE_DEVCONTAINER").MustBool(true)
|
Service.DefaultAllowCreateDevcontainer = sec.Key("DEFAULT_ALLOW_CREATE_DEVCONTAINER").MustBool(true)
|
||||||
|
Service.DefaultAllowCreateActRunner = sec.Key("DEFAULT_ALLOW_CREATE_ACTRUNNER").MustBool(false)
|
||||||
Service.DefaultUserIsRestricted = sec.Key("DEFAULT_USER_IS_RESTRICTED").MustBool(false)
|
Service.DefaultUserIsRestricted = sec.Key("DEFAULT_USER_IS_RESTRICTED").MustBool(false)
|
||||||
Service.EnableTimetracking = sec.Key("ENABLE_TIMETRACKING").MustBool(true)
|
Service.EnableTimetracking = sec.Key("ENABLE_TIMETRACKING").MustBool(true)
|
||||||
if Service.EnableTimetracking {
|
if Service.EnableTimetracking {
|
||||||
|
|||||||
@@ -55,6 +55,7 @@ type EditUserOption struct {
|
|||||||
ProhibitLogin *bool `json:"prohibit_login"`
|
ProhibitLogin *bool `json:"prohibit_login"`
|
||||||
AllowCreateOrganization *bool `json:"allow_create_organization"`
|
AllowCreateOrganization *bool `json:"allow_create_organization"`
|
||||||
AllowCreateDevcontainer *bool `json:"allow_create_devcontainer"`
|
AllowCreateDevcontainer *bool `json:"allow_create_devcontainer"`
|
||||||
|
AllowCreateActRunner *bool `json:"allow_create_actrunner"`
|
||||||
Restricted *bool `json:"restricted"`
|
Restricted *bool `json:"restricted"`
|
||||||
Visibility string `json:"visibility" binding:"In(,public,limited,private)"`
|
Visibility string `json:"visibility" binding:"In(,public,limited,private)"`
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -245,8 +245,8 @@ license_desc = Go get <a target="_blank" rel="noopener noreferrer" href="%[1]s">
|
|||||||
install=Instalace
|
install=Instalace
|
||||||
installing_desc=Probíhá instalace, čekejte prosím...
|
installing_desc=Probíhá instalace, čekejte prosím...
|
||||||
title=Výchozí konfigurace
|
title=Výchozí konfigurace
|
||||||
docker_helper=Pokud spouštíte Gitea v Dockeru, přečtěte si <a target="_blank" rel="noopener noreferrer" href="%s">dokumentaci</a>, než budete měnit jakákoliv nastavení.
|
k8s_helper=Pokud spouštíte DevStar v Kubernetesu, přečtěte si <a target="_blank" rel="noopener noreferrer" href="%s">dokumentaci</a>, než budete měnit jakákoliv nastavení.
|
||||||
require_db_desc=Gitea requires MySQL, PostgreSQL, MSSQL, SQLite3 or TiDB (MySQL protocol).
|
require_db_desc=DevStar requires MySQL, PostgreSQL, MSSQL, SQLite3 or TiDB (MySQL protocol).
|
||||||
db_title=Nastavení databáze
|
db_title=Nastavení databáze
|
||||||
db_type=Typ databáze
|
db_type=Typ databáze
|
||||||
host=Hostitel
|
host=Hostitel
|
||||||
@@ -351,7 +351,7 @@ password_algorithm=Hash algoritmus hesla
|
|||||||
invalid_password_algorithm=Neplatný algoritmus hash hesla
|
invalid_password_algorithm=Neplatný algoritmus hash hesla
|
||||||
password_algorithm_helper=Nastavte algoritmus hashování hesla. Algoritmy mají odlišné požadavky a sílu. Algoritmus argon2 je poměrně bezpečný, ale používá spoustu paměti a může být nevhodný pro malé systémy.
|
password_algorithm_helper=Nastavte algoritmus hashování hesla. Algoritmy mají odlišné požadavky a sílu. Algoritmus argon2 je poměrně bezpečný, ale používá spoustu paměti a může být nevhodný pro malé systémy.
|
||||||
enable_update_checker=Povolit kontrolu aktualizací
|
enable_update_checker=Povolit kontrolu aktualizací
|
||||||
enable_update_checker_helper=Kontroluje vydání nových verzí pravidelně připojením ke gitea.io.
|
enable_update_checker_helper=Kontroluje vydání nových verzí pravidelně připojením ke devstar.cn.
|
||||||
env_config_keys=Konfigurace prostředí
|
env_config_keys=Konfigurace prostředí
|
||||||
env_config_keys_prompt=Následující proměnné prostředí budou také použity pro váš konfigurační soubor:
|
env_config_keys_prompt=Následující proměnné prostředí budou také použity pro váš konfigurační soubor:
|
||||||
config_write_file_prompt=Tyto možnosti konfigurace budou zapsány do: %s
|
config_write_file_prompt=Tyto možnosti konfigurace budou zapsány do: %s
|
||||||
|
|||||||
@@ -251,8 +251,8 @@ license_desc = Go get <a target="_blank" rel="noopener noreferrer" href="%[1]s">
|
|||||||
install=Installation
|
install=Installation
|
||||||
installing_desc=Wird jetzt installiert, bitte warten...
|
installing_desc=Wird jetzt installiert, bitte warten...
|
||||||
title=Erstkonfiguration
|
title=Erstkonfiguration
|
||||||
docker_helper=Wenn du Gitea in einem Docker-Container nutzt, lies bitte die <a target="_blank" rel="noopener noreferrer" href="%s">Dokumentation</a>, bevor du irgendwelche Einstellungen veränderst.
|
k8s_helper=Wenn du DevStar in einem Kubernetes-Container nutzt, lies bitte die <a target="_blank" rel="noopener noreferrer" href="%s">Dokumentation</a>, bevor du irgendwelche Einstellungen veränderst.
|
||||||
require_db_desc=Gitea benötigt MySQL, PostgreSQL, MSSQL, SQLite3 oder TiDB (MySQL-Protokoll).
|
require_db_desc=DevStar benötigt MySQL, PostgreSQL, MSSQL, SQLite3 oder TiDB (MySQL-Protokoll).
|
||||||
db_title=Datenbankeinstellungen
|
db_title=Datenbankeinstellungen
|
||||||
db_type=Datenbanktyp
|
db_type=Datenbanktyp
|
||||||
host=Host
|
host=Host
|
||||||
@@ -357,7 +357,7 @@ password_algorithm=Passwort Hashing Algorithmus
|
|||||||
invalid_password_algorithm=Ungültiger Passwort-Hash-Algorithmus
|
invalid_password_algorithm=Ungültiger Passwort-Hash-Algorithmus
|
||||||
password_algorithm_helper=Lege einen Passwort-Hashing-Algorithmus fest. Algorithmen haben unterschiedliche Anforderungen und Stärken. Der argon2-Algorithmus ist ziemlich sicher, aber er verbraucht viel Speicher und kann für kleine Systeme ungeeignet sein.
|
password_algorithm_helper=Lege einen Passwort-Hashing-Algorithmus fest. Algorithmen haben unterschiedliche Anforderungen und Stärken. Der argon2-Algorithmus ist ziemlich sicher, aber er verbraucht viel Speicher und kann für kleine Systeme ungeeignet sein.
|
||||||
enable_update_checker=Aktualisierungsprüfung aktivieren
|
enable_update_checker=Aktualisierungsprüfung aktivieren
|
||||||
enable_update_checker_helper=Stellt regelmäßig eine Verbindung zu gitea.io her, um nach neuen Versionen zu prüfen.
|
enable_update_checker_helper=Stellt regelmäßig eine Verbindung zu devstar.cn her, um nach neuen Versionen zu prüfen.
|
||||||
env_config_keys=Umgebungskonfiguration
|
env_config_keys=Umgebungskonfiguration
|
||||||
env_config_keys_prompt=Die folgenden Umgebungsvariablen werden auch auf Ihre Konfigurationsdatei angewendet:
|
env_config_keys_prompt=Die folgenden Umgebungsvariablen werden auch auf Ihre Konfigurationsdatei angewendet:
|
||||||
config_write_file_prompt=Diese Konfigurationsoptionen werden in %s geschrieben
|
config_write_file_prompt=Diese Konfigurationsoptionen werden in %s geschrieben
|
||||||
|
|||||||
@@ -203,8 +203,8 @@ license_desc = Go get <a target="_blank" rel="noopener noreferrer" href="%[1]s">
|
|||||||
[install]
|
[install]
|
||||||
install=Εγκατάσταση
|
install=Εγκατάσταση
|
||||||
title=Αρχικές Ρυθμίσεις
|
title=Αρχικές Ρυθμίσεις
|
||||||
docker_helper=Αν εκτελέσετε το Gitea μέσα στο Docker, παρακαλώ διαβάστε την <a target="_blank" rel="noopener noreferrer" href="%s">τεκμηρίωση</a> πριν αλλάξετε τις ρυθμίσεις.
|
k8s_helper=Αν εκτελέσετε το DevStar μέσα στο Kubernetes, παρακαλώ διαβάστε την <a target="_blank" rel="noopener noreferrer" href="%s">τεκμηρίωση</a> πριν αλλάξετε τις ρυθμίσεις.
|
||||||
require_db_desc=Το Gitea απαιτεί MySQL, PostgreSQL, MSSQL, SQLite3 ή TiDB (με πρωτόκολλο MySQL).
|
require_db_desc=Το DevStar απαιτεί MySQL, PostgreSQL, MSSQL, SQLite3 ή TiDB (με πρωτόκολλο MySQL).
|
||||||
db_title=Ρυθμίσεις Βάσης Δεδομένων
|
db_title=Ρυθμίσεις Βάσης Δεδομένων
|
||||||
db_type=Τύπος της Βάσης Δεδομένων
|
db_type=Τύπος της Βάσης Δεδομένων
|
||||||
host=Διακομιστής
|
host=Διακομιστής
|
||||||
@@ -308,7 +308,7 @@ password_algorithm=Αλγόριθμος Hash Κωδικού Πρόσβασης
|
|||||||
invalid_password_algorithm=Μη έγκυρος αλγόριθμος κωδικού πρόσβασης
|
invalid_password_algorithm=Μη έγκυρος αλγόριθμος κωδικού πρόσβασης
|
||||||
password_algorithm_helper=Ορίστε τον αλγόριθμο κατακερματισμού για το κωδικό πρόσβασης. Οι αλγόριθμοι διαφέρουν σε απαιτήσεις και αντοχή. Ο αλγόριθμος argon2 είναι αρκετά ασφαλής, αλλά χρησιμοποιεί πολλή μνήμη και μπορεί να είναι ακατάλληλος για μικρά συστήματα.
|
password_algorithm_helper=Ορίστε τον αλγόριθμο κατακερματισμού για το κωδικό πρόσβασης. Οι αλγόριθμοι διαφέρουν σε απαιτήσεις και αντοχή. Ο αλγόριθμος argon2 είναι αρκετά ασφαλής, αλλά χρησιμοποιεί πολλή μνήμη και μπορεί να είναι ακατάλληλος για μικρά συστήματα.
|
||||||
enable_update_checker=Ενεργοποίηση Ελεγκτή Ενημερώσεων
|
enable_update_checker=Ενεργοποίηση Ελεγκτή Ενημερώσεων
|
||||||
enable_update_checker_helper=Ελέγχει περιοδικά για νέες εκδόσεις κάνοντας σύνδεση στο gitea.io.
|
enable_update_checker_helper=Ελέγχει περιοδικά για νέες εκδόσεις κάνοντας σύνδεση στο devstar.cn.
|
||||||
env_config_keys=Ρυθμίσεις Περιβάλλοντος
|
env_config_keys=Ρυθμίσεις Περιβάλλοντος
|
||||||
env_config_keys_prompt=Οι ακόλουθες μεταβλητές περιβάλλοντος θα εφαρμοστούν επίσης στο αρχείο ρυθμίσεων σας:
|
env_config_keys_prompt=Οι ακόλουθες μεταβλητές περιβάλλοντος θα εφαρμοστούν επίσης στο αρχείο ρυθμίσεων σας:
|
||||||
|
|
||||||
|
|||||||
@@ -256,8 +256,8 @@ license_desc = Go get <a target="_blank" rel="noopener noreferrer" href="%[1]s">
|
|||||||
install = Installation
|
install = Installation
|
||||||
installing_desc = Installing now, please wait...
|
installing_desc = Installing now, please wait...
|
||||||
title = Initial Configuration
|
title = Initial Configuration
|
||||||
docker_helper = If you run Gitea inside Docker, please read the <a target="_blank" rel="noopener noreferrer" href="%s">documentation</a> before changing any settings.
|
k8s_helper = If you run DevStar inside Kubernetes, please read the <a target="_blank" rel="noopener noreferrer" href="%s">documentation</a> before changing any settings.
|
||||||
require_db_desc = Gitea requires MySQL, PostgreSQL, MSSQL, SQLite3 or TiDB (MySQL protocol).
|
require_db_desc = DevStar requires MySQL, PostgreSQL, MSSQL, SQLite3 or TiDB (MySQL protocol).
|
||||||
db_title = Database Settings
|
db_title = Database Settings
|
||||||
db_type = Database Type
|
db_type = Database Type
|
||||||
host = Host
|
host = Host
|
||||||
@@ -363,8 +363,10 @@ default_keep_email_private = Hide Email Addresses by Default
|
|||||||
default_keep_email_private_popup = Hide email addresses of new user accounts by default.
|
default_keep_email_private_popup = Hide email addresses of new user accounts by default.
|
||||||
default_allow_create_organization = Allow Creation of Organizations by Default
|
default_allow_create_organization = Allow Creation of Organizations by Default
|
||||||
default_allow_create_devcontainer = Allow Creation of DevContainers by Default
|
default_allow_create_devcontainer = Allow Creation of DevContainers by Default
|
||||||
|
default_allow_create_actrunner = Allow Creation of ActionRunners by Default
|
||||||
default_allow_create_organization_popup = Allow new user accounts to create organizations by default.
|
default_allow_create_organization_popup = Allow new user accounts to create organizations by default.
|
||||||
default_allow_create_devcontainer_popup = Allow new user accounts to create devcontainers by default.
|
default_allow_create_devcontainer_popup = Allow new user accounts to create devcontainers by default.
|
||||||
|
default_allow_create_actrunner_popup = Allow new user accounts to create ActionRunner by default.
|
||||||
default_enable_timetracking = Enable Time Tracking by Default
|
default_enable_timetracking = Enable Time Tracking by Default
|
||||||
default_enable_timetracking_popup = Enable time tracking for new repositories by default.
|
default_enable_timetracking_popup = Enable time tracking for new repositories by default.
|
||||||
no_reply_address = Hidden Email Domain
|
no_reply_address = Hidden Email Domain
|
||||||
@@ -373,7 +375,7 @@ password_algorithm = Password Hash Algorithm
|
|||||||
invalid_password_algorithm = Invalid password hash algorithm
|
invalid_password_algorithm = Invalid password hash algorithm
|
||||||
password_algorithm_helper = Set the password hashing algorithm. Algorithms have differing requirements and strength. The argon2 algorithm is rather secure but uses a lot of memory and may be inappropriate for small systems.
|
password_algorithm_helper = Set the password hashing algorithm. Algorithms have differing requirements and strength. The argon2 algorithm is rather secure but uses a lot of memory and may be inappropriate for small systems.
|
||||||
enable_update_checker = Enable Update Checker
|
enable_update_checker = Enable Update Checker
|
||||||
enable_update_checker_helper = Checks for new version releases periodically by connecting to gitea.io.
|
enable_update_checker_helper = Checks for new version releases periodically by connecting to devstar.cn
|
||||||
env_config_keys = Environment Configuration
|
env_config_keys = Environment Configuration
|
||||||
env_config_keys_prompt = The following environment variables will also be applied to your configuration file:
|
env_config_keys_prompt = The following environment variables will also be applied to your configuration file:
|
||||||
config_write_file_prompt = These configuration options will be written into: %s
|
config_write_file_prompt = These configuration options will be written into: %s
|
||||||
@@ -3163,6 +3165,7 @@ users.allow_git_hook_tooltip = Git Hooks are executed as the OS user running Git
|
|||||||
users.allow_import_local = May Import Local Repositories
|
users.allow_import_local = May Import Local Repositories
|
||||||
users.allow_create_organization = May Create Organizations
|
users.allow_create_organization = May Create Organizations
|
||||||
users.allow_create_devcontainer= May Create Devcontainers
|
users.allow_create_devcontainer= May Create Devcontainers
|
||||||
|
users.allow_create_actrunner= May Create ActRunners
|
||||||
users.update_profile = Update User Account
|
users.update_profile = Update User Account
|
||||||
users.delete_account = Delete User Account
|
users.delete_account = Delete User Account
|
||||||
users.cannot_delete_self = "You cannot delete yourself"
|
users.cannot_delete_self = "You cannot delete yourself"
|
||||||
@@ -3881,7 +3884,7 @@ status.blocked = "Blocked"
|
|||||||
runners = Runners
|
runners = Runners
|
||||||
runners.runner_manage_panel = Runners Management
|
runners.runner_manage_panel = Runners Management
|
||||||
runners.new = Create new Runner
|
runners.new = Create new Runner
|
||||||
runners.new_notice = How to start a runner
|
runners.new_notice = How to start a runner manually
|
||||||
runners.status = Status
|
runners.status = Status
|
||||||
runners.id = ID
|
runners.id = ID
|
||||||
runners.name = Name
|
runners.name = Name
|
||||||
|
|||||||
@@ -201,8 +201,8 @@ license_desc = Go get <a target="_blank" rel="noopener noreferrer" href="%[1]s">
|
|||||||
[install]
|
[install]
|
||||||
install=Instalación
|
install=Instalación
|
||||||
title=Configuración inicial
|
title=Configuración inicial
|
||||||
docker_helper=Si está ejecutando Gitea dentro de un contenedor Docker, por favor lea la <a target="_blank" rel="noopener noreferrer" href="%s">documentación</a> antes de realizar cambios en la configuración.
|
k8s_helper=Si está ejecutando DevStar dentro de un contenedor Kubernetes, por favor lea la <a target="_blank" rel="noopener noreferrer" href="%s">documentación</a> antes de realizar cambios en la configuración.
|
||||||
require_db_desc=Gitea requiere una base de datos MySQL, PostgreSQL, MSSQL, SQLite3 o TiDB (usar el protocolo MySQL).
|
require_db_desc=DevStar requiere una base de datos MySQL, PostgreSQL, MSSQL, SQLite3 o TiDB (usar el protocolo MySQL).
|
||||||
db_title=Configuración de base de datos
|
db_title=Configuración de base de datos
|
||||||
db_type=Tipo de base de datos
|
db_type=Tipo de base de datos
|
||||||
host=Servidor
|
host=Servidor
|
||||||
@@ -306,7 +306,7 @@ password_algorithm=Algoritmo Hash de Contraseña
|
|||||||
invalid_password_algorithm=Algoritmo hash de contraseña no válido
|
invalid_password_algorithm=Algoritmo hash de contraseña no válido
|
||||||
password_algorithm_helper=Establece el algoritmo de hashing de contraseña. Los algoritmos tienen diferentes requisitos y fuerza. El algoritmo argon2 es bastante seguro, pero usa mucha memoria y puede ser inapropiado para sistemas pequeños.
|
password_algorithm_helper=Establece el algoritmo de hashing de contraseña. Los algoritmos tienen diferentes requisitos y fuerza. El algoritmo argon2 es bastante seguro, pero usa mucha memoria y puede ser inapropiado para sistemas pequeños.
|
||||||
enable_update_checker=Activar comprobador de actualizaciones
|
enable_update_checker=Activar comprobador de actualizaciones
|
||||||
enable_update_checker_helper=Comprueba el lanzamiento de nuevas versiones periódicamente en gitea.io.
|
enable_update_checker_helper=Comprueba el lanzamiento de nuevas versiones periódicamente en devstar.cn.
|
||||||
env_config_keys=Configuración del entorno
|
env_config_keys=Configuración del entorno
|
||||||
env_config_keys_prompt=Las siguientes variables de entorno también se aplicarán a su archivo de configuración:
|
env_config_keys_prompt=Las siguientes variables de entorno también se aplicarán a su archivo de configuración:
|
||||||
|
|
||||||
|
|||||||
@@ -134,7 +134,7 @@ license_desc = Go get <a target="_blank" rel="noopener noreferrer" href="%[1]s">
|
|||||||
[install]
|
[install]
|
||||||
install=نصب و راه اندازی
|
install=نصب و راه اندازی
|
||||||
title=تنظیمات اولیه
|
title=تنظیمات اولیه
|
||||||
docker_helper=اگر گیتی را با داکر اجرا کردهاید، لطفا قبل از هر تغییری <a target="_blank" rel="noopener noreferrer" href="%s">مستندات</a> را مطالعه نمایید.
|
k8s_helper=اگر گیتی را با داکر اجرا کردهاید، لطفا قبل از هر تغییری <a target="_blank" rel="noopener noreferrer" href="%s">مستندات</a> را مطالعه نمایید.
|
||||||
db_title=تنظیمات پایگاه داده
|
db_title=تنظیمات پایگاه داده
|
||||||
db_type=نوع پایگاه داده
|
db_type=نوع پایگاه داده
|
||||||
host=میزبان
|
host=میزبان
|
||||||
|
|||||||
@@ -152,8 +152,8 @@ license_desc = Go get <a target="_blank" rel="noopener noreferrer" href="%[1]s">
|
|||||||
[install]
|
[install]
|
||||||
install=Asennus
|
install=Asennus
|
||||||
title=Alkuperäiset asetukset
|
title=Alkuperäiset asetukset
|
||||||
docker_helper=Jos ajat Giteaa Dockerin sisällä, lue <a target="_blank" rel="noopener noreferrer" href="%s">ohjeet</a> ennen minkään asetuksen muuttamista.
|
k8s_helper=Jos ajat DevStara Kubernetesin sisällä, lue <a target="_blank" rel="noopener noreferrer" href="%s">ohjeet</a> ennen minkään asetuksen muuttamista.
|
||||||
require_db_desc=Gitea tarvitsee toimiakseen MySQL, PostgreSQL, MSSQL, SQLite3 tai TiDB (MySQL protokolla) tietokannan.
|
require_db_desc=DevStar tarvitsee toimiakseen MySQL, PostgreSQL, MSSQL, SQLite3 tai TiDB (MySQL protokolla) tietokannan.
|
||||||
db_title=Tietokanta asetukset
|
db_title=Tietokanta asetukset
|
||||||
db_type=Tietokanta tyyppi
|
db_type=Tietokanta tyyppi
|
||||||
host=Isäntä
|
host=Isäntä
|
||||||
|
|||||||
@@ -254,8 +254,8 @@ license_desc = Go get <a target="_blank" rel="noopener noreferrer" href="%[1]s">
|
|||||||
install=Installation
|
install=Installation
|
||||||
installing_desc=Installation en cours, veuillez patienter…
|
installing_desc=Installation en cours, veuillez patienter…
|
||||||
title=Configuration initiale
|
title=Configuration initiale
|
||||||
docker_helper=Si vous exécutez Gitea dans Docker, veuillez lire la <a target="_blank" rel="noopener noreferrer" href="%s">documentation</a> avant de modifier les paramètres.
|
k8s_helper=Si vous exécutez DevStar dans Kubernetes, veuillez lire la <a target="_blank" rel="noopener noreferrer" href="%s">documentation</a> avant de modifier les paramètres.
|
||||||
require_db_desc=Gitea nécessite MySQL, PostgreSQL, MSSQL, SQLite3 ou TiDB (avec le protocole MySQL).
|
require_db_desc=DevStar nécessite MySQL, PostgreSQL, MSSQL, SQLite3 ou TiDB (avec le protocole MySQL).
|
||||||
db_title=Paramètres de la base de données
|
db_title=Paramètres de la base de données
|
||||||
db_type=Type de base de données
|
db_type=Type de base de données
|
||||||
host=Hôte
|
host=Hôte
|
||||||
@@ -360,7 +360,7 @@ password_algorithm=Algorithme de hachage du mot de passe
|
|||||||
invalid_password_algorithm=Algorithme de hachage du mot de passe invalide
|
invalid_password_algorithm=Algorithme de hachage du mot de passe invalide
|
||||||
password_algorithm_helper=Définissez l’algorithme de hachage du mot de passe. Les algorithmes ont des exigences matérielles et une résistance différentes. L’algorithme argon2 est bien sécurisé mais utilise beaucoup de mémoire et peut être inapproprié pour les systèmes limités en ressources.
|
password_algorithm_helper=Définissez l’algorithme de hachage du mot de passe. Les algorithmes ont des exigences matérielles et une résistance différentes. L’algorithme argon2 est bien sécurisé mais utilise beaucoup de mémoire et peut être inapproprié pour les systèmes limités en ressources.
|
||||||
enable_update_checker=Activer la vérification des mises-à-jour
|
enable_update_checker=Activer la vérification des mises-à-jour
|
||||||
enable_update_checker_helper=Vérifie les mises à jour régulièrement en se connectant à gitea.io.
|
enable_update_checker_helper=Vérifie les mises à jour régulièrement en se connectant à devstar.cn.
|
||||||
env_config_keys=Configuration de l'environnement
|
env_config_keys=Configuration de l'environnement
|
||||||
env_config_keys_prompt=Les variables d'environnement suivantes seront également ajoutées à votre fichier de configuration :
|
env_config_keys_prompt=Les variables d'environnement suivantes seront également ajoutées à votre fichier de configuration :
|
||||||
config_write_file_prompt=Ces options de configuration seront écrites dans : %s
|
config_write_file_prompt=Ces options de configuration seront écrites dans : %s
|
||||||
|
|||||||
@@ -254,7 +254,7 @@ license_desc = Go get <a target="_blank" rel="noopener noreferrer" href="%[1]s">
|
|||||||
install=Suiteáil
|
install=Suiteáil
|
||||||
installing_desc=Suiteáil anois, fan go fóill...
|
installing_desc=Suiteáil anois, fan go fóill...
|
||||||
title=Cumraíocht Tosaigh
|
title=Cumraíocht Tosaigh
|
||||||
docker_helper=Má ritheann tú Gitea taobh istigh de Docker, léigh an <a target="_blank" rel="noopener noreferrer" href="%s">doiciméadúchán</a> roimh aon socruithe a athrú.
|
k8s_helper=Má ritheann tú DevStar taobh istigh de Kubernetes, léigh an <a target="_blank" rel="noopener noreferrer" href="%s">doiciméadúchán</a> roimh aon socruithe a athrú.
|
||||||
require_db_desc=Éilíonn Gitea MySQL, PostgreSQL, MSSQL, SQLite3 nó TiDB (prótacal MySQL).
|
require_db_desc=Éilíonn Gitea MySQL, PostgreSQL, MSSQL, SQLite3 nó TiDB (prótacal MySQL).
|
||||||
db_title=Socruithe Bunachar Sonraí
|
db_title=Socruithe Bunachar Sonraí
|
||||||
db_type=Cineál Bunachar Sonraí
|
db_type=Cineál Bunachar Sonraí
|
||||||
@@ -360,7 +360,7 @@ password_algorithm=Algartam Hais Pasfhocal
|
|||||||
invalid_password_algorithm=Algartam hais pasfhocail neamhbhailí
|
invalid_password_algorithm=Algartam hais pasfhocail neamhbhailí
|
||||||
password_algorithm_helper=Socraigh an algartam hashing pasfhocal. Tá riachtanais agus neart éagsúla ag halgartaim. Tá an algartam argon2 sách slán ach úsáideann sé go leor cuimhne agus d'fhéadfadh sé a bheith míchuí do chórais bheaga.
|
password_algorithm_helper=Socraigh an algartam hashing pasfhocal. Tá riachtanais agus neart éagsúla ag halgartaim. Tá an algartam argon2 sách slán ach úsáideann sé go leor cuimhne agus d'fhéadfadh sé a bheith míchuí do chórais bheaga.
|
||||||
enable_update_checker=Cumasaigh Seiceoir Nuashonraithe
|
enable_update_checker=Cumasaigh Seiceoir Nuashonraithe
|
||||||
enable_update_checker_helper=Seiceálacha ar eisiúintí leagan nua go tréimhsiúil trí nascadh le gitea.io.
|
enable_update_checker_helper=Seiceálacha ar eisiúintí leagan nua go tréimhsiúil trí nascadh le devstar.cn.
|
||||||
env_config_keys=Cumraíocht Comhshaoil
|
env_config_keys=Cumraíocht Comhshaoil
|
||||||
env_config_keys_prompt=Cuirfear na hathróga comhshaoil seo a leanas i bhfeidhm ar do chomhad cumraíochta freisin:
|
env_config_keys_prompt=Cuirfear na hathróga comhshaoil seo a leanas i bhfeidhm ar do chomhad cumraíochta freisin:
|
||||||
config_write_file_prompt=Scríobhfar na roghanna cumraíochta seo isteach: %s
|
config_write_file_prompt=Scríobhfar na roghanna cumraíochta seo isteach: %s
|
||||||
|
|||||||
@@ -123,7 +123,7 @@ license_desc = Go get <a target="_blank" rel="noopener noreferrer" href="%[1]s">
|
|||||||
[install]
|
[install]
|
||||||
install=Telepítés
|
install=Telepítés
|
||||||
title=Kezdeti konfiguráció
|
title=Kezdeti konfiguráció
|
||||||
docker_helper=Ha ön a Gitea-t Docker-ből futtatja, kérem olvassa el a <a target="_blank" rel="noopener noreferrer" href="%s">dokumentációt</a> a beállítások megváltoztatása előtt.
|
k8s_helper=Ha ön a DevStar-t Kubernetes-ből futtatja, kérem olvassa el a <a target="_blank" rel="noopener noreferrer" href="%s">dokumentációt</a> a beállítások megváltoztatása előtt.
|
||||||
db_title=Adatbázis beállítások
|
db_title=Adatbázis beállítások
|
||||||
db_type=Adatbázis típusa
|
db_type=Adatbázis típusa
|
||||||
host=Kiszolgáló
|
host=Kiszolgáló
|
||||||
|
|||||||
@@ -148,8 +148,8 @@ license_desc = Go get <a target="_blank" rel="noopener noreferrer" href="%[1]s">
|
|||||||
[install]
|
[install]
|
||||||
install=Uppsetning
|
install=Uppsetning
|
||||||
title=Upphafleg Uppsetning
|
title=Upphafleg Uppsetning
|
||||||
docker_helper=Ef þú keyrir Gitea inni í Docker þá viltu vinsamlegast lesa <a target="_blank" rel="noopener noreferrer" href="%s">leiðbeiningaritið</a> áður en þú breytir stillingum.
|
k8s_helper=Ef þú keyrir DevStar inni í Kubernetes þá viltu vinsamlegast lesa <a target="_blank" rel="noopener noreferrer" href="%s">leiðbeiningaritið</a> áður en þú breytir stillingum.
|
||||||
require_db_desc=Gitea krefst MySQL, PostgreSQL, MSSQL, SQLite3 eða TiDB (MySQL samskiptareglur).
|
require_db_desc=DevStar krefst MySQL, PostgreSQL, MSSQL, SQLite3 eða TiDB (MySQL samskiptareglur).
|
||||||
db_title=Gagnagrunnsstillingar
|
db_title=Gagnagrunnsstillingar
|
||||||
db_type=Tegund Gagnagrunns
|
db_type=Tegund Gagnagrunns
|
||||||
host=Hýsill
|
host=Hýsill
|
||||||
|
|||||||
@@ -154,8 +154,8 @@ license_desc = Go get <a target="_blank" rel="noopener noreferrer" href="%[1]s">
|
|||||||
[install]
|
[install]
|
||||||
install=Installazione
|
install=Installazione
|
||||||
title=Configurazione Iniziale
|
title=Configurazione Iniziale
|
||||||
docker_helper=Se stai usando Gitea con Docker, leggi <a target="_blank" rel="noopener noreferrer" href="%s">la documentazione</a> prima di cambiare qualsiasi impostazione.
|
k8s_helper=Se stai usando DevStar con Kubernetes, leggi <a target="_blank" rel="noopener noreferrer" href="%s">la documentazione</a> prima di cambiare qualsiasi impostazione.
|
||||||
require_db_desc=Gitea requires MySQL, PostgreSQL, MSSQL, SQLite3 or TiDB (MySQL protocol).
|
require_db_desc=DevStar requires MySQL, PostgreSQL, MSSQL, SQLite3 or TiDB (MySQL protocol).
|
||||||
db_title=Impostazioni Database
|
db_title=Impostazioni Database
|
||||||
db_type=Tipo di database
|
db_type=Tipo di database
|
||||||
host=Host
|
host=Host
|
||||||
|
|||||||
@@ -251,8 +251,8 @@ license_desc = Go get <a target="_blank" rel="noopener noreferrer" href="%[1]s">
|
|||||||
install=インストール
|
install=インストール
|
||||||
installing_desc=インストール中です、お待ちください...
|
installing_desc=インストール中です、お待ちください...
|
||||||
title=初期設定
|
title=初期設定
|
||||||
docker_helper=GiteaをDocker内で実行する場合は、設定を変更する前に<a target="_blank" rel="noopener noreferrer" href="%s">ドキュメント</a>を読んでください。
|
k8s_helper=DevStarをKubernetes内で実行する場合は、設定を変更する前に<a target="_blank" rel="noopener noreferrer" href="%s">ドキュメント</a>を読んでください。
|
||||||
require_db_desc=Giteaには、MySQL、PostgreSQL、MSSQL、SQLite3、またはTiDB(MySQL プロトコル) が必要です。
|
require_db_desc=DevStarには、MySQL、PostgreSQL、MSSQL、SQLite3、またはTiDB(MySQL プロトコル) が必要です。
|
||||||
db_title=データベース設定
|
db_title=データベース設定
|
||||||
db_type=データベースのタイプ
|
db_type=データベースのタイプ
|
||||||
host=ホスト
|
host=ホスト
|
||||||
@@ -357,7 +357,7 @@ password_algorithm=パスワードハッシュアルゴリズム
|
|||||||
invalid_password_algorithm=無効なパスワードハッシュアルゴリズム
|
invalid_password_algorithm=無効なパスワードハッシュアルゴリズム
|
||||||
password_algorithm_helper=パスワードハッシュアルゴリズムを設定します。 アルゴリズムにより動作要件と強度が異なります。 argon2アルゴリズムはかなり安全ですが、多くのメモリを使用するため小さなシステムには適さない場合があります。
|
password_algorithm_helper=パスワードハッシュアルゴリズムを設定します。 アルゴリズムにより動作要件と強度が異なります。 argon2アルゴリズムはかなり安全ですが、多くのメモリを使用するため小さなシステムには適さない場合があります。
|
||||||
enable_update_checker=アップデートチェッカーを有効にする
|
enable_update_checker=アップデートチェッカーを有効にする
|
||||||
enable_update_checker_helper=gitea.ioに接続して定期的に新しいバージョンのリリースを確認します。
|
enable_update_checker_helper=devstar.cnに接続して定期的に新しいバージョンのリリースを確認します。
|
||||||
env_config_keys=環境設定
|
env_config_keys=環境設定
|
||||||
env_config_keys_prompt=以下の環境変数も設定ファイルに適用されます:
|
env_config_keys_prompt=以下の環境変数も設定ファイルに適用されます:
|
||||||
config_write_file_prompt=これらの設定オプションは %s に書き込まれます
|
config_write_file_prompt=これらの設定オプションは %s に書き込まれます
|
||||||
|
|||||||
@@ -115,7 +115,7 @@ license_desc = Go get <a target="_blank" rel="noopener noreferrer" href="%[1]s">
|
|||||||
[install]
|
[install]
|
||||||
install=설치
|
install=설치
|
||||||
title=초기 설정
|
title=초기 설정
|
||||||
docker_helper=Gitea를 Docker에서 실행하려면 설정 전에 이 <a target="_blank" rel="noopener noreferrer" href="%s">문서</a>를 읽어보세요.
|
k8s_helper=DevStar를 Kubernetes에서 실행하려면 설정 전에 이 <a target="_blank" rel="noopener noreferrer" href="%s">문서</a>를 읽어보세요.
|
||||||
db_title=데이터베이스 설정
|
db_title=데이터베이스 설정
|
||||||
db_type=데이터베이스 유형
|
db_type=데이터베이스 유형
|
||||||
host=호스트
|
host=호스트
|
||||||
|
|||||||
@@ -206,8 +206,8 @@ license_desc = Go get <a target="_blank" rel="noopener noreferrer" href="%[1]s">
|
|||||||
[install]
|
[install]
|
||||||
install=Instalācija
|
install=Instalācija
|
||||||
title=Sākotnējā konfigurācija
|
title=Sākotnējā konfigurācija
|
||||||
docker_helper=Ja Gitea ir uzstādīts Docker konteinerī, izlasiet <a target="_blank" rel="noopener noreferrer" href="%s">vadlīninas</a> pirms maināt iestatījumus.
|
k8s_helper=Ja DevStar ir uzstādīts Kubernetes konteinerī, izlasiet <a target="_blank" rel="noopener noreferrer" href="%s">vadlīninas</a> pirms maināt iestatījumus.
|
||||||
require_db_desc=Gitea nepieciešams MySQL, PostgreSQL, MSSQL, SQLite3 vai TiDB (izmantojot MySQL protokolu).
|
require_db_desc=DevStar nepieciešams MySQL, PostgreSQL, MSSQL, SQLite3 vai TiDB (izmantojot MySQL protokolu).
|
||||||
db_title=Datu bāzes iestatījumi
|
db_title=Datu bāzes iestatījumi
|
||||||
db_type=Datu bāzes veids
|
db_type=Datu bāzes veids
|
||||||
host=Resursdators
|
host=Resursdators
|
||||||
@@ -311,7 +311,7 @@ password_algorithm=Paroles jaucējsummas algoritms
|
|||||||
invalid_password_algorithm=Kļūdaina paroles jaucējfunkcija
|
invalid_password_algorithm=Kļūdaina paroles jaucējfunkcija
|
||||||
password_algorithm_helper=Norādiet paroles jaucējalgoritmu. Algoritmi atšķirās pēc prasībām pret resursiem un stipruma. Argon2 algoritms ir drošs, bet tam nepieciešams daudz operatīvās atmiņas, līdz ar ko tas var nebūt piemērots sistēmām ar maz pieejamajiem resursiem.
|
password_algorithm_helper=Norādiet paroles jaucējalgoritmu. Algoritmi atšķirās pēc prasībām pret resursiem un stipruma. Argon2 algoritms ir drošs, bet tam nepieciešams daudz operatīvās atmiņas, līdz ar ko tas var nebūt piemērots sistēmām ar maz pieejamajiem resursiem.
|
||||||
enable_update_checker=Iespējot jaunu versiju paziņojumus
|
enable_update_checker=Iespējot jaunu versiju paziņojumus
|
||||||
enable_update_checker_helper=Periodiski pārbaudīt jaunu version pieejamību, izgūstot datus no gitea.io.
|
enable_update_checker_helper=Periodiski pārbaudīt jaunu version pieejamību, izgūstot datus no devstar.cn.
|
||||||
env_config_keys=Vides konfigurācija
|
env_config_keys=Vides konfigurācija
|
||||||
env_config_keys_prompt=Šie vides mainīgie tiks pielietoti arī konfigurācijas failā:
|
env_config_keys_prompt=Šie vides mainīgie tiks pielietoti arī konfigurācijas failā:
|
||||||
|
|
||||||
|
|||||||
@@ -153,8 +153,8 @@ license_desc = Go get <a target="_blank" rel="noopener noreferrer" href="%[1]s">
|
|||||||
[install]
|
[install]
|
||||||
install=Installatie
|
install=Installatie
|
||||||
title=Initiële configuratie
|
title=Initiële configuratie
|
||||||
docker_helper=Als je gitea draait in Docker, Lees eerst de <a target="_blank" rel="noopener noreferrer" href="%s">documentatie</a> voordat je een instelling aanpast.
|
k8s_helper=Als je gitea draait in Kubernetes, Lees eerst de <a target="_blank" rel="noopener noreferrer" href="%s">documentatie</a> voordat je een instelling aanpast.
|
||||||
require_db_desc=Gitea vereist MySQL, PostgreSQL, MSSQL, SQLite3 of TiDB (MySQL protocol).
|
require_db_desc=DevStar vereist MySQL, PostgreSQL, MSSQL, SQLite3 of TiDB (MySQL protocol).
|
||||||
db_title=Database-instellingen
|
db_title=Database-instellingen
|
||||||
db_type=Database-type
|
db_type=Database-type
|
||||||
host=Server
|
host=Server
|
||||||
|
|||||||
@@ -149,8 +149,8 @@ license_desc = Go get <a target="_blank" rel="noopener noreferrer" href="%[1]s">
|
|||||||
[install]
|
[install]
|
||||||
install=Instalacja
|
install=Instalacja
|
||||||
title=Wstępna konfiguracja
|
title=Wstępna konfiguracja
|
||||||
docker_helper=Jeśli używasz Gitea za pomocą Docker'a, przeczytaj <a target="_blank" rel="noopener noreferrer" href="%s">dokumentację</a> przed wprowadzeniem jakichkolwiek zmian.
|
k8s_helper=Jeśli używasz DevStar za pomocą Kubernetes'a, przeczytaj <a target="_blank" rel="noopener noreferrer" href="%s">dokumentację</a> przed wprowadzeniem jakichkolwiek zmian.
|
||||||
require_db_desc=Gitea wymaga MySQL, PostgreSQL, MSSQL, SQLite3 lub TiDB (protokół MySQL).
|
require_db_desc=DevStar wymaga MySQL, PostgreSQL, MSSQL, SQLite3 lub TiDB (protokół MySQL).
|
||||||
db_title=Ustawienia bazy danych
|
db_title=Ustawienia bazy danych
|
||||||
db_type=Typ bazy danych
|
db_type=Typ bazy danych
|
||||||
host=Serwer
|
host=Serwer
|
||||||
|
|||||||
@@ -202,8 +202,8 @@ license_desc = Go get <a target="_blank" rel="noopener noreferrer" href="%[1]s">
|
|||||||
[install]
|
[install]
|
||||||
install=Instalação
|
install=Instalação
|
||||||
title=Configuração inicial
|
title=Configuração inicial
|
||||||
docker_helper=Se você está rodando o Gitea dentro do Docker, por favor leia a <a target="_blank" rel="noopener noreferrer" href="%s">documentação</a> cuidadosamente antes de alterar qualquer coisa nesta página.
|
k8s_helper=Se você está rodando o DevStar dentro do Kubernetes, por favor leia a <a target="_blank" rel="noopener noreferrer" href="%s">documentação</a> cuidadosamente antes de alterar qualquer coisa nesta página.
|
||||||
require_db_desc=Gitea requer MySQL, PostgreSQL, MSSQL, SQLite3 ou TiDB (protocolo MySQL).
|
require_db_desc=DevStar requer MySQL, PostgreSQL, MSSQL, SQLite3 ou TiDB (protocolo MySQL).
|
||||||
db_title=Configurações de banco de dados
|
db_title=Configurações de banco de dados
|
||||||
db_type=Tipo de banco de dados
|
db_type=Tipo de banco de dados
|
||||||
host=Servidor
|
host=Servidor
|
||||||
@@ -307,7 +307,7 @@ password_algorithm=Algoritmo Hash de Senha
|
|||||||
invalid_password_algorithm=Algoritmo de hash de senha inválido
|
invalid_password_algorithm=Algoritmo de hash de senha inválido
|
||||||
password_algorithm_helper=Escolha o algoritmo de hash para as senhas. Diferentes algoritmos têm requerimentos e forças diversos. O algoritmo argon2 é bastante seguro, mas usa muita memória e pode ser inapropriado para sistemas com menos recursos.
|
password_algorithm_helper=Escolha o algoritmo de hash para as senhas. Diferentes algoritmos têm requerimentos e forças diversos. O algoritmo argon2 é bastante seguro, mas usa muita memória e pode ser inapropriado para sistemas com menos recursos.
|
||||||
enable_update_checker=Habilitar Verificador de Atualizações
|
enable_update_checker=Habilitar Verificador de Atualizações
|
||||||
enable_update_checker_helper=Procura por novas versões periodicamente conectando-se ao gitea.io.
|
enable_update_checker_helper=Procura por novas versões periodicamente conectando-se ao devstar.cn.
|
||||||
env_config_keys=Configuração do ambiente
|
env_config_keys=Configuração do ambiente
|
||||||
env_config_keys_prompt=As seguintes variáveis de ambiente também serão aplicadas ao seu arquivo de configuração:
|
env_config_keys_prompt=As seguintes variáveis de ambiente também serão aplicadas ao seu arquivo de configuração:
|
||||||
|
|
||||||
|
|||||||
@@ -254,8 +254,8 @@ license_desc = Go get <a target="_blank" rel="noopener noreferrer" href="%[1]s">
|
|||||||
install=Instalação
|
install=Instalação
|
||||||
installing_desc=Instalando agora, por favor aguarde...
|
installing_desc=Instalando agora, por favor aguarde...
|
||||||
title=Configuração inicial
|
title=Configuração inicial
|
||||||
docker_helper=Se correr o Gitea dentro do Docker, leia a <a target="_blank" rel="noopener noreferrer" href="%s">documentação</a> antes de alterar quaisquer configurações.
|
k8s_helper=Se correr o DevStar dentro do Kubernetes, leia a <a target="_blank" rel="noopener noreferrer" href="%s">documentação</a> antes de alterar quaisquer configurações.
|
||||||
require_db_desc=Gitea requer MySQL, PostgreSQL, MSSQL, SQLite3 ou TiDB (protocolo MySQL).
|
require_db_desc=DevStar requer MySQL, PostgreSQL, MSSQL, SQLite3 ou TiDB (protocolo MySQL).
|
||||||
db_title=Configurações da base de dados
|
db_title=Configurações da base de dados
|
||||||
db_type=Tipo de base de dados
|
db_type=Tipo de base de dados
|
||||||
host=Servidor
|
host=Servidor
|
||||||
@@ -360,7 +360,7 @@ password_algorithm=Algoritmo de Hash da Senha
|
|||||||
invalid_password_algorithm=Algoritmo de hash da senha inválido
|
invalid_password_algorithm=Algoritmo de hash da senha inválido
|
||||||
password_algorithm_helper=Definir o algoritmo de hash da senha. Os algoritmos têm requisitos e resistência distintos. `argon2` é bastante seguro, mas usa muita memória e pode ser inapropriado para sistemas pequenos.
|
password_algorithm_helper=Definir o algoritmo de hash da senha. Os algoritmos têm requisitos e resistência distintos. `argon2` é bastante seguro, mas usa muita memória e pode ser inapropriado para sistemas pequenos.
|
||||||
enable_update_checker=Habilitar verificador de novidades
|
enable_update_checker=Habilitar verificador de novidades
|
||||||
enable_update_checker_helper=Verifica, periodicamente, se foi lançada alguma versão nova, fazendo uma ligação ao gitea.io.
|
enable_update_checker_helper=Verifica, periodicamente, se foi lançada alguma versão nova, fazendo uma ligação ao devstar.cn.
|
||||||
env_config_keys=Configuração do ambiente
|
env_config_keys=Configuração do ambiente
|
||||||
env_config_keys_prompt=As seguintes variáveis de ambiente também serão aplicadas ao seu ficheiro de configuração:
|
env_config_keys_prompt=As seguintes variáveis de ambiente também serão aplicadas ao seu ficheiro de configuração:
|
||||||
config_write_file_prompt=Estas opções de configuração serão escritas em: %s
|
config_write_file_prompt=Estas opções de configuração serão escritas em: %s
|
||||||
|
|||||||
@@ -201,8 +201,8 @@ license_desc = Go get <a target="_blank" rel="noopener noreferrer" href="%[1]s">
|
|||||||
[install]
|
[install]
|
||||||
install=Установка
|
install=Установка
|
||||||
title=Начальная конфигурация
|
title=Начальная конфигурация
|
||||||
docker_helper=Если вы запускаете Gitea внутри Docker, пожалуйста внимательно прочтите <a target="_blank" rel="noopener noreferrer" href="%s">документацию</a> перед тем, как изменить любые настройки.
|
k8s_helper=Если вы запускаете DevStar внутри Kubernetes, пожалуйста внимательно прочтите <a target="_blank" rel="noopener noreferrer" href="%s">документацию</a> перед тем, как изменить любые настройки.
|
||||||
require_db_desc=Gitea требует MySQL, PostgreSQL, MSSQL, SQLite3 или TiDB (через протокол MySQL).
|
require_db_desc=DevStar требует MySQL, PostgreSQL, MSSQL, SQLite3 или TiDB (через протокол MySQL).
|
||||||
db_title=Настройки базы данных
|
db_title=Настройки базы данных
|
||||||
db_type=Тип базы данных
|
db_type=Тип базы данных
|
||||||
host=Хост
|
host=Хост
|
||||||
@@ -306,7 +306,7 @@ password_algorithm=Алгоритм хеширования пароля
|
|||||||
invalid_password_algorithm=Некорректный алгоритм хеширования пароля
|
invalid_password_algorithm=Некорректный алгоритм хеширования пароля
|
||||||
password_algorithm_helper=Задайте алгоритм хеширования паролей. Алгоритмы имеют различные требования и стойкость. Алгоритм argon2 довольно безопасен, но он использует много памяти и может не подходить для слабых систем.
|
password_algorithm_helper=Задайте алгоритм хеширования паролей. Алгоритмы имеют различные требования и стойкость. Алгоритм argon2 довольно безопасен, но он использует много памяти и может не подходить для слабых систем.
|
||||||
enable_update_checker=Включить проверку обновлений
|
enable_update_checker=Включить проверку обновлений
|
||||||
enable_update_checker_helper=Периодически проверяет наличие новых версий, подключаясь к gitea.io.
|
enable_update_checker_helper=Периодически проверяет наличие новых версий, подключаясь к devstar.cn.
|
||||||
env_config_keys=Настройка окружения
|
env_config_keys=Настройка окружения
|
||||||
env_config_keys_prompt=Следующие переменные окружения также будут применены к вашему конфигурационному файлу:
|
env_config_keys_prompt=Следующие переменные окружения также будут применены к вашему конфигурационному файлу:
|
||||||
|
|
||||||
|
|||||||
@@ -134,7 +134,7 @@ license_desc = Go get <a target="_blank" rel="noopener noreferrer" href="%[1]s">
|
|||||||
[install]
|
[install]
|
||||||
install=ස්ථාපනය
|
install=ස්ථාපනය
|
||||||
title=මූලික වින්යාසය
|
title=මූලික වින්යාසය
|
||||||
docker_helper=ඔබ Docker තුළ Gitea ධාවනය කරන්නේ නම්, කරුණාකර ඕනෑම සැකසුම් වෙනස් කිරීමට පෙර <a target="_blank" rel="noopener noreferrer" href="%s">ලියකියවිලි</a> කියවන්න.
|
k8s_helper=ඔබ Kubernetes තුළ DevStar ධාවනය කරන්නේ නම්, කරුණාකර ඕනෑම සැකසුම් වෙනස් කිරීමට පෙර <a target="_blank" rel="noopener noreferrer" href="%s">ලියකියවිලි</a> කියවන්න.
|
||||||
db_title=දත්ත සමුදායේ සැකසුම්
|
db_title=දත්ත සමුදායේ සැකසුම්
|
||||||
db_type=දත්ත සමුදායේ වර්ගය
|
db_type=දත්ත සමුදායේ වර්ගය
|
||||||
host=සත්කාරක
|
host=සත්කාරක
|
||||||
|
|||||||
@@ -200,8 +200,8 @@ license_desc = Go get <a target="_blank" rel="noopener noreferrer" href="%[1]s">
|
|||||||
[install]
|
[install]
|
||||||
install=Inštalácia
|
install=Inštalácia
|
||||||
title=Východzia konfigurácia
|
title=Východzia konfigurácia
|
||||||
docker_helper=Ak spúšťate Gitea v Docker kontajneri, prečítajte si <a target="_blank" rel="noopener noreferrer" href="%s">dokumentáciu</a> pred zmenou akýchkoľvek nastavení.
|
k8s_helper=Ak spúšťate DevStar v Kubernetes kontajneri, prečítajte si <a target="_blank" rel="noopener noreferrer" href="%s">dokumentáciu</a> pred zmenou akýchkoľvek nastavení.
|
||||||
require_db_desc=Gitea vyžaduje MySQL, PostgreSQL, MSSQL, SQLite3 alebo TiDB (MySQL protokol).
|
require_db_desc=DevStar vyžaduje MySQL, PostgreSQL, MSSQL, SQLite3 alebo TiDB (MySQL protokol).
|
||||||
db_title=Nastavenie databázy
|
db_title=Nastavenie databázy
|
||||||
db_type=Typ databázy
|
db_type=Typ databázy
|
||||||
host=Host
|
host=Host
|
||||||
@@ -303,7 +303,7 @@ password_algorithm=Hašovací algoritmus hesla
|
|||||||
invalid_password_algorithm=Neplatný hash algoritmus hesla
|
invalid_password_algorithm=Neplatný hash algoritmus hesla
|
||||||
password_algorithm_helper=Nastavte algoritmus hashovania hesla. Algoritmy majú rôzne požiadavky a silu. Algoritmus argon2 je pomerne bezpečný, ale využíva veľa pamäte a môže byť nevhodný pre malé systémy.
|
password_algorithm_helper=Nastavte algoritmus hashovania hesla. Algoritmy majú rôzne požiadavky a silu. Algoritmus argon2 je pomerne bezpečný, ale využíva veľa pamäte a môže byť nevhodný pre malé systémy.
|
||||||
enable_update_checker=Povoliť kontrolu aktualizácií
|
enable_update_checker=Povoliť kontrolu aktualizácií
|
||||||
enable_update_checker_helper=Pravidelne kontroluje nové verzie pripojením k gitea.io.
|
enable_update_checker_helper=Pravidelne kontroluje nové verzie pripojením k devstar.cn.
|
||||||
|
|
||||||
[home]
|
[home]
|
||||||
uname_holder=Používateľské meno alebo emailová adresa
|
uname_holder=Používateľské meno alebo emailová adresa
|
||||||
|
|||||||
@@ -124,7 +124,7 @@ license_desc = Go get <a target="_blank" rel="noopener noreferrer" href="%[1]s">
|
|||||||
[install]
|
[install]
|
||||||
install=Installation
|
install=Installation
|
||||||
title=Ursprunglig konfiguration
|
title=Ursprunglig konfiguration
|
||||||
docker_helper=Om du kör Gitea i Docker, vänligen läs igenom <a target="_blank" rel="noopener noreferrer" href="%s">dokumentationen</a> innan några inställningar ändras.
|
k8s_helper=Om du kör DevStar i Kubernetes, vänligen läs igenom <a target="_blank" rel="noopener noreferrer" href="%s">dokumentationen</a> innan några inställningar ändras.
|
||||||
db_title=Databasinställningar
|
db_title=Databasinställningar
|
||||||
db_type=Databastyp
|
db_type=Databastyp
|
||||||
host=Server
|
host=Server
|
||||||
|
|||||||
@@ -251,8 +251,8 @@ license_desc = Go get <a target="_blank" rel="noopener noreferrer" href="%[1]s">
|
|||||||
install=Kurulum
|
install=Kurulum
|
||||||
installing_desc=Şimdi kuruluyor, lütfen bekleyin...
|
installing_desc=Şimdi kuruluyor, lütfen bekleyin...
|
||||||
title=Başlangıç Yapılandırması
|
title=Başlangıç Yapılandırması
|
||||||
docker_helper=Eğer Gitea'yı Docker içerisinde çalıştırıyorsanız, lütfen herhangi bir değişiklik yapmadan önce <a target="_blank" rel="noopener noreferrer" href="%s">belgeleri</a> okuyun.
|
k8s_helper=Eğer DevStar'yı Kubernetes içerisinde çalıştırıyorsanız, lütfen herhangi bir değişiklik yapmadan önce <a target="_blank" rel="noopener noreferrer" href="%s">belgeleri</a> okuyun.
|
||||||
require_db_desc=Gitea MySQL, PostgreSQL, MSSQL, SQLite3 veya TiDB (MySQL protokolü) gerektirir.
|
require_db_desc=DevStar MySQL, PostgreSQL, MSSQL, SQLite3 veya TiDB (MySQL protokolü) gerektirir.
|
||||||
db_title=Veritabanı Ayarları
|
db_title=Veritabanı Ayarları
|
||||||
db_type=Veritabanı Türü
|
db_type=Veritabanı Türü
|
||||||
host=Sunucu
|
host=Sunucu
|
||||||
@@ -357,7 +357,7 @@ password_algorithm=Parola Hash Algoritması
|
|||||||
invalid_password_algorithm=Hatalı parola hash algoritması
|
invalid_password_algorithm=Hatalı parola hash algoritması
|
||||||
password_algorithm_helper=Parola hash algoritmasını ayarlayın. Algoritmalar değişen gereksinimlere ve güce sahiptirler. argon2 algoritması iyi özelliklere sahip olmasına rağmen fazla miktarda bellek kullanır ve küçük sistemler için uygun olmayabilir.
|
password_algorithm_helper=Parola hash algoritmasını ayarlayın. Algoritmalar değişen gereksinimlere ve güce sahiptirler. argon2 algoritması iyi özelliklere sahip olmasına rağmen fazla miktarda bellek kullanır ve küçük sistemler için uygun olmayabilir.
|
||||||
enable_update_checker=Güncelleme Denetleyicisini Etkinleştir
|
enable_update_checker=Güncelleme Denetleyicisini Etkinleştir
|
||||||
enable_update_checker_helper=Düzenli olarak gitea.io'ya bağlanarak yeni yayınlanan sürümleri denetler.
|
enable_update_checker_helper=Düzenli olarak devstar.cn'ya bağlanarak yeni yayınlanan sürümleri denetler.
|
||||||
env_config_keys=Ortam Yapılandırma
|
env_config_keys=Ortam Yapılandırma
|
||||||
env_config_keys_prompt=Aşağıdaki ortam değişkenleri de yapılandırma dosyanıza eklenecektir:
|
env_config_keys_prompt=Aşağıdaki ortam değişkenleri de yapılandırma dosyanıza eklenecektir:
|
||||||
config_write_file_prompt=Bu yapılandırma seçenekleri şuraya yazılacak: %s
|
config_write_file_prompt=Bu yapılandırma seçenekleri şuraya yazılacak: %s
|
||||||
|
|||||||
@@ -246,8 +246,8 @@ license_desc = Go get <a target="_blank" rel="noopener noreferrer" href="%[1]s">
|
|||||||
install=Встановлення
|
install=Встановлення
|
||||||
installing_desc=Встановлення, будь ласка, зачекайте...
|
installing_desc=Встановлення, будь ласка, зачекайте...
|
||||||
title=Початкова конфігурація
|
title=Початкова конфігурація
|
||||||
docker_helper=Якщо ви запускаєте Gitea у Docker, будь ласка, прочитайте <a target="_blank" rel="noopener noreferrer" href="%s">документацію</a> перед тим, як змінювати будь-які налаштування.
|
k8s_helper=Якщо ви запускаєте DevStar у Kubernetes, будь ласка, прочитайте <a target="_blank" rel="noopener noreferrer" href="%s">документацію</a> перед тим, як змінювати будь-які налаштування.
|
||||||
require_db_desc=Gitea потребує MySQL, PostgreSQL, MSSQL, SQLite3 або TiDB (протокол MySQL).
|
require_db_desc=DevStar потребує MySQL, PostgreSQL, MSSQL, SQLite3 або TiDB (протокол MySQL).
|
||||||
db_title=Налаштування бази даних
|
db_title=Налаштування бази даних
|
||||||
db_type=Тип бази даних
|
db_type=Тип бази даних
|
||||||
host=Хост
|
host=Хост
|
||||||
@@ -352,7 +352,7 @@ password_algorithm=Алгоритм хешування пароля
|
|||||||
invalid_password_algorithm=Недійсний хеш-алгоритм пароля
|
invalid_password_algorithm=Недійсний хеш-алгоритм пароля
|
||||||
password_algorithm_helper=Встановіть алгоритм хешування пароля. Алгоритми мають різні вимоги та стійкість. Алгоритм argon2 є досить безпечним, але використовує багато пам'яті і може бути недоречним для малих систем.
|
password_algorithm_helper=Встановіть алгоритм хешування пароля. Алгоритми мають різні вимоги та стійкість. Алгоритм argon2 є досить безпечним, але використовує багато пам'яті і може бути недоречним для малих систем.
|
||||||
enable_update_checker=Увімкнути перевірку оновлень
|
enable_update_checker=Увімкнути перевірку оновлень
|
||||||
enable_update_checker_helper=Періодично перевіряти наявність нових версій, підключаючись до gitea.io.
|
enable_update_checker_helper=Періодично перевіряти наявність нових версій, підключаючись до devstar.cn.
|
||||||
env_config_keys=Конфігурація середовища
|
env_config_keys=Конфігурація середовища
|
||||||
env_config_keys_prompt=Наступні змінні середовища також будуть застосовані до вашого файлу конфігурації:
|
env_config_keys_prompt=Наступні змінні середовища також будуть застосовані до вашого файлу конфігурації:
|
||||||
config_write_file_prompt=Ці параметри будуть записані в: %s
|
config_write_file_prompt=Ці параметри будуть записані в: %s
|
||||||
|
|||||||
@@ -251,8 +251,8 @@ license_desc=所有的代码都开源在 <a target="_blank" rel="noopener norefe
|
|||||||
install=安装页面
|
install=安装页面
|
||||||
installing_desc=正在安装,请稍候...
|
installing_desc=正在安装,请稍候...
|
||||||
title=初始配置
|
title=初始配置
|
||||||
docker_helper=如果您正在使用 Docker 容器运行 Gitea,请务必先仔细阅读 <a target="_blank" rel="noopener noreferrer" href="%s">官方文档</a> 后再对本页面进行填写。
|
k8s_helper=如果您正在使用 Kubernetes 运行 DevStar,请务必先仔细阅读 <a target="_blank" rel="noopener noreferrer" href="%s">官方文档</a> 后再对本页面进行填写。
|
||||||
require_db_desc=Gitea 需要使用 MySQL、PostgreSQL、MSSQL、SQLite3 或 TiDB (MySQL协议) 等数据库
|
require_db_desc=DevStar 需要使用 MySQL、PostgreSQL、MSSQL、SQLite3 或 TiDB (MySQL协议) 等数据库
|
||||||
db_title=数据库设置
|
db_title=数据库设置
|
||||||
db_type=数据库类型
|
db_type=数据库类型
|
||||||
host=数据库主机
|
host=数据库主机
|
||||||
@@ -358,8 +358,10 @@ default_keep_email_private=默认情况下隐藏邮箱地址
|
|||||||
default_keep_email_private_popup=默认情况下,隐藏新用户帐户的邮箱地址。
|
default_keep_email_private_popup=默认情况下,隐藏新用户帐户的邮箱地址。
|
||||||
default_allow_create_organization=默认情况下允许创建组织
|
default_allow_create_organization=默认情况下允许创建组织
|
||||||
default_allow_create_devcontainer=默认情况下允许创建容器
|
default_allow_create_devcontainer=默认情况下允许创建容器
|
||||||
|
default_allow_create_actrunner=默认情况下允许创建工作流运行器
|
||||||
default_allow_create_organization_popup=默认情况下, 允许新用户帐户创建组织。
|
default_allow_create_organization_popup=默认情况下, 允许新用户帐户创建组织。
|
||||||
default_allow_create_devcontainer_popup=默认情况下, 允许新用户帐户创建容器。
|
default_allow_create_devcontainer_popup=默认情况下, 允许新用户帐户创建容器。
|
||||||
|
default_allow_create_actrunner_popup=默认情况下, 允许新用户帐户创建工作流运行器。
|
||||||
default_enable_timetracking=默认情况下启用时间跟踪
|
default_enable_timetracking=默认情况下启用时间跟踪
|
||||||
default_enable_timetracking_popup=默认情况下启用新仓库的时间跟踪。
|
default_enable_timetracking_popup=默认情况下启用新仓库的时间跟踪。
|
||||||
no_reply_address=隐藏邮件域
|
no_reply_address=隐藏邮件域
|
||||||
@@ -368,7 +370,7 @@ password_algorithm=密码哈希算法
|
|||||||
invalid_password_algorithm=无效的密码哈希算法
|
invalid_password_algorithm=无效的密码哈希算法
|
||||||
password_algorithm_helper=设置密码散列算法。算法有不同的要求和强度。 argon2 算法相当安全,但使用大量内存,因此可能不适合小型系统。
|
password_algorithm_helper=设置密码散列算法。算法有不同的要求和强度。 argon2 算法相当安全,但使用大量内存,因此可能不适合小型系统。
|
||||||
enable_update_checker=启用更新检查
|
enable_update_checker=启用更新检查
|
||||||
enable_update_checker_helper=通过连接到 gitea.io 定期检查新版本发布。
|
enable_update_checker_helper=通过连接到 devstar.cn 定期检查新版本发布。
|
||||||
env_config_keys=环境配置
|
env_config_keys=环境配置
|
||||||
env_config_keys_prompt=以下环境变量也将应用于您的配置文件:
|
env_config_keys_prompt=以下环境变量也将应用于您的配置文件:
|
||||||
config_write_file_prompt=这些配置选项将写入以下位置: %s
|
config_write_file_prompt=这些配置选项将写入以下位置: %s
|
||||||
@@ -3153,6 +3155,7 @@ users.allow_git_hook_tooltip=Git 钩子将会以操作系统用户运行,拥
|
|||||||
users.allow_import_local=允许导入本地仓库
|
users.allow_import_local=允许导入本地仓库
|
||||||
users.allow_create_organization=允许创建组织
|
users.allow_create_organization=允许创建组织
|
||||||
users.allow_create_devcontainer=允许创建开发容器
|
users.allow_create_devcontainer=允许创建开发容器
|
||||||
|
users.allow_create_actrunner=允许创建工作流运行器
|
||||||
users.update_profile=更新帐户
|
users.update_profile=更新帐户
|
||||||
users.delete_account=删除帐户
|
users.delete_account=删除帐户
|
||||||
users.cannot_delete_self=您不能删除自己
|
users.cannot_delete_self=您不能删除自己
|
||||||
@@ -3412,6 +3415,7 @@ config.reset_password_code_lives=恢复账户验证码过期时间
|
|||||||
config.default_keep_email_private=默认隐藏邮箱地址
|
config.default_keep_email_private=默认隐藏邮箱地址
|
||||||
config.default_allow_create_organization=默认情况下允许创建组织
|
config.default_allow_create_organization=默认情况下允许创建组织
|
||||||
config.default_allow_create_devcontainer=默认情况下允许创建 DevContainer
|
config.default_allow_create_devcontainer=默认情况下允许创建 DevContainer
|
||||||
|
config.default_allow_create_actrunner=默认情况下允许创建 ActRunner
|
||||||
config.enable_timetracking=启用时间跟踪
|
config.enable_timetracking=启用时间跟踪
|
||||||
config.default_enable_timetracking=默认情况下启用时间跟踪
|
config.default_enable_timetracking=默认情况下启用时间跟踪
|
||||||
config.default_allow_only_contributors_to_track_time=仅允许成员跟踪时间
|
config.default_allow_only_contributors_to_track_time=仅允许成员跟踪时间
|
||||||
@@ -3869,7 +3873,7 @@ status.blocked=阻塞中
|
|||||||
runners=运行器
|
runners=运行器
|
||||||
runners.runner_manage_panel=运行器管理
|
runners.runner_manage_panel=运行器管理
|
||||||
runners.new=创建新运行器
|
runners.new=创建新运行器
|
||||||
runners.new_notice=如何启动一个运行器
|
runners.new_notice=如何手动启动一个运行器
|
||||||
runners.status=状态
|
runners.status=状态
|
||||||
runners.id=ID
|
runners.id=ID
|
||||||
runners.name=名称
|
runners.name=名称
|
||||||
|
|||||||
@@ -243,8 +243,8 @@ license_desc=所有的代码都开源在 <a target="_blank" rel="noopener norefe
|
|||||||
[install]
|
[install]
|
||||||
install=安裝頁面
|
install=安裝頁面
|
||||||
title=初始組態
|
title=初始組態
|
||||||
docker_helper=如果您在 Docker 中執行 Gitea,請先閱讀<a target="_blank" rel="noopener noreferrer" href="%s">安裝指南</a>再來調整設定。
|
k8s_helper=如果您在 Kubernetes 中執行 DevStar,請先閱讀<a target="_blank" rel="noopener noreferrer" href="%s">安裝指南</a>再來調整設定。
|
||||||
require_db_desc=Gitea 需要 MySQL、PostgreSQL、SQLite3、MSSQL、TiDB (MySQL 協定) 等其中一項。
|
require_db_desc=DevStar 需要 MySQL、PostgreSQL、SQLite3、MSSQL、TiDB (MySQL 協定) 等其中一項。
|
||||||
db_title=資料庫設定
|
db_title=資料庫設定
|
||||||
db_type=資料庫類型
|
db_type=資料庫類型
|
||||||
host=主機
|
host=主機
|
||||||
@@ -349,7 +349,7 @@ password_algorithm=密碼雜湊演算法
|
|||||||
invalid_password_algorithm=無效的密碼雜湊演算法
|
invalid_password_algorithm=無效的密碼雜湊演算法
|
||||||
password_algorithm_helper=設定密碼雜湊演算法。演算法有不同的需求與強度。argon2 演算法雖然較安全但會使用大量記憶體,可能不適用於小型系統。
|
password_algorithm_helper=設定密碼雜湊演算法。演算法有不同的需求與強度。argon2 演算法雖然較安全但會使用大量記憶體,可能不適用於小型系統。
|
||||||
enable_update_checker=啟用更新檢查器
|
enable_update_checker=啟用更新檢查器
|
||||||
enable_update_checker_helper=定期連線到 gitea.io 檢查更新。
|
enable_update_checker_helper=定期連線到 devstar.cn 檢查更新。
|
||||||
env_config_keys=環境組態設定
|
env_config_keys=環境組態設定
|
||||||
env_config_keys_prompt=下列環境變數也會套用到您的組態檔:
|
env_config_keys_prompt=下列環境變數也會套用到您的組態檔:
|
||||||
config_write_file_prompt=這些配置選項將被寫入到: %s
|
config_write_file_prompt=這些配置選項將被寫入到: %s
|
||||||
|
|||||||
@@ -93,6 +93,13 @@ function install {
|
|||||||
sudo docker pull devstar.cn/devstar/webterminal:latest
|
sudo docker pull devstar.cn/devstar/webterminal:latest
|
||||||
success "Successfully pulled devstar.cn/devstar/webterminal:latest"
|
success "Successfully pulled devstar.cn/devstar/webterminal:latest"
|
||||||
fi
|
fi
|
||||||
|
if sudo docker pull mengning997/act_runner:latest; then
|
||||||
|
sudo docker tag mengning997/act_runner:latest devstar.cn/devstar/act_runner:latest
|
||||||
|
success "Successfully pulled mengning997/act_runner:latest renamed to devstar.cn/devstar/act_runner:latest"
|
||||||
|
else
|
||||||
|
sudo docker pull devstar.cn/devstar/act_runner:latest
|
||||||
|
success "Successfully pulled devstar.cn/devstar/act_runner:latest"
|
||||||
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
# Function to start
|
# Function to start
|
||||||
@@ -140,7 +147,10 @@ function stop {
|
|||||||
fi
|
fi
|
||||||
if [ $(docker ps -a --filter "name=^/webterminal-" -q | wc -l) -gt 0 ]; then
|
if [ $(docker ps -a --filter "name=^/webterminal-" -q | wc -l) -gt 0 ]; then
|
||||||
sudo docker stop $(docker ps -a --filter "name=^/webterminal-" -q) && sudo docker rm -f $(docker ps -a --filter "name=^/webterminal-" -q)
|
sudo docker stop $(docker ps -a --filter "name=^/webterminal-" -q) && sudo docker rm -f $(docker ps -a --filter "name=^/webterminal-" -q)
|
||||||
fi
|
fi
|
||||||
|
if [ $(docker ps -a --filter "name=^/runner-" -q | wc -l) -gt 0 ]; then
|
||||||
|
sudo docker stop $(docker ps -a --filter "name=^/runner-" -q) && sudo docker rm -f $(docker ps -a --filter "name=^/runner-" -q)
|
||||||
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
# Function to logs
|
# Function to logs
|
||||||
|
|||||||
1
public/assets/version.json
Normal file
1
public/assets/version.json
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{"latest":{"version":"1.25.1"}}
|
||||||
@@ -246,6 +246,7 @@ func EditUser(ctx *context.APIContext) {
|
|||||||
MaxRepoCreation: optional.FromPtr(form.MaxRepoCreation),
|
MaxRepoCreation: optional.FromPtr(form.MaxRepoCreation),
|
||||||
AllowCreateOrganization: optional.FromPtr(form.AllowCreateOrganization),
|
AllowCreateOrganization: optional.FromPtr(form.AllowCreateOrganization),
|
||||||
AllowCreateDevcontainer: optional.FromPtr(form.AllowCreateDevcontainer),
|
AllowCreateDevcontainer: optional.FromPtr(form.AllowCreateDevcontainer),
|
||||||
|
AllowCreateActRunner: optional.FromPtr(form.AllowCreateActRunner),
|
||||||
IsRestricted: optional.FromPtr(form.Restricted),
|
IsRestricted: optional.FromPtr(form.Restricted),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -156,6 +156,7 @@ func Install(ctx *context.Context) {
|
|||||||
form.DefaultKeepEmailPrivate = setting.Service.DefaultKeepEmailPrivate
|
form.DefaultKeepEmailPrivate = setting.Service.DefaultKeepEmailPrivate
|
||||||
form.DefaultAllowCreateOrganization = setting.Service.DefaultAllowCreateOrganization
|
form.DefaultAllowCreateOrganization = setting.Service.DefaultAllowCreateOrganization
|
||||||
form.DefaultAllowCreateDevcontainer = setting.Service.DefaultAllowCreateDevcontainer
|
form.DefaultAllowCreateDevcontainer = setting.Service.DefaultAllowCreateDevcontainer
|
||||||
|
form.DefaultAllowCreateActRunner = setting.Service.DefaultAllowCreateActRunner
|
||||||
form.DefaultEnableTimetracking = setting.Service.DefaultEnableTimetracking
|
form.DefaultEnableTimetracking = setting.Service.DefaultEnableTimetracking
|
||||||
form.NoReplyAddress = setting.Service.NoReplyAddress
|
form.NoReplyAddress = setting.Service.NoReplyAddress
|
||||||
form.PasswordAlgorithm = hash.ConfigHashAlgorithm(setting.PasswordHashAlgo)
|
form.PasswordAlgorithm = hash.ConfigHashAlgorithm(setting.PasswordHashAlgo)
|
||||||
@@ -492,6 +493,7 @@ func SubmitInstall(ctx *context.Context) {
|
|||||||
cfg.Section("service").Key("DEFAULT_KEEP_EMAIL_PRIVATE").SetValue(strconv.FormatBool(form.DefaultKeepEmailPrivate))
|
cfg.Section("service").Key("DEFAULT_KEEP_EMAIL_PRIVATE").SetValue(strconv.FormatBool(form.DefaultKeepEmailPrivate))
|
||||||
cfg.Section("service").Key("DEFAULT_ALLOW_CREATE_ORGANIZATION").SetValue(strconv.FormatBool(form.DefaultAllowCreateOrganization))
|
cfg.Section("service").Key("DEFAULT_ALLOW_CREATE_ORGANIZATION").SetValue(strconv.FormatBool(form.DefaultAllowCreateOrganization))
|
||||||
cfg.Section("service").Key("DEFAULT_ALLOW_CREATE_DEVCONTAINER").SetValue(strconv.FormatBool(form.DefaultAllowCreateDevcontainer))
|
cfg.Section("service").Key("DEFAULT_ALLOW_CREATE_DEVCONTAINER").SetValue(strconv.FormatBool(form.DefaultAllowCreateDevcontainer))
|
||||||
|
cfg.Section("service").Key("DEFAULT_ALLOW_CREATE_ACTRUNNER").SetValue(strconv.FormatBool(form.DefaultAllowCreateActRunner))
|
||||||
cfg.Section("service").Key("DEFAULT_ENABLE_TIMETRACKING").SetValue(strconv.FormatBool(form.DefaultEnableTimetracking))
|
cfg.Section("service").Key("DEFAULT_ENABLE_TIMETRACKING").SetValue(strconv.FormatBool(form.DefaultEnableTimetracking))
|
||||||
cfg.Section("service").Key("NO_REPLY_ADDRESS").SetValue(form.NoReplyAddress)
|
cfg.Section("service").Key("NO_REPLY_ADDRESS").SetValue(form.NoReplyAddress)
|
||||||
cfg.Section("cron.update_checker").Key("ENABLED").SetValue(strconv.FormatBool(form.EnableUpdateChecker))
|
cfg.Section("cron.update_checker").Key("ENABLED").SetValue(strconv.FormatBool(form.EnableUpdateChecker))
|
||||||
@@ -630,17 +632,24 @@ func SubmitInstall(ctx *context.Context) {
|
|||||||
|
|
||||||
if form.K8sEnable {
|
if form.K8sEnable {
|
||||||
//K8s环境检测
|
//K8s环境检测
|
||||||
|
cfg.Section("devstar.devcontainer").Key("HOST").SetValue(form.Domain)
|
||||||
} else {
|
} else {
|
||||||
if !checkDocker(ctx, &form) {
|
if !checkDocker(ctx, &form) {
|
||||||
ctx.RenderWithErr("There is no docker environment", tplInstall, &form)
|
ctx.RenderWithErr("There is no docker environment", tplInstall, &form)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// 注册Global Runners
|
||||||
|
if setting.Runner.AutoStart {
|
||||||
|
for i := 0; i < setting.Runner.Count; i++ {
|
||||||
|
runners_service.RegistGlobalRunner(ctx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
setting.ClearEnvConfigKeys()
|
setting.ClearEnvConfigKeys()
|
||||||
log.Info("First-time run install finished!")
|
log.Info("First-time run install finished!")
|
||||||
InstallDone(ctx)
|
InstallDone(ctx)
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
// Sleep for a while to make sure the user's browser has loaded the post-install page and its assets (images, css, js)
|
// Sleep for a while to make sure the user's browser has loaded the post-install page and its assets (images, css, js)
|
||||||
// What if this duration is not long enough? That's impossible -- if the user can't load the simple page in time, how could they install or use Gitea in the future ....
|
// What if this duration is not long enough? That's impossible -- if the user can't load the simple page in time, how could they install or use Gitea in the future ....
|
||||||
@@ -654,8 +663,6 @@ func SubmitInstall(ctx *context.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
runners_service.RegistGlobalRunner(otherCtx)
|
|
||||||
|
|
||||||
// Now get the http.Server from this request and shut it down
|
// Now get the http.Server from this request and shut it down
|
||||||
// NB: This is not our hammerable graceful shutdown this is http.Server.Shutdown
|
// NB: This is not our hammerable graceful shutdown this is http.Server.Shutdown
|
||||||
srv := ctx.Value(http.ServerContextKey).(*http.Server)
|
srv := ctx.Value(http.ServerContextKey).(*http.Server)
|
||||||
|
|||||||
@@ -437,6 +437,7 @@ func EditUserPost(ctx *context.Context) {
|
|||||||
MaxRepoCreation: optional.Some(form.MaxRepoCreation),
|
MaxRepoCreation: optional.Some(form.MaxRepoCreation),
|
||||||
AllowCreateOrganization: optional.Some(form.AllowCreateOrganization),
|
AllowCreateOrganization: optional.Some(form.AllowCreateOrganization),
|
||||||
AllowCreateDevcontainer: optional.Some(form.AllowCreateDevcontainer),
|
AllowCreateDevcontainer: optional.Some(form.AllowCreateDevcontainer),
|
||||||
|
AllowCreateActRunner: optional.Some(form.AllowCreateActRunner),
|
||||||
IsRestricted: optional.Some(form.Restricted),
|
IsRestricted: optional.Some(form.Restricted),
|
||||||
Visibility: optional.Some(form.Visibility),
|
Visibility: optional.Some(form.Visibility),
|
||||||
Language: optional.Some(form.Language),
|
Language: optional.Some(form.Language),
|
||||||
@@ -450,7 +451,6 @@ func EditUserPost(ctx *context.Context) {
|
|||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
log.Trace("Account profile updated by admin (%s): %s", ctx.Doer.Name, u.Name)
|
|
||||||
|
|
||||||
if form.Reset2FA {
|
if form.Reset2FA {
|
||||||
tf, err := auth.GetTwoFactorByUID(ctx, u.ID)
|
tf, err := auth.GetTwoFactorByUID(ctx, u.ID)
|
||||||
|
|||||||
@@ -160,6 +160,7 @@ func Runners(ctx *context.Context) {
|
|||||||
ctx.Data["RunnerOwnerID"] = opts.OwnerID
|
ctx.Data["RunnerOwnerID"] = opts.OwnerID
|
||||||
ctx.Data["RunnerRepoID"] = opts.RepoID
|
ctx.Data["RunnerRepoID"] = opts.RepoID
|
||||||
ctx.Data["SortType"] = opts.Sort
|
ctx.Data["SortType"] = opts.Sort
|
||||||
|
ctx.Data["AllowCreateActRunner"] = ctx.Doer.AllowCreateActRunner
|
||||||
|
|
||||||
pager := context.NewPagination(int(count), opts.PageSize, opts.Page, 5)
|
pager := context.NewPagination(int(count), opts.PageSize, opts.Page, 5)
|
||||||
|
|
||||||
@@ -300,6 +301,14 @@ func RegisterARunner(ctx *context.Context) {
|
|||||||
ctx.ServerError("getRunnersCtx", err)
|
ctx.ServerError("getRunnersCtx", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 检查用户是否有权创建 runner
|
||||||
|
if !ctx.Doer.AllowCreateActRunner {
|
||||||
|
ctx.Flash.Error(ctx.Tr("actions.runners.create_runner_permission_denied"))
|
||||||
|
ctx.Redirect(rCtx.RedirectLink)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
token, err := actions_model.NewRunnerToken(ctx, rCtx.OwnerID, rCtx.RepoID)
|
token, err := actions_model.NewRunnerToken(ctx, rCtx.OwnerID, rCtx.RepoID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.ServerError("NewRunnerToken", err)
|
ctx.ServerError("NewRunnerToken", err)
|
||||||
|
|||||||
@@ -399,6 +399,8 @@ func repoAssignment(ctx *Context, repo *repo_model.Repository) {
|
|||||||
ctx.Data["Permission"] = &ctx.Repo.Permission
|
ctx.Data["Permission"] = &ctx.Repo.Permission
|
||||||
if ctx.Doer != nil {
|
if ctx.Doer != nil {
|
||||||
ctx.Data["AllowCreateDevcontainer"] = ctx.Doer.AllowCreateDevcontainer
|
ctx.Data["AllowCreateDevcontainer"] = ctx.Doer.AllowCreateDevcontainer
|
||||||
|
ctx.Data["AllowCreateActRunner"] = ctx.Doer.AllowCreateActRunner
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
query := ctx.Req.URL.Query()
|
query := ctx.Req.URL.Query()
|
||||||
userID := query.Get("user")
|
userID := query.Get("user")
|
||||||
@@ -416,6 +418,7 @@ func repoAssignment(ctx *Context, repo *repo_model.Repository) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
ctx.Data["AllowCreateDevcontainer"] = u.AllowCreateDevcontainer
|
ctx.Data["AllowCreateDevcontainer"] = u.AllowCreateDevcontainer
|
||||||
|
ctx.Data["AllowCreateActRunner"] = u.AllowCreateActRunner
|
||||||
}
|
}
|
||||||
|
|
||||||
if repo.IsMirror {
|
if repo.IsMirror {
|
||||||
|
|||||||
@@ -150,7 +150,7 @@ func registerUpdateGiteaChecker() {
|
|||||||
RunAtStart: false,
|
RunAtStart: false,
|
||||||
Schedule: "@every 168h",
|
Schedule: "@every 168h",
|
||||||
},
|
},
|
||||||
HTTPEndpoint: "https://dl.gitea.com/gitea/version.json",
|
HTTPEndpoint: "https://devstar.cn/assets/version.json",
|
||||||
}, func(ctx context.Context, _ *user_model.User, config Config) error {
|
}, func(ctx context.Context, _ *user_model.User, config Config) error {
|
||||||
updateCheckerConfig := config.(*UpdateCheckerConfig)
|
updateCheckerConfig := config.(*UpdateCheckerConfig)
|
||||||
return updatechecker.GiteaUpdateChecker(updateCheckerConfig.HTTPEndpoint)
|
return updatechecker.GiteaUpdateChecker(updateCheckerConfig.HTTPEndpoint)
|
||||||
|
|||||||
@@ -161,7 +161,29 @@ func GetWebTerminalURL(ctx context.Context, userID, repoID int64) (string, error
|
|||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
if cfg.Section("k8s").Key("ENABLE").Value() == "true" {
|
if cfg.Section("k8s").Key("ENABLE").Value() == "true" {
|
||||||
//k8s的逻辑
|
// K8s 模式:使用 Istio Gateway + VirtualService
|
||||||
|
log.Info("GetWebTerminalURL: 使用 Istio 模式获取 WebTerminal URL for DevContainer: %s", devcontainerName)
|
||||||
|
|
||||||
|
// 从配置中读取域名
|
||||||
|
domain := cfg.Section("server").Key("DOMAIN").Value()
|
||||||
|
|
||||||
|
// 从容器名称中提取用户名和仓库名
|
||||||
|
parts := strings.Split(devcontainerName, "-")
|
||||||
|
var username, repoName string
|
||||||
|
if len(parts) >= 2 {
|
||||||
|
username = parts[0]
|
||||||
|
repoName = parts[1]
|
||||||
|
} else {
|
||||||
|
username = "unknown"
|
||||||
|
repoName = "unknown"
|
||||||
|
}
|
||||||
|
|
||||||
|
// 构建基于 Istio Gateway 的 URL
|
||||||
|
path := fmt.Sprintf("/%s/%s/dev-container-webterminal", username, repoName)
|
||||||
|
webTerminalURL := fmt.Sprintf("http://%s%s", domain, path)
|
||||||
|
|
||||||
|
log.Info("GetWebTerminalURL: 生成 Istio WebTerminal URL: %s", webTerminalURL)
|
||||||
|
return webTerminalURL, nil
|
||||||
}
|
}
|
||||||
return "", nil
|
return "", nil
|
||||||
}
|
}
|
||||||
@@ -181,6 +203,7 @@ func GetWebTerminalURL(ctx context.Context, userID, repoID int64) (string, error
|
|||||||
10已删除
|
10已删除
|
||||||
*/
|
*/
|
||||||
func GetDevContainerStatus(ctx context.Context, userID, repoID string) (string, error) {
|
func GetDevContainerStatus(ctx context.Context, userID, repoID string) (string, error) {
|
||||||
|
log.Info("GetDevContainerStatus: Starting - userID: %s, repoID: %s", userID, repoID)
|
||||||
var id int
|
var id int
|
||||||
var containerName string
|
var containerName string
|
||||||
|
|
||||||
@@ -188,6 +211,7 @@ func GetDevContainerStatus(ctx context.Context, userID, repoID string) (string,
|
|||||||
var realTimeStatus uint16
|
var realTimeStatus uint16
|
||||||
cfg, err := setting.NewConfigProviderFromFile(setting.CustomConf)
|
cfg, err := setting.NewConfigProviderFromFile(setting.CustomConf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Error("GetDevContainerStatus: Failed to load config: %v", err)
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
dbEngine := db.GetEngine(ctx)
|
dbEngine := db.GetEngine(ctx)
|
||||||
@@ -197,19 +221,42 @@ func GetDevContainerStatus(ctx context.Context, userID, repoID string) (string,
|
|||||||
Where("user_id = ? AND repo_id = ?", userID, repoID).
|
Where("user_id = ? AND repo_id = ?", userID, repoID).
|
||||||
Get(&status, &id, &containerName)
|
Get(&status, &id, &containerName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Error("GetDevContainerStatus: Failed to query database: %v", err)
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log.Info("GetDevContainerStatus: Database query result - id: %d, containerName: %s, status: %d", id, containerName, status)
|
||||||
|
|
||||||
if id == 0 {
|
if id == 0 {
|
||||||
|
log.Info("GetDevContainerStatus: No devcontainer found, returning -1")
|
||||||
return fmt.Sprintf("%d", -1), nil
|
return fmt.Sprintf("%d", -1), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
realTimeStatus = status
|
realTimeStatus = status
|
||||||
|
log.Info("GetDevContainerStatus: Initial realTimeStatus: %d", realTimeStatus)
|
||||||
switch status {
|
switch status {
|
||||||
//正在重启
|
//正在重启
|
||||||
case 6:
|
case 6:
|
||||||
if cfg.Section("k8s").Key("ENABLE").Value() == "true" {
|
if cfg.Section("k8s").Key("ENABLE").Value() == "true" {
|
||||||
//k8s的逻辑
|
// k8s 逻辑:检查 Pod 是否已恢复运行
|
||||||
|
log.Info("GetDevContainerStatus: K8s branch for case 6 (restarting), container: %s", containerName)
|
||||||
|
opts := &OpenDevcontainerAppDispatcherOptions{
|
||||||
|
Name: containerName,
|
||||||
|
Wait: false,
|
||||||
|
}
|
||||||
|
log.Info("GetDevContainerStatus: Calling AssignDevcontainerGetting2K8sOperator with opts: %+v", opts)
|
||||||
|
devcontainerApp, err := AssignDevcontainerGetting2K8sOperator(&ctx, opts)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("GetDevContainerStatus: AssignDevcontainerGetting2K8sOperator failed: %v", err)
|
||||||
|
} else if devcontainerApp != nil {
|
||||||
|
log.Info("GetDevContainerStatus: DevcontainerApp retrieved - Name: %s, Ready: %v", devcontainerApp.Name, devcontainerApp.Status.Ready)
|
||||||
|
if devcontainerApp.Status.Ready {
|
||||||
|
realTimeStatus = 4 // 已恢复运行
|
||||||
|
log.Info("GetDevContainerStatus: Container %s is ready, updating status to 4", containerName)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
log.Warn("GetDevContainerStatus: DevcontainerApp is nil for container: %s", containerName)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
containerRealTimeStatus, err := GetDevContainerStatusFromDocker(ctx, containerName)
|
containerRealTimeStatus, err := GetDevContainerStatusFromDocker(ctx, containerName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -222,7 +269,24 @@ func GetDevContainerStatus(ctx context.Context, userID, repoID string) (string,
|
|||||||
//正在关闭
|
//正在关闭
|
||||||
case 7:
|
case 7:
|
||||||
if cfg.Section("k8s").Key("ENABLE").Value() == "true" {
|
if cfg.Section("k8s").Key("ENABLE").Value() == "true" {
|
||||||
//k8s的逻辑
|
// k8s 逻辑:检查 Pod 是否已停止
|
||||||
|
log.Info("GetDevContainerStatus: K8s branch for case 7 (stopping), container: %s", containerName)
|
||||||
|
opts := &OpenDevcontainerAppDispatcherOptions{
|
||||||
|
Name: containerName,
|
||||||
|
Wait: false,
|
||||||
|
}
|
||||||
|
log.Info("GetDevContainerStatus: Calling AssignDevcontainerGetting2K8sOperator for stop check with opts: %+v", opts)
|
||||||
|
devcontainerApp, err := AssignDevcontainerGetting2K8sOperator(&ctx, opts)
|
||||||
|
if err != nil {
|
||||||
|
log.Info("GetDevContainerStatus: DevcontainerApp not found or error, considering stopped: %v", err)
|
||||||
|
realTimeStatus = 8 // 已停止
|
||||||
|
} else if devcontainerApp == nil || !devcontainerApp.Status.Ready {
|
||||||
|
log.Info("GetDevContainerStatus: DevcontainerApp is nil or not ready, considering stopped")
|
||||||
|
realTimeStatus = 8 // 已停止
|
||||||
|
} else {
|
||||||
|
log.Info("GetDevContainerStatus: DevcontainerApp still running - Name: %s, Ready: %v", devcontainerApp.Name, devcontainerApp.Status.Ready)
|
||||||
|
}
|
||||||
|
// 已在外部通过 StopDevContainer 触发,此处仅检查状态
|
||||||
} else {
|
} else {
|
||||||
containerRealTimeStatus, err := GetDevContainerStatusFromDocker(ctx, containerName)
|
containerRealTimeStatus, err := GetDevContainerStatusFromDocker(ctx, containerName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -240,7 +304,21 @@ func GetDevContainerStatus(ctx context.Context, userID, repoID string) (string,
|
|||||||
break
|
break
|
||||||
case 9:
|
case 9:
|
||||||
if cfg.Section("k8s").Key("ENABLE").Value() == "true" {
|
if cfg.Section("k8s").Key("ENABLE").Value() == "true" {
|
||||||
//k8s的逻辑
|
// k8s 逻辑:检查 Pod 是否已删除
|
||||||
|
log.Info("GetDevContainerStatus: K8s branch for case 9 (deleting), container: %s", containerName)
|
||||||
|
opts := &OpenDevcontainerAppDispatcherOptions{
|
||||||
|
Name: containerName,
|
||||||
|
Wait: false,
|
||||||
|
}
|
||||||
|
log.Info("GetDevContainerStatus: Calling AssignDevcontainerGetting2K8sOperator for delete check with opts: %+v", opts)
|
||||||
|
_, err := AssignDevcontainerGetting2K8sOperator(&ctx, opts)
|
||||||
|
if err != nil {
|
||||||
|
log.Info("GetDevContainerStatus: DevcontainerApp not found, considering deleted: %v", err)
|
||||||
|
realTimeStatus = 10 // 已删除
|
||||||
|
} else {
|
||||||
|
log.Info("GetDevContainerStatus: DevcontainerApp still exists, not deleted yet")
|
||||||
|
}
|
||||||
|
// 已在外部通过 DeleteDevContainer 触发,此处仅检查状态
|
||||||
} else {
|
} else {
|
||||||
isContainerNotFound, err := IsContainerNotFound(ctx, containerName)
|
isContainerNotFound, err := IsContainerNotFound(ctx, containerName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -259,6 +337,22 @@ func GetDevContainerStatus(ctx context.Context, userID, repoID string) (string,
|
|||||||
default:
|
default:
|
||||||
log.Info("other status")
|
log.Info("other status")
|
||||||
}
|
}
|
||||||
|
// K8s: 仅在 Ready 后才返回 4;否则维持/降为 3
|
||||||
|
if cfg.Section("k8s").Key("ENABLE").Value() == "true" && (status == 3 || status == 4) {
|
||||||
|
opts := &OpenDevcontainerAppDispatcherOptions{
|
||||||
|
Name: containerName,
|
||||||
|
Wait: false,
|
||||||
|
}
|
||||||
|
app, err := AssignDevcontainerGetting2K8sOperator(&ctx, opts)
|
||||||
|
if err != nil || app == nil {
|
||||||
|
// 获取不到 CR 或出错时,保守认为未就绪
|
||||||
|
realTimeStatus = 3
|
||||||
|
} else if app.Status.Ready {
|
||||||
|
realTimeStatus = 4
|
||||||
|
} else {
|
||||||
|
realTimeStatus = 3
|
||||||
|
}
|
||||||
|
}
|
||||||
//状态更新
|
//状态更新
|
||||||
if realTimeStatus != status {
|
if realTimeStatus != status {
|
||||||
if realTimeStatus == 10 {
|
if realTimeStatus == 10 {
|
||||||
@@ -289,6 +383,7 @@ func GetDevContainerStatus(ctx context.Context, userID, repoID string) (string,
|
|||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
log.Info("GetDevContainerStatus: Final realTimeStatus: %d, returning status string", realTimeStatus)
|
||||||
return fmt.Sprintf("%d", realTimeStatus), nil
|
return fmt.Sprintf("%d", realTimeStatus), nil
|
||||||
}
|
}
|
||||||
func CreateDevContainer(ctx context.Context, repo *repo.Repository, doer *user.User, publicKeyList []string, isWebTerminal bool) error {
|
func CreateDevContainer(ctx context.Context, repo *repo.Repository, doer *user.User, publicKeyList []string, isWebTerminal bool) error {
|
||||||
@@ -330,7 +425,28 @@ func CreateDevContainer(ctx context.Context, repo *repo.Repository, doer *user.U
|
|||||||
go func() {
|
go func() {
|
||||||
otherCtx := context.Background()
|
otherCtx := context.Background()
|
||||||
if cfg.Section("k8s").Key("ENABLE").Value() == "true" {
|
if cfg.Section("k8s").Key("ENABLE").Value() == "true" {
|
||||||
//k8s的逻辑
|
// K8s 模式:直接调用 K8s Operator 创建 DevContainer
|
||||||
|
configurationString, err := GetDevcontainerConfigurationString(otherCtx, repo)
|
||||||
|
if err != nil {
|
||||||
|
log.Info("CreateDevContainer: 读取 devcontainer 配置失败: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
configurationModel, err := UnmarshalDevcontainerConfigContent(configurationString)
|
||||||
|
if err != nil {
|
||||||
|
log.Info("CreateDevContainer: 解析 devcontainer 配置失败: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
newDTO := &CreateDevcontainerDTO{
|
||||||
|
Devcontainer: newDevcontainer,
|
||||||
|
SSHPublicKeyList: publicKeyList,
|
||||||
|
GitRepositoryURL: strings.TrimSuffix(setting.AppURL, "/") + repo.Link(),
|
||||||
|
Image: configurationModel.Image,
|
||||||
|
}
|
||||||
|
if err := AssignDevcontainerCreation2K8sOperator(&otherCtx, newDTO); err != nil {
|
||||||
|
log.Error("CreateDevContainer: K8s 创建失败: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
imageName, err := CreateDevContainerByDockerCommand(otherCtx, &newDevcontainer, repo, publicKeyList)
|
imageName, err := CreateDevContainerByDockerCommand(otherCtx, &newDevcontainer, repo, publicKeyList)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -367,7 +483,9 @@ func DeleteDevContainer(ctx context.Context, userID, repoID int64) error {
|
|||||||
go func() {
|
go func() {
|
||||||
otherCtx := context.Background()
|
otherCtx := context.Background()
|
||||||
if cfg.Section("k8s").Key("ENABLE").Value() == "true" {
|
if cfg.Section("k8s").Key("ENABLE").Value() == "true" {
|
||||||
//k8s的逻辑
|
// k8s 模式:调用 K8s Operator 删除 DevContainer 资源
|
||||||
|
devList := []devcontainer_models.Devcontainer{devContainerInfo}
|
||||||
|
_ = AssignDevcontainerDeletion2K8sOperator(&otherCtx, &devList)
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
err = DeleteDevContainerByDocker(otherCtx, devContainerInfo.Name)
|
err = DeleteDevContainerByDocker(otherCtx, devContainerInfo.Name)
|
||||||
@@ -402,7 +520,15 @@ func RestartDevContainer(ctx context.Context, userID, repoID int64) error {
|
|||||||
go func() {
|
go func() {
|
||||||
otherCtx := context.Background()
|
otherCtx := context.Background()
|
||||||
if cfg.Section("k8s").Key("ENABLE").Value() == "true" {
|
if cfg.Section("k8s").Key("ENABLE").Value() == "true" {
|
||||||
//k8s的逻辑
|
// k8s 模式:调用 K8s Operator 重启 DevContainer
|
||||||
|
vo := &DevcontainerVO{
|
||||||
|
DevContainerName: devContainerInfo.Name,
|
||||||
|
UserId: userID,
|
||||||
|
RepoId: repoID,
|
||||||
|
}
|
||||||
|
if err := AssignDevcontainerRestart2K8sOperator(&otherCtx, vo); err != nil {
|
||||||
|
log.Error("RestartDevContainer: K8s 重启失败: %v", err)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
err = RestartDevContainerByDocker(otherCtx, devContainerInfo.Name)
|
err = RestartDevContainerByDocker(otherCtx, devContainerInfo.Name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -436,7 +562,15 @@ func StopDevContainer(ctx context.Context, userID, repoID int64) error {
|
|||||||
go func() {
|
go func() {
|
||||||
otherCtx := context.Background()
|
otherCtx := context.Background()
|
||||||
if cfg.Section("k8s").Key("ENABLE").Value() == "true" {
|
if cfg.Section("k8s").Key("ENABLE").Value() == "true" {
|
||||||
//k8s的逻辑
|
// k8s 模式:调用 K8s Operator 停止 DevContainer
|
||||||
|
vo := &DevcontainerVO{
|
||||||
|
DevContainerName: devContainerInfo.Name,
|
||||||
|
UserId: userID,
|
||||||
|
RepoId: repoID,
|
||||||
|
}
|
||||||
|
if err := AssignDevcontainerStop2K8sOperator(&otherCtx, vo); err != nil {
|
||||||
|
log.Error("StopDevContainer: K8s 停止失败: %v", err)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
err = StopDevContainerByDocker(otherCtx, devContainerInfo.Name)
|
err = StopDevContainerByDocker(otherCtx, devContainerInfo.Name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -891,7 +1025,20 @@ func Get_IDE_TerminalURL(ctx *gitea_context.Context, doer *user.User, repo *gite
|
|||||||
var port string
|
var port string
|
||||||
|
|
||||||
if cfg.Section("k8s").Key("ENABLE").Value() == "true" {
|
if cfg.Section("k8s").Key("ENABLE").Value() == "true" {
|
||||||
|
// K8s 环境:通过 DevcontainerApp 的 NodePort 作为 SSH 端口
|
||||||
|
apiRequestCtx := ctx.Req.Context()
|
||||||
|
opts := &OpenDevcontainerAppDispatcherOptions{
|
||||||
|
Name: devContainerInfo.Name,
|
||||||
|
Wait: false,
|
||||||
|
}
|
||||||
|
devcontainerApp, err := AssignDevcontainerGetting2K8sOperator(&apiRequestCtx, opts)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
if devcontainerApp == nil || devcontainerApp.Status.NodePortAssigned == 0 {
|
||||||
|
return "", fmt.Errorf("k8s DevcontainerApp 未就绪或未分配 NodePort: %s", devContainerInfo.Name)
|
||||||
|
}
|
||||||
|
port = fmt.Sprintf("%d", devcontainerApp.Status.NodePortAssigned)
|
||||||
} else {
|
} else {
|
||||||
mappedPort, err := docker_module.GetMappedPort(ctx, devContainerInfo.Name, "22")
|
mappedPort, err := docker_module.GetMappedPort(ctx, devContainerInfo.Name, "22")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
891
services/devcontainer/k8s_agent.go
Normal file
891
services/devcontainer/k8s_agent.go
Normal file
@@ -0,0 +1,891 @@
|
|||||||
|
package devcontainer
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"code.gitea.io/gitea/models/db"
|
||||||
|
devcontainer_model "code.gitea.io/gitea/models/devcontainer"
|
||||||
|
devcontainer_dto "code.gitea.io/gitea/modules/k8s"
|
||||||
|
devcontainer_k8s_agent_module "code.gitea.io/gitea/modules/k8s"
|
||||||
|
k8s_api_v1 "code.gitea.io/gitea/modules/k8s/api/devcontainer/v1"
|
||||||
|
"code.gitea.io/gitea/modules/k8s/errors"
|
||||||
|
|
||||||
|
"code.gitea.io/gitea/modules/log"
|
||||||
|
"code.gitea.io/gitea/modules/setting"
|
||||||
|
|
||||||
|
v1 "k8s.io/api/core/v1"
|
||||||
|
k8serrors "k8s.io/apimachinery/pkg/api/errors"
|
||||||
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||||
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||||
|
"k8s.io/apimachinery/pkg/types"
|
||||||
|
"k8s.io/client-go/kubernetes"
|
||||||
|
"k8s.io/client-go/rest"
|
||||||
|
"k8s.io/client-go/tools/clientcmd"
|
||||||
|
"k8s.io/client-go/tools/remotecommand"
|
||||||
|
"k8s.io/kubectl/pkg/scheme"
|
||||||
|
// Istio 资源改为 dynamic/unstructured,不再直接使用 typed API
|
||||||
|
)
|
||||||
|
|
||||||
|
// 为 K8s Agent 暴露所需的 DTO 类型,便于 K8s 分支创建/查询入口使用
|
||||||
|
type CreateDevcontainerDTO struct {
|
||||||
|
devcontainer_model.Devcontainer
|
||||||
|
SSHPublicKeyList []string
|
||||||
|
GitRepositoryURL string
|
||||||
|
Image string
|
||||||
|
DockerfileContent string
|
||||||
|
DevcontainerPort uint16
|
||||||
|
}
|
||||||
|
|
||||||
|
type OpenDevcontainerAppDispatcherOptions struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
Wait bool `json:"wait"`
|
||||||
|
Status uint16
|
||||||
|
Port uint16
|
||||||
|
UserPublicKey string
|
||||||
|
RepoID int64
|
||||||
|
UserID int64
|
||||||
|
}
|
||||||
|
|
||||||
|
var k8sGroupVersionResource = schema.GroupVersionResource{
|
||||||
|
Group: "devcontainer.devstar.cn",
|
||||||
|
Version: "v1",
|
||||||
|
Resource: "devcontainerapps",
|
||||||
|
}
|
||||||
|
|
||||||
|
type ErrIllegalK8sAgentParams struct {
|
||||||
|
FieldNameList []string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (err ErrIllegalK8sAgentParams) Error() string {
|
||||||
|
return fmt.Sprintf("Illegal Params: %v", err.FieldNameList)
|
||||||
|
}
|
||||||
|
|
||||||
|
// AssignDevcontainerGetting2K8sOperator 获取 k8s CRD 资源 DevcontainerApp 最新状态(需要根据用户传入的 wait 参数决定是否要阻塞等待 DevContainer 就绪)
|
||||||
|
func AssignDevcontainerGetting2K8sOperator(ctx *context.Context, opts *OpenDevcontainerAppDispatcherOptions) (*k8s_api_v1.DevcontainerApp, error) {
|
||||||
|
log.Info("AssignDevcontainerGetting2K8sOperator: Starting lookup for container: %s, wait=%v",
|
||||||
|
opts.Name, opts.Wait)
|
||||||
|
|
||||||
|
// 0. 检查参数
|
||||||
|
if ctx == nil || opts == nil || len(opts.Name) == 0 {
|
||||||
|
return nil, ErrIllegalK8sAgentParams{
|
||||||
|
FieldNameList: []string{"ctx", "opts", "opts.Name"},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 1. 获取 Dynamic Client
|
||||||
|
ctxVal := *ctx
|
||||||
|
client, err := devcontainer_k8s_agent_module.GetKubernetesClient(ctxVal, nil, "")
|
||||||
|
if err != nil {
|
||||||
|
// 层层返回错误,结束数据库事务
|
||||||
|
return nil, errors.ErrOperateDevcontainer{
|
||||||
|
Action: "Connect to k8s API Server",
|
||||||
|
Message: err.Error(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
log.Info("AssignDevcontainerGetting2K8sOperator: K8s client created successfully")
|
||||||
|
|
||||||
|
// 2. 调用 modules 层 k8s Agent 获取 k8s CRD 资源 DevcontainerApp
|
||||||
|
optsGetDevcontainer := &devcontainer_dto.GetDevcontainerOptions{
|
||||||
|
GetOptions: metav1.GetOptions{},
|
||||||
|
Name: opts.Name,
|
||||||
|
Namespace: setting.DevContainerConfig.Namespace,
|
||||||
|
Wait: opts.Wait,
|
||||||
|
}
|
||||||
|
log.Info("AssignDevcontainerGetting2K8sOperator: Retrieving DevcontainerApp %s in namespace %s (wait=%v)",
|
||||||
|
opts.Name, setting.DevContainerConfig.Namespace, opts.Wait)
|
||||||
|
devcontainerApp, err := devcontainer_k8s_agent_module.GetDevcontainer(ctxVal, client, optsGetDevcontainer)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("AssignDevcontainerGetting2K8sOperator: Failed to get DevcontainerApp: %v", err)
|
||||||
|
return nil, errors.ErrOperateDevcontainer{
|
||||||
|
Action: fmt.Sprintf("Open Devcontainer '%s' (wait=%v)", opts.Name, opts.Wait),
|
||||||
|
Message: err.Error(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
log.Info("AssignDevcontainerGetting2K8sOperator: DevcontainerApp retrieved successfully - Name: %s, NodePort: %d, Ready: %v",
|
||||||
|
devcontainerApp.Name, devcontainerApp.Status.NodePortAssigned, devcontainerApp.Status.Ready)
|
||||||
|
|
||||||
|
// 添加额外端口的日志
|
||||||
|
if len(devcontainerApp.Status.ExtraPortsAssigned) > 0 {
|
||||||
|
for i, port := range devcontainerApp.Status.ExtraPortsAssigned {
|
||||||
|
log.Info("AssignDevcontainerGetting2K8sOperator: Extra port %d - Name: %s, NodePort: %d, ContainerPort: %d",
|
||||||
|
i, port.Name, port.NodePort, port.ContainerPort)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
log.Info("AssignDevcontainerGetting2K8sOperator: No extra ports found for DevcontainerApp %s", devcontainerApp.Name)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. 成功获取最新的 DevcontainerApp,返回
|
||||||
|
return devcontainerApp, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// 补充笔记: modules/ 与 services/ 两个目录中的 k8s Agent 区别是什么?
|
||||||
|
// - modules/ 与 k8s API Server 交互密切相关
|
||||||
|
// - services/ 进行了封装,简化用户界面使用
|
||||||
|
|
||||||
|
func AssignDevcontainerDeletion2K8sOperator(ctx *context.Context, devcontainersList *[]devcontainer_model.Devcontainer) error {
|
||||||
|
log.Info("AssignDevcontainerDeletion2K8sOperator: Starting Deletion for containers")
|
||||||
|
// 1. 获取 Dynamic Client
|
||||||
|
ctxVal := *ctx
|
||||||
|
client, err := devcontainer_k8s_agent_module.GetKubernetesClient(ctxVal, nil, "")
|
||||||
|
if err != nil {
|
||||||
|
// 层层返回错误,结束数据库事务
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取标准 Kubernetes 客户端,用于删除 Ingress
|
||||||
|
stdClient, err := getStandardKubernetesClient()
|
||||||
|
if err != nil {
|
||||||
|
log.Warn("AssignDevcontainerDeletion2K8sOperator: 获取标准 K8s 客户端失败: %v", err)
|
||||||
|
// 继续执行,不阻止主流程
|
||||||
|
} else {
|
||||||
|
// 先删除与 DevContainer 相关的 Ingress 资源
|
||||||
|
for _, devcontainer := range *devcontainersList {
|
||||||
|
ingressName := fmt.Sprintf("%s-ttyd-ingress", devcontainer.Name)
|
||||||
|
log.Info("AssignDevcontainerDeletion2K8sOperator: 删除 Ingress %s", ingressName)
|
||||||
|
|
||||||
|
err := stdClient.NetworkingV1().Ingresses(setting.DevContainerConfig.Namespace).Delete(*ctx, ingressName, metav1.DeleteOptions{})
|
||||||
|
if err != nil {
|
||||||
|
if k8serrors.IsNotFound(err) {
|
||||||
|
// Ingress 已经不存在,视为正常情况
|
||||||
|
log.Info("AssignDevcontainerDeletion2K8sOperator: Ingress %s 不存在,跳过删除", ingressName)
|
||||||
|
} else {
|
||||||
|
log.Warn("AssignDevcontainerDeletion2K8sOperator: 删除 Ingress %s 失败: %v", ingressName, err)
|
||||||
|
// 继续执行,不阻止主流程
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
log.Info("AssignDevcontainerDeletion2K8sOperator: 成功删除 Ingress %s", ingressName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 调用 modules 层 k8s Agent,执行删除资源
|
||||||
|
opts := &devcontainer_dto.DeleteDevcontainerOptions{
|
||||||
|
DeleteOptions: metav1.DeleteOptions{},
|
||||||
|
Namespace: setting.DevContainerConfig.Namespace,
|
||||||
|
}
|
||||||
|
if devcontainersList == nil || len(*devcontainersList) == 0 {
|
||||||
|
return fmt.Errorf("delete devcontainer in namespace '%s': %s", opts.Namespace, "the DevContainer list is empty")
|
||||||
|
}
|
||||||
|
// 3. 遍历列表删除 DevContainer,如果删除出错,交由 module 层打印日志,交由管理员手动处理
|
||||||
|
for _, devcontainer := range *devcontainersList {
|
||||||
|
opts.Name = devcontainer.Name
|
||||||
|
_ = devcontainer_k8s_agent_module.DeleteDevcontainer(ctxVal, client, opts)
|
||||||
|
|
||||||
|
// 删除对应的 VirtualService
|
||||||
|
if err := deleteDevContainerWebTerminalVirtualService(ctx, devcontainer.Name); err != nil {
|
||||||
|
log.Warn("AssignDevcontainerDeletion2K8sOperator: 删除 VirtualService 失败 for DevContainer %s: %v", devcontainer.Name, err)
|
||||||
|
// 不阻止主流程,只记录警告
|
||||||
|
} else {
|
||||||
|
log.Info("AssignDevcontainerDeletion2K8sOperator: 成功删除 VirtualService for DevContainer: %s", devcontainer.Name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// 补充笔记: modules/ 与 services/ 两个目录中的 k8s Agent 区别是什么?
|
||||||
|
// - modules/ 与 k8s API Server 交互密切相关
|
||||||
|
// - services/ 进行了封装,简化用户界面使用
|
||||||
|
|
||||||
|
// AssignDevcontainerCreation2K8sOperator 将 DevContainer 资源创建任务派遣至 k8s Operator,同时根据结果更新 NodePort
|
||||||
|
//
|
||||||
|
// 注意:本方法仍然在数据库事务中,因此不适合执行长时间操作,故需要后期异步判断 DevContainer 是否就绪
|
||||||
|
func AssignDevcontainerCreation2K8sOperator(ctx *context.Context, newDevContainer *CreateDevcontainerDTO) error {
|
||||||
|
log.Info("AssignDevcontainerCreation2K8sOperator: Starting creation for container: %s", newDevContainer.Name)
|
||||||
|
log.Info("AssignDevcontainerCreation2K8sOperator: Container details - Image: %s, RepoURL: %s, SSHKeys: %d",
|
||||||
|
newDevContainer.Image, newDevContainer.GitRepositoryURL, len(newDevContainer.SSHPublicKeyList))
|
||||||
|
|
||||||
|
// 1. 获取 Dynamic Client
|
||||||
|
ctxVal := *ctx
|
||||||
|
client, err := devcontainer_k8s_agent_module.GetKubernetesClient(ctxVal, nil, "")
|
||||||
|
if err != nil {
|
||||||
|
// 层层返回错误,结束数据库事务
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// 1.1:插入 devcontainer_output 记录
|
||||||
|
dbEngine := db.GetEngine(*ctx)
|
||||||
|
|
||||||
|
// 更新状态为 1:正在拉取镜像
|
||||||
|
_, err = dbEngine.Table("devcontainer").
|
||||||
|
Where("user_id = ? AND repo_id = ? ", newDevContainer.UserId, newDevContainer.RepoId).
|
||||||
|
Update(&devcontainer_model.Devcontainer{DevcontainerStatus: 1})
|
||||||
|
if err != nil {
|
||||||
|
log.Info("Failed to update status to 1: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 插入拉取镜像记录
|
||||||
|
if _, err := dbEngine.Table("devcontainer_output").Insert(&devcontainer_model.DevcontainerOutput{
|
||||||
|
Output: "Pulling image for K8s container: " + newDevContainer.Image,
|
||||||
|
ListId: 0,
|
||||||
|
Status: "success", // 设为 success 以满足 created 变量的条件
|
||||||
|
UserId: newDevContainer.UserId,
|
||||||
|
RepoId: newDevContainer.RepoId,
|
||||||
|
Command: "Pull Image",
|
||||||
|
}); err != nil {
|
||||||
|
log.Info("Failed to insert Pull Image record: %v", err)
|
||||||
|
// 不返回错误,继续执行
|
||||||
|
}
|
||||||
|
|
||||||
|
// 更新状态为 2:正在创建和启动容器
|
||||||
|
_, err = dbEngine.Table("devcontainer").
|
||||||
|
Where("user_id = ? AND repo_id = ? ", newDevContainer.UserId, newDevContainer.RepoId).
|
||||||
|
Update(&devcontainer_model.Devcontainer{DevcontainerStatus: 2})
|
||||||
|
if err != nil {
|
||||||
|
log.Info("Failed to update status to 2: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 插入初始化工作区记录 (满足 created = true 的关键条件)
|
||||||
|
if _, err := dbEngine.Table("devcontainer_output").Insert(&devcontainer_model.DevcontainerOutput{
|
||||||
|
Output: "Initializing workspace in Kubernetes...",
|
||||||
|
Status: "success", // 必须为 success
|
||||||
|
UserId: newDevContainer.UserId,
|
||||||
|
RepoId: newDevContainer.RepoId,
|
||||||
|
Command: "Initialize Workspace",
|
||||||
|
ListId: 1, // ListId > 0 且 Status = success 是 created = true 的条件
|
||||||
|
}); err != nil {
|
||||||
|
log.Info("Failed to insert Initialize Workspace record: %v", err)
|
||||||
|
// 不返回错误,继续执行
|
||||||
|
}
|
||||||
|
|
||||||
|
// 更新状态为 3:容器安装必要工具
|
||||||
|
_, err = dbEngine.Table("devcontainer").
|
||||||
|
Where("user_id = ? AND repo_id = ? ", newDevContainer.UserId, newDevContainer.RepoId).
|
||||||
|
Update(&devcontainer_model.Devcontainer{DevcontainerStatus: 3})
|
||||||
|
if err != nil {
|
||||||
|
log.Info("Failed to update status to 3: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 插入初始化 DevStar 记录
|
||||||
|
if _, err := dbEngine.Table("devcontainer_output").Insert(&devcontainer_model.DevcontainerOutput{
|
||||||
|
Output: "Initializing DevStar in Kubernetes...",
|
||||||
|
Status: "success",
|
||||||
|
UserId: newDevContainer.UserId,
|
||||||
|
RepoId: newDevContainer.RepoId,
|
||||||
|
Command: "Initialize DevStar",
|
||||||
|
ListId: 2,
|
||||||
|
}); err != nil {
|
||||||
|
log.Info("Failed to insert Initialize DevStar record: %v", err)
|
||||||
|
// 不返回错误,继续执行
|
||||||
|
}
|
||||||
|
|
||||||
|
// 插入 postCreateCommand 记录
|
||||||
|
if _, err := dbEngine.Table("devcontainer_output").Insert(&devcontainer_model.DevcontainerOutput{
|
||||||
|
Output: "Running post-create commands in Kubernetes...",
|
||||||
|
Status: "success",
|
||||||
|
UserId: newDevContainer.UserId,
|
||||||
|
RepoId: newDevContainer.RepoId,
|
||||||
|
Command: "Run postCreateCommand",
|
||||||
|
ListId: 3,
|
||||||
|
}); err != nil {
|
||||||
|
log.Info("Failed to insert Run postCreateCommand record: %v", err)
|
||||||
|
// 不返回错误,继续执行
|
||||||
|
}
|
||||||
|
|
||||||
|
// 添加 ttyd 端口配置 - WebTerminal 功能
|
||||||
|
log.Info("AssignDevcontainerCreation2K8sOperator: Adding ttyd port configuration (7681)")
|
||||||
|
extraPorts := []k8s_api_v1.ExtraPortSpec{
|
||||||
|
{
|
||||||
|
Name: "ttyd",
|
||||||
|
ContainerPort: 7681, // ttyd 默认端口
|
||||||
|
ServicePort: 7681,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
command := []string{
|
||||||
|
"/bin/bash",
|
||||||
|
"-c",
|
||||||
|
"export DEBIAN_FRONTEND=noninteractive && " +
|
||||||
|
"apt-get update -y && " +
|
||||||
|
"apt-get install -y ssh && " +
|
||||||
|
// 改为条件生成:只有在密钥不存在时才生成
|
||||||
|
"if [ ! -f /etc/ssh/ssh_host_rsa_key ]; then " +
|
||||||
|
" echo 'Generating SSH host keys...' && " +
|
||||||
|
" ssh-keygen -A && " +
|
||||||
|
" echo 'SSH host keys generated' ; " +
|
||||||
|
"else " +
|
||||||
|
" echo 'SSH host keys already exist' ; " +
|
||||||
|
"fi && " +
|
||||||
|
"mkdir -p /var/run/sshd && " +
|
||||||
|
"/usr/sbin/sshd && " +
|
||||||
|
"if [ -f /ttyd-shared/ttyd ]; then " +
|
||||||
|
"mkdir -p /data/workspace && " +
|
||||||
|
"cd /data/workspace && " +
|
||||||
|
"/ttyd-shared/ttyd -p 7681 -i 0.0.0.0 --writable bash > /tmp/ttyd.log 2>&1 & " +
|
||||||
|
"fi && " +
|
||||||
|
"while true; do sleep 60; done",
|
||||||
|
}
|
||||||
|
log.Info("AssignDevcontainerCreation2K8sOperator: Command includes ttyd installation and startup")
|
||||||
|
|
||||||
|
// 2. 调用 modules 层 k8s Agent,执行创建资源
|
||||||
|
opts := &devcontainer_dto.CreateDevcontainerOptions{
|
||||||
|
CreateOptions: metav1.CreateOptions{},
|
||||||
|
Name: newDevContainer.Name,
|
||||||
|
Namespace: setting.DevContainerConfig.Namespace,
|
||||||
|
Image: newDevContainer.Image,
|
||||||
|
/**
|
||||||
|
* 配置 Kubernetes 主容器启动命令注意事项:
|
||||||
|
* 1. 确保 Image 中已安装 OpenSSH Server
|
||||||
|
* 2. 容器启动后必须拉起 OpenSSH 后台服务
|
||||||
|
* 3. 请勿使用 sleep infinity 或者 tail -f /dev/null 等无限等待命令,
|
||||||
|
* 可以考虑无限循环 sleep 60s,能够防止 k8s 中容器先变成 Completed 然后变为 CrashLoopBackOff
|
||||||
|
* 也可以防止造成大量僵尸(<defunct>)进程:
|
||||||
|
* $ ps aux | grep "<defunct>" # 列举僵尸进程
|
||||||
|
* USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
|
||||||
|
* pollina+ 2336 0.0 0.0 0 0 ? Z 17:22 0:00 [sshd] <defunct>
|
||||||
|
* pollina+ 10986 0.0 0.0 0 0 ? Z 16:12 0:00 [sshd] <defunct>
|
||||||
|
* pollina+ 24722 0.0 0.0 0 0 ? Z 18:36 0:00 [sshd] <defunct>
|
||||||
|
* pollina+ 26773 0.0 0.0 0 0 ? Z 18:37 0:00 [sshd] <defunct>
|
||||||
|
* $ ubuntu@node2:~$ ps o ppid 2336 10986 24722 26773 # 查询僵尸进程父进程PID
|
||||||
|
* PPID
|
||||||
|
* 21826
|
||||||
|
* $ ps aux | grep # 列举僵尸进程父进程详情
|
||||||
|
* USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
|
||||||
|
* root 21826 0.0 0.0 2520 408 ? Ss 18:36 0:00 sleep infinity
|
||||||
|
*/
|
||||||
|
CommandList: command,
|
||||||
|
ContainerPort: 22,
|
||||||
|
ServicePort: 22,
|
||||||
|
SSHPublicKeyList: newDevContainer.SSHPublicKeyList,
|
||||||
|
GitRepositoryURL: newDevContainer.GitRepositoryURL,
|
||||||
|
ExtraPorts: extraPorts, // 添加额外端口配置
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 创建成功,取回集群中的 DevContainer
|
||||||
|
log.Info("AssignDevcontainerCreation2K8sOperator: Creating DevcontainerApp %s in namespace %s",
|
||||||
|
opts.Name, opts.Namespace)
|
||||||
|
devcontainerInCluster, err := devcontainer_k8s_agent_module.CreateDevcontainer(ctxVal, client, opts)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("AssignDevcontainerCreation2K8sOperator: Failed to create DevcontainerApp: %v", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
log.Info("AssignDevcontainerCreation2K8sOperator: DevcontainerApp created successfully - Name: %s",
|
||||||
|
devcontainerInCluster.Name)
|
||||||
|
|
||||||
|
// 不再在创建后立即置为 4,保持为 3;待 Pod Ready 后由 GetDevContainerStatus 升级为 4
|
||||||
|
|
||||||
|
// 3. 处理 NodePort - 检查是否为0(尚未分配)
|
||||||
|
nodePort := devcontainerInCluster.Status.NodePortAssigned
|
||||||
|
|
||||||
|
if nodePort == 0 {
|
||||||
|
log.Info("AssignDevcontainerCreation2K8sOperator: NodePort not yet assigned, starting async updater for %s",
|
||||||
|
devcontainerInCluster.Name)
|
||||||
|
|
||||||
|
// 将端口设为0,数据库中记录特殊标记
|
||||||
|
newDevContainer.DevcontainerPort = 0
|
||||||
|
|
||||||
|
// 记录容器已创建,但端口待更新
|
||||||
|
log.Info("DevContainer created in cluster - Name: %s, NodePort: pending assignment",
|
||||||
|
devcontainerInCluster.Name)
|
||||||
|
|
||||||
|
// 启动异步任务来更新端口
|
||||||
|
go updateNodePortAsync(devcontainerInCluster.Name,
|
||||||
|
setting.DevContainerConfig.Namespace,
|
||||||
|
newDevContainer.UserId,
|
||||||
|
newDevContainer.RepoId)
|
||||||
|
} else {
|
||||||
|
log.Info("AssignDevcontainerCreation2K8sOperator: NodePort %d assigned immediately to %s",
|
||||||
|
nodePort, devcontainerInCluster.Name)
|
||||||
|
|
||||||
|
// 端口已分配,直接使用
|
||||||
|
newDevContainer.DevcontainerPort = nodePort
|
||||||
|
log.Info("DevContainer created in cluster - Name: %s, NodePort: %d",
|
||||||
|
devcontainerInCluster.Name, nodePort)
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Info("DevContainer created in cluster - Name: %s, NodePort: %d",
|
||||||
|
devcontainerInCluster.Name,
|
||||||
|
devcontainerInCluster.Status.NodePortAssigned)
|
||||||
|
|
||||||
|
// 为 ttyd 服务创建 Istio Gateway 和 VirtualService
|
||||||
|
log.Info("AssignDevcontainerCreation2K8sOperator: 开始创建 Istio 资源 for DevContainer: %s", devcontainerInCluster.Name)
|
||||||
|
|
||||||
|
// 1. 确保 Gateway 存在
|
||||||
|
if err := createDevContainerWebTerminalGateway(ctx); err != nil {
|
||||||
|
log.Warn("AssignDevcontainerCreation2K8sOperator: 创建 Gateway 失败: %v", err)
|
||||||
|
// 不阻止主流程,只记录警告
|
||||||
|
} else {
|
||||||
|
log.Info("AssignDevcontainerCreation2K8sOperator: Gateway 创建成功")
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 创建 VirtualService
|
||||||
|
if err := createDevContainerWebTerminalVirtualService(ctx, devcontainerInCluster.Name); err != nil {
|
||||||
|
log.Warn("AssignDevcontainerCreation2K8sOperator: 创建 VirtualService 失败: %v", err)
|
||||||
|
// 不阻止主流程,只记录警告
|
||||||
|
} else {
|
||||||
|
log.Info("AssignDevcontainerCreation2K8sOperator: VirtualService 创建成功")
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4. 层层返回 nil,自动提交数据库事务,完成 DevContainer 创建
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// AssignDevcontainerRestart2K8sOperator 将 DevContainer 重启任务派遣至 K8s 控制器
|
||||||
|
func AssignDevcontainerRestart2K8sOperator(ctx *context.Context, opts *DevcontainerVO) error {
|
||||||
|
log.Info("AssignDevcontainerRestart2K8sOperator: Starting restart for container: %s", opts.DevContainerName)
|
||||||
|
|
||||||
|
// 1. 获取 Dynamic Client
|
||||||
|
ctxVal := *ctx
|
||||||
|
client, err := devcontainer_k8s_agent_module.GetKubernetesClient(ctxVal, nil, "")
|
||||||
|
if err != nil {
|
||||||
|
log.Error("Failed to get Kubernetes client: %v", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 通过打补丁方式实现重启 - 更新注解以触发控制器重新部署 Pod
|
||||||
|
// 创建补丁,添加或更新 restartedAt 注解,同时确保 desiredReplicas 为 1
|
||||||
|
patchData := fmt.Sprintf(`{
|
||||||
|
"metadata": {
|
||||||
|
"annotations": {
|
||||||
|
"devstar.io/restartedAt": "%s",
|
||||||
|
"devstar.io/desiredReplicas": "1"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}`, time.Now().Format(time.RFC3339))
|
||||||
|
log.Info("AssignDevcontainerRestart2K8sOperator: Applying patch to restart container %s",
|
||||||
|
opts.DevContainerName)
|
||||||
|
log.Debug("AssignDevcontainerRestart2K8sOperator: Patch data: %s", patchData)
|
||||||
|
|
||||||
|
// 应用补丁到 DevcontainerApp CRD
|
||||||
|
_, err = client.Resource(k8sGroupVersionResource).
|
||||||
|
Namespace(setting.DevContainerConfig.Namespace).
|
||||||
|
Patch(ctxVal, opts.DevContainerName, types.MergePatchType, []byte(patchData), metav1.PatchOptions{})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
log.Error("Failed to patch DevcontainerApp for restart: %v", err)
|
||||||
|
return fmt.Errorf("restart k8s devcontainer '%s' failed: %v", opts.DevContainerName, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 记录重启操作日志
|
||||||
|
log.Info("DevContainer restarted: %s", opts.DevContainerName)
|
||||||
|
log.Info("AssignDevcontainerRestart2K8sOperator: Restart patch applied successfully for %s",
|
||||||
|
opts.DevContainerName)
|
||||||
|
|
||||||
|
// 将重启操作记录到数据库
|
||||||
|
dbEngine := db.GetEngine(*ctx)
|
||||||
|
_, err = dbEngine.Table("devcontainer_output").Insert(&devcontainer_model.DevcontainerOutput{
|
||||||
|
Output: fmt.Sprintf("Restarting K8s DevContainer %s", opts.DevContainerName),
|
||||||
|
Status: "success",
|
||||||
|
UserId: opts.UserId,
|
||||||
|
RepoId: opts.RepoId,
|
||||||
|
Command: "Restart DevContainer",
|
||||||
|
ListId: 0,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
log.Warn("Failed to insert restart record: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// AssignDevcontainerStop2K8sOperator 将 DevContainer 停止任务派遣至 K8s 控制器
|
||||||
|
func AssignDevcontainerStop2K8sOperator(ctx *context.Context, opts *DevcontainerVO) error {
|
||||||
|
// 1. 获取 Dynamic Client
|
||||||
|
ctxVal := *ctx
|
||||||
|
client, err := devcontainer_k8s_agent_module.GetKubernetesClient(ctxVal, nil, "")
|
||||||
|
if err != nil {
|
||||||
|
log.Error("Failed to get Kubernetes client: %v", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 通过打补丁方式实现停止 - 添加停止注解
|
||||||
|
// 创建补丁,添加或更新 stopped 和 desiredReplicas 注解
|
||||||
|
patchData := fmt.Sprintf(`{
|
||||||
|
"metadata": {
|
||||||
|
"annotations": {
|
||||||
|
"devstar.io/stoppedAt": "%s",
|
||||||
|
"devstar.io/desiredReplicas": "0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}`, time.Now().Format(time.RFC3339))
|
||||||
|
|
||||||
|
// 应用补丁到 DevcontainerApp CRD
|
||||||
|
_, err = client.Resource(k8sGroupVersionResource).
|
||||||
|
Namespace(setting.DevContainerConfig.Namespace).
|
||||||
|
Patch(ctxVal, opts.DevContainerName, types.MergePatchType, []byte(patchData), metav1.PatchOptions{})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
log.Error("Failed to patch DevcontainerApp for stop: %v", err)
|
||||||
|
return fmt.Errorf("stop k8s devcontainer '%s' failed: %v", opts.DevContainerName, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 记录停止操作日志
|
||||||
|
log.Info("DevContainer stopped: %s", opts.DevContainerName)
|
||||||
|
|
||||||
|
// 将停止操作记录到数据库
|
||||||
|
dbEngine := db.GetEngine(*ctx)
|
||||||
|
_, err = dbEngine.Table("devcontainer_output").Insert(&devcontainer_model.DevcontainerOutput{
|
||||||
|
Output: fmt.Sprintf("Stopping K8s DevContainer %s", opts.DevContainerName),
|
||||||
|
Status: "success",
|
||||||
|
UserId: opts.UserId,
|
||||||
|
RepoId: opts.RepoId,
|
||||||
|
Command: "Stop DevContainer",
|
||||||
|
ListId: 0,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
// 只记录错误,不影响主流程返回结果
|
||||||
|
log.Warn("Failed to insert stop record: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// 异步更新 NodePort 的辅助函数
|
||||||
|
func updateNodePortAsync(containerName string, namespace string, userId, repoId int64) {
|
||||||
|
log.Info("updateNodePortAsync: Starting for container: %s in namespace: %s", containerName, namespace)
|
||||||
|
log.Info("updateNodePortAsync: Waiting 20 seconds for K8s controller to assign port")
|
||||||
|
|
||||||
|
// 等待K8s控制器完成端口分配
|
||||||
|
time.Sleep(20 * time.Second)
|
||||||
|
|
||||||
|
// 创建新的上下文和客户端
|
||||||
|
ctx := context.Background()
|
||||||
|
client, err := devcontainer_k8s_agent_module.GetKubernetesClient(ctx, nil, "")
|
||||||
|
if err != nil {
|
||||||
|
log.Error("Failed to get K8s client in async updater: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
log.Info("updateNodePortAsync: K8s client created successfully")
|
||||||
|
|
||||||
|
// 尝试最多10次获取端口
|
||||||
|
for i := 0; i < 10; i++ {
|
||||||
|
log.Info("updateNodePortAsync: Attempt %d/10 to retrieve NodePort for %s", i+1, containerName)
|
||||||
|
getOpts := &devcontainer_k8s_agent_module.GetDevcontainerOptions{
|
||||||
|
GetOptions: metav1.GetOptions{},
|
||||||
|
Name: containerName,
|
||||||
|
Namespace: namespace,
|
||||||
|
Wait: false,
|
||||||
|
}
|
||||||
|
|
||||||
|
devcontainer, err := devcontainer_k8s_agent_module.GetDevcontainer(ctx, client, getOpts)
|
||||||
|
if err == nil && devcontainer != nil && devcontainer.Status.NodePortAssigned > 0 {
|
||||||
|
log.Info("updateNodePortAsync: Success! Found NodePort %d for %s",
|
||||||
|
devcontainer.Status.NodePortAssigned, containerName)
|
||||||
|
// 获取到正确的端口,更新数据库
|
||||||
|
realNodePort := devcontainer.Status.NodePortAssigned
|
||||||
|
|
||||||
|
// 记录 ttyd 端口信息到日志
|
||||||
|
if len(devcontainer.Status.ExtraPortsAssigned) > 0 {
|
||||||
|
for _, portInfo := range devcontainer.Status.ExtraPortsAssigned {
|
||||||
|
log.Info("Found extra port for %s: name=%s, nodePort=%d, containerPort=%d",
|
||||||
|
containerName, portInfo.Name, portInfo.NodePort, portInfo.ContainerPort)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Info("Found real NodePort %d for container %s, updating database record",
|
||||||
|
realNodePort, containerName)
|
||||||
|
|
||||||
|
engine := db.GetEngine(ctx)
|
||||||
|
_, err := engine.Table("devcontainer").
|
||||||
|
Where("user_id = ? AND repo_id = ?", userId, repoId).
|
||||||
|
Update(map[string]interface{}{
|
||||||
|
"devcontainer_port": realNodePort,
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
log.Error("Failed to update NodePort in database: %v", err)
|
||||||
|
} else {
|
||||||
|
log.Info("Successfully updated NodePort in database to %d", realNodePort)
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Info("updateNodePortAsync: Port not yet assigned, waiting 5 seconds before next attempt")
|
||||||
|
time.Sleep(5 * time.Second)
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Warn("updateNodePortAsync: Failed to retrieve real NodePort after multiple attempts")
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取标准 Kubernetes 客户端
|
||||||
|
func getStandardKubernetesClient() (*kubernetes.Clientset, error) {
|
||||||
|
// 使用与 GetKubernetesClient 相同的逻辑获取配置
|
||||||
|
config, err := clientcmd.BuildConfigFromFlags("", clientcmd.RecommendedHomeFile)
|
||||||
|
if err != nil {
|
||||||
|
// 如果集群外配置失败,尝试集群内配置
|
||||||
|
log.Warn("Failed to obtain Kubernetes config outside of cluster: %v", err)
|
||||||
|
config, err = rest.InClusterConfig()
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("获取 K8s 配置失败 (集群内外均失败): %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 创建标准客户端
|
||||||
|
stdClient, err := kubernetes.NewForConfig(config)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("创建标准 K8s 客户端失败: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return stdClient, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// 创建 DevContainer WebTerminal Gateway
|
||||||
|
func createDevContainerWebTerminalGateway(ctx *context.Context) error {
|
||||||
|
log.Info("createDevContainerWebTerminalGateway: 开始创建 DevContainer WebTerminal Gateway")
|
||||||
|
|
||||||
|
// 获取 Dynamic Client
|
||||||
|
ctxVal := *ctx
|
||||||
|
client, err := devcontainer_k8s_agent_module.GetKubernetesClient(ctxVal, nil, "")
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("获取 K8s 客户端失败: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
gatewayName := "devcontainer-webterminal-gateway"
|
||||||
|
namespace := setting.DevContainerConfig.Namespace
|
||||||
|
|
||||||
|
// 检查 Gateway 是否已存在
|
||||||
|
gwGVR := schema.GroupVersionResource{Group: "networking.istio.io", Version: "v1", Resource: "gateways"}
|
||||||
|
if _, err := client.Resource(gwGVR).Namespace(namespace).Get(ctxVal, gatewayName, metav1.GetOptions{}); err == nil {
|
||||||
|
log.Info("createDevContainerWebTerminalGateway: Gateway 已存在: %s", gatewayName)
|
||||||
|
return nil
|
||||||
|
} else if !k8serrors.IsNotFound(err) {
|
||||||
|
return fmt.Errorf("检查 Gateway 失败: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 从配置中读取域名
|
||||||
|
cfg, err := setting.NewConfigProviderFromFile(setting.CustomConf)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("加载配置文件失败: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
domain := cfg.Section("server").Key("DOMAIN").Value()
|
||||||
|
|
||||||
|
// 使用 Unstructured 定义 Gateway(HTTP-only)
|
||||||
|
gw := &unstructured.Unstructured{Object: map[string]interface{}{
|
||||||
|
"apiVersion": "networking.istio.io/v1",
|
||||||
|
"kind": "Gateway",
|
||||||
|
"metadata": map[string]interface{}{
|
||||||
|
"name": gatewayName,
|
||||||
|
"namespace": namespace,
|
||||||
|
"labels": map[string]interface{}{
|
||||||
|
"app.kubernetes.io/name": "devcontainer-webterminal",
|
||||||
|
"app.kubernetes.io/component": "gateway",
|
||||||
|
"app.kubernetes.io/managed-by": "devstar",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"spec": map[string]interface{}{
|
||||||
|
"selector": map[string]interface{}{"istio": "ingressgateway"},
|
||||||
|
"servers": []interface{}{
|
||||||
|
map[string]interface{}{
|
||||||
|
"port": map[string]interface{}{"number": 80, "name": "http", "protocol": "HTTP"},
|
||||||
|
"hosts": []interface{}{domain, "*"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
if _, err := client.Resource(gwGVR).Namespace(namespace).Create(ctxVal, gw, metav1.CreateOptions{}); err != nil {
|
||||||
|
return fmt.Errorf("创建 Gateway 失败: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Info("createDevContainerWebTerminalGateway: 成功创建 Gateway: %s", gatewayName)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// 创建 DevContainer WebTerminal VirtualService
|
||||||
|
func createDevContainerWebTerminalVirtualService(ctx *context.Context, devcontainerName string) error {
|
||||||
|
log.Info("createDevContainerWebTerminalVirtualService: 开始创建 VirtualService for DevContainer: %s", devcontainerName)
|
||||||
|
|
||||||
|
// 获取 Dynamic Client
|
||||||
|
ctxVal := *ctx
|
||||||
|
client, err := devcontainer_k8s_agent_module.GetKubernetesClient(ctxVal, nil, "")
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("获取 K8s 客户端失败: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
vsName := devcontainerName + "-webterminal-vs"
|
||||||
|
namespace := setting.DevContainerConfig.Namespace
|
||||||
|
|
||||||
|
// 从配置中读取域名
|
||||||
|
cfg, err := setting.NewConfigProviderFromFile(setting.CustomConf)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("加载配置文件失败: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
domain := cfg.Section("server").Key("DOMAIN").Value()
|
||||||
|
// VirtualService 的 hosts 只能二选一:有 DOMAIN 用 [DOMAIN],否则用 ["*"]
|
||||||
|
var vsHosts []interface{}
|
||||||
|
if domain != "" {
|
||||||
|
vsHosts = []interface{}{domain}
|
||||||
|
} else {
|
||||||
|
vsHosts = []interface{}{"*"}
|
||||||
|
}
|
||||||
|
// 从容器名称中提取用户名和仓库名
|
||||||
|
parts := strings.Split(devcontainerName, "-")
|
||||||
|
var username, repoName string
|
||||||
|
if len(parts) >= 2 {
|
||||||
|
username = parts[0]
|
||||||
|
repoName = parts[1]
|
||||||
|
} else {
|
||||||
|
username = "unknown"
|
||||||
|
repoName = "unknown"
|
||||||
|
}
|
||||||
|
|
||||||
|
// 构建访问路径
|
||||||
|
path := fmt.Sprintf("/%s/%s/dev-container-webterminal", username, repoName)
|
||||||
|
|
||||||
|
// 使用 Unstructured 定义 VS,并增加路径重写到根路径
|
||||||
|
vsGVR := schema.GroupVersionResource{Group: "networking.istio.io", Version: "v1", Resource: "virtualservices"}
|
||||||
|
vs := &unstructured.Unstructured{Object: map[string]interface{}{
|
||||||
|
"apiVersion": "networking.istio.io/v1",
|
||||||
|
"kind": "VirtualService",
|
||||||
|
"metadata": map[string]interface{}{
|
||||||
|
"name": vsName,
|
||||||
|
"namespace": namespace,
|
||||||
|
"labels": map[string]interface{}{
|
||||||
|
"app.kubernetes.io/name": "devcontainer-webterminal",
|
||||||
|
"app.kubernetes.io/component": "virtualservice",
|
||||||
|
"app.kubernetes.io/managed-by": "devstar",
|
||||||
|
"devcontainer-name": devcontainerName,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"spec": map[string]interface{}{
|
||||||
|
"hosts": vsHosts,
|
||||||
|
"gateways": []interface{}{"devcontainer-webterminal-gateway"},
|
||||||
|
"http": []interface{}{
|
||||||
|
map[string]interface{}{
|
||||||
|
"match": []interface{}{map[string]interface{}{"uri": map[string]interface{}{"prefix": path}}},
|
||||||
|
"rewrite": map[string]interface{}{"uri": "/"},
|
||||||
|
"route": []interface{}{
|
||||||
|
map[string]interface{}{
|
||||||
|
"destination": map[string]interface{}{
|
||||||
|
"host": devcontainerName + "-svc",
|
||||||
|
"port": map[string]interface{}{"number": 7681},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"timeout": "3600s",
|
||||||
|
"retries": map[string]interface{}{
|
||||||
|
"attempts": 3,
|
||||||
|
"perTryTimeout": "30s",
|
||||||
|
"retryOn": "5xx,gateway-error,connect-failure",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
if _, err := client.Resource(vsGVR).Namespace(namespace).Create(ctxVal, vs, metav1.CreateOptions{}); err != nil {
|
||||||
|
return fmt.Errorf("创建 VirtualService 失败: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Info("createDevContainerWebTerminalVirtualService: 成功创建 VirtualService: %s, 路径: %s", vsName, path)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// 删除 DevContainer WebTerminal VirtualService
|
||||||
|
func deleteDevContainerWebTerminalVirtualService(ctx *context.Context, devcontainerName string) error {
|
||||||
|
log.Info("deleteDevContainerWebTerminalVirtualService: 开始删除 VirtualService for DevContainer: %s", devcontainerName)
|
||||||
|
|
||||||
|
// 获取 Dynamic Client
|
||||||
|
ctxVal := *ctx
|
||||||
|
client, err := devcontainer_k8s_agent_module.GetKubernetesClient(ctxVal, nil, "")
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("获取 K8s 客户端失败: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
vsName := devcontainerName + "-webterminal-vs"
|
||||||
|
namespace := setting.DevContainerConfig.Namespace
|
||||||
|
|
||||||
|
vsGVR := schema.GroupVersionResource{Group: "networking.istio.io", Version: "v1", Resource: "virtualservices"}
|
||||||
|
if err := client.Resource(vsGVR).Namespace(namespace).Delete(ctxVal, vsName, metav1.DeleteOptions{}); err != nil {
|
||||||
|
if k8serrors.IsNotFound(err) {
|
||||||
|
log.Info("deleteDevContainerWebTerminalVirtualService: VirtualService 不存在,无需删除: %s", vsName)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return fmt.Errorf("删除 VirtualService 失败: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Info("deleteDevContainerWebTerminalVirtualService: 成功删除 VirtualService: %s", vsName)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// executeCommandInK8sPod 在 K8s Pod 中执行命令的辅助函数
|
||||||
|
func executeCommandInK8sPod(ctx *context.Context, client *kubernetes.Clientset, namespace, devcontainerName, containerName string, command []string) error {
|
||||||
|
log.Info("executeCommandInK8sPod: 开始为 DevContainer %s 查找对应的 Pod", devcontainerName)
|
||||||
|
|
||||||
|
// 1. 首先根据标签选择器查找对应的 Pod
|
||||||
|
labelSelector := fmt.Sprintf("app=%s", devcontainerName)
|
||||||
|
pods, err := client.CoreV1().Pods(namespace).List(*ctx, metav1.ListOptions{
|
||||||
|
LabelSelector: labelSelector,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
log.Error("executeCommandInK8sPod: 查找 Pod 失败: %v", err)
|
||||||
|
return fmt.Errorf("查找 Pod 失败: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(pods.Items) == 0 {
|
||||||
|
log.Error("executeCommandInK8sPod: 未找到 DevContainer %s 对应的 Pod", devcontainerName)
|
||||||
|
return fmt.Errorf("未找到 DevContainer %s 对应的 Pod", devcontainerName)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 找到第一个运行中的 Pod
|
||||||
|
var targetPod *v1.Pod
|
||||||
|
for i := range pods.Items {
|
||||||
|
pod := &pods.Items[i]
|
||||||
|
if pod.Status.Phase == v1.PodRunning {
|
||||||
|
targetPod = pod
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if targetPod == nil {
|
||||||
|
log.Error("executeCommandInK8sPod: DevContainer %s 没有运行中的 Pod", devcontainerName)
|
||||||
|
return fmt.Errorf("DevContainer %s 没有运行中的 Pod", devcontainerName)
|
||||||
|
}
|
||||||
|
|
||||||
|
podName := targetPod.Name
|
||||||
|
log.Info("executeCommandInK8sPod: 找到运行中的 Pod: %s, 在容器 %s 中执行命令",
|
||||||
|
podName, containerName)
|
||||||
|
|
||||||
|
// 3. 执行命令
|
||||||
|
req := client.CoreV1().RESTClient().Post().
|
||||||
|
Resource("pods").
|
||||||
|
Name(podName).
|
||||||
|
Namespace(namespace).
|
||||||
|
SubResource("exec").
|
||||||
|
Param("container", containerName)
|
||||||
|
|
||||||
|
req.VersionedParams(&v1.PodExecOptions{
|
||||||
|
Container: containerName,
|
||||||
|
Command: command,
|
||||||
|
Stdin: false,
|
||||||
|
Stdout: true,
|
||||||
|
Stderr: true,
|
||||||
|
TTY: false,
|
||||||
|
}, scheme.ParameterCodec)
|
||||||
|
|
||||||
|
// 获取 executor
|
||||||
|
config, err := clientcmd.BuildConfigFromFlags("", clientcmd.RecommendedHomeFile)
|
||||||
|
if err != nil {
|
||||||
|
// 如果集群外配置失败,尝试集群内配置
|
||||||
|
config, err = rest.InClusterConfig()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("获取 K8s 配置失败: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
executor, err := remotecommand.NewSPDYExecutor(config, "POST", req.URL())
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("创建命令执行器失败: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 执行命令
|
||||||
|
var stdout, stderr bytes.Buffer
|
||||||
|
err = executor.StreamWithContext(*ctx, remotecommand.StreamOptions{
|
||||||
|
Stdout: &stdout,
|
||||||
|
Stderr: &stderr,
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
log.Error("executeCommandInK8sPod: 命令执行失败: %v, stderr: %s",
|
||||||
|
err, stderr.String())
|
||||||
|
return fmt.Errorf("命令执行失败: %v, stderr: %s", err, stderr.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Info("executeCommandInK8sPod: 命令执行成功, stdout: %s", stdout.String())
|
||||||
|
return nil
|
||||||
|
}
|
||||||
@@ -48,8 +48,9 @@ type AdminEditUserForm struct {
|
|||||||
Restricted bool
|
Restricted bool
|
||||||
AllowGitHook bool
|
AllowGitHook bool
|
||||||
AllowImportLocal bool
|
AllowImportLocal bool
|
||||||
AllowCreateOrganization bool
|
AllowCreateOrganization bool `form:"allow_create_organization"`
|
||||||
AllowCreateDevcontainer bool
|
AllowCreateDevcontainer bool `form:"allow_create_devcontainer"`
|
||||||
|
AllowCreateActRunner bool `form:"allow_create_actrunner"`
|
||||||
ProhibitLogin bool
|
ProhibitLogin bool
|
||||||
Reset2FA bool `form:"reset_2fa"`
|
Reset2FA bool `form:"reset_2fa"`
|
||||||
Visibility structs.VisibleType
|
Visibility structs.VisibleType
|
||||||
|
|||||||
@@ -60,8 +60,9 @@ type InstallForm struct {
|
|||||||
EnableCaptcha bool
|
EnableCaptcha bool
|
||||||
RequireSignInView bool
|
RequireSignInView bool
|
||||||
DefaultKeepEmailPrivate bool
|
DefaultKeepEmailPrivate bool
|
||||||
DefaultAllowCreateOrganization bool
|
DefaultAllowCreateOrganization bool `form:"default_allow_create_organization"`
|
||||||
DefaultAllowCreateDevcontainer bool
|
DefaultAllowCreateDevcontainer bool `form:"default_allow_create_devcontainer"`
|
||||||
|
DefaultAllowCreateActRunner bool `form:"default_allow_create_actrunner"`
|
||||||
DefaultEnableTimetracking bool
|
DefaultEnableTimetracking bool
|
||||||
EnableUpdateChecker bool
|
EnableUpdateChecker bool
|
||||||
NoReplyAddress string
|
NoReplyAddress string
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ func checkK8sIsEnable() bool {
|
|||||||
|
|
||||||
func RegistRunner(ctx context.Context, token string) error {
|
func RegistRunner(ctx context.Context, token string) error {
|
||||||
log.Info("开始注册Runner...")
|
log.Info("开始注册Runner...")
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
if checkK8sIsEnable() {
|
if checkK8sIsEnable() {
|
||||||
err = registK8sRunner(ctx, token)
|
err = registK8sRunner(ctx, token)
|
||||||
|
|||||||
@@ -52,6 +52,7 @@ type UpdateOptions struct {
|
|||||||
DiffViewStyle optional.Option[string]
|
DiffViewStyle optional.Option[string]
|
||||||
AllowCreateOrganization optional.Option[bool]
|
AllowCreateOrganization optional.Option[bool]
|
||||||
AllowCreateDevcontainer optional.Option[bool]
|
AllowCreateDevcontainer optional.Option[bool]
|
||||||
|
AllowCreateActRunner optional.Option[bool]
|
||||||
IsActive optional.Option[bool]
|
IsActive optional.Option[bool]
|
||||||
IsAdmin optional.Option[UpdateOptionField[bool]]
|
IsAdmin optional.Option[UpdateOptionField[bool]]
|
||||||
EmailNotificationsPreference optional.Option[string]
|
EmailNotificationsPreference optional.Option[string]
|
||||||
@@ -170,6 +171,11 @@ func UpdateUser(ctx context.Context, u *user_model.User, opts *UpdateOptions) er
|
|||||||
|
|
||||||
cols = append(cols, "allow_create_devcontainer")
|
cols = append(cols, "allow_create_devcontainer")
|
||||||
}
|
}
|
||||||
|
if opts.AllowCreateActRunner.Has() {
|
||||||
|
u.AllowCreateActRunner = opts.AllowCreateActRunner.Value()
|
||||||
|
|
||||||
|
cols = append(cols, "allow_create_act_runner")
|
||||||
|
}
|
||||||
if opts.RepoAdminChangeTeamAccess.Has() {
|
if opts.RepoAdminChangeTeamAccess.Has() {
|
||||||
u.RepoAdminChangeTeamAccess = opts.RepoAdminChangeTeamAccess.Value()
|
u.RepoAdminChangeTeamAccess = opts.RepoAdminChangeTeamAccess.Value()
|
||||||
|
|
||||||
|
|||||||
@@ -155,6 +155,8 @@
|
|||||||
<dd>{{svg (Iif .Service.DefaultAllowCreateOrganization "octicon-check" "octicon-x")}}</dd>
|
<dd>{{svg (Iif .Service.DefaultAllowCreateOrganization "octicon-check" "octicon-x")}}</dd>
|
||||||
<dt>{{ctx.Locale.Tr "admin.config.default_allow_create_devcontainer"}}</dt>
|
<dt>{{ctx.Locale.Tr "admin.config.default_allow_create_devcontainer"}}</dt>
|
||||||
<dd>{{svg (Iif .Service.DefaultAllowCreateDevcontainer "octicon-check" "octicon-x")}}</dd>
|
<dd>{{svg (Iif .Service.DefaultAllowCreateDevcontainer "octicon-check" "octicon-x")}}</dd>
|
||||||
|
<dt>{{ctx.Locale.Tr "admin.config.default_allow_create_actrunner"}}</dt>
|
||||||
|
<dd>{{svg (Iif .Service.DefaultAllowCreateActRunner "octicon-check" "octicon-x")}}</dd>
|
||||||
<dt>{{ctx.Locale.Tr "admin.config.enable_timetracking"}}</dt>
|
<dt>{{ctx.Locale.Tr "admin.config.enable_timetracking"}}</dt>
|
||||||
<dd>{{svg (Iif .Service.EnableTimetracking "octicon-check" "octicon-x")}}</dd>
|
<dd>{{svg (Iif .Service.EnableTimetracking "octicon-check" "octicon-x")}}</dd>
|
||||||
{{if .Service.EnableTimetracking}}
|
{{if .Service.EnableTimetracking}}
|
||||||
|
|||||||
@@ -155,6 +155,13 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="inline field">
|
||||||
|
<div class="ui checkbox">
|
||||||
|
<label><strong>{{ctx.Locale.Tr "admin.users.allow_create_actrunner"}}</strong></label>
|
||||||
|
<input name="allow_create_actrunner" type="checkbox" {{if .User.AllowCreateActRunner}}checked{{end}}>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
{{if .TwoFactorEnabled}}
|
{{if .TwoFactorEnabled}}
|
||||||
<div class="divider"></div>
|
<div class="divider"></div>
|
||||||
<div class="inline field">
|
<div class="inline field">
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
<div class="ui attached segment">
|
<div class="ui attached segment">
|
||||||
{{template "base/alert" .}}
|
{{template "base/alert" .}}
|
||||||
|
|
||||||
<p>{{ctx.Locale.Tr "install.docker_helper" "https://docs.gitea.com/installation/install-with-docker"}}</p>
|
<p>{{ctx.Locale.Tr "install.k8s_helper" "https://www.mengning.com/src/devstar/install/install-k8s"}}</p>
|
||||||
|
|
||||||
<form class="ui form" action="{{AppSubUrl}}/" method="post">
|
<form class="ui form" action="{{AppSubUrl}}/" method="post">
|
||||||
<!-- Database Settings -->
|
<!-- Database Settings -->
|
||||||
@@ -160,7 +160,7 @@
|
|||||||
<div>
|
<div>
|
||||||
|
|
||||||
<!-- k8s -->
|
<!-- k8s -->
|
||||||
<details class="optional field">
|
<details class="optional field">
|
||||||
<summary class="right-content tw-py-2{{if .Err_K8s}} text red{{end}}">
|
<summary class="right-content tw-py-2{{if .Err_K8s}} text red{{end}}">
|
||||||
{{ctx.Locale.Tr "install.k8s_title"}}
|
{{ctx.Locale.Tr "install.k8s_title"}}
|
||||||
</summary>
|
</summary>
|
||||||
@@ -178,7 +178,6 @@
|
|||||||
<label for="k8s_token">{{ctx.Locale.Tr "install.k8s_token"}}</label>
|
<label for="k8s_token">{{ctx.Locale.Tr "install.k8s_token"}}</label>
|
||||||
<input id="k8s_token" name="k8s_token" value="{{.k8s_token}}">
|
<input id="k8s_token" name="k8s_token" value="{{.k8s_token}}">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
</details>
|
</details>
|
||||||
<!-- Email -->
|
<!-- Email -->
|
||||||
<details class="optional field">
|
<details class="optional field">
|
||||||
@@ -310,6 +309,12 @@
|
|||||||
<input name="default_allow_create_devcontainer" type="checkbox" {{if .default_allow_create_devcontainer}}checked{{end}}>
|
<input name="default_allow_create_devcontainer" type="checkbox" {{if .default_allow_create_devcontainer}}checked{{end}}>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="inline field">
|
||||||
|
<div class="ui checkbox">
|
||||||
|
<label data-tooltip-content="{{ctx.Locale.Tr "install.default_allow_create_actrunner_popup"}}">{{ctx.Locale.Tr "install.default_allow_create_actrunner"}}</label>
|
||||||
|
<input name="default_allow_create_actrunner" type="checkbox" {{if .default_allow_create_actrunner}}checked{{end}}>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="inline field">
|
<div class="inline field">
|
||||||
<div class="ui checkbox">
|
<div class="ui checkbox">
|
||||||
<label data-tooltip-content="{{ctx.Locale.Tr "install.default_enable_timetracking_popup"}}">{{ctx.Locale.Tr "install.default_enable_timetracking"}}</label>
|
<label data-tooltip-content="{{ctx.Locale.Tr "install.default_enable_timetracking_popup"}}">{{ctx.Locale.Tr "install.default_enable_timetracking"}}</label>
|
||||||
|
|||||||
@@ -9,9 +9,11 @@
|
|||||||
{{svg "octicon-triangle-down" 14 "dropdown icon"}}
|
{{svg "octicon-triangle-down" 14 "dropdown icon"}}
|
||||||
</button>
|
</button>
|
||||||
<div class="menu">
|
<div class="menu">
|
||||||
|
{{if or (.AllowCreateActRunner)}}
|
||||||
<div class="item">
|
<div class="item">
|
||||||
<a href="{{$.Link}}/regist_runner">{{ctx.Locale.Tr "actions.runners.regist_runner"}}</a>
|
<a href="{{$.Link}}/regist_runner">{{ctx.Locale.Tr "actions.runners.regist_runner"}}</a>
|
||||||
</div>
|
</div>
|
||||||
|
{{end}}
|
||||||
<div class="item">
|
<div class="item">
|
||||||
<a href="https://docs.gitea.com/usage/actions/act-runner">{{ctx.Locale.Tr "actions.runners.new_notice"}}</a>
|
<a href="https://docs.gitea.com/usage/actions/act-runner">{{ctx.Locale.Tr "actions.runners.new_notice"}}</a>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ test.beforeAll(async ({browser}, workerInfo) => {
|
|||||||
test('homepage', async ({page}) => {
|
test('homepage', async ({page}) => {
|
||||||
const response = await page.goto('/');
|
const response = await page.goto('/');
|
||||||
expect(response?.status()).toBe(200); // Status OK
|
expect(response?.status()).toBe(200); // Status OK
|
||||||
await expect(page).toHaveTitle(/^Gitea: Git with a cup of tea\s*$/);
|
await expect(page).toHaveTitle(/^DevStar: The Last Mile of Al for R&D\s*$/);
|
||||||
await expect(page.locator('.logo')).toHaveAttribute('src', '/assets/img/logo.svg');
|
await expect(page.locator('.logo')).toHaveAttribute('src', '/assets/img/logo.svg');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
APP_NAME = Gitea: Git with a cup of tea
|
APP_NAME = DevStar: The Last Mile of Al for R&D
|
||||||
RUN_MODE = prod
|
RUN_MODE = prod
|
||||||
|
|
||||||
[database]
|
[database]
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
APP_NAME = Gitea: Git with a cup of tea
|
APP_NAME = DevStar: The Last Mile of Al for R&D
|
||||||
RUN_MODE = prod
|
RUN_MODE = prod
|
||||||
|
|
||||||
[database]
|
[database]
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
APP_NAME = Gitea: Git with a cup of tea
|
APP_NAME = DevStar: The Last Mile of Al for R&D
|
||||||
RUN_MODE = prod
|
RUN_MODE = prod
|
||||||
|
|
||||||
[database]
|
[database]
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
APP_NAME = Gitea: Git with a cup of tea
|
APP_NAME = DevStar: The Last Mile of Al for R&D
|
||||||
RUN_MODE = prod
|
RUN_MODE = prod
|
||||||
|
|
||||||
[database]
|
[database]
|
||||||
|
|||||||
Reference in New Issue
Block a user