diff --git a/e2e/commonContext.go b/e2e/commonContext.go index 312dd92cd..fcd05bdda 100644 --- a/e2e/commonContext.go +++ b/e2e/commonContext.go @@ -46,7 +46,9 @@ var ( output, err := Exec("vela system update") gomega.Expect(err).NotTo(gomega.HaveOccurred()) gomega.Expect(output).To(gomega.ContainSubstring("syncing workload definitions from cluster...")) - gomega.Expect(output).To(gomega.ContainSubstring("successfully synced")) + gomega.Expect(output).To(gomega.ContainSubstring("sync")) + gomega.Expect(output).To(gomega.ContainSubstring("successfully")) + gomega.Expect(output).To(gomega.ContainSubstring("remove")) }) }) } diff --git a/pkg/commands/refresh.go b/pkg/commands/refresh.go index a3a6b6a15..4aa3fb77e 100644 --- a/pkg/commands/refresh.go +++ b/pkg/commands/refresh.go @@ -38,22 +38,28 @@ func NewRefreshCommand(c types.Args, ioStreams cmdutil.IOStreams) *cobra.Command func RefreshDefinitions(ctx context.Context, c client.Client, ioStreams cmdutil.IOStreams) error { dir, _ := system.GetCapabilityDir() + syncedTemplates := []types.Capability{} ioStreams.Info("syncing workload definitions from cluster...") templates, err := plugins.GetWorkloadsFromCluster(ctx, types.DefaultOAMNS, c, dir, nil) if err != nil { return err } - ioStreams.Infof("get %d workload definitions from cluster, syncing...", len(templates)) + syncedTemplates = append(syncedTemplates, templates...) + ioStreams.Infof("get %d workload definition(s) from cluster, syncing...", len(templates)) successNum := plugins.SinkTemp2Local(templates, dir) - ioStreams.Infof("%d workload definitions successfully synced\n", successNum) + ioStreams.Infof("sync %d workload definition(s) successfully\n", successNum) ioStreams.Info("syncing trait definitions from cluster...") templates, err = plugins.GetTraitsFromCluster(ctx, types.DefaultOAMNS, c, dir, nil) if err != nil { return err } - ioStreams.Infof("get %d trait definitions from cluster, syncing...", len(templates)) + syncedTemplates = append(syncedTemplates, templates...) + ioStreams.Infof("get %d trait definition(s) from cluster, syncing...", len(templates)) successNum = plugins.SinkTemp2Local(templates, dir) - ioStreams.Infof("%d trait definitions successfully synced\n", successNum) + ioStreams.Infof("sync %d trait definition(s) successfully\n", successNum) + + legacyNum := plugins.RemoveLegacyTemps(syncedTemplates, dir) + ioStreams.Infof("remove %d legacy capability definition(s) successfully\n", legacyNum) return nil } diff --git a/pkg/plugins/local.go b/pkg/plugins/local.go index c5436b890..10c594758 100644 --- a/pkg/plugins/local.go +++ b/pkg/plugins/local.go @@ -139,6 +139,41 @@ func SinkTemp2Local(templates []types.Capability, dir string) int { return success } +// RemoveLegacyTemps will remove capability definitions under `dir` but not included in `retainedTemps`. +func RemoveLegacyTemps(retainedTemps []types.Capability, dir string) int { + success := 0 + retainedFiles := []string{} + subDirs := []string{GetSubDir(dir, types.TypeWorkload), GetSubDir(dir, types.TypeTrait)} + for _, tmp := range retainedTemps { + subDir := GetSubDir(dir, tmp.Type) + tmpFilePath := filepath.Join(subDir, tmp.Name) + retainedFiles = append(retainedFiles, tmpFilePath) + } + + for _, subDir := range subDirs { + if err := filepath.Walk(subDir, func(path string, info os.FileInfo, err error) error { + if info == nil || info.IsDir() { + // omit subDir or subDir not exist + return nil + } + for _, retainedFile := range retainedFiles { + if retainedFile == path { + return nil + } + } + if err := os.Remove(path); err != nil { + fmt.Printf("remove legacy %s err: %v\n", path, err) + return err + } + success++ + return nil + }); err != nil { + continue + } + } + return success +} + func LoadCapabilityFromSyncedCenter(dir string) ([]types.Capability, error) { var tmps []types.Capability files, err := ioutil.ReadDir(dir) diff --git a/pkg/plugins/local_test.go b/pkg/plugins/local_test.go index 4db7fe3cc..0f2fa22f3 100644 --- a/pkg/plugins/local_test.go +++ b/pkg/plugins/local_test.go @@ -9,8 +9,8 @@ import ( "github.com/stretchr/testify/assert" ) -func TestLocalSink(t *testing.T) { - deployment := types.Capability{ +var ( + deployment = types.Capability{ Name: "deployment", Type: types.TypeWorkload, Parameters: []types.Parameter{ @@ -21,7 +21,7 @@ func TestLocalSink(t *testing.T) { }, }, } - statefulset := types.Capability{ + statefulset = types.Capability{ Name: "statefulset", Type: types.TypeWorkload, Parameters: []types.Parameter{ @@ -32,7 +32,7 @@ func TestLocalSink(t *testing.T) { }, }, } - route := types.Capability{ + route = types.Capability{ Name: "route", Type: types.TypeTrait, Parameters: []types.Parameter{ @@ -43,6 +43,9 @@ func TestLocalSink(t *testing.T) { }, }, } +) + +func TestLocalSink(t *testing.T) { cases := map[string]struct { dir string @@ -103,3 +106,43 @@ func testInDir(t *testing.T, casename, dir string, tmps, defexp []types.Capabili assert.Equal(t, defexp, gotDef, casename) } } + +func TestRemoveLegacyTemps(t *testing.T) { + + cases := []struct { + caseName string + newTemps []types.Capability + rmNum int + }{ + { + caseName: "remove all", + newTemps: []types.Capability{}, + rmNum: 3, + }, + { + caseName: "nothing removed", + newTemps: []types.Capability{deployment, statefulset, route}, + rmNum: 0, + }, + { + caseName: "remove part of existings", + newTemps: []types.Capability{statefulset, route}, + rmNum: 1, + }, + } + for _, c := range cases { + runInDirRemoveLegacyTemps(t, c.caseName, c.newTemps, c.rmNum) + } +} + +func runInDirRemoveLegacyTemps(t *testing.T, caseName string, newTemps []types.Capability, rmNum int) { + dir := "vela-test-rm-temps" + err := os.MkdirAll(dir, 0755) + assert.NoError(t, err, caseName) + defer os.RemoveAll(dir) + existingTemps := []types.Capability{deployment, statefulset, route} + number := SinkTemp2Local(existingTemps, dir) + assert.Equal(t, 3, number) + resultRemoveNum := RemoveLegacyTemps(newTemps, dir) + assert.Equal(t, rmNum, resultRemoveNum, caseName) +}