test
This commit is contained in:
commit
af4582c591
BIN
go/.DS_Store
vendored
Normal file
BIN
go/.DS_Store
vendored
Normal file
Binary file not shown.
3
go/go.mod
Normal file
3
go/go.mod
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
// go.mod
|
||||||
|
module gitlab.hobot.cc/dep/d-cloud/infra/deploy
|
||||||
|
go 1.23.4
|
||||||
280
go/main/main.go
Normal file
280
go/main/main.go
Normal file
@ -0,0 +1,280 @@
|
|||||||
|
// main.go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"log"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// BuildRequest represents a build job in the queue
|
||||||
|
type BuildRequest struct {
|
||||||
|
RepoURL string
|
||||||
|
Branch string
|
||||||
|
}
|
||||||
|
|
||||||
|
// BuildQueue manages the build requests
|
||||||
|
type BuildQueue struct {
|
||||||
|
queue []BuildRequest
|
||||||
|
mu sync.Mutex
|
||||||
|
}
|
||||||
|
|
||||||
|
var buildQueue = &BuildQueue{}
|
||||||
|
|
||||||
|
// Add adds a new build request to the queue
|
||||||
|
func (bq *BuildQueue) Add(req BuildRequest) {
|
||||||
|
bq.mu.Lock()
|
||||||
|
defer bq.mu.Unlock()
|
||||||
|
bq.queue = append(bq.queue, req)
|
||||||
|
go bq.processQueue() // Start processing if not already running
|
||||||
|
}
|
||||||
|
|
||||||
|
// processQueue handles the build requests one at a time
|
||||||
|
func (bq *BuildQueue) processQueue() {
|
||||||
|
bq.mu.Lock()
|
||||||
|
if len(bq.queue) == 0 {
|
||||||
|
bq.mu.Unlock()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the next request
|
||||||
|
req := bq.queue[0]
|
||||||
|
queueLength := len(bq.queue) - 1 // 减去当前正在处理的请求
|
||||||
|
bq.queue = bq.queue[1:]
|
||||||
|
bq.mu.Unlock()
|
||||||
|
|
||||||
|
// 发送准备构建通知
|
||||||
|
webhookURL := "https://open.feishu.cn/open-apis/bot/v2/hook/8648822c-fbf8-45ba-bd4d-907c2abdb885"
|
||||||
|
if err := sendFeishuNotification(webhookURL, &req, "", "prepare", queueLength); err != nil {
|
||||||
|
log.Printf("发送准备构建通知失败: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Process the build request
|
||||||
|
err := processBuild(&req)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Error processing build: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Process next item in queue
|
||||||
|
go bq.processQueue()
|
||||||
|
}
|
||||||
|
|
||||||
|
func processBuild(req *BuildRequest) error {
|
||||||
|
log.Printf("开始处理构建请求 - 仓库: %s, 分支: %s", req.RepoURL, req.Branch)
|
||||||
|
|
||||||
|
// 发送开始构建通知
|
||||||
|
webhookURL := "https://open.feishu.cn/open-apis/bot/v2/hook/8648822c-fbf8-45ba-bd4d-907c2abdb885"
|
||||||
|
if err := sendFeishuNotification(webhookURL, req, "", "start", 0); err != nil {
|
||||||
|
log.Printf("发送开始构建通知失败: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a temporary directory for the build
|
||||||
|
buildDir, err := os.MkdirTemp("", "build-*")
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("创建构建目录失败: %v", err)
|
||||||
|
}
|
||||||
|
log.Printf("创建临时构建目录: %s", buildDir)
|
||||||
|
defer func() {
|
||||||
|
log.Printf("清理临时构建目录: %s", buildDir)
|
||||||
|
os.RemoveAll(buildDir)
|
||||||
|
}()
|
||||||
|
|
||||||
|
// Clone the repository
|
||||||
|
log.Printf("开始克隆仓库...")
|
||||||
|
cloneCmd := exec.Command("git", "clone", "-b", req.Branch, req.RepoURL, buildDir)
|
||||||
|
output, err := cloneCmd.CombinedOutput()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("git clone失败:\n命令输出: %s\n错误: %v", string(output), err)
|
||||||
|
}
|
||||||
|
log.Printf("仓库克隆成功")
|
||||||
|
|
||||||
|
// 获取版本号
|
||||||
|
log.Printf("获取版本号...")
|
||||||
|
cmd := exec.Command("git", "describe", "--tags", "--abbrev=0", "--exact-match", "HEAD")
|
||||||
|
cmd.Dir = buildDir
|
||||||
|
version, err := cmd.Output()
|
||||||
|
if err != nil {
|
||||||
|
// 如果没有tag,则使用commit id
|
||||||
|
cmd = exec.Command("git", "rev-parse", "--short", "HEAD")
|
||||||
|
cmd.Dir = buildDir
|
||||||
|
version, err = cmd.Output()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("获取commit id失败: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
versionStr := strings.TrimSpace(string(version))
|
||||||
|
log.Printf("版本号: %s", versionStr)
|
||||||
|
|
||||||
|
// Run make deploy
|
||||||
|
log.Printf("开始执行make all命令...")
|
||||||
|
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Minute)
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
makeCmd := exec.CommandContext(ctx, "make")
|
||||||
|
makeCmd.Dir = buildDir
|
||||||
|
|
||||||
|
// 直接设置标准输出和错误输出
|
||||||
|
makeCmd.Stdout = os.Stdout
|
||||||
|
makeCmd.Stderr = os.Stderr
|
||||||
|
|
||||||
|
log.Printf("正在启动make 命令...")
|
||||||
|
if err := makeCmd.Start(); err != nil {
|
||||||
|
return fmt.Errorf("启动make命令失败: %v", err)
|
||||||
|
}
|
||||||
|
log.Printf("make all命令已启动,开始执行...")
|
||||||
|
|
||||||
|
// 等待命令完成
|
||||||
|
if err := makeCmd.Wait(); err != nil {
|
||||||
|
if exitErr, ok := err.(*exec.ExitError); ok {
|
||||||
|
return fmt.Errorf("命令执行失败,退出码: %d", exitErr.ExitCode())
|
||||||
|
}
|
||||||
|
return fmt.Errorf("make命令执行失败: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if ctx.Err() == context.DeadlineExceeded {
|
||||||
|
return fmt.Errorf("命令执行超时")
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Printf("cicd执行完成")
|
||||||
|
|
||||||
|
// 发送飞书通知
|
||||||
|
if err := sendFeishuNotification(webhookURL, req, versionStr, "success", 0); err != nil {
|
||||||
|
log.Printf("发送飞书通知失败: %v", err)
|
||||||
|
} else {
|
||||||
|
log.Printf("飞书通知发送成功")
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// FeishuMessage 飞书消息结构
|
||||||
|
type FeishuMessage struct {
|
||||||
|
MsgType string `json:"msg_type"`
|
||||||
|
Content struct {
|
||||||
|
Text string `json:"text"`
|
||||||
|
} `json:"content"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// sendFeishuNotification 发送飞书通知
|
||||||
|
func sendFeishuNotification(webhook string, request *BuildRequest, version string, msgType string, queueLength int) error {
|
||||||
|
var messageText string
|
||||||
|
switch msgType {
|
||||||
|
case "prepare":
|
||||||
|
waitTime := queueLength * 3 // 假设每个构建大约需要3分钟
|
||||||
|
messageText = fmt.Sprintf("⌛ 构建请求已收到\n"+
|
||||||
|
"───────────────\n"+
|
||||||
|
"📦 项目: %s\n"+
|
||||||
|
"🌿 分支: %s\n"+
|
||||||
|
"📊 队列状态: 前面还有 %d 个构建请求\n"+
|
||||||
|
"⏳ 预计等待: 约 %d 分钟\n"+
|
||||||
|
"───────────────\n"+
|
||||||
|
"请耐心等待...",
|
||||||
|
request.RepoURL,
|
||||||
|
request.Branch,
|
||||||
|
queueLength,
|
||||||
|
waitTime)
|
||||||
|
case "start":
|
||||||
|
messageText = fmt.Sprintf("🏗️ 开始构建\n"+
|
||||||
|
"───────────────\n"+
|
||||||
|
"📦 项目: %s\n"+
|
||||||
|
"🌿 分支: %s\n"+
|
||||||
|
"🕐 时间: %s\n"+
|
||||||
|
"───────────────\n"+
|
||||||
|
"构建进行中...",
|
||||||
|
request.RepoURL,
|
||||||
|
request.Branch,
|
||||||
|
time.Now().Format("2006-01-02 15:04:05"))
|
||||||
|
case "success":
|
||||||
|
messageText = fmt.Sprintf("🚀 部署通知\n"+
|
||||||
|
"───────────────\n"+
|
||||||
|
"📦 项目: %s\n"+
|
||||||
|
"🌿 分支: %s\n"+
|
||||||
|
"🏷️ 版本: %s\n"+
|
||||||
|
"✨ 状态: 部署成功\n"+
|
||||||
|
"🕐 时间: %s\n"+
|
||||||
|
"───────────────\n"+
|
||||||
|
"祝您工作愉快!👨💻",
|
||||||
|
request.RepoURL,
|
||||||
|
request.Branch,
|
||||||
|
version,
|
||||||
|
time.Now().Format("2006-01-02 15:04:05"))
|
||||||
|
}
|
||||||
|
|
||||||
|
message := FeishuMessage{
|
||||||
|
MsgType: "text",
|
||||||
|
Content: struct {
|
||||||
|
Text string `json:"text"`
|
||||||
|
}{
|
||||||
|
Text: messageText,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
jsonData, err := json.Marshal(message)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("序列化消息失败: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := http.Post(webhook, "application/json", bytes.NewBuffer(jsonData))
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("发送通知失败: %v", err)
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
if resp.StatusCode != http.StatusOK {
|
||||||
|
body, _ := io.ReadAll(resp.Body)
|
||||||
|
return fmt.Errorf("飞书API返回错误: status=%d, body=%s", resp.StatusCode, string(body))
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func webhookHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
|
if r.Method != http.MethodPost {
|
||||||
|
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var payload struct {
|
||||||
|
Repository struct {
|
||||||
|
GitHTTPURL string `json:"git_http_url"`
|
||||||
|
} `json:"repository"`
|
||||||
|
Ref string `json:"ref"`
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := json.NewDecoder(r.Body).Decode(&payload); err != nil {
|
||||||
|
http.Error(w, "Failed to parse webhook payload", http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extract branch name from ref (refs/heads/master -> master)
|
||||||
|
branch := filepath.Base(payload.Ref)
|
||||||
|
|
||||||
|
// Add build request to queue
|
||||||
|
buildQueue.Add(BuildRequest{
|
||||||
|
RepoURL: payload.Repository.GitHTTPURL,
|
||||||
|
Branch: branch,
|
||||||
|
})
|
||||||
|
|
||||||
|
w.WriteHeader(http.StatusOK)
|
||||||
|
fmt.Fprintf(w, "Build request queued")
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
http.HandleFunc("/webhook", webhookHandler)
|
||||||
|
|
||||||
|
port := "29999"
|
||||||
|
log.Printf("Starting server on port %s", port)
|
||||||
|
if err := http.ListenAndServe(":"+port, nil); err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
k8s/.DS_Store
vendored
Normal file
BIN
k8s/.DS_Store
vendored
Normal file
Binary file not shown.
0
k8s/Yapi/Dockerfile
Normal file
0
k8s/Yapi/Dockerfile
Normal file
23
k8s/busybox.yaml
Normal file
23
k8s/busybox.yaml
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: busy-dep
|
||||||
|
name: busy-dep
|
||||||
|
namespace: wk
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: busy-dep
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: busy-dep
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- image: ccr-29eug8s3-vpc.cnc.bj.baidubce.com/public/busybox
|
||||||
|
name: busybox
|
||||||
|
command: ["/bin/sh","-c","sleep 3600"]
|
||||||
|
nodeSelector:
|
||||||
|
disktype: ssd
|
||||||
36
k8s/cloud-api/deployment.yaml
Normal file
36
k8s/cloud-api/deployment.yaml
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: cloud-ai-project
|
||||||
|
namespace: bj2-vector
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: cloud-ai-project
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: cloud-ai-project
|
||||||
|
spec:
|
||||||
|
hostNetwork: true
|
||||||
|
imagePullSecrets:
|
||||||
|
- name: registry-auth
|
||||||
|
containers:
|
||||||
|
- name: cloud-ai-project
|
||||||
|
image: ccr-29eug8s3-vpc.cnc.bj.baidubce.com/service/cloud_ai_project:v6
|
||||||
|
imagePullPolicy: Always
|
||||||
|
ports:
|
||||||
|
- containerPort: 8006
|
||||||
|
securityContext:
|
||||||
|
runAsUser: 0
|
||||||
|
privileged: true
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
nvidia.com/gpu: 1
|
||||||
|
cpu: "1"
|
||||||
|
memory: "20Gi"
|
||||||
|
limits:
|
||||||
|
nvidia.com/gpu: 1
|
||||||
|
cpu: "1"
|
||||||
|
memory: "30Gi"
|
||||||
20
k8s/cloud-api/ingress.yaml
Normal file
20
k8s/cloud-api/ingress.yaml
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: Ingress
|
||||||
|
metadata:
|
||||||
|
name: cloud-ai-ingress
|
||||||
|
namespace: bj2-vector
|
||||||
|
labels:
|
||||||
|
app: cloud-ai-project
|
||||||
|
spec:
|
||||||
|
ingressClassName: nginx
|
||||||
|
rules:
|
||||||
|
- host: cloud-test.d-robotics.cc
|
||||||
|
http:
|
||||||
|
paths:
|
||||||
|
- path: /vector
|
||||||
|
pathType: ImplementationSpecific
|
||||||
|
backend:
|
||||||
|
service:
|
||||||
|
name: cloud-api-svc
|
||||||
|
port:
|
||||||
|
number: 80
|
||||||
16
k8s/cloud-api/svc.yaml
Normal file
16
k8s/cloud-api/svc.yaml
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: cloud-api-svc
|
||||||
|
namespace: bj2-vector
|
||||||
|
labels:
|
||||||
|
app: cloud-ai-project
|
||||||
|
spec:
|
||||||
|
ports:
|
||||||
|
- name: http
|
||||||
|
port: 80
|
||||||
|
protocol: TCP
|
||||||
|
targetPort: 8006
|
||||||
|
selector:
|
||||||
|
app: cloud-ai-project
|
||||||
|
type: ClusterIP
|
||||||
36
k8s/cvpr/deploy.yaml
Normal file
36
k8s/cvpr/deploy.yaml
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: cvpr-competition-server
|
||||||
|
namespace: bj1-cvpr
|
||||||
|
labels:
|
||||||
|
app: cvpr-competition-server
|
||||||
|
spec:
|
||||||
|
replicas: 2
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: cvpr-competition-server
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: cvpr-competition-server
|
||||||
|
spec:
|
||||||
|
imagePullSecrets:
|
||||||
|
- name: registry-auth
|
||||||
|
containers:
|
||||||
|
- name: cvpr-competition-server
|
||||||
|
image: ccr-29eug8s3-vpc.cnc.bj.baidubce.com/public/cvpr-competition-server:v3
|
||||||
|
ports:
|
||||||
|
- containerPort: 8080
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
cpu: "100m"
|
||||||
|
memory: "128Mi"
|
||||||
|
limits:
|
||||||
|
cpu: "200m"
|
||||||
|
memory: "256Mi"
|
||||||
|
env:
|
||||||
|
- name: DB_HOST
|
||||||
|
value: "mysql-prod.rdsmd4w68w703bh.rds.bj.baidubce.com"
|
||||||
|
restartPolicy: Always
|
||||||
|
|
||||||
18
k8s/cvpr/ingress.yaml
Normal file
18
k8s/cvpr/ingress.yaml
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: Ingress
|
||||||
|
metadata:
|
||||||
|
name: cvpr-competition-ingress
|
||||||
|
namespace: bj1-cvpr
|
||||||
|
spec:
|
||||||
|
ingressClassName: nginx
|
||||||
|
rules:
|
||||||
|
- host: cvpr-competition.d-robotics.cc
|
||||||
|
http:
|
||||||
|
paths:
|
||||||
|
- path: /
|
||||||
|
pathType: Prefix
|
||||||
|
backend:
|
||||||
|
service:
|
||||||
|
name: cvpr-competition-server
|
||||||
|
port:
|
||||||
|
number: 8080
|
||||||
12
k8s/cvpr/service.yaml
Normal file
12
k8s/cvpr/service.yaml
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: cvpr-competition-server
|
||||||
|
namespace: bj1-cvpr
|
||||||
|
spec:
|
||||||
|
selector:
|
||||||
|
app: cvpr-competition-server
|
||||||
|
ports:
|
||||||
|
- protocol: TCP
|
||||||
|
port: 8080
|
||||||
|
targetPort: 8080
|
||||||
18
k8s/ingress.yaml
Normal file
18
k8s/ingress.yaml
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: Ingress
|
||||||
|
metadata:
|
||||||
|
name: nginx-ing
|
||||||
|
namespace: wk
|
||||||
|
spec:
|
||||||
|
ingressClassName: nginx
|
||||||
|
rules:
|
||||||
|
- host: nginx.example.com
|
||||||
|
http:
|
||||||
|
paths:
|
||||||
|
- path: /
|
||||||
|
pathType: Prefix
|
||||||
|
backend:
|
||||||
|
service:
|
||||||
|
name: nginx-svc
|
||||||
|
port:
|
||||||
|
number: 80
|
||||||
7
k8s/ingressClass.yaml
Normal file
7
k8s/ingressClass.yaml
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: IngressClass
|
||||||
|
metadata:
|
||||||
|
name: nginx
|
||||||
|
namespace: wk
|
||||||
|
spec:
|
||||||
|
controller: k8s.io/ingress-nginx
|
||||||
27
k8s/jumpserver/jms-token.yaml
Normal file
27
k8s/jumpserver/jms-token.yaml
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: ServiceAccount
|
||||||
|
metadata:
|
||||||
|
name: d-robotics
|
||||||
|
namespace: kube-system
|
||||||
|
---
|
||||||
|
kind: ClusterRoleBinding
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
metadata:
|
||||||
|
name: d-robotics
|
||||||
|
subjects:
|
||||||
|
- kind: ServiceAccount
|
||||||
|
name: d-robotics
|
||||||
|
namespace: kube-system
|
||||||
|
roleRef:
|
||||||
|
kind: ClusterRole
|
||||||
|
name: cluster-admin
|
||||||
|
apiGroup: rbac.authorization.k8s.io
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Secret
|
||||||
|
metadata:
|
||||||
|
name: d-robotics
|
||||||
|
namespace: kube-system
|
||||||
|
annotations:
|
||||||
|
kubernetes.io/service-account.name: "d-robotics"
|
||||||
|
type: kubernetes.io/service-account-token
|
||||||
41
k8s/jumpserver/tocken-muban.yaml
Normal file
41
k8s/jumpserver/tocken-muban.yaml
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: ServiceAccount
|
||||||
|
metadata:
|
||||||
|
name: jumpserver-admin
|
||||||
|
namespace: test
|
||||||
|
---
|
||||||
|
kind: Role
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
metadata:
|
||||||
|
name: jumpserver-admin-role
|
||||||
|
namespace: test
|
||||||
|
rules:
|
||||||
|
- apiGroups: [""]
|
||||||
|
resources: ["pods", "services", "configmaps", "secrets"]
|
||||||
|
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
|
||||||
|
- apiGroups: ["apps"]
|
||||||
|
resources: ["deployments", "replicasets"]
|
||||||
|
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
|
||||||
|
---
|
||||||
|
kind: RoleBinding
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
metadata:
|
||||||
|
name: jumpserver-admin-rolebinding
|
||||||
|
namespace: test
|
||||||
|
subjects:
|
||||||
|
- kind: ServiceAccount
|
||||||
|
name: jumpserver-admin
|
||||||
|
namespace: test
|
||||||
|
roleRef:
|
||||||
|
kind: Role
|
||||||
|
name: jumpserver-admin-role
|
||||||
|
apiGroup: rbac.authorization.k8s.io
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Secret
|
||||||
|
metadata:
|
||||||
|
name: jumpserver-admin
|
||||||
|
namespace: test
|
||||||
|
annotations:
|
||||||
|
kubernetes.io/service-account.name: "jumpserver-admin"
|
||||||
|
type: kubernetes.io/service-account-token
|
||||||
48
k8s/one-api-deploy.yaml
Normal file
48
k8s/one-api-deploy.yaml
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: one-api-deployment
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: one-api
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: one-api
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: one-api
|
||||||
|
image: "ghcr.io/songquanpeng/one-api:latest"
|
||||||
|
ports:
|
||||||
|
- containerPort: 3000
|
||||||
|
env:
|
||||||
|
- name: SQL_DSN
|
||||||
|
value: "oneapi:9Qr4a4a_bpjTXHmWkD8V@tcp(mysql-prod.rdsmd4w68w703bh.rds.bj.baidubce.com:3306)/oneapi"
|
||||||
|
- name: REDIS_CONN_STRING
|
||||||
|
value: "redis://"
|
||||||
|
- name: SESSION_SECRET
|
||||||
|
value: "3*#>%YLX>@pG"
|
||||||
|
- name: TZ
|
||||||
|
value: "Asia/Shanghai"
|
||||||
|
volumeMounts:
|
||||||
|
- name: oneapi-data
|
||||||
|
mountPath: /data
|
||||||
|
volumes:
|
||||||
|
- name: oneapi-data
|
||||||
|
emptyDir: {}
|
||||||
|
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: one-api-service
|
||||||
|
spec:
|
||||||
|
selector:
|
||||||
|
app: one-api
|
||||||
|
ports:
|
||||||
|
- protocol: TCP
|
||||||
|
port: 80
|
||||||
|
targetPort: 3000
|
||||||
|
type: ClusterIP
|
||||||
22
k8s/one-api.yaml
Normal file
22
k8s/one-api.yaml
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
services:
|
||||||
|
one-api:
|
||||||
|
image: "ghcr.io/songquanpeng/one-api:latest"
|
||||||
|
container_name: ghs-one-api
|
||||||
|
restart: unless-stopped
|
||||||
|
# command: --log-dir /app/logs
|
||||||
|
ports:
|
||||||
|
- "3000:3000"
|
||||||
|
volumes:
|
||||||
|
- ./data/oneapi:/data
|
||||||
|
environment:
|
||||||
|
- SQL_DSN=oneapi:9Qr4a4a_bpjTXHmWkD8V@tcp(mysql-prod.rdsmd4w68w703bh.rds.bj.baidubce.com:3306)/oneapi
|
||||||
|
- REDIS_CONN_STRING=redis://redis
|
||||||
|
- SESSION_SECRET=3*#>%YLX>@pG
|
||||||
|
- TZ=Asia/Shanghai
|
||||||
|
depends_on:
|
||||||
|
- redis
|
||||||
|
healthcheck:
|
||||||
|
test: [ "CMD-SHELL", "wget -q -O - http://localhost:3000/api/status | grep -o '\"success\":\\s*true' | awk -F: '{print $2}'" ]
|
||||||
|
interval: 60s
|
||||||
|
timeout: 10s
|
||||||
|
retries: 3
|
||||||
35
k8s/one-api/deploy.yaml
Normal file
35
k8s/one-api/deploy.yaml
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: one-api-deployment
|
||||||
|
namespace: bj1-dcloud
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: one-api
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: one-api
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: one-api
|
||||||
|
image: ccr-29eug8s3-vpc.cnc.bj.baidubce.com/public/one-api:latest
|
||||||
|
ports:
|
||||||
|
- containerPort: 3000
|
||||||
|
env:
|
||||||
|
- name: SQL_DSN
|
||||||
|
value: "oneapi:9Qr4a4a_bpjTXHmWkD8V@tcp(mysql-prod.rdsmd4w68w703bh.rds.bj.baidubce.com:3306)/oneapi"
|
||||||
|
- name: REDIS_CONN_STRING
|
||||||
|
value: "onr-api://lv8zcY^Xj)96@redis.uqthtfjpcagp.scs.bj.baidubce.com:6379"
|
||||||
|
- name: SESSION_SECRET
|
||||||
|
value: "3*#>%YLX>@pG"
|
||||||
|
- name: TZ
|
||||||
|
value: "Asia/Shanghai"
|
||||||
|
volumeMounts:
|
||||||
|
- name: oneapi-data
|
||||||
|
mountPath: /data
|
||||||
|
volumes:
|
||||||
|
- name: oneapi-data
|
||||||
|
emptyDir: {}
|
||||||
18
k8s/one-api/ingress.yml
Normal file
18
k8s/one-api/ingress.yml
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: Ingress
|
||||||
|
metadata:
|
||||||
|
name: one-api-ingress
|
||||||
|
namespace: bj1-dcloud
|
||||||
|
spec:
|
||||||
|
ingressClassName: nginx
|
||||||
|
rules:
|
||||||
|
- host: llmproxy.d-robotics.cc # 替换为你的域名
|
||||||
|
http:
|
||||||
|
paths:
|
||||||
|
- path: /
|
||||||
|
pathType: Prefix
|
||||||
|
backend:
|
||||||
|
service:
|
||||||
|
name: one-api-service
|
||||||
|
port:
|
||||||
|
number: 80
|
||||||
13
k8s/one-api/svc.yaml
Normal file
13
k8s/one-api/svc.yaml
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: one-api-service
|
||||||
|
namespace: bj1-dcloud
|
||||||
|
spec:
|
||||||
|
selector:
|
||||||
|
app: one-api
|
||||||
|
ports:
|
||||||
|
- protocol: TCP
|
||||||
|
port: 80
|
||||||
|
targetPort: 3000
|
||||||
|
type: ClusterIP
|
||||||
27
k8s/rdk-backend/backend-config.yaml
Normal file
27
k8s/rdk-backend/backend-config.yaml
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: backend-config
|
||||||
|
namespace: bj2-copilot
|
||||||
|
data:
|
||||||
|
.env: |
|
||||||
|
CURRENT_ENV = "测试环境"
|
||||||
|
COPILOT_SERVER_MONITOR_FEISHU_NOTICE_WEBHOOK="https://open.feishu.cn/open-apis/bot/v2/hook/edb14958-6566-41d2-86b6-4981efe06d45"
|
||||||
|
COPILOT_SERVER_MONITOR_FEISHU_NOTICE_COOKIE="QXV0aHpDb250ZXh0=a1a7227498d04ff49920e4a150350f1a; passport_web_did=7176225323518902274"
|
||||||
|
CODE_GEE_X_ENDPOINT = "http://120.48.158.165:8901/v1/chat/completions"
|
||||||
|
CODE_GEE_X_MODEL_NAME = "/codegeex4-all-9b"
|
||||||
|
DB_HOST="mysql1.rdsmbk3ednsgnnt.rds.bj.baidubce.com"
|
||||||
|
DB_PORT="3306"
|
||||||
|
DB_NAME="rdk_copilot_dev"
|
||||||
|
DB_USER="rdk_copilot"
|
||||||
|
DB_PASSWORD="tol_Ck1@3fqa"
|
||||||
|
BAIDU_MOCHOW_ACCOUNT="root"
|
||||||
|
BAIDU_MOCHOW_API_KEY="vdb$t7te2t5nn5n"
|
||||||
|
BAIDU_MOCHOW_ENDPOINT="http://180.76.107.178:5287"
|
||||||
|
BAIDU_QIANFAN_API_KEY = "PO7E1BhAXAJbEYeCCZuYDKHH"
|
||||||
|
BAIDU_QIANFAN_SECRET_KEY = "HFurKwTrUfXvCZZIAG6hnpK4tqBpXlrL"
|
||||||
|
CMS_BASE_URL= http://cloud-test.d-robotics.cc
|
||||||
|
RDK_DOC_BASE_URL="https://developer.d-robotics.cc/"
|
||||||
|
AZURE_OPENAI_API_KEY = "d4fe0f5d07e24f049685decfd98adc98"
|
||||||
|
AZURE_OPENAI_ENDPOINT = "https://embodiedai.openai.azure.com"
|
||||||
|
AZURE_API_VERSION = "2023-12-01-preview"
|
||||||
18
k8s/rdk-backend/backend-ingress.yaml
Normal file
18
k8s/rdk-backend/backend-ingress.yaml
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: Ingress
|
||||||
|
metadata:
|
||||||
|
name: backend-ingress
|
||||||
|
namespace: bj2-copilot
|
||||||
|
spec:
|
||||||
|
ingressClassName: nginx
|
||||||
|
rules:
|
||||||
|
- host: copilotdev.d-robotics.cc
|
||||||
|
http:
|
||||||
|
paths:
|
||||||
|
- path: /llm(/|$)(.*)
|
||||||
|
pathType: ImplementationSpecific
|
||||||
|
backend:
|
||||||
|
service:
|
||||||
|
name: backend-svc
|
||||||
|
port:
|
||||||
|
number: 80
|
||||||
14
k8s/rdk-backend/backend-svc.yaml
Normal file
14
k8s/rdk-backend/backend-svc.yaml
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: backend-svc
|
||||||
|
namespace: bj2-copilot
|
||||||
|
spec:
|
||||||
|
ports:
|
||||||
|
- name: http
|
||||||
|
port: 80
|
||||||
|
protocol: TCP
|
||||||
|
targetPort: 8001
|
||||||
|
selector:
|
||||||
|
app.kubernetes.io/name: rdkcopilot-backend
|
||||||
|
type: ClusterIP
|
||||||
43
k8s/rdk-backend/rdkcopilot-backend.yaml
Normal file
43
k8s/rdk-backend/rdkcopilot-backend.yaml
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: rdkcopilot-backend-dc84951
|
||||||
|
namespace: bj2-copilot
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app.kubernetes.io/name: rdkcopilot-backend
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: rdkcopilot-backend
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: backend
|
||||||
|
image: ccr-29eug8s3-vpc.cnc.bj.baidubce.com/traint_cloud_disk/rdkcopilot-backend:130e6be
|
||||||
|
imagePullPolicy: Always
|
||||||
|
ports:
|
||||||
|
- containerPort: 8001
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
|
cpu: 200m
|
||||||
|
ephemeral-storage: 100Mi
|
||||||
|
memory: 400Mi
|
||||||
|
requests:
|
||||||
|
cpu: 200m
|
||||||
|
ephemeral-storage: 100Mi
|
||||||
|
memory: 400Mi
|
||||||
|
volumeMounts:
|
||||||
|
- mountPath: /data/log
|
||||||
|
name: log-dir
|
||||||
|
- mountPath: /ws/src/.env
|
||||||
|
name: config
|
||||||
|
subPath: .env
|
||||||
|
volumes:
|
||||||
|
- emptyDir: {}
|
||||||
|
name: log-dir
|
||||||
|
- configMap:
|
||||||
|
defaultMode: 420
|
||||||
|
name: backend-config
|
||||||
|
name: config
|
||||||
26
k8s/rdk-monitor/rdk-monitor-deploy.yaml
Normal file
26
k8s/rdk-monitor/rdk-monitor-deploy.yaml
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: rdk-monitor
|
||||||
|
namespace: monitoring
|
||||||
|
labels:
|
||||||
|
app: rdk-monitor
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: rdk-monitor
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: rdk-monitor
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: rdk-monitor-container
|
||||||
|
image: ccr-29eug8s3-vpc.cnc.bj.baidubce.com/public/rdk-moniter:v1
|
||||||
|
args:
|
||||||
|
- "3"
|
||||||
|
- "https://copilot.d-robotics.cc/llm/rdkCopilotApi/v1/monitor/health_check"
|
||||||
|
- "https://open.feishu.cn/open-apis/bot/v2/hook/edb14958-6566-41d2-86b6-4981efe06d45"
|
||||||
|
imagePullPolicy: Always
|
||||||
|
|
||||||
27
k8s/rdk-monitor/rdk-monitor-deploy.yml
Normal file
27
k8s/rdk-monitor/rdk-monitor-deploy.yml
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: rdk-monitor
|
||||||
|
namespace: monitoring
|
||||||
|
labels:
|
||||||
|
app: rdk-monitor
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: rdk-monitor
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: rdk-monitor
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: rdk-monitor-container
|
||||||
|
image: ccr-29eug8s3-vpc.cnc.bj.baidubce.com/service/rdk-moniter:v1
|
||||||
|
args:
|
||||||
|
- "3"
|
||||||
|
- "https://copilot.d-robotics.cc/llm/rdkCopilotApi/v1/monitor/health_check"
|
||||||
|
- "https://open.feishu.cn/open-apis/bot/v2/hook/edb14958-6566-41d2-86b6-4981efe06d45"
|
||||||
|
imagePullPolicy: Always
|
||||||
|
imagePullSecrets:
|
||||||
|
- name: trainer-cloud-disk-secret
|
||||||
25
k8s/rdk-monitor/rdk-monitor-dev-deploy.yaml
Normal file
25
k8s/rdk-monitor/rdk-monitor-dev-deploy.yaml
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: rdk-monitor-dev
|
||||||
|
namespace: monitoring
|
||||||
|
labels:
|
||||||
|
app: rdk-monitor-dev
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: rdk-monitor-dev
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: rdk-monitor-dev
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: rdk-monitor-container-dev
|
||||||
|
image: ccr-29eug8s3-vpc.cnc.bj.baidubce.com/public/rdk-moniter:v1
|
||||||
|
args:
|
||||||
|
- "3"
|
||||||
|
- "https://copilotdev.d-robotics.cc/llm/rdkCopilotApi/v1/monitor/health_check"
|
||||||
|
- "https://open.feishu.cn/open-apis/bot/v2/hook/edb14958-6566-41d2-86b6-4981efe06d45"
|
||||||
|
imagePullPolicy: Always
|
||||||
59
passwd/main/main.go
Normal file
59
passwd/main/main.go
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"math/rand"
|
||||||
|
"os"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// 定义包含大小写字母、数字、特殊符号的字符集
|
||||||
|
const charset = "abcdefghijklmnopqrstuvwxyz" +
|
||||||
|
"ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" +
|
||||||
|
"!@#$%^*()"
|
||||||
|
|
||||||
|
// 生成指定长度的随机字符串
|
||||||
|
func generateRandomString(length int) string {
|
||||||
|
// 初始化随机数种子
|
||||||
|
rand.Seed(time.Now().UnixNano())
|
||||||
|
|
||||||
|
// 用于存储生成的随机字符串
|
||||||
|
b := make([]byte, length)
|
||||||
|
|
||||||
|
// 遍历指定长度,从字符集中随机选取字符添加到结果中
|
||||||
|
for i := range b {
|
||||||
|
b[i] = charset[rand.Intn(len(charset))]
|
||||||
|
}
|
||||||
|
return string(b)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 将内容追加到文件中
|
||||||
|
func appendToFile(filePath string, content string) error {
|
||||||
|
// 以追加和创建文件的模式打开文件
|
||||||
|
file, err := os.OpenFile(filePath, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
// 确保文件在函数结束时关闭
|
||||||
|
defer file.Close()
|
||||||
|
|
||||||
|
// 向文件中写入内容并添加换行符
|
||||||
|
_, err = file.WriteString(content + "\n")
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
// 调用函数生成 32 位的随机密码
|
||||||
|
password := generateRandomString(32)
|
||||||
|
fmt.Println("生成的 32 位密码是:", password)
|
||||||
|
|
||||||
|
// 定义要写入的文件路径
|
||||||
|
filePath := "/Users/d-robotics/dep/passwd/passwd.txt"
|
||||||
|
// 调用函数将密码追加到文件中
|
||||||
|
err := appendToFile(filePath, password)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("写入文件时出错: %v\n", err)
|
||||||
|
} else {
|
||||||
|
fmt.Printf("密码已成功追加到 %s 文件中。\n", filePath)
|
||||||
|
}
|
||||||
|
}
|
||||||
26
passwd/passwd.txt
Normal file
26
passwd/passwd.txt
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
p5}C;(.QJ0LcB*h..}(AU3|-^bd?Y:lR
|
||||||
|
7=x]b*l/gDZUPP7DMf,asz+s6UmA(A.U
|
||||||
|
aFgAv<}=/e8qi]!,Yz}:TjE]K%6qPwLx
|
||||||
|
>viXEJ|W^RzS^Nt+Zle_Z@leTdm?D-sV
|
||||||
|
w5i39_|h4crl]XS]E)RG!h00L|&1>'bi
|
||||||
|
a3Hl(wuEqngwauJY
|
||||||
|
XR8qu9mh^9Leg5iJ
|
||||||
|
|
||||||
|
iLth@y3XR7zryFaSfxLph@Cxp8NEz5eL
|
||||||
|
gr2M#7uP$SoV%sF7*5w8U(A8niEijUrl
|
||||||
|
T^9Muu%(rDQwb(#GIkfJ$s$h#9VrPEw@
|
||||||
|
0Uf9FbijlbmEm3BeuAhfmT$XjsO$KgB8
|
||||||
|
k69ujNYyNRTkGY0w9)81rjRu$1Mfl#W1
|
||||||
|
yvthnfO73sR9!
|
||||||
|
6HSw(cryvI3v$3eICkNpK0dy0)QpWsgZ
|
||||||
|
BpwdZgEU9w)EUCCeEfxDMZpDrLb444)%
|
||||||
|
uRC0EKTFm*4
|
||||||
|
lv8zcY^Xj)96
|
||||||
|
jZ7*HmD8*hkQeYAw!*!xwAFGF@)y5F51
|
||||||
|
aJ3R1$gzSr!^)*kH1G7jhQNk3Ih^4gpn
|
||||||
|
qzRaNjS$WusViUeT2VQaZvE4jPj0u9Pu
|
||||||
|
lrTaejEGXRihN*p@Sf)p06e2XDSexxUP
|
||||||
|
jzNI0bq2Ju%cwZzysbrmV1XEAZ0%))M5
|
||||||
|
dZF7jbXVS3QqDbooxO3uJQKqDRg$FHKL
|
||||||
|
vnCzJ@r09aXQzka4oycH@hi32y#yXC8$
|
||||||
|
u()XONJf2PgyQM
|
||||||
39
passwd/useradd.sh
Normal file
39
passwd/useradd.sh
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
username=$1
|
||||||
|
homedir="/data/"
|
||||||
|
num=1
|
||||||
|
check_command() {
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
let num = $num + 1
|
||||||
|
exit 1 # 退出脚本并返回错误状态
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
mkdir -p $homedir/$usernames
|
||||||
|
check_command
|
||||||
|
chown -R $username:$username $homedir/$username
|
||||||
|
check_command
|
||||||
|
useradd -m -d $homedir/$username -s /bin/bash $username
|
||||||
|
check_command
|
||||||
|
password= $(openssl rand -base64 48 | cut -c1-6)
|
||||||
|
echo "$password" | passwd --stdin $username
|
||||||
|
check_command
|
||||||
|
chown -R $username:$username $homedir/$username
|
||||||
|
check_command
|
||||||
|
usermod -aG docker $username
|
||||||
|
check_command
|
||||||
|
newgrp docker
|
||||||
|
check_command
|
||||||
|
read -p "是否需要sudo权限(y/n):" yn
|
||||||
|
if [ $yn = "是" ]; then
|
||||||
|
usermod -aG sudo $username
|
||||||
|
fi
|
||||||
|
echo "用户创建成功!"
|
||||||
|
echo "================================================================"
|
||||||
|
IP=$(curl ifconfig.me)
|
||||||
|
echo "公网IP:$IP"
|
||||||
|
ip=$(hostname -I)
|
||||||
|
echo "内网IP(默认使用第一个):$ip"
|
||||||
|
echo "用户名:$username"
|
||||||
|
echo "密码:$password"
|
||||||
|
|
||||||
Loading…
x
Reference in New Issue
Block a user