diff --git a/app.go b/app.go index ea08a21..8c854b9 100644 --- a/app.go +++ b/app.go @@ -120,7 +120,8 @@ func root() *cobra.Command { rootCommand.Flags().BoolVar(&opts.IncludeTripleDash, "include-triple-dash", false, "if enabled, the typical \"---\" YAML separator is included at the beginning of resources sliced") rootCommand.Flags().BoolVar(&opts.PruneOutputDir, "prune", false, "if enabled, the output directory will be pruned before writing the files") rootCommand.Flags().BoolVar(&opts.RemoveFileComments, "remove-comments", false, "if enabled, comments generated by the app are removed from the sliced files (but keep comments from the original file)") - + rootCommand.Flags().StringSliceVar(&opts.IncludedGroups, "include-group", nil, "resource kind to include in the output (singular, case insensitive, glob supported)") + rootCommand.Flags().StringSliceVar(&opts.ExcludedGroups, "exclude-group", nil, "resource kind to exclude in the output (singular, case insensitive, glob supported)") _ = rootCommand.Flags().MarkHidden("debug") return rootCommand } diff --git a/slice/execute.go b/slice/execute.go index 9db2bd0..584c865 100644 --- a/slice/execute.go +++ b/slice/execute.go @@ -10,8 +10,8 @@ import ( ) const ( - folderChmod = 0775 - defaultChmod = 0664 + folderChmod = 0o775 + defaultChmod = 0o664 ) func (s *Split) processSingleFile(file []byte) error { @@ -108,7 +108,6 @@ func (s *Split) scan() error { for { // Grab a single line line, err := scanner.ReadString('\n') - // Find if there's an error if err != nil { // If we reached the end of file, handle up to this point diff --git a/slice/execute_test.go b/slice/execute_test.go index 545de92..cafb6d0 100644 --- a/slice/execute_test.go +++ b/slice/execute_test.go @@ -223,7 +223,7 @@ func TestExecute_writeToFileCases(t *testing.T) { t.Run("truncate existent file", func(tt *testing.T) { preexistent := filepath.Join(tempdir, "test_no_newline.txt") - require.NoError(tt, os.WriteFile(preexistent, []byte("foobarbaz"), 0644)) + require.NoError(tt, os.WriteFile(preexistent, []byte("foobarbaz"), 0o644)) require.NoError(tt, s.writeToFile(preexistent, []byte("test"))) content, err := os.ReadFile(preexistent) @@ -232,12 +232,12 @@ func TestExecute_writeToFileCases(t *testing.T) { }) t.Run("attempt writing to a read only directory", func(tt *testing.T) { - require.NoError(tt, os.MkdirAll(filepath.Join(tempdir, "readonly"), 0444)) + require.NoError(tt, os.MkdirAll(filepath.Join(tempdir, "readonly"), 0o444)) require.Error(tt, s.writeToFile(filepath.Join(tempdir, "readonly", "test.txt"), []byte("test"))) }) t.Run("attempt writing to a read only sub-directory", func(tt *testing.T) { - require.NoError(tt, os.MkdirAll(filepath.Join(tempdir, "readonly_sub"), 0444)) + require.NoError(tt, os.MkdirAll(filepath.Join(tempdir, "readonly_sub"), 0o444)) require.Error(tt, s.writeToFile(filepath.Join(tempdir, "readonly_sub", "readonly", "test.txt"), []byte("test"))) }) } @@ -317,7 +317,7 @@ metadata: tdoutput := t.TempDir() require.NotEqual(t, tdinput, tdoutput, "input and output directories should be different") - err := os.WriteFile(filepath.Join(tdinput, "input.yaml"), []byte(tt.input), 0644) + err := os.WriteFile(filepath.Join(tdinput, "input.yaml"), []byte(tt.input), 0o644) require.NoError(t, err, "error found while writing input file") s, err := New(Options{ diff --git a/slice/kube.go b/slice/kube.go index baebf9d..723a0ee 100644 --- a/slice/kube.go +++ b/slice/kube.go @@ -2,6 +2,7 @@ package slice import ( "sort" + "strings" ) type yamlFile struct { @@ -15,6 +16,16 @@ type kubeObjectMeta struct { Kind string Name string Namespace string + Group string +} + +func (objectMeta *kubeObjectMeta) GetGroupFromAPIVersion() string { + fields := strings.Split(objectMeta.APIVersion, "/") + if len(fields) == 2 { + return strings.ToLower(fields[0]) + } + + return "" } func (k kubeObjectMeta) empty() bool { diff --git a/slice/process.go b/slice/process.go index 6b14f00..5d0db82 100644 --- a/slice/process.go +++ b/slice/process.go @@ -79,6 +79,23 @@ func (s *Split) parseYAMLManifest(contents []byte) (yamlFile, error) { } } + if len(s.opts.IncludedGroups) > 0 || len(s.opts.ExcludedGroups) > 0 { + if k8smeta.APIVersion == "" { + return yamlFile{}, &cantFindFieldErr{fieldName: "apiVersion", fileCount: s.fileCount, meta: k8smeta} + } + + var groups []string + if len(s.opts.IncludedGroups) > 0 { + groups = s.opts.IncludedGroups + } else if len(s.opts.ExcludedGroups) > 0 { + groups = s.opts.ExcludedGroups + } + + if err := checkGroup(k8smeta, groups, len(s.opts.IncludedGroups) > 0); err != nil { + return yamlFile{}, &skipErr{} + } + } + // Trim the file name name := strings.TrimSpace(buf.String()) @@ -151,3 +168,24 @@ func checkKubernetesBasics(manifest map[string]interface{}) kubeObjectMeta { return metadata } + +func checkGroup(objmeta kubeObjectMeta, groupName []string, included bool) error { + + for _, group := range groupName { + if included { + if objmeta.GetGroupFromAPIVersion() == strings.ToLower(group) { + return nil + } + } else { + if objmeta.GetGroupFromAPIVersion() == strings.ToLower(group) { + return &skipErr{} + } + } + } + + if included { + return &skipErr{} + } else { + return nil + } +} diff --git a/slice/split.go b/slice/split.go index 2f74ce3..4569778 100644 --- a/slice/split.go +++ b/slice/split.go @@ -89,4 +89,7 @@ type Options struct { AllowEmptyNames bool AllowEmptyKinds bool + + IncludedGroups []string + ExcludedGroups []string } diff --git a/slice/template/funcs_test.go b/slice/template/funcs_test.go index 417d398..ed6a94d 100644 --- a/slice/template/funcs_test.go +++ b/slice/template/funcs_test.go @@ -275,7 +275,7 @@ func Test_jsonReplace(t *testing.T) { } func Test_env(t *testing.T) { - var letters = []rune("abcdefghijklmnopqrstuvwxyz") + letters := []rune("abcdefghijklmnopqrstuvwxyz") randSeq := func(n int) string { rnd := rand.New(rand.NewSource(time.Now().UnixNano())) @@ -417,7 +417,6 @@ func Test_jsonLowerAndUpper(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - lowered, err := jsonLower(tt.args.val) requireErrorIf(t, tt.wantErr, err) diff --git a/slice/utils.go b/slice/utils.go index f5371c7..739a1a8 100644 --- a/slice/utils.go +++ b/slice/utils.go @@ -56,7 +56,6 @@ func loadfolder(extensions []string, folderPath string, recurse bool) (*bytes.Bu return nil }) - if err != nil { return nil, 0, err } diff --git a/slice/validate.go b/slice/validate.go index cad3c9b..8fdd109 100644 --- a/slice/validate.go +++ b/slice/validate.go @@ -104,6 +104,10 @@ func (s *Split) validateFilters() error { return fmt.Errorf("cannot specify both included and excluded") } + if len(s.opts.ExcludedGroups) > 0 && len(s.opts.IncludedGroups) > 0 { + return fmt.Errorf("cannot specify both included and excluded groups") + } + // Merge all filters into excluded and included. for _, v := range s.opts.IncludedKinds { s.opts.Included = append(s.opts.Included, fmt.Sprintf("%s/*", v))