Skip to content

Commit

Permalink
improve preview
Browse files Browse the repository at this point in the history
Signed-off-by: Patrick Zhao <[email protected]>
  • Loading branch information
PetrusZ committed Jan 24, 2025
1 parent e363519 commit 25897a7
Show file tree
Hide file tree
Showing 4 changed files with 221 additions and 67 deletions.
23 changes: 22 additions & 1 deletion pkg/microservice/aslan/core/environment/handler/environment.go
Original file line number Diff line number Diff line change
Expand Up @@ -681,6 +681,21 @@ func AffectedServices(c *gin.Context) {
ctx.Resp, ctx.RespErr = service.GetAffectedServices(projectName, envName, arg, ctx.Logger)
}

// @summary 预览Helm服务环境变量
// @description
// @tags environment
// @accept json
// @produce json
// @Param projectName query string true "项目标识"
// @Param name path string true "环境名称"
// @Param serviceName query string true "服务名称或release名称"
// @Param scene query service.EstimateValuesScene true "使用场景"
// @Param isHelmChartDeploy query bool true "是否是helm实力化部署"
// @Param updateServiceRevision query bool true "是否更新服务配置"
// @Param production query bool true "是否为生产环境"
// @Param body body service.EstimateValuesArg true "body"
// @Success 200 {object} service.GetHelmValuesDifferenceResp
// @router /api/aslan/environment/environments/{name}/estimated-values [post]
func EstimatedValues(c *gin.Context) {
ctx := internalhandler.NewContext(c)
defer func() { internalhandler.JSONResponse(c, ctx) }()
Expand All @@ -704,6 +719,12 @@ func EstimatedValues(c *gin.Context) {
return
}

updateServiceRevision := c.Query("updateServiceRevision")
if updateServiceRevision == "" {
ctx.RespErr = e.ErrInvalidParam.AddDesc("updateServiceRevision can't be empty!")
return
}

arg := new(service.EstimateValuesArg)
if err := c.ShouldBind(arg); err != nil {
ctx.RespErr = e.ErrInvalidParam.AddDesc(err.Error())
Expand All @@ -720,7 +741,7 @@ func EstimatedValues(c *gin.Context) {
}
}

ctx.Resp, ctx.RespErr = service.GeneEstimatedValues(projectName, envName, serviceName, c.Query("scene"), c.Query("format"), arg, isHelmChartDeploy == "true", ctx.Logger)
ctx.Resp, ctx.RespErr = service.GeneEstimatedValues2(projectName, envName, serviceName, service.EstimateValuesScene(c.Query("scene")), arg, updateServiceRevision == "true", production, isHelmChartDeploy == "true", ctx.Logger)
}
func SyncHelmProductRenderset(c *gin.Context) {
ctx, err := internalhandler.NewContextWithAuthorization(c)
Expand Down
234 changes: 185 additions & 49 deletions pkg/microservice/aslan/core/environment/service/environment.go
Original file line number Diff line number Diff line change
Expand Up @@ -1339,12 +1339,12 @@ func genImageFromYaml(c *commonmodels.Container, serviceValuesYaml, defaultValue
return image, nil
}

func prepareEstimateDataForEnvCreation(productName, serviceName string, production bool, isHelmChartDeploy bool, log *zap.SugaredLogger) (*commonmodels.ProductService, *commonmodels.Service, error) {
func prepareEstimateDataForEnvCreation(projectName, serviceName string, production bool, isHelmChartDeploy bool, log *zap.SugaredLogger) (*commonmodels.ProductService, *commonmodels.Service, error) {
if isHelmChartDeploy {
prodSvc := &commonmodels.ProductService{
ServiceName: serviceName,
ReleaseName: serviceName,
ProductName: productName,
ProductName: projectName,
Type: setting.HelmChartDeployType,
Render: &templatemodels.ServiceRender{
ServiceName: serviceName,
Expand All @@ -1358,7 +1358,7 @@ func prepareEstimateDataForEnvCreation(productName, serviceName string, producti
} else {
templateService, err := repository.QueryTemplateService(&commonrepo.ServiceFindOption{
ServiceName: serviceName,
ProductName: productName,
ProductName: projectName,
Type: setting.HelmDeployType,
}, production)
if err != nil {
Expand All @@ -1367,11 +1367,10 @@ func prepareEstimateDataForEnvCreation(productName, serviceName string, producti
}

prodSvc := &commonmodels.ProductService{
ServiceName: serviceName,
ProductName: productName,
Revision: templateService.Revision,
Containers: templateService.Containers,
VariableYaml: templateService.VariableYaml,
ServiceName: serviceName,
ProductName: projectName,
Revision: templateService.Revision,
Containers: templateService.Containers,
Render: &templatemodels.ServiceRender{
ServiceName: serviceName,
OverrideYaml: &templatemodels.CustomYaml{},
Expand All @@ -1383,7 +1382,7 @@ func prepareEstimateDataForEnvCreation(productName, serviceName string, producti
}
}

func prepareEstimateDataForEnvUpdate(productName, envName, serviceOrReleaseName, scene string, production bool, isHelmChartDeploy bool, log *zap.SugaredLogger) (
func prepareEstimateDataForEnvUpdate(productName, envName, serviceOrReleaseName string, scene EstimateValuesScene, production bool, isHelmChartDeploy bool, log *zap.SugaredLogger) (
*commonmodels.ProductService, *commonmodels.Service, *commonmodels.Product, error) {
productInfo, err := commonrepo.NewProductColl().Find(&commonrepo.ProductFindOptions{
Name: productName,
Expand Down Expand Up @@ -1416,7 +1415,7 @@ func prepareEstimateDataForEnvUpdate(productName, envName, serviceOrReleaseName,
} else {
targetSvcTmplRevision := int64(0)
prodSvc = productInfo.GetServiceMap()[serviceOrReleaseName]
if scene == usageScenarioUpdateRenderSet {
if scene == EstimateValuesSceneUpdateService {
if prodSvc == nil {
return nil, nil, nil, fmt.Errorf("can't find service in env: %s, name %s", productInfo.EnvName, serviceOrReleaseName)
}
Expand Down Expand Up @@ -1488,85 +1487,222 @@ func GetAffectedServices(productName, envName string, arg *K8sRendersetArg, log
return ret, nil
}

func GeneEstimatedValues(productName, envName, serviceOrReleaseName, scene, format string, arg *EstimateValuesArg, isHelmChartDeploy bool, log *zap.SugaredLogger) (interface{}, error) {
type EstimateValuesScene string

const (
EstimateValuesSceneCreateEnv EstimateValuesScene = "create_env"
EstimateValuesSceneCreateService EstimateValuesScene = "create_service"
EstimateValuesSceneUpdateService EstimateValuesScene = "update_service"
EstimateValuesSceneGenFlatMap EstimateValuesScene = "gen_flat_map"
)

type GetHelmValuesDifferenceResp struct {
Current string `json:"current"`
Latest string `json:"latest"`
LatestFlatMap map[string]interface{} `json:"latest_flat_map"`
}

func GeneEstimatedValues2(projectName, envName, serviceOrReleaseName string, scene EstimateValuesScene, arg *EstimateValuesArg, updateServiceRevision, isProduction, isHelmChartDeploy bool, log *zap.SugaredLogger) (*GetHelmValuesDifferenceResp, error) {
var (
productSvc *commonmodels.ProductService
tmplSvc *commonmodels.Service
productInfo *commonmodels.Product
err error
prodSvc *commonmodels.ProductService
tmplSvc *commonmodels.Service
prod *commonmodels.Product
err error
)

switch scene {
case usageScenarioCreateEnv:
productInfo = &commonmodels.Product{}
productSvc, tmplSvc, err = prepareEstimateDataForEnvCreation(productName, serviceOrReleaseName, arg.Production, isHelmChartDeploy, log)
case EstimateValuesSceneCreateEnv:
prod = &commonmodels.Product{}
prodSvc, tmplSvc, err = prepareEstimateDataForEnvCreation(projectName, serviceOrReleaseName, arg.Production, isHelmChartDeploy, log)
if err != nil {
return nil, fmt.Errorf("failed to prepare estimate data for env creation, err: %s", err)
}
case EstimateValuesSceneCreateService, EstimateValuesSceneUpdateService, EstimateValuesSceneGenFlatMap:
prodSvc, tmplSvc, prod, err = prepareEstimateDataForEnvUpdate(projectName, envName, serviceOrReleaseName, scene, arg.Production, isHelmChartDeploy, log)
if err != nil {
return nil, fmt.Errorf("failed to prepare estimate data for env update, err: %s", err)
}
default:
productSvc, tmplSvc, productInfo, err = prepareEstimateDataForEnvUpdate(productName, envName, serviceOrReleaseName, scene, arg.Production, isHelmChartDeploy, log)
}

if err != nil {
return nil, fmt.Errorf("failed to prepare estimated value data, err %s", err)
}

targetChart := productSvc.Render

tempArg := &commonservice.HelmSvcRenderArg{OverrideValues: arg.OverrideValues}
if targetChart.OverrideYaml == nil {
targetChart.OverrideYaml = &templatemodels.CustomYaml{}
return nil, fmt.Errorf("invalid scene: %s", scene)
}

currentYaml := ""
latestYaml := ""
if scene == EstimateValuesSceneCreateEnv || scene == EstimateValuesSceneCreateService || scene == EstimateValuesSceneGenFlatMap {
// service already exists in the current environment, create it
currentYaml = ""
} else if scene == EstimateValuesSceneUpdateService {
// service not exists in the current environment, update it
//
// get current values yaml
resp, err := commonservice.GetChartValues(projectName, envName, serviceOrReleaseName, isHelmChartDeploy, isProduction, true)
if err != nil {
err = fmt.Errorf("failed to get the current service[%s] values from project: %s, env: %s", serviceOrReleaseName, projectName, envName)
log.Error(err)
return nil, err
} else {
currentYaml = resp.ValuesYaml
}
}
targetChart.OverrideYaml.YamlContent = arg.OverrideYaml
targetChart.OverrideValues = tempArg.ToOverrideValueString()

mergedValues := ""
// generate the new yaml content
if isHelmChartDeploy {
chartRepo, err := commonrepo.NewHelmRepoColl().Find(&commonrepo.HelmRepoFindOption{RepoName: arg.ChartRepo})
if err != nil {
return nil, fmt.Errorf("failed to query chart-repo info, repoName: %s", arg.ChartRepo)
}

client, err := commonutil.NewHelmClient(chartRepo)
if err != nil {
return nil, fmt.Errorf("failed to new helm client, err %s", err)
}

valuesYaml, err := client.GetChartValues(commonutil.GeneHelmRepo(chartRepo), productName, serviceOrReleaseName, arg.ChartRepo, arg.ChartName, arg.ChartVersion, arg.Production)
latestChartValuesYaml, err := client.GetChartValues(commonutil.GeneHelmRepo(chartRepo), projectName, serviceOrReleaseName, arg.ChartRepo, arg.ChartName, arg.ChartVersion, arg.Production)
if err != nil {
return nil, fmt.Errorf("failed to get chart values, chartRepo: %s, chartName: %s, chartVersion: %s, err %s", arg.ChartRepo, arg.ChartName, arg.ChartVersion, err)
}

tempArg := &commonservice.HelmSvcRenderArg{OverrideValues: arg.OverrideValues}
prodSvc.GetServiceRender().SetOverrideYaml(arg.OverrideYaml)
prodSvc.GetServiceRender().OverrideValues = tempArg.ToOverrideValueString()

helmDeploySvc := helmservice.NewHelmDeployService()
mergedValues, err = helmDeploySvc.GenMergedValues(productSvc, productInfo.DefaultValues, nil)
mergedYaml, err := helmDeploySvc.GenMergedValues(prodSvc, prod.DefaultValues, nil)
if err != nil {
return nil, e.ErrUpdateRenderSet.AddDesc(fmt.Sprintf("failed to merge values, err %s", err))
return nil, fmt.Errorf("failed to merge override values, err: %s", err)
}
mergedValues, err = helmDeploySvc.GeneFullValues(valuesYaml, mergedValues)

latestYaml, err = helmDeploySvc.GeneFullValues(latestChartValuesYaml, mergedYaml)
if err != nil {
return nil, e.ErrUpdateRenderSet.AddDesc(fmt.Sprintf("failed to generate full values, err %s", err))
return nil, fmt.Errorf("failed to generate full values, err: %s", err)
}

currentYaml = strings.TrimSuffix(currentYaml, "\n")
latestYaml = strings.TrimSuffix(latestYaml, "\n")
} else {
tempArg := &commonservice.HelmSvcRenderArg{OverrideValues: arg.OverrideValues}
prodSvc.GetServiceRender().SetOverrideYaml(arg.OverrideYaml)
prodSvc.GetServiceRender().OverrideValues = tempArg.ToOverrideValueString()

helmDeploySvc := helmservice.NewHelmDeployService()
mergedValues, err = helmDeploySvc.GenMergedValues(productSvc, productInfo.DefaultValues, nil)
yamlContent, err := helmDeploySvc.GenMergedValues(prodSvc, prod.DefaultValues, nil)
if err != nil {
return nil, e.ErrUpdateRenderSet.AddDesc(fmt.Sprintf("failed to merge values, err %s", err))
return nil, fmt.Errorf("failed to generate merged values yaml, err: %s", err)
}
mergedValues, err = helmDeploySvc.GeneFullValues(tmplSvc.HelmChart.ValuesYaml, mergedValues)

fullValuesYaml, err := helmDeploySvc.GeneFullValues(tmplSvc.HelmChart.ValuesYaml, yamlContent)
if err != nil {
return nil, e.ErrUpdateRenderSet.AddDesc(fmt.Sprintf("failed to generate full values, err %s", err))
return nil, fmt.Errorf("failed to generate full values yaml, err: %s", err)
}

// re-marshal it into string to make sure indentation is right
tmp := make(map[string]interface{})
if err := yaml.Unmarshal([]byte(fullValuesYaml), &tmp); err != nil {
log.Errorf("failed to unmarshal latest yaml content, err: %s", err)
return nil, err
}
latestYamlBytes, err := yaml.Marshal(tmp)
if err != nil {
log.Errorf("failed to marshal latest yaml content, err: %s", err)
return nil, err
}
latestYaml = string(latestYamlBytes)
}

resp := &GetHelmValuesDifferenceResp{
Current: currentYaml,
Latest: latestYaml,
}

switch format {
case "flatMap":
mapData, err := converter.YamlToFlatMap([]byte(mergedValues))
if scene == EstimateValuesSceneGenFlatMap {
mapData, err := converter.YamlToFlatMap([]byte(latestYaml))
if err != nil {
return nil, e.ErrUpdateRenderSet.AddDesc(fmt.Sprintf("failed to generate flat map , err %s", err))
}
return mapData, nil
default:
return &RawYamlResp{YamlContent: mergedValues}, nil
resp.LatestFlatMap = mapData
}

return resp, nil
}

// func GeneEstimatedValues(productName, envName, serviceOrReleaseName, scene, format string, arg *EstimateValuesArg, isHelmChartDeploy bool, log *zap.SugaredLogger) (interface{}, error) {
// var (
// productSvc *commonmodels.ProductService
// tmplSvc *commonmodels.Service
// productInfo *commonmodels.Product
// err error
// )

// switch scene {
// case usageScenarioCreateEnv:
// productInfo = &commonmodels.Product{}
// productSvc, tmplSvc, err = prepareEstimateDataForEnvCreation(productName, serviceOrReleaseName, arg.Production, isHelmChartDeploy, log)
// default:
// productSvc, tmplSvc, productInfo, err = prepareEstimateDataForEnvUpdate(productName, envName, serviceOrReleaseName, scene, arg.Production, isHelmChartDeploy, log)
// }

// if err != nil {
// return nil, fmt.Errorf("failed to prepare estimated value data, err %s", err)
// }

// targetChart := productSvc.Render

// tempArg := &commonservice.HelmSvcRenderArg{OverrideValues: arg.OverrideValues}
// if targetChart.OverrideYaml == nil {
// targetChart.OverrideYaml = &templatemodels.CustomYaml{}
// }
// targetChart.OverrideYaml.YamlContent = arg.OverrideYaml
// targetChart.OverrideValues = tempArg.ToOverrideValueString()

// mergedValues := ""
// if isHelmChartDeploy {
// chartRepo, err := commonrepo.NewHelmRepoColl().Find(&commonrepo.HelmRepoFindOption{RepoName: arg.ChartRepo})
// if err != nil {
// return nil, fmt.Errorf("failed to query chart-repo info, repoName: %s", arg.ChartRepo)
// }

// client, err := commonutil.NewHelmClient(chartRepo)
// if err != nil {
// return nil, fmt.Errorf("failed to new helm client, err %s", err)
// }

// valuesYaml, err := client.GetChartValues(commonutil.GeneHelmRepo(chartRepo), productName, serviceOrReleaseName, arg.ChartRepo, arg.ChartName, arg.ChartVersion, arg.Production)
// if err != nil {
// return nil, fmt.Errorf("failed to get chart values, chartRepo: %s, chartName: %s, chartVersion: %s, err %s", arg.ChartRepo, arg.ChartName, arg.ChartVersion, err)
// }

// helmDeploySvc := helmservice.NewHelmDeployService()
// mergedValues, err = helmDeploySvc.GenMergedValues(productSvc, productInfo.DefaultValues, nil)
// if err != nil {
// return nil, e.ErrUpdateRenderSet.AddDesc(fmt.Sprintf("failed to merge values, err %s", err))
// }
// mergedValues, err = helmDeploySvc.GeneFullValues(valuesYaml, mergedValues)
// if err != nil {
// return nil, e.ErrUpdateRenderSet.AddDesc(fmt.Sprintf("failed to generate full values, err %s", err))
// }
// } else {
// helmDeploySvc := helmservice.NewHelmDeployService()
// mergedValues, err = helmDeploySvc.GenMergedValues(productSvc, productInfo.DefaultValues, nil)
// if err != nil {
// return nil, e.ErrUpdateRenderSet.AddDesc(fmt.Sprintf("failed to merge values, err %s", err))
// }
// mergedValues, err = helmDeploySvc.GeneFullValues(tmplSvc.HelmChart.ValuesYaml, mergedValues)
// if err != nil {
// return nil, e.ErrUpdateRenderSet.AddDesc(fmt.Sprintf("failed to generate full values, err %s", err))
// }
// }

// switch format {
// case "flatMap":
// mapData, err := converter.YamlToFlatMap([]byte(mergedValues))
// if err != nil {
// return nil, e.ErrUpdateRenderSet.AddDesc(fmt.Sprintf("failed to generate flat map , err %s", err))
// }
// return mapData, nil
// default:
// return &RawYamlResp{YamlContent: mergedValues}, nil
// }
// }

// check if override values or yaml content changes
// return [need-Redeploy] and [need-SaveToDB]
func checkOverrideValuesChange(source *templatemodels.ServiceRender, args *commonservice.HelmSvcRenderArg) (bool, bool) {
Expand Down
20 changes: 7 additions & 13 deletions pkg/microservice/aslan/core/workflow/handler/workflow_v4.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,13 +53,12 @@ type filterDeployServiceVarsQuery struct {
}

type getHelmValuesDifferenceReq struct {
ServiceName string `json:"service_name"`
VariableYaml string `json:"variable_yaml"`
EnvName string `json:"env_name"`
IsProduction bool `json:"production"`
IsHelmChartDeploy bool `json:"is_helm_chart_deploy"`
UpdateServiceRevision bool `json:"update_service_revision"`
ServiceModules []*ModuleAndImage `json:"service_modules"`
ServiceName string `json:"service_name"`
VariableYaml string `json:"variable_yaml"`
EnvName string `json:"env_name"`
IsProduction bool `json:"production"`
IsHelmChartDeploy bool `json:"is_helm_chart_deploy"`
UpdateServiceRevision bool `json:"update_service_revision"`
}

type ModuleAndImage struct {
Expand Down Expand Up @@ -1303,12 +1302,7 @@ func CompareHelmServiceYamlInEnv(c *gin.Context) {
return
}
projectName := c.Query("projectName")

images := make([]string, 0)
for _, imageInfos := range req.ServiceModules {
images = append(images, imageInfos.Image)
}
ctx.Resp, ctx.RespErr = workflow.CompareHelmServiceYamlInEnv(req.ServiceName, req.VariableYaml, req.EnvName, projectName, images, req.IsProduction, req.UpdateServiceRevision, req.IsHelmChartDeploy, ctx.Logger)
ctx.Resp, ctx.RespErr = workflow.CompareHelmServiceYamlInEnv(projectName, req.EnvName, req.ServiceName, req.VariableYaml, req.IsProduction, req.UpdateServiceRevision, req.IsHelmChartDeploy, ctx.Logger)
}

type YamlResponse struct {
Expand Down
Loading

0 comments on commit 25897a7

Please sign in to comment.