Change kubectl diff to exclude managedFields by default
Changes kubectl diff to exclude managedFields by default. Adds a new --show-managed-fields flag that allows you to include managed fields in the diff.
This commit is contained in:
		@@ -103,9 +103,10 @@ func diffError(err error) exec.ExitError {
 | 
				
			|||||||
type DiffOptions struct {
 | 
					type DiffOptions struct {
 | 
				
			||||||
	FilenameOptions resource.FilenameOptions
 | 
						FilenameOptions resource.FilenameOptions
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ServerSideApply bool
 | 
						ServerSideApply   bool
 | 
				
			||||||
	FieldManager    string
 | 
						FieldManager      string
 | 
				
			||||||
	ForceConflicts  bool
 | 
						ForceConflicts    bool
 | 
				
			||||||
 | 
						ShowManagedFields bool
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	Selector         string
 | 
						Selector         string
 | 
				
			||||||
	OpenAPISchema    openapi.Resources
 | 
						OpenAPISchema    openapi.Resources
 | 
				
			||||||
@@ -164,6 +165,7 @@ func NewCmdDiff(f cmdutil.Factory, streams genericclioptions.IOStreams) *cobra.C
 | 
				
			|||||||
	usage := "contains the configuration to diff"
 | 
						usage := "contains the configuration to diff"
 | 
				
			||||||
	cmd.Flags().StringArray("prune-allowlist", []string{}, "Overwrite the default whitelist with <group/version/kind> for --prune")
 | 
						cmd.Flags().StringArray("prune-allowlist", []string{}, "Overwrite the default whitelist with <group/version/kind> for --prune")
 | 
				
			||||||
	cmd.Flags().Bool("prune", false, "Include resources that would be deleted by pruning. Can be used with -l and default shows all resources would be pruned")
 | 
						cmd.Flags().Bool("prune", false, "Include resources that would be deleted by pruning. Can be used with -l and default shows all resources would be pruned")
 | 
				
			||||||
 | 
						cmd.Flags().BoolVar(&options.ShowManagedFields, "show-managed-fields", options.ShowManagedFields, "If true, include managed fields in the diff.")
 | 
				
			||||||
	cmdutil.AddFilenameOptionFlags(cmd, &options.FilenameOptions, usage)
 | 
						cmdutil.AddFilenameOptionFlags(cmd, &options.FilenameOptions, usage)
 | 
				
			||||||
	cmdutil.AddServerSideApplyFlags(cmd)
 | 
						cmdutil.AddServerSideApplyFlags(cmd)
 | 
				
			||||||
	cmdutil.AddFieldManagerFlagVar(cmd, &options.FieldManager, apply.FieldManagerClientSideApply)
 | 
						cmdutil.AddFieldManagerFlagVar(cmd, &options.FieldManager, apply.FieldManagerClientSideApply)
 | 
				
			||||||
@@ -555,7 +557,7 @@ func NewDiffer(from, to string) (*Differ, error) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Diff diffs to versions of a specific object, and print both versions to directories.
 | 
					// Diff diffs to versions of a specific object, and print both versions to directories.
 | 
				
			||||||
func (d *Differ) Diff(obj Object, printer Printer) error {
 | 
					func (d *Differ) Diff(obj Object, printer Printer, showManagedFields bool) error {
 | 
				
			||||||
	from, err := d.From.getObject(obj)
 | 
						from, err := d.From.getObject(obj)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
@@ -565,6 +567,11 @@ func (d *Differ) Diff(obj Object, printer Printer) error {
 | 
				
			|||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if !showManagedFields {
 | 
				
			||||||
 | 
							from = omitManagedFields(from)
 | 
				
			||||||
 | 
							to = omitManagedFields(to)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Mask secret values if object is V1Secret
 | 
						// Mask secret values if object is V1Secret
 | 
				
			||||||
	if gvk := to.GetObjectKind().GroupVersionKind(); gvk.Version == "v1" && gvk.Kind == "Secret" {
 | 
						if gvk := to.GetObjectKind().GroupVersionKind(); gvk.Version == "v1" && gvk.Kind == "Secret" {
 | 
				
			||||||
		m, err := NewMasker(from, to)
 | 
							m, err := NewMasker(from, to)
 | 
				
			||||||
@@ -583,6 +590,16 @@ func (d *Differ) Diff(obj Object, printer Printer) error {
 | 
				
			|||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func omitManagedFields(o runtime.Object) runtime.Object {
 | 
				
			||||||
 | 
						a, err := meta.Accessor(o)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							// The object is not a `metav1.Object`, ignore it.
 | 
				
			||||||
 | 
							return o
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						a.SetManagedFields(nil)
 | 
				
			||||||
 | 
						return o
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Run runs the diff program against both directories.
 | 
					// Run runs the diff program against both directories.
 | 
				
			||||||
func (d *Differ) Run(diff *DiffProgram) error {
 | 
					func (d *Differ) Run(diff *DiffProgram) error {
 | 
				
			||||||
	return diff.Run(d.From.Dir.Name, d.To.Dir.Name)
 | 
						return diff.Run(d.From.Dir.Name, d.To.Dir.Name)
 | 
				
			||||||
@@ -653,7 +670,7 @@ func (o *DiffOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []str
 | 
				
			|||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// RunDiff uses the factory to parse file arguments, find the version to
 | 
					// Run uses the factory to parse file arguments, find the version to
 | 
				
			||||||
// diff, and find each Info object for each files, and runs against the
 | 
					// diff, and find each Info object for each files, and runs against the
 | 
				
			||||||
// differ.
 | 
					// differ.
 | 
				
			||||||
func (o *DiffOptions) Run() error {
 | 
					func (o *DiffOptions) Run() error {
 | 
				
			||||||
@@ -718,7 +735,7 @@ func (o *DiffOptions) Run() error {
 | 
				
			|||||||
				o.pruner.MarkVisited(info)
 | 
									o.pruner.MarkVisited(info)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			err = differ.Diff(obj, printer)
 | 
								err = differ.Diff(obj, printer, o.ShowManagedFields)
 | 
				
			||||||
			if !isConflict(err) {
 | 
								if !isConflict(err) {
 | 
				
			||||||
				break
 | 
									break
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -18,6 +18,7 @@ package diff
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"bytes"
 | 
						"bytes"
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
	"io/ioutil"
 | 
						"io/ioutil"
 | 
				
			||||||
	"os"
 | 
						"os"
 | 
				
			||||||
	"path"
 | 
						"path"
 | 
				
			||||||
@@ -200,7 +201,7 @@ func TestDiffer(t *testing.T) {
 | 
				
			|||||||
		live:   map[string]interface{}{"live": true},
 | 
							live:   map[string]interface{}{"live": true},
 | 
				
			||||||
		merged: map[string]interface{}{"merged": true},
 | 
							merged: map[string]interface{}{"merged": true},
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	err = diff.Diff(&obj, Printer{})
 | 
						err = diff.Diff(&obj, Printer{}, true)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		t.Fatal(err)
 | 
							t.Fatal(err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -223,6 +224,85 @@ func TestDiffer(t *testing.T) {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestShowManagedFields(t *testing.T) {
 | 
				
			||||||
 | 
						diff, err := NewDiffer("LIVE", "MERGED")
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							t.Fatal(err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						defer diff.TearDown()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						testCases := []struct {
 | 
				
			||||||
 | 
							name                string
 | 
				
			||||||
 | 
							showManagedFields   bool
 | 
				
			||||||
 | 
							expectedFromContent string
 | 
				
			||||||
 | 
							expectedToContent   string
 | 
				
			||||||
 | 
						}{
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								name:              "without managed fields",
 | 
				
			||||||
 | 
								showManagedFields: false,
 | 
				
			||||||
 | 
								expectedFromContent: `live: true
 | 
				
			||||||
 | 
					metadata:
 | 
				
			||||||
 | 
					  name: foo
 | 
				
			||||||
 | 
					`,
 | 
				
			||||||
 | 
								expectedToContent: `merged: true
 | 
				
			||||||
 | 
					metadata:
 | 
				
			||||||
 | 
					  name: foo
 | 
				
			||||||
 | 
					`,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								name:              "with managed fields",
 | 
				
			||||||
 | 
								showManagedFields: true,
 | 
				
			||||||
 | 
								expectedFromContent: `live: true
 | 
				
			||||||
 | 
					metadata:
 | 
				
			||||||
 | 
					  managedFields: mf-data
 | 
				
			||||||
 | 
					  name: foo
 | 
				
			||||||
 | 
					`,
 | 
				
			||||||
 | 
								expectedToContent: `merged: true
 | 
				
			||||||
 | 
					metadata:
 | 
				
			||||||
 | 
					  managedFields: mf-data
 | 
				
			||||||
 | 
					  name: foo
 | 
				
			||||||
 | 
					`,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for i, tc := range testCases {
 | 
				
			||||||
 | 
							t.Run(tc.name, func(t *testing.T) {
 | 
				
			||||||
 | 
								obj := FakeObject{
 | 
				
			||||||
 | 
									name: fmt.Sprintf("TestCase%d", i),
 | 
				
			||||||
 | 
									live: map[string]interface{}{
 | 
				
			||||||
 | 
										"live": true,
 | 
				
			||||||
 | 
										"metadata": map[string]interface{}{
 | 
				
			||||||
 | 
											"managedFields": "mf-data",
 | 
				
			||||||
 | 
											"name":          "foo",
 | 
				
			||||||
 | 
										},
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
									merged: map[string]interface{}{
 | 
				
			||||||
 | 
										"merged": true,
 | 
				
			||||||
 | 
										"metadata": map[string]interface{}{
 | 
				
			||||||
 | 
											"managedFields": "mf-data",
 | 
				
			||||||
 | 
											"name":          "foo",
 | 
				
			||||||
 | 
										},
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								err = diff.Diff(&obj, Printer{}, tc.showManagedFields)
 | 
				
			||||||
 | 
								if err != nil {
 | 
				
			||||||
 | 
									t.Fatal(err)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								actualFromContent, _ := ioutil.ReadFile(path.Join(diff.From.Dir.Name, obj.Name()))
 | 
				
			||||||
 | 
								if string(actualFromContent) != tc.expectedFromContent {
 | 
				
			||||||
 | 
									t.Fatalf("File has %q, expected %q", string(actualFromContent), tc.expectedFromContent)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								actualToContent, _ := ioutil.ReadFile(path.Join(diff.To.Dir.Name, obj.Name()))
 | 
				
			||||||
 | 
								if string(actualToContent) != tc.expectedToContent {
 | 
				
			||||||
 | 
									t.Fatalf("File has %q, expected %q", string(actualToContent), tc.expectedToContent)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func TestMasker(t *testing.T) {
 | 
					func TestMasker(t *testing.T) {
 | 
				
			||||||
	type diff struct {
 | 
						type diff struct {
 | 
				
			||||||
		from runtime.Object
 | 
							from runtime.Object
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user