Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 46 additions & 26 deletions pkg/microservice/aslan/core/common/service/kube/render.go
Original file line number Diff line number Diff line change
Expand Up @@ -1005,6 +1005,7 @@ func GenerateRenderedYaml(option *GeneSvcYamlOption) (string, int, []*WorkloadRe
latestSvcTemplate.Containers = commonutil.FoldManualModulesInto(latestSvcTemplate.Containers, manualContainers)

mergedContainers := mergeContainers(curContainers, latestSvcTemplate.Containers, svcContainersInProduct, option.Containers)

fullRenderedYaml, workloadResource, err := ReplaceWorkloadImages(fullRenderedYaml, mergedContainers)
if err != nil {
return "", 0, nil, fmt.Errorf("failed to replace workload images: %v", err)
Expand Down Expand Up @@ -1105,6 +1106,14 @@ func RenderServiceYaml(originYaml, productName, serviceName string, svcRender *t

// RenderEnvService renders service with particular revision and service vars in environment
func RenderEnvService(prod *commonmodels.Product, serviceRender *template.ServiceRender, service *commonmodels.ProductService) (yaml string, err error) {
return renderEnvService(prod, serviceRender, service, true)
}

func RenderEnvServiceNotSetImages(prod *commonmodels.Product, serviceRender *template.ServiceRender, service *commonmodels.ProductService) (yaml string, err error) {
return renderEnvService(prod, serviceRender, service, false)
}

func renderEnvService(prod *commonmodels.Product, serviceRender *template.ServiceRender, service *commonmodels.ProductService, setImages bool) (yaml string, err error) {
opt := &commonrepo.ServiceFindOption{
ServiceName: service.ServiceName,
ProductName: service.ProductName,
Expand All @@ -1121,10 +1130,18 @@ func RenderEnvService(prod *commonmodels.Product, serviceRender *template.Servic
if err != nil {
return "", err
}
return RenderEnvServiceWithTempl(prod, serviceRender, service, svcTmpl, cluster.Name)
return renderEnvServiceWithTempl(prod, serviceRender, service, svcTmpl, cluster.Name, setImages)
}

func RenderEnvServiceWithTempl(prod *commonmodels.Product, serviceRender *template.ServiceRender, service *commonmodels.ProductService, svcTmpl *commonmodels.Service, clusterName string) (yaml string, err error) {
return renderEnvServiceWithTempl(prod, serviceRender, service, svcTmpl, clusterName, true)
}

func RenderEnvServiceWithTemplNotSetImages(prod *commonmodels.Product, serviceRender *template.ServiceRender, service *commonmodels.ProductService, svcTmpl *commonmodels.Service, clusterName string) (yaml string, err error) {
return renderEnvServiceWithTempl(prod, serviceRender, service, svcTmpl, clusterName, false)
}

func renderEnvServiceWithTempl(prod *commonmodels.Product, serviceRender *template.ServiceRender, service *commonmodels.ProductService, svcTmpl *commonmodels.Service, clusterName string, setImages bool) (yaml string, err error) {
// Note only the keys in TemplateService.ServiceVar can work
parsedYaml, err := RenderServiceYaml(svcTmpl.Yaml, prod.ProductName, svcTmpl.ServiceName, serviceRender)
if err != nil {
Expand All @@ -1133,33 +1150,36 @@ func RenderEnvServiceWithTempl(prod *commonmodels.Product, serviceRender *templa
}
parsedYaml = ParseSysKeys(prod.Namespace, prod.EnvName, prod.ProductName, service.ServiceName, clusterName, parsedYaml)

// Fold manual modules into service.Containers before substitution.
//
// service.Containers nominally reflects the env's runtime snapshot, but
// callers like buildPreviewCandidateOverrides clone a ProductService and
// only override Revision - Containers still reflect the OLD revision's
// state. When the new revision's YAML carries $<name>-image$ for a
// module that wasn't in the env before, substitution fails without this
// re-merge.
//
// For "true env snapshot" callers (e.g. genuinely rendering what's in
// env), the fold is a no-op when env state is consistent. The only
// observable difference is in the candidate-render path, which is what
// we want.
manualContainers, err := repository.ListManualServiceModules(context.Background(), prod.ProductName, service.ServiceName, prod.Production)
if err != nil {
return "", fmt.Errorf("failed to list manual service modules: %v", err)
}
allContainers := commonutil.FoldManualModulesInto(service.Containers, manualContainers)
if setImages {
// Fold manual modules into service.Containers before substitution.
//
// service.Containers nominally reflects the env's runtime snapshot, but
// callers like buildPreviewCandidateOverrides clone a ProductService and
// only override Revision - Containers still reflect the OLD revision's
// state. When the new revision's YAML carries $<name>-image$ for a
// module that wasn't in the env before, substitution fails without this
// re-merge.
//
// For "true env snapshot" callers (e.g. genuinely rendering what's in
// env), the fold is a no-op when env state is consistent. The only
// observable difference is in the candidate-render path, which is what
// we want.
manualContainers, err := repository.ListManualServiceModules(context.Background(), prod.ProductName, service.ServiceName, prod.Production)
if err != nil {
return "", fmt.Errorf("failed to list manual service modules: %v", err)
}
allContainers := commonutil.FoldManualModulesInto(service.Containers, manualContainers)

parsedYaml, _, err = ReplaceWorkloadImages(parsedYaml, allContainers)
if err != nil {
return "", err
}
parsedYaml, err = ParseModuleImageKeys(parsedYaml, allContainers, false)
if err != nil {
return "", err
parsedYaml, _, err = ReplaceWorkloadImages(parsedYaml, allContainers)
if err != nil {
return "", err
}
parsedYaml, err = ParseModuleImageKeys(parsedYaml, allContainers, false)
if err != nil {
return "", err
}
}

return ApplyReplicaOverrides(parsedYaml, service.WorkLoads)
}

Expand Down
31 changes: 23 additions & 8 deletions pkg/microservice/aslan/core/environment/service/environment.go
Original file line number Diff line number Diff line change
Expand Up @@ -3030,15 +3030,30 @@ func upsertService(env *commonmodels.Product, newService *commonmodels.ProductSe
return nil, nil
}

parsedYaml, err := kube.RenderEnvService(env, newService.GetServiceRender(), newService)
if err != nil {
log.Errorf("Failed to render newService %s, error: %v", newService.ServiceName, err)
errList = multierror.Append(errList, fmt.Errorf("newService template %s error: %v", newService.ServiceName, err))
return nil, errList
}
var err error
var parsedYaml string

if prevSvc != nil {
parsedYaml, err = kube.RenderEnvService(env, newService.GetServiceRender(), newService)
if err != nil {
log.Errorf("Failed to render newService %s, error: %v", newService.ServiceName, err)
errList = multierror.Append(errList, fmt.Errorf("newService template %s error: %v", newService.ServiceName, err))
return nil, errList
}
} else {
// When prevSvc is nil, it means this is a new service.
// So we need to render the service yaml without setting the images.
parsedYaml, err = kube.RenderEnvServiceNotSetImages(env, newService.GetServiceRender(), newService)
if err != nil {
return nil, err
}

fakeTemplateSvc := &commonmodels.Service{
ServiceName: newService.ServiceName,
ProductName: newService.ServiceName,
KubeYamls: util.SplitYaml(parsedYaml),
}

if prevSvc == nil {
fakeTemplateSvc := &commonmodels.Service{ServiceName: newService.ServiceName, ProductName: newService.ServiceName, KubeYamls: util.SplitYaml(parsedYaml)}
commonutil.SetCurrentContainerImages(fakeTemplateSvc)
// Merge instead of overwrite. fakeTemplateSvc.Containers is the
// auto set re-parsed from the just-rendered YAML — authoritative
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,7 @@ func updateK8sProduct(exitedProd *commonmodels.Product, user, requestID string,
log.Errorf("[%s][P:%s] GetProductTemplate error: %v", envName, productName, err)
return e.ErrUpdateEnv.AddDesc(e.FindProductTmplErrMsg)
}

updateProd.Production = exitedProd.Production
updateProd.GlobalVariables = exitedProd.GlobalVariables
updateProd.DefaultValues = exitedProd.DefaultValues
Expand Down
Loading