feat: 构建环境添加 kaniko 字段
This commit is contained in:
parent
3cb8e8be5f
commit
5534401f16
|
@ -18,10 +18,11 @@
|
|||
- [x] 运行流水线 & 构建流水线客户端镜像;
|
||||
- [x] 流水线运行历史展示;
|
||||
- [x] 获取流水线运行日志;
|
||||
- [x] 支持挂载 PVC 以持久化构建数据;
|
||||
- [x] 支持终止执行中的构建任务;
|
||||
- [x] 流水线参数化支持;
|
||||
- [x] 支持克隆流水线;
|
||||
- [ ] 支持挂载多种类型的卷以持久化构建数据;
|
||||
- [ ] 支持 kaniko 构建上传镜像
|
||||
|
||||
## 预览地址
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@ import (
|
|||
"devops-super/api"
|
||||
"devops-super/internal/model/entity"
|
||||
"devops-super/internal/model/mid"
|
||||
"github.com/gogf/gf/v2/container/gmap"
|
||||
"github.com/gogf/gf/v2/encoding/gjson"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
)
|
||||
|
@ -64,7 +65,7 @@ type GetConfigReq struct {
|
|||
|
||||
type GetConfigRes struct {
|
||||
Config *gjson.Json `json:"config"`
|
||||
EnvMap map[int]string `json:"envMap"`
|
||||
EnvMap gmap.IntAnyMap `json:"envMap"`
|
||||
}
|
||||
|
||||
type RunReq struct {
|
||||
|
|
|
@ -2,12 +2,12 @@ package ci_pipeline
|
|||
|
||||
import (
|
||||
"context"
|
||||
"devops-super/api/ci_pipeline/v1"
|
||||
"devops-super/internal/model/do"
|
||||
"devops-super/internal/model/entity"
|
||||
"devops-super/internal/model/mid"
|
||||
"devops-super/internal/service"
|
||||
|
||||
"devops-super/api/ci_pipeline/v1"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
)
|
||||
|
||||
func (c *ControllerV1) GetConfig(ctx context.Context, req *v1.GetConfigReq) (res *v1.GetConfigRes, err error) {
|
||||
|
@ -17,7 +17,6 @@ func (c *ControllerV1) GetConfig(ctx context.Context, req *v1.GetConfigReq) (res
|
|||
entityMap map[int]*entity.CiEnv
|
||||
)
|
||||
res = new(v1.GetConfigRes)
|
||||
res.EnvMap = make(map[int]string, 0)
|
||||
ePipeline, err = service.CiPipeline().Get(ctx, &do.CiPipeline{Id: req.Id})
|
||||
if err != nil {
|
||||
return
|
||||
|
@ -30,7 +29,7 @@ func (c *ControllerV1) GetConfig(ctx context.Context, req *v1.GetConfigReq) (res
|
|||
|
||||
entityMap, err = service.CiEnv().GetEntityMap(ctx, config.GetEnvIds())
|
||||
for id, e := range entityMap {
|
||||
res.EnvMap[id] = e.Name
|
||||
res.EnvMap.Set(id, g.Map{"name": e.Name, "isKaniko": e.IsKaniko})
|
||||
}
|
||||
|
||||
return
|
||||
|
|
|
@ -25,6 +25,7 @@ type CiEnvColumns struct {
|
|||
Image string // 镜像
|
||||
SecretName string // Kubernetes Secret 名称,拉取镜像使用
|
||||
PersistenceConfig string // 持久化配置
|
||||
IsKaniko string // 是否是 kaniko 客户端
|
||||
UpdatedAt string // 更新时间
|
||||
}
|
||||
|
||||
|
@ -35,6 +36,7 @@ var ciEnvColumns = CiEnvColumns{
|
|||
Image: "image",
|
||||
SecretName: "secret_name",
|
||||
PersistenceConfig: "persistence_config",
|
||||
IsKaniko: "is_kaniko",
|
||||
UpdatedAt: "updated_at",
|
||||
}
|
||||
|
||||
|
|
|
@ -77,7 +77,7 @@ func (*sCiEnv) GetEntityMap(ctx context.Context, ids []int) (out map[int]*entity
|
|||
return
|
||||
}
|
||||
var es []*entity.CiEnv
|
||||
if err = dao.CiEnv.Ctx(ctx).WhereIn(cols.Id, ids).Limit(1).Scan(&es); err != nil {
|
||||
if err = dao.CiEnv.Ctx(ctx).WhereIn(cols.Id, ids).Scan(&es); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
|
|
|
@ -4,4 +4,6 @@ image.push:
|
|||
rm -f devops-super-cli && go env -w 'GOPROXY=https://goproxy.cn,direct' && CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o devops-super-cli
|
||||
docker build --platform linux/amd64 -t registry.cn-shenzhen.aliyuncs.com/zze/devops-super-ci-client:$(DATE) .
|
||||
docker push registry.cn-shenzhen.aliyuncs.com/zze/devops-super-ci-client:$(DATE)
|
||||
docker tag registry.cn-shenzhen.aliyuncs.com/zze/devops-super-ci-client:$(DATE) registry.cn-shenzhen.aliyuncs.com/zze/devops-super-ci-client:latest
|
||||
docker push registry.cn-shenzhen.aliyuncs.com/zze/devops-super-ci-client:latest
|
||||
rm -f devops-super-cli
|
|
@ -12,6 +12,7 @@ import (
|
|||
"devops-super/utility/thirdclients/kubernetes"
|
||||
"devops-super/utility/util"
|
||||
"fmt"
|
||||
"github.com/gogf/gf/v2/container/gset"
|
||||
"github.com/gogf/gf/v2/encoding/gjson"
|
||||
"github.com/gogf/gf/v2/errors/gerror"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
|
@ -21,6 +22,7 @@ import (
|
|||
corev1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/watch"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
|
@ -69,6 +71,7 @@ func (s *sCiPipeline) Run(ctx context.Context, id int, params *gjson.Json) (err
|
|||
for _, envItem := range arrangeConfig {
|
||||
envItem.Image = envMap[envItem.Id].Image
|
||||
envItem.SecretName = envMap[envItem.Id].SecretName
|
||||
envItem.IsKaniko = envMap[envItem.Id].IsKaniko
|
||||
|
||||
for _, stageItem := range envItem.Stages {
|
||||
for _, taskItem := range stageItem.Tasks {
|
||||
|
@ -292,9 +295,11 @@ WATCH:
|
|||
// 创建 ci pod
|
||||
func createCiPod(kubeClient *kubernetes.Client, namespace, name string, arrangeConfig mid.CiPipelineConfig, envMap map[int]*entity.CiEnv) error {
|
||||
var (
|
||||
containers []corev1.Container
|
||||
initContainers []corev1.Container
|
||||
volumes []corev1.Volume
|
||||
containers []corev1.Container
|
||||
initContainers []corev1.Container
|
||||
volumes []corev1.Volume
|
||||
imagePullSecretNames = gset.New()
|
||||
imagePullSecrets []corev1.LocalObjectReference
|
||||
)
|
||||
|
||||
var createEnvs = func(envs map[string]string) []corev1.EnvVar {
|
||||
|
@ -306,16 +311,9 @@ func createCiPod(kubeClient *kubernetes.Client, namespace, name string, arrangeC
|
|||
}
|
||||
|
||||
for idx, envItem := range arrangeConfig {
|
||||
stagesJson, err := gjson.EncodeString(envItem.Stages)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
container := corev1.Container{
|
||||
Name: fmt.Sprintf("env-%d", idx),
|
||||
Image: arrangeConfig[0].Image,
|
||||
Env: createEnvs(map[string]string{
|
||||
consts.CI_CLIENT_POD_CONTAINER_STAGES_ENV_NAME: stagesJson,
|
||||
}),
|
||||
Name: fmt.Sprintf("env-%d", idx),
|
||||
Image: envItem.Image,
|
||||
ImagePullPolicy: corev1.PullAlways,
|
||||
VolumeMounts: []corev1.VolumeMount{
|
||||
{
|
||||
|
@ -324,6 +322,17 @@ func createCiPod(kubeClient *kubernetes.Client, namespace, name string, arrangeC
|
|||
},
|
||||
},
|
||||
}
|
||||
if envItem.IsKaniko {
|
||||
container.Args = strings.Split(envItem.Params, " ")
|
||||
} else {
|
||||
stagesJson, err := gjson.EncodeString(envItem.Stages)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
container.Env = createEnvs(map[string]string{
|
||||
consts.CI_CLIENT_POD_CONTAINER_STAGES_ENV_NAME: stagesJson,
|
||||
})
|
||||
}
|
||||
|
||||
// 判断该环境启用了持久化
|
||||
var persistenceConfig mid.CiEnvPersistenceConfig
|
||||
|
@ -369,6 +378,13 @@ func createCiPod(kubeClient *kubernetes.Client, namespace, name string, arrangeC
|
|||
}
|
||||
}
|
||||
|
||||
if !gutil.IsEmpty(envItem.SecretName) {
|
||||
imagePullSecretNames.Add(envItem.SecretName)
|
||||
}
|
||||
}
|
||||
|
||||
for _, imageSecretName := range imagePullSecretNames.Slice() {
|
||||
imagePullSecrets = append(imagePullSecrets, corev1.LocalObjectReference{Name: imageSecretName.(string)})
|
||||
}
|
||||
|
||||
pod := &corev1.Pod{
|
||||
|
@ -377,8 +393,9 @@ func createCiPod(kubeClient *kubernetes.Client, namespace, name string, arrangeC
|
|||
Namespace: namespace,
|
||||
},
|
||||
Spec: corev1.PodSpec{
|
||||
InitContainers: initContainers,
|
||||
Containers: containers,
|
||||
ImagePullSecrets: imagePullSecrets,
|
||||
InitContainers: initContainers,
|
||||
Containers: containers,
|
||||
Volumes: append(volumes, corev1.Volume{
|
||||
Name: consts.CI_CLIENT_POD_WORKSPACE_VOLUME_NAME,
|
||||
VolumeSource: corev1.VolumeSource{
|
||||
|
|
|
@ -101,9 +101,9 @@ WATCH:
|
|||
podInfo = event.Object.(*corev1.Pod)
|
||||
// 如果 Pod 运行失败了,直接输出当前容器的日志然后中断
|
||||
if podInfo.Status.Phase == corev1.PodFailed {
|
||||
if err := wsCtx.tailLog(logIndex); err != nil {
|
||||
return err
|
||||
}
|
||||
//if err := wsCtx.tailLog(logIndex); err != nil {
|
||||
// return err
|
||||
//}
|
||||
break WATCH
|
||||
}
|
||||
for _, status := range append(podInfo.Status.InitContainerStatuses, podInfo.Status.ContainerStatuses...) {
|
||||
|
@ -117,7 +117,7 @@ WATCH:
|
|||
}
|
||||
|
||||
// 最后一个容器日志获取完毕才终止监听
|
||||
if logIndex == len(podInfo.Status.InitContainerStatuses)+len(podInfo.Status.ContainerStatuses)-1 {
|
||||
if logIndex == len(podInfo.Status.InitContainerStatuses)+len(podInfo.Status.ContainerStatuses)-1 && podInfo.Status.Phase != corev1.PodRunning {
|
||||
break WATCH
|
||||
}
|
||||
logIndex++
|
||||
|
|
|
@ -18,5 +18,6 @@ type CiEnv struct {
|
|||
Image interface{} // 镜像
|
||||
SecretName interface{} // Kubernetes Secret 名称,拉取镜像使用
|
||||
PersistenceConfig *gjson.Json // 持久化配置
|
||||
IsKaniko interface{} // 是否是 kaniko 客户端
|
||||
UpdatedAt *gtime.Time // 更新时间
|
||||
}
|
||||
|
|
|
@ -16,5 +16,6 @@ type CiEnv struct {
|
|||
Image string `json:"image" description:"镜像"` // 镜像
|
||||
SecretName string `json:"secretName" description:"Kubernetes Secret 名称,拉取镜像使用"` // Kubernetes Secret 名称,拉取镜像使用
|
||||
PersistenceConfig *gjson.Json `json:"persistenceConfig" description:"持久化配置"` // 持久化配置
|
||||
IsKaniko bool `json:"isKaniko" description:"是否是 kaniko 客户端"` // 是否是 kaniko 客户端
|
||||
UpdatedAt *gtime.Time `json:"updatedAt" description:"更新时间"` // 更新时间
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ type CiEnv struct {
|
|||
Name string `v:"required|max-length:30" json:"name"`
|
||||
Image string `v:"required" json:"image"`
|
||||
SecretName string `json:"secretName"`
|
||||
IsKaniko bool `json:"isKaniko"`
|
||||
PersistenceConfig *gjson.Json `json:"persistenceConfig"`
|
||||
}
|
||||
|
||||
|
|
|
@ -23,6 +23,8 @@ type CiPipelineConfigItem struct {
|
|||
Id int `json:"id" yaml:"id"`
|
||||
Image string `json:"image" yaml:"image"`
|
||||
SecretName string `json:"secretName" yaml:"secretName"`
|
||||
IsKaniko bool `json:"isKaniko" yaml:"isKaniko"`
|
||||
Params string `json:"params" yaml:"params"`
|
||||
Stages []*CiPipelineConfigEnvStageItem `json:"stages" yaml:"stages"`
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue