github.com/oam-dev/kubevela@v1.9.11/pkg/appfile/dryrun/diff_test.go (about)

     1  /*
     2  Copyright 2021 The KubeVela Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package dryrun
    18  
    19  import (
    20  	"bytes"
    21  	"context"
    22  	"os"
    23  
    24  	. "github.com/onsi/ginkgo/v2"
    25  	. "github.com/onsi/gomega"
    26  	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
    27  	"k8s.io/apimachinery/pkg/types"
    28  	"sigs.k8s.io/yaml"
    29  
    30  	"github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1"
    31  	"github.com/oam-dev/kubevela/pkg/appfile"
    32  )
    33  
    34  var _ = Describe("Test Live-Diff", func() {
    35  	appMultiChangesYAML := readDataFromFile("./testdata/diff-input-app-multichanges.yaml")
    36  	appNoChangeYAML := readDataFromFile("./testdata/diff-input-app-nochange.yaml")
    37  	appOnlyAddYAML := readDataFromFile("./testdata/diff-input-app-onlyadd.yaml")
    38  	appOnlyModifYAML := readDataFromFile("./testdata/diff-input-app-onlymodif.yaml")
    39  	appOnlyRemoveYAML := readDataFromFile("./testdata/diff-input-app-onlyremove.yaml")
    40  
    41  	appMultiChanges := new(v1beta1.Application)
    42  	appNoChange := new(v1beta1.Application)
    43  	appOnlyAdd := new(v1beta1.Application)
    44  	appOnlyModif := new(v1beta1.Application)
    45  	appOnlyRemove := new(v1beta1.Application)
    46  
    47  	origAppRevYAML := readDataFromFile("./testdata/diff-apprevision.yaml")
    48  	originalAppRev := new(v1beta1.ApplicationRevision)
    49  
    50  	diffAndPrint := func(app *v1beta1.Application) string {
    51  		By("Execute Live-diff")
    52  		diffResult, err := diffOpt.Diff(context.Background(), app, originalAppRev)
    53  		Expect(err).Should(BeNil())
    54  		Expect(diffResult).ShouldNot(BeNil())
    55  
    56  		By("Print diff result into buffer")
    57  		buff := &bytes.Buffer{}
    58  		reportOpt := NewReportDiffOption(10, buff)
    59  		reportOpt.PrintDiffReport(diffResult)
    60  
    61  		return buff.String()
    62  	}
    63  
    64  	BeforeEach(func() {
    65  		By("Prepare AppRevision data")
    66  		Expect(yaml.Unmarshal([]byte(origAppRevYAML), originalAppRev)).Should(Succeed())
    67  	})
    68  
    69  	It("Test app containing multiple changes(add/modify/remove/no)", func() {
    70  		Expect(yaml.Unmarshal([]byte(appMultiChangesYAML), appMultiChanges)).Should(Succeed())
    71  		diffResultStr := diffAndPrint(appMultiChanges)
    72  		Expect(diffResultStr).Should(SatisfyAll(
    73  			ContainSubstring("Application (livediff-demo) has been modified(*)"),
    74  			ContainSubstring("Component (myweb-1) has been modified(*)"),
    75  			ContainSubstring("Component (myweb-1) / Trait (myingress/service) has been modified(*)"),
    76  			ContainSubstring("Component (myweb-1) / Trait (myingress/ingress) has been modified(*)"),
    77  			ContainSubstring("Component (myweb-2) has no change"),
    78  			ContainSubstring("Component (myweb-2) / Trait (myingress/service) has been added(+)"),
    79  			ContainSubstring("Component (myweb-2) / Trait (myingress/ingress) has been added(+)"),
    80  			ContainSubstring("Component (myweb-3) has been added(+)"),
    81  			ContainSubstring("Component (myweb-3) / Trait (myingress/service) has been added(+)"),
    82  			ContainSubstring("Component (myweb-3) / Trait (myingress/ingress) has been added(+)"),
    83  		))
    84  	})
    85  
    86  	It("Test no change", func() {
    87  		Expect(yaml.Unmarshal([]byte(appNoChangeYAML), appNoChange)).Should(Succeed())
    88  		diffResultStr := diffAndPrint(appNoChange)
    89  		Expect(diffResultStr).Should(SatisfyAll(
    90  			ContainSubstring("Application (livediff-demo) has no change"),
    91  			ContainSubstring("Component (myweb-1) has no change"),
    92  			ContainSubstring("Component (myweb-1) / Trait (myingress/service) has no change"),
    93  			ContainSubstring("Component (myweb-1) / Trait (myingress/ingress) has no change"),
    94  			ContainSubstring("Component (myweb-2) has no change"),
    95  		))
    96  		Expect(diffResultStr).ShouldNot(SatisfyAny(
    97  			ContainSubstring("added"),
    98  			ContainSubstring("removed"),
    99  			ContainSubstring("modified"),
   100  		))
   101  	})
   102  
   103  	It("Test only added change", func() {
   104  		Expect(yaml.Unmarshal([]byte(appOnlyAddYAML), appOnlyAdd)).Should(Succeed())
   105  		diffResultStr := diffAndPrint(appOnlyAdd)
   106  		Expect(diffResultStr).Should(SatisfyAll(
   107  			ContainSubstring("Application (livediff-demo) has been modified"),
   108  			ContainSubstring("Component (myweb-1) has no change"),
   109  			ContainSubstring("Component (myweb-1) / Trait (myingress/service) has no change"),
   110  			ContainSubstring("Component (myweb-1) / Trait (myingress/ingress) has no change"),
   111  			ContainSubstring("Component (myweb-2) has no change"),
   112  			ContainSubstring("Component (myweb-2) / Trait (myingress/service) has been added"),
   113  			ContainSubstring("Component (myweb-2) / Trait (myingress/ingress) has been added"),
   114  			ContainSubstring("Component (myweb-3) has been added"),
   115  			ContainSubstring("Component (myweb-3) / Trait (myingress/service) has been added"),
   116  			ContainSubstring("Component (myweb-3) / Trait (myingress/ingress) has been added"),
   117  		))
   118  		Expect(diffResultStr).ShouldNot(SatisfyAny(
   119  			ContainSubstring("removed"),
   120  		))
   121  	})
   122  
   123  	It("Test only modified change", func() {
   124  		Expect(yaml.Unmarshal([]byte(appOnlyModifYAML), appOnlyModif)).Should(Succeed())
   125  		diffResultStr := diffAndPrint(appOnlyModif)
   126  		Expect(diffResultStr).Should(SatisfyAll(
   127  			ContainSubstring("Application (livediff-demo) has been modified"),
   128  			ContainSubstring("Component (myweb-1) has been modified"),
   129  			ContainSubstring("Component (myweb-1) / Trait (myingress/service) has been modified"),
   130  			ContainSubstring("Component (myweb-1) / Trait (myingress/ingress) has been modified"),
   131  			ContainSubstring("Component (myweb-2) has no change"),
   132  		))
   133  		Expect(diffResultStr).ShouldNot(SatisfyAny(
   134  			ContainSubstring("removed"),
   135  			ContainSubstring("added"),
   136  		))
   137  	})
   138  
   139  	It("Test only removed change", func() {
   140  		Expect(yaml.Unmarshal([]byte(appOnlyRemoveYAML), appOnlyRemove)).Should(Succeed())
   141  		diffResultStr := diffAndPrint(appOnlyRemove)
   142  		Expect(diffResultStr).Should(SatisfyAll(
   143  			ContainSubstring("Application (livediff-demo) has been modified"),
   144  			ContainSubstring("Component (myweb-1) has no change"),
   145  			ContainSubstring("Component (myweb-1) / Trait (myingress/service) has no change"),
   146  			ContainSubstring("Component (myweb-1) / Trait (myingress/ingress) has no change"),
   147  			ContainSubstring("Component (myweb-2) has been removed"),
   148  		))
   149  		Expect(diffResultStr).ShouldNot(SatisfyAny(
   150  			ContainSubstring("added"),
   151  		))
   152  	})
   153  
   154  	It("Test renderless diff", func() {
   155  		liveDiffOpt := LiveDiffOption{
   156  			DryRun: NewDryRunOption(k8sClient, cfg, pd, nil, false),
   157  			Parser: appfile.NewApplicationParser(k8sClient, pd),
   158  		}
   159  		applyFile := func(filename string, ns string) {
   160  			bs, err := os.ReadFile("./testdata/" + filename)
   161  			Expect(err).Should(Succeed())
   162  			un := &unstructured.Unstructured{}
   163  			Expect(yaml.Unmarshal(bs, un)).Should(Succeed())
   164  			un.SetNamespace(ns)
   165  			Expect(k8sClient.Create(context.Background(), un)).Should(Succeed())
   166  		}
   167  		ctx := context.Background()
   168  		applyFile("diff-input-app-with-externals.yaml", "default")
   169  		applyFile("diff-apprevision.yaml", "default")
   170  		app := &v1beta1.Application{}
   171  		apprev := &v1beta1.ApplicationRevision{}
   172  		Expect(k8sClient.Get(ctx, types.NamespacedName{Namespace: "default", Name: "livediff-demo"}, app)).Should(Succeed())
   173  		Expect(k8sClient.Get(ctx, types.NamespacedName{Namespace: "default", Name: "livediff-demo-v1"}, apprev)).Should(Succeed())
   174  		reverse := false
   175  		runDiff := func() string {
   176  			a, b := LiveDiffObject{Application: app}, LiveDiffObject{ApplicationRevision: apprev}
   177  			if reverse {
   178  				a, b = b, a
   179  			}
   180  			de, err := liveDiffOpt.RenderlessDiff(ctx, a, b)
   181  			Expect(err).Should(Succeed())
   182  			buff := &bytes.Buffer{}
   183  			reportOpt := NewReportDiffOption(-1, buff)
   184  			reportOpt.PrintDiffReport(de)
   185  			return buff.String()
   186  		}
   187  		Expect(runDiff()).Should(ContainSubstring("\"myworker\" not found"))
   188  		applyFile("td-myingress.yaml", "vela-system")
   189  		applyFile("cd-myworker.yaml", "vela-system")
   190  		applyFile("wd-ref-objects.yaml", "vela-system")
   191  		Expect(runDiff()).Should(ContainSubstring("\"deploy-livediff-demo\" not found"))
   192  		applyFile("external-workflow.yaml", "default")
   193  		Expect(runDiff()).Should(ContainSubstring("topology-local not found"))
   194  		applyFile("external-policy.yaml", "default")
   195  		Expect(runDiff()).Should(ContainSubstring("deployments.apps \"livediff-demo\" not found"))
   196  		applyFile("livediff-demo-deploy.yaml", "default")
   197  		e := runDiff()
   198  		_ = e
   199  		Expect(runDiff()).Should(SatisfyAll(
   200  			ContainSubstring("Application (livediff-demo) has been modified(*)"),
   201  			ContainSubstring("External Policy (topology-local) has been added(+)"),
   202  			ContainSubstring("External Workflow (deploy-livediff-demo) has been added(+)"),
   203  			ContainSubstring("Referred Object (apps/v1 Deployment default/livediff-demo) has been added(+)"),
   204  		))
   205  		reverse = true
   206  		Expect(runDiff()).Should(SatisfyAll(
   207  			ContainSubstring("Application (livediff-demo) has been modified(*)"),
   208  			ContainSubstring("External Policy (topology-local) has been removed(-)"),
   209  			ContainSubstring("External Workflow (deploy-livediff-demo) has been removed(-)"),
   210  			ContainSubstring("Referred Object (apps/v1 Deployment default/livediff-demo) has been removed(-)"),
   211  		))
   212  	})
   213  
   214  })