Skip to content

Commit e398d21

Browse files
authored
support diff helm mainfest by file (#4451)
Signed-off-by: Patrick Zhao <zhaoyu@koderover.com>
1 parent 31cea19 commit e398d21

File tree

2 files changed

+118
-58
lines changed

2 files changed

+118
-58
lines changed

pkg/microservice/aslan/core/common/service/kube/helm.go

Lines changed: 41 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -925,14 +925,19 @@ func batchExecutor(interval time.Duration, serviceList []*ReleaseInstallParam, f
925925
return errList
926926
}
927927

928-
func GetHelmChartManifest(service *commonmodels.Service, valuesYaml, chartName, chartVersion string, production bool, isChartInstantiateDeploy bool, helmClient *helmtool.HelmClient) (string, error) {
928+
type HelmManifestFile struct {
929+
Source string `json:"source"`
930+
Content string `json:"content"`
931+
}
932+
933+
func GetHelmChartManifest(service *commonmodels.Service, valuesYaml, chartName, chartVersion string, production bool, isChartInstantiateDeploy bool, helmClient *helmtool.HelmClient) ([]*HelmManifestFile, error) {
929934
chartPath, err := PreLoadHelmServiceChart(service, production, &chartInstantiateDeploy{
930935
ChartName: chartName,
931936
ChartVersion: chartVersion,
932937
isChartInstantiateDeploy: isChartInstantiateDeploy,
933938
})
934939
if err != nil {
935-
return "", fmt.Errorf("failed to pre load helm service chart, serviceName: %s, chartName: %s, chartVersion: %s, err: %s", service.ServiceName, chartName, chartVersion, err)
940+
return nil, fmt.Errorf("failed to pre load helm service chart, serviceName: %s, chartName: %s, chartVersion: %s, err: %s", service.ServiceName, chartName, chartVersion, err)
936941
}
937942

938943
chartSpec := &helmclient.ChartSpec{
@@ -944,8 +949,40 @@ func GetHelmChartManifest(service *commonmodels.Service, valuesYaml, chartName,
944949

945950
manifestBytes, err := helmClient.TemplateChart(chartSpec, nil)
946951
if err != nil {
947-
return "", fmt.Errorf("failed to template chart %s/%s, chartPath: %s, err: %s", chartName, chartVersion, chartPath, err)
952+
return nil, fmt.Errorf("failed to template chart %s/%s, chartPath: %s, err: %s", chartName, chartVersion, chartPath, err)
953+
}
954+
955+
sourceContentMap := map[string]string{}
956+
manifestFiles := make([]*HelmManifestFile, 0)
957+
manifests := strings.Split(string(manifestBytes), "---")
958+
for _, manifest := range manifests {
959+
manifest = strings.TrimSpace(manifest)
960+
if manifest == "" {
961+
continue
962+
}
963+
964+
sourceStr := strings.Split(manifest, "\n")[0]
965+
if strings.HasPrefix(sourceStr, "# Source: ") {
966+
source := strings.TrimPrefix(sourceStr, "# Source: ")
967+
manifest = strings.TrimPrefix(manifest, sourceStr+"\n")
968+
969+
if sourceContentMap[source] == "" {
970+
sourceContentMap[source] = manifest
971+
972+
manifestFiles = append(manifestFiles, &HelmManifestFile{
973+
Source: source,
974+
})
975+
} else {
976+
sourceContentMap[source] += fmt.Sprintf("\n---\n%s", manifest)
977+
}
978+
} else {
979+
log.Errorf("failed to get source from manifest, sourceStr: %s, manifest: %s", sourceStr, manifest)
980+
}
981+
}
982+
983+
for _, manifestFile := range manifestFiles {
984+
manifestFile.Content = sourceContentMap[manifestFile.Source]
948985
}
949986

950-
return string(manifestBytes), nil
987+
return manifestFiles, nil
951988
}

pkg/microservice/aslan/core/environment/service/environment.go

Lines changed: 77 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -1391,18 +1391,19 @@ func prepareEstimateDataForEnvCreation(projectName, serviceName string, producti
13911391
}
13921392

13931393
func prepareEstimateDataForEnvUpdate(productName, envName, serviceOrReleaseName string, scene EstimateValuesScene, updateServiceRevision, production bool, isHelmChartDeploy bool, log *zap.SugaredLogger) (
1394-
*commonmodels.ProductService, *commonmodels.Service, *commonmodels.Product, error) {
1394+
*commonmodels.ProductService, *commonmodels.Service, *commonmodels.Service, *commonmodels.Product, error) {
13951395
productInfo, err := commonrepo.NewProductColl().Find(&commonrepo.ProductFindOptions{
13961396
Name: productName,
13971397
EnvName: envName,
13981398
Production: util.GetBoolPointer(production),
13991399
})
14001400
if err != nil {
1401-
return nil, nil, nil, fmt.Errorf("failed to query product info, name %s", envName)
1401+
return nil, nil, nil, nil, fmt.Errorf("failed to query product info, name %s", envName)
14021402
}
14031403

14041404
var prodSvc *commonmodels.ProductService
1405-
var templateService *commonmodels.Service
1405+
var currentTmplSvc *commonmodels.Service
1406+
var latestTmplSvc *commonmodels.Service
14061407
if isHelmChartDeploy {
14071408
prodSvc = productInfo.GetChartServiceMap()[serviceOrReleaseName]
14081409
if prodSvc == nil {
@@ -1421,32 +1422,51 @@ func prepareEstimateDataForEnvUpdate(productName, envName, serviceOrReleaseName
14211422
}
14221423
}
14231424
} else {
1424-
targetSvcTmplRevision := int64(0)
14251425
prodSvc = productInfo.GetServiceMap()[serviceOrReleaseName]
1426+
1427+
// get latest template service
1428+
targetSvcTmplRevision := int64(0)
14261429
if scene == EstimateValuesSceneUpdateService && !updateServiceRevision {
14271430
if prodSvc == nil {
1428-
return nil, nil, nil, fmt.Errorf("can't find service in env: %s, name %s", productInfo.EnvName, serviceOrReleaseName)
1431+
return nil, nil, nil, nil, fmt.Errorf("can't find service in env: %s, name %s", productInfo.EnvName, serviceOrReleaseName)
14291432
}
14301433
targetSvcTmplRevision = prodSvc.Revision
14311434
}
14321435

1433-
templateService, err = repository.QueryTemplateService(&commonrepo.ServiceFindOption{
1436+
latestTmplSvc, err = repository.QueryTemplateService(&commonrepo.ServiceFindOption{
14341437
ServiceName: serviceOrReleaseName,
14351438
ProductName: productName,
14361439
Type: setting.HelmDeployType,
14371440
Revision: targetSvcTmplRevision,
14381441
}, production)
14391442
if err != nil {
1440-
log.Errorf("failed to query service, name %s, err %s", serviceOrReleaseName, err)
1441-
return nil, nil, nil, fmt.Errorf("failed to query service, name %s", serviceOrReleaseName)
1443+
err = errors.Wrapf(err, "failed to query service, name %s, revision %d", serviceOrReleaseName, targetSvcTmplRevision)
1444+
log.Error(err)
1445+
return nil, nil, nil, nil, err
1446+
}
1447+
1448+
// get current template service
1449+
currentTmplSvc = latestTmplSvc
1450+
if prodSvc != nil {
1451+
currentTmplSvc, err = repository.QueryTemplateService(&commonrepo.ServiceFindOption{
1452+
ServiceName: serviceOrReleaseName,
1453+
ProductName: productName,
1454+
Type: setting.HelmDeployType,
1455+
Revision: prodSvc.Revision,
1456+
}, production)
1457+
if err != nil {
1458+
err = errors.Wrapf(err, "failed to query service, name %s, revision %d", serviceOrReleaseName, prodSvc.Revision)
1459+
log.Error(err)
1460+
return nil, nil, nil, nil, err
1461+
}
14421462
}
14431463

14441464
if prodSvc == nil {
14451465
prodSvc = &commonmodels.ProductService{
14461466
ServiceName: serviceOrReleaseName,
14471467
ProductName: productName,
1448-
Revision: templateService.Revision,
1449-
Containers: templateService.Containers,
1468+
Revision: latestTmplSvc.Revision,
1469+
Containers: latestTmplSvc.Containers,
14501470
}
14511471
}
14521472

@@ -1457,10 +1477,12 @@ func prepareEstimateDataForEnvUpdate(productName, envName, serviceOrReleaseName
14571477
}
14581478
}
14591479
// prodSvc.Render.ValuesYaml = templateService.HelmChart.ValuesYaml
1460-
prodSvc.Render.ChartVersion = templateService.HelmChart.Version
1480+
prodSvc.Render.ChartVersion = latestTmplSvc.HelmChart.Version
14611481
}
14621482

1463-
return prodSvc, templateService, productInfo, nil
1483+
log.Debugf("current revision: %d, latest revision: %d", currentTmplSvc.Revision, latestTmplSvc.Revision)
1484+
1485+
return prodSvc, currentTmplSvc, latestTmplSvc, productInfo, nil
14641486
}
14651487

14661488
func GetAffectedServices(productName, envName string, arg *K8sRendersetArg, log *zap.SugaredLogger) (map[string][]string, error) {
@@ -1518,29 +1540,32 @@ const (
15181540
)
15191541

15201542
type GetHelmValuesDifferenceResp struct {
1521-
Current string `json:"current"`
1522-
Latest string `json:"latest"`
1523-
LatestFlatMap map[string]interface{} `json:"latest_flat_map"`
1543+
Current string `json:"current"`
1544+
Latest string `json:"latest"`
1545+
LatestFlatMap map[string]interface{} `json:"latest_flat_map"`
1546+
CurrentManifestFiles []*kube.HelmManifestFile `json:"current_manifest_files"`
1547+
LatestManifestFiles []*kube.HelmManifestFile `json:"latest_manifest_files"`
15241548
}
15251549

15261550
func GenEstimatedValues(projectName, envName, serviceOrReleaseName string, scene EstimateValuesScene, contextType EstimateContentType, format EstimateValuesResponseFormat, arg *EstimateValuesArg, updateServiceRevision, isProduction, isHelmChartDeploy bool, valueMergeStrategy config.ValueMergeStrategy, log *zap.SugaredLogger) (*GetHelmValuesDifferenceResp, error) {
15271551
var (
1528-
prodSvc *commonmodels.ProductService
1529-
tmplSvc *commonmodels.Service
1530-
prod *commonmodels.Product
1531-
err error
1552+
prodSvc *commonmodels.ProductService
1553+
currentTmplSvc *commonmodels.Service
1554+
latestTmplSvc *commonmodels.Service
1555+
prod *commonmodels.Product
1556+
err error
15321557
)
15331558

15341559
switch scene {
15351560
case EstimateValuesSceneCreateEnv:
15361561
prod = &commonmodels.Product{}
15371562
prod.DefaultValues = arg.DefaultValues
1538-
prodSvc, tmplSvc, err = prepareEstimateDataForEnvCreation(projectName, serviceOrReleaseName, arg.Production, isHelmChartDeploy, log)
1563+
prodSvc, latestTmplSvc, err = prepareEstimateDataForEnvCreation(projectName, serviceOrReleaseName, arg.Production, isHelmChartDeploy, log)
15391564
if err != nil {
15401565
return nil, fmt.Errorf("failed to prepare estimate data for env creation, err: %s", err)
15411566
}
15421567
case EstimateValuesSceneCreateService, EstimateValuesSceneUpdateService:
1543-
prodSvc, tmplSvc, prod, err = prepareEstimateDataForEnvUpdate(projectName, envName, serviceOrReleaseName, scene, updateServiceRevision, arg.Production, isHelmChartDeploy, log)
1568+
prodSvc, currentTmplSvc, latestTmplSvc, prod, err = prepareEstimateDataForEnvUpdate(projectName, envName, serviceOrReleaseName, scene, updateServiceRevision, arg.Production, isHelmChartDeploy, log)
15441569
if err != nil {
15451570
return nil, fmt.Errorf("failed to prepare estimate data for env update, err: %s", err)
15461571
}
@@ -1563,6 +1588,8 @@ func GenEstimatedValues(projectName, envName, serviceOrReleaseName string, scene
15631588

15641589
currentYaml := ""
15651590
latestYaml := ""
1591+
currentManifestFiles := make([]*kube.HelmManifestFile, 0)
1592+
latestManifestFiles := make([]*kube.HelmManifestFile, 0)
15661593
if scene == EstimateValuesSceneCreateEnv || scene == EstimateValuesSceneCreateService {
15671594
// service already exists in the current environment, create it
15681595
currentYaml = ""
@@ -1596,7 +1623,7 @@ func GenEstimatedValues(projectName, envName, serviceOrReleaseName string, scene
15961623
}
15971624

15981625
if contextType == EstimateContentTypeManifest {
1599-
tmplSvc = kube.GeneFakeInstantiateService(prodSvc.ReleaseName, projectName, render.ChartRepo, render.ChartName, render.ChartVersion)
1626+
latestTmplSvc = kube.GeneFakeInstantiateService(prodSvc.ReleaseName, projectName, render.ChartRepo, render.ChartName, render.ChartVersion)
16001627

16011628
err = kube.DownloadInstantiateChart(projectName, render.ChartRepo, render.ChartName, render.ChartVersion, prodSvc.ReleaseName, arg.Production)
16021629
if err != nil {
@@ -1608,11 +1635,10 @@ func GenEstimatedValues(projectName, envName, serviceOrReleaseName string, scene
16081635
return nil, fmt.Errorf("failed to new helm client, err %s", err)
16091636
}
16101637

1611-
manifest, err := kube.GetHelmChartManifest(tmplSvc, currentYaml, render.ChartName, render.ChartVersion, arg.Production, true, helmClient)
1638+
currentManifestFiles, err = kube.GetHelmChartManifest(latestTmplSvc, currentYaml, render.ChartName, render.ChartVersion, arg.Production, true, helmClient)
16121639
if err != nil {
1613-
return nil, fmt.Errorf("failed to get current helm chart manifest, serviceName: %s, chartName: %s, chartVersion: %s, err: %s", tmplSvc.ServiceName, render.ChartName, render.ChartVersion, err)
1640+
return nil, fmt.Errorf("failed to get current helm chart manifest, serviceName: %s, chartName: %s, chartVersion: %s, err: %s", latestTmplSvc.ServiceName, render.ChartName, render.ChartVersion, err)
16141641
}
1615-
currentYaml = manifest
16161642
}
16171643
} else {
16181644
helmDeploySvc := helmservice.NewHelmDeployService()
@@ -1633,11 +1659,10 @@ func GenEstimatedValues(projectName, envName, serviceOrReleaseName string, scene
16331659
return nil, fmt.Errorf("failed to new helm client, err %s", err)
16341660
}
16351661

1636-
manifest, err := kube.GetHelmChartManifest(tmplSvc, currentYaml, render.ChartName, render.ChartVersion, arg.Production, false, helmClient)
1662+
currentManifestFiles, err = kube.GetHelmChartManifest(currentTmplSvc, currentYaml, render.ChartName, render.ChartVersion, arg.Production, false, helmClient)
16371663
if err != nil {
1638-
return nil, fmt.Errorf("failed to get current helm chart manifest, serviceName: %s, chartName: %s, chartVersion: %s, err: %s", tmplSvc.ServiceName, render.ChartName, render.ChartVersion, err)
1664+
return nil, fmt.Errorf("failed to get current helm chart manifest, serviceName: %s, chartName: %s, chartVersion: %s, err: %s", currentTmplSvc.ServiceName, render.ChartName, render.ChartVersion, err)
16391665
}
1640-
currentYaml = manifest
16411666
}
16421667
}
16431668
}
@@ -1674,7 +1699,7 @@ func GenEstimatedValues(projectName, envName, serviceOrReleaseName string, scene
16741699
}
16751700

16761701
if contextType == EstimateContentTypeManifest {
1677-
tmplSvc = kube.GeneFakeInstantiateService(prodSvc.ReleaseName, projectName, arg.ChartRepo, arg.ChartName, arg.ChartVersion)
1702+
latestTmplSvc = kube.GeneFakeInstantiateService(prodSvc.ReleaseName, projectName, arg.ChartRepo, arg.ChartName, arg.ChartVersion)
16781703

16791704
err = kube.DownloadInstantiateChart(projectName, arg.ChartRepo, arg.ChartName, arg.ChartVersion, prodSvc.ReleaseName, arg.Production)
16801705
if err != nil {
@@ -1686,11 +1711,10 @@ func GenEstimatedValues(projectName, envName, serviceOrReleaseName string, scene
16861711
return nil, fmt.Errorf("failed to new helm client, err %s", err)
16871712
}
16881713

1689-
manifest, err := kube.GetHelmChartManifest(tmplSvc, latestYaml, arg.ChartName, arg.ChartVersion, arg.Production, true, helmClient)
1714+
latestManifestFiles, err = kube.GetHelmChartManifest(latestTmplSvc, latestYaml, arg.ChartName, arg.ChartVersion, arg.Production, true, helmClient)
16901715
if err != nil {
1691-
return nil, fmt.Errorf("failed to get latest helm chart manifest, serviceName: %s, chartName: %s, chartVersion: %s, err: %s", tmplSvc.ServiceName, arg.ChartName, arg.ChartVersion, err)
1716+
return nil, fmt.Errorf("failed to get latest helm chart manifest, serviceName: %s, chartName: %s, chartVersion: %s, err: %s", latestTmplSvc.ServiceName, arg.ChartName, arg.ChartVersion, err)
16921717
}
1693-
latestYaml = manifest
16941718
}
16951719

16961720
currentYaml = strings.TrimSuffix(currentYaml, "\n")
@@ -1726,7 +1750,7 @@ func GenEstimatedValues(projectName, envName, serviceOrReleaseName string, scene
17261750
return nil, fmt.Errorf("failed to generate merged values yaml, err: %s", err)
17271751
}
17281752

1729-
latestYaml, err = helmDeploySvc.GeneFullValues(tmplSvc.HelmChart.ValuesYaml, yamlContent)
1753+
latestYaml, err = helmDeploySvc.GeneFullValues(latestTmplSvc.HelmChart.ValuesYaml, yamlContent)
17301754
if err != nil {
17311755
return nil, fmt.Errorf("failed to generate full values yaml, err: %s", err)
17321756
}
@@ -1738,38 +1762,37 @@ func GenEstimatedValues(projectName, envName, serviceOrReleaseName string, scene
17381762
return nil, fmt.Errorf("failed to new helm client, err %s", err)
17391763
}
17401764

1741-
manifest, err := kube.GetHelmChartManifest(tmplSvc, latestYaml, render.ChartName, render.ChartVersion, arg.Production, false, helmClient)
1765+
latestManifestFiles, err = kube.GetHelmChartManifest(latestTmplSvc, latestYaml, render.ChartName, render.ChartVersion, arg.Production, false, helmClient)
17421766
if err != nil {
1743-
return nil, fmt.Errorf("failed to get latest helm chart manifest, serviceName: %s, chartName: %s, chartVersion: %s, err: %s", tmplSvc.ServiceName, render.ChartName, render.ChartVersion, err)
1767+
return nil, fmt.Errorf("failed to get latest helm chart manifest, serviceName: %s, chartName: %s, chartVersion: %s, err: %s", latestTmplSvc.ServiceName, render.ChartName, render.ChartVersion, err)
17441768
}
1745-
latestYaml = manifest
17461769
}
17471770
}
17481771

17491772
mapData := make(map[string]interface{})
1750-
if contextType == EstimateContentTypeValues {
1751-
// re-marshal it into string to make sure indentation is right
1752-
currentYaml, err = formatYamlIndent(currentYaml, log)
1753-
if err != nil {
1754-
return nil, fmt.Errorf("failed to format yaml content, err: %s", err)
1755-
}
1756-
latestYaml, err = formatYamlIndent(latestYaml, log)
1757-
if err != nil {
1758-
return nil, fmt.Errorf("failed to format yaml content, err: %s", err)
1759-
}
1773+
// re-marshal it into string to make sure indentation is right
1774+
currentYaml, err = formatYamlIndent(currentYaml, log)
1775+
if err != nil {
1776+
return nil, fmt.Errorf("failed to format yaml content, err: %s", err)
1777+
}
1778+
latestYaml, err = formatYamlIndent(latestYaml, log)
1779+
if err != nil {
1780+
return nil, fmt.Errorf("failed to format yaml content, err: %s", err)
1781+
}
17601782

1761-
if format == EstimateValuesResponseFormatFlatMap {
1762-
mapData, err = converter.YamlToFlatMap([]byte(latestYaml))
1763-
if err != nil {
1764-
return nil, e.ErrUpdateRenderSet.AddDesc(fmt.Sprintf("failed to generate flat map , err %s", err))
1765-
}
1783+
if format == EstimateValuesResponseFormatFlatMap {
1784+
mapData, err = converter.YamlToFlatMap([]byte(latestYaml))
1785+
if err != nil {
1786+
return nil, e.ErrUpdateRenderSet.AddDesc(fmt.Sprintf("failed to generate flat map , err %s", err))
17661787
}
17671788
}
17681789

17691790
resp := &GetHelmValuesDifferenceResp{
1770-
Current: currentYaml,
1771-
Latest: latestYaml,
1772-
LatestFlatMap: mapData,
1791+
Current: currentYaml,
1792+
Latest: latestYaml,
1793+
LatestFlatMap: mapData,
1794+
CurrentManifestFiles: currentManifestFiles,
1795+
LatestManifestFiles: latestManifestFiles,
17731796
}
17741797

17751798
return resp, nil

0 commit comments

Comments
 (0)