Skip to content

Commit

Permalink
replace old workflow with v4 in auto create workflow api
Browse files Browse the repository at this point in the history
Signed-off-by: Patrick Zhao <[email protected]>
  • Loading branch information
PetrusZ committed Dec 28, 2023
1 parent 45444d6 commit d69537b
Show file tree
Hide file tree
Showing 3 changed files with 103 additions and 88 deletions.
2 changes: 1 addition & 1 deletion pkg/microservice/aslan/core/workflow/handler/router.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,6 @@ func (*Router) Inject(router *gin.RouterGroup) {
// ---------------------------------------------------------------------------------------
workflow := router.Group("workflow")
{
workflow.POST("/:productName/auto", AutoCreateWorkflow)
workflow.POST("", GetWorkflowProductName, CreateWorkflow)
workflow.PUT("/:workflowName", GetWorkflowProductName, UpdateWorkflow)
workflow.GET("", ListWorkflows)
Expand Down Expand Up @@ -172,6 +171,7 @@ func (*Router) Inject(router *gin.RouterGroup) {
workflowV4.POST("/:name/workflowtask/field", SetWorkflowTasksCustomFields)
workflowV4.GET("/:name/workflowtask/field", GetWorkflowTasksCustomFields)
workflowV4.GET("", ListWorkflowV4)
workflowV4.POST("/:productName/auto", AutoCreateWorkflow)
workflowV4.GET("/trigger", ListWorkflowV4CanTrigger)
workflowV4.POST("/lint", LintWorkflowV4)
workflowV4.POST("/check/:name", CheckWorkflowV4Approval)
Expand Down
5 changes: 2 additions & 3 deletions pkg/microservice/aslan/core/workflow/handler/workflow.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,18 +67,17 @@ func AutoCreateWorkflow(c *gin.Context) {
defer func() { internalhandler.JSONResponse(c, ctx) }()

if err != nil {

ctx.Err = fmt.Errorf("authorization Info Generation failed: err %s", err)
ctx.UnAuthorized = true
return
}

projectKey := c.Param("productName")
log.Debugf("uri: %v", c.Request.URL.RequestURI())

// TODO: Authorization leak
// this API is sometimes used in edit/create workflow scenario, thus giving the edit/create workflow permission
// authorization check
permitted := false
projectKey := c.Param("productName")

if ctx.Resources.IsSystemAdmin {
permitted = true
Expand Down
184 changes: 100 additions & 84 deletions pkg/microservice/aslan/core/workflow/service/workflow/workflow.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"fmt"
"sort"
"sync"
"time"

"github.com/hashicorp/go-multierror"
"go.mongodb.org/mongo-driver/bson/primitive"
Expand Down Expand Up @@ -83,10 +84,10 @@ type TaskInfo struct {
}

type workflowCreateArg struct {
name string
envName string
buildStageEnabled bool
ArtifactStageEnabled bool
name string
envName string
buildStageEnabled bool
dockerRegistryID string
}

type workflowCreateArgs struct {
Expand All @@ -103,27 +104,27 @@ func FindWorkflowRaw(name string, logger *zap.SugaredLogger) (*commonmodels.Work
return workflow, err
}

func (args *workflowCreateArgs) addWorkflowArg(envName string, buildStageEnabled, artifactStageEnabled bool) {
func (args *workflowCreateArgs) addWorkflowArg(envName, dockerRegistryID string, buildStageEnabled bool) {
wName := fmt.Sprintf("%s-workflow-%s", args.productName, envName)
if artifactStageEnabled {
wName = fmt.Sprintf("%s-%s-workflow", args.productName, "ops")
}
// The hosting env workflow name is not bound to the environment
if !artifactStageEnabled && envName == "" {
if envName == "" {
wName = fmt.Sprintf("%s-workflow", args.productName)
}
if !buildStageEnabled {
wName = fmt.Sprintf("%s-%s-workflow", args.productName, "ops")
}
args.argsMap[wName] = &workflowCreateArg{
name: wName,
envName: envName,
buildStageEnabled: buildStageEnabled,
ArtifactStageEnabled: artifactStageEnabled,
name: wName,
envName: envName,
buildStageEnabled: buildStageEnabled,
dockerRegistryID: dockerRegistryID,
}
}

func (args *workflowCreateArgs) initDefaultWorkflows() {
args.addWorkflowArg("dev", true, false)
args.addWorkflowArg("qa", true, false)
args.addWorkflowArg("", false, true)
args.addWorkflowArg("dev", "", true)
args.addWorkflowArg("qa", "", true)
args.addWorkflowArg("", "", false)
}

func (args *workflowCreateArgs) clear() {
Expand All @@ -150,118 +151,133 @@ func AutoCreateWorkflow(productName string, log *zap.SugaredLogger) *EnvStatus {
createArgs.initDefaultWorkflows()

// helm/k8syaml project may have customized products, use the real created products
if productTmpl.IsHelmProduct() || productTmpl.IsK8sYamlProduct() {
if productTmpl.IsHelmProduct() || productTmpl.IsK8sYamlProduct() || productTmpl.IsHostProduct() {
productList, err := commonrepo.NewProductColl().List(&commonrepo.ProductListOptions{
Name: productName,
Production: util.GetBoolPointer(false),
})
if err != nil {
log.Errorf("fialed to list products, projectName %s, err %s", productName, err)
}

createArgs.clear()
for _, product := range productList {
createArgs.addWorkflowArg(product.EnvName, true, false)
createArgs.addWorkflowArg(product.EnvName, product.RegistryID, true)
}
if !productTmpl.IsHostProduct() {
createArgs.addWorkflowArg("", "", false)
}
createArgs.addWorkflowArg("", false, true)
}

// Only one workflow is created in the hosting environment
if productTmpl.ProductFeature != nil && productTmpl.ProductFeature.CreateEnvType == setting.SourceFromExternal {
createArgs.clear()
createArgs.addWorkflowArg("", true, false)
}

workflowSlice := sets.NewString()
workflowSet := sets.NewString()
for workflowName := range createArgs.argsMap {
_, err := FindWorkflow(workflowName, log)
_, err := FindWorkflowV4Raw(workflowName, log)
if err == nil {
workflowSlice.Insert(workflowName)
workflowSet.Insert(workflowName)
}
}

if len(workflowSlice) < len(createArgs.argsMap) {
preSetResps, err := PreSetWorkflow(productName, log)
if len(workflowSet) < len(createArgs.argsMap) {
services, err := commonrepo.NewServiceColl().ListMaxRevisionsForServices(productTmpl.AllTestServiceInfos(), "")
if err != nil {
log.Errorf("ServiceTmpl.ListMaxRevisionsByProject error: %v", err)
errList = multierror.Append(errList, err)
}
buildModules := make([]*commonmodels.BuildModule, 0)
artifactModules := make([]*commonmodels.ArtifactModule, 0)
for _, preSetResp := range preSetResps {
buildModule := &commonmodels.BuildModule{
Target: preSetResp.Target,
BuildModuleVer: setting.Version,
}
buildModules = append(buildModules, buildModule)

artifactModule := &commonmodels.ArtifactModule{
Target: preSetResp.Target,
buildList, err := commonrepo.NewBuildColl().List(&commonrepo.BuildListOption{
ProductName: productName,
})
if err != nil {
log.Errorf("[Build.List] error: %v", err)
errList = multierror.Append(errList, err)
}
buildMap := map[string]*commonmodels.Build{}
for _, build := range buildList {
for _, target := range build.Targets {
buildMap[target.ServiceName] = build
}
artifactModules = append(artifactModules, artifactModule)
}

for workflowName, workflowArg := range createArgs.argsMap {
if workflowSlice.Has(workflowName) {
if workflowSet.Has(workflowName) {
continue
}
if dupWorkflow, err := commonrepo.NewWorkflowColl().Find(workflowName); err == nil {
errList = multierror.Append(errList, fmt.Errorf("workflow [%s] 在项目 [%s] 中已经存在", workflowName, dupWorkflow.ProductTmplName))
if dupWorkflow, err := commonrepo.NewWorkflowV4Coll().Find(workflowName); err == nil {
errList = multierror.Append(errList, fmt.Errorf("workflow [%s] 在项目 [%s] 中已经存在", workflowName, dupWorkflow.Project))
}
workflow := new(commonmodels.Workflow)
workflow.Enabled = true
workflow.ProductTmplName = productName
workflow := new(commonmodels.WorkflowV4)
workflow.Project = productName
workflow.Name = workflowName
workflow.DisplayName = workflowName
workflow.CreateBy = setting.SystemUser
workflow.UpdateBy = setting.SystemUser
workflow.EnvName = workflowArg.envName
workflow.BuildStage = &commonmodels.BuildStage{
Enabled: workflowArg.buildStageEnabled,
Modules: buildModules,
}

//如果是开启artifactStage,则关闭buildStage
if workflowArg.ArtifactStageEnabled {
workflow.ArtifactStage = &commonmodels.ArtifactStage{
Enabled: true,
Modules: artifactModules,
workflow.CreatedBy = setting.SystemUser
workflow.UpdatedBy = setting.SystemUser
workflow.CreateTime = time.Now().Unix()
workflow.UpdateTime = time.Now().Unix()
workflow.ConcurrencyLimit = 1

buildJobName := ""
if workflowArg.buildStageEnabled {
serviceAndBuilds := []*commonmodels.ServiceAndBuild{}
for _, serviceTmpl := range services {
if build, ok := buildMap[serviceTmpl.ServiceName]; ok {
for _, target := range build.Targets {
serviceAndBuild := &commonmodels.ServiceAndBuild{
ServiceName: target.ServiceName,
ServiceModule: target.ServiceModule,
BuildName: build.Name,
}
serviceAndBuilds = append(serviceAndBuilds, serviceAndBuild)
}
}
}
buildJobName = "构建"
buildJob := &commonmodels.Job{
Name: buildJobName,
JobType: config.JobZadigBuild,
Spec: &commonmodels.ZadigBuildJobSpec{
DockerRegistryID: workflowArg.dockerRegistryID,
ServiceAndBuilds: serviceAndBuilds,
},
}
stage := &commonmodels.WorkflowStage{
Name: "构建",
Jobs: []*commonmodels.Job{buildJob},
}
workflow.Stages = append(workflow.Stages, stage)
}

workflow.Schedules = &commonmodels.ScheduleCtrl{
Enabled: false,
Items: []*commonmodels.Schedule{},
}
workflow.TestStage = &commonmodels.TestStage{
Enabled: false,
TestNames: []string{},
spec := &commonmodels.ZadigDeployJobSpec{
Env: workflowArg.envName,
DeployContents: []config.DeployContent{
config.DeployImage,
},
Source: config.SourceRuntime,
Production: true,
}
workflow.NotifyCtl = &commonmodels.NotifyCtl{
Enabled: false,
NotifyTypes: []string{},
WeChatWebHook: "",
if workflowArg.buildStageEnabled {
spec.Source = config.SourceFromJob
spec.JobName = buildJobName
spec.Production = false
}
workflow.HookCtl = &commonmodels.WorkflowHookCtrl{
Enabled: false,
Items: []*commonmodels.WorkflowHook{},
deployJob := &commonmodels.Job{
Name: "部署",
JobType: config.JobZadigDeploy,
Spec: spec,
}
workflow.DistributeStage = &commonmodels.DistributeStage{
Enabled: false,
S3StorageID: "",
ImageRepo: "",
JumpBoxHost: "",
Releases: []commonmodels.RepoImage{},
Distributes: []*commonmodels.ProductDistribute{},
stage := &commonmodels.WorkflowStage{
Name: "部署",
Jobs: []*commonmodels.Job{deployJob},
}
workflow.Stages = append(workflow.Stages, stage)

if err := commonrepo.NewWorkflowColl().Create(workflow); err != nil {
if _, err := commonrepo.NewWorkflowV4Coll().Create(workflow); err != nil {
errList = multierror.Append(errList, err)
}
}
if err = errList.ErrorOrNil(); err != nil {
return &EnvStatus{Status: setting.ProductStatusFailed, ErrMessage: err.Error()}
}
return &EnvStatus{Status: setting.ProductStatusCreating}
} else if len(workflowSlice) == len(createArgs.argsMap) {
} else if len(workflowSet) == len(createArgs.argsMap) {
return &EnvStatus{Status: setting.ProductStatusSuccess}
}
return nil
Expand Down

0 comments on commit d69537b

Please sign in to comment.