From f309826194a45d864c3f1d058b3539855d5cfdb0 Mon Sep 17 00:00:00 2001 From: Mehul Arora Date: Sun, 13 Jun 2021 16:01:11 +0530 Subject: [PATCH] implemented diff between two images Signed-off-by: Mehul Arora --- cmd/podman/common/diffChanges.go | 9 +++++--- cmd/podman/images/diff.go | 8 ++++++- pkg/bindings/images/diff.go | 6 ++++- pkg/bindings/images/types.go | 1 + pkg/bindings/images/types_diff_options.go | 16 +++++++++++++ pkg/domain/entities/types.go | 1 + pkg/domain/infra/abi/images.go | 14 ++++++++++-- pkg/domain/infra/tunnel/images.go | 3 ++- test/e2e/diff_test.go | 28 +++++++++++++++++++++++ 9 files changed, 78 insertions(+), 8 deletions(-) diff --git a/cmd/podman/common/diffChanges.go b/cmd/podman/common/diffChanges.go index 7930e4f2c6..746923baea 100644 --- a/cmd/podman/common/diffChanges.go +++ b/cmd/podman/common/diffChanges.go @@ -29,10 +29,13 @@ func ChangesToJSON(diffs *entities.DiffReport) error { return errors.Errorf("output kind %q not recognized", row.Kind) } } - // Pull in configured json library - enc := json.NewEncoder(os.Stdout) - return enc.Encode(body) + output, err := json.MarshalIndent(body, "", " ") + if err != nil { + return err + } + fmt.Fprintln(os.Stdout, string(output)) + return nil } func ChangesToTable(diffs *entities.DiffReport) error { diff --git a/cmd/podman/images/diff.go b/cmd/podman/images/diff.go index 2e883d7ae1..1816ea1b60 100644 --- a/cmd/podman/images/diff.go +++ b/cmd/podman/images/diff.go @@ -14,7 +14,7 @@ var ( // podman container _inspect_ diffCmd = &cobra.Command{ Use: "diff [options] IMAGE", - Args: cobra.ExactArgs(1), + Args: cobra.RangeArgs(1, 2), Short: "Inspect changes to the image's file systems", Long: `Displays changes to the image's filesystem. The image will be compared to its parent layer.`, RunE: diff, @@ -48,6 +48,12 @@ func diff(cmd *cobra.Command, args []string) error { return errors.New("image diff does not support --latest") } + if len(args) == 2 { + diffOpts.OtherImg = args[1] + } else { + diffOpts.OtherImg = "" + } + results, err := registry.ImageEngine().Diff(registry.GetContext(), args[0], *diffOpts) if err != nil { return err diff --git a/pkg/bindings/images/diff.go b/pkg/bindings/images/diff.go index 79b0df8c99..634816636c 100644 --- a/pkg/bindings/images/diff.go +++ b/pkg/bindings/images/diff.go @@ -18,8 +18,12 @@ func Diff(ctx context.Context, nameOrID string, options *DiffOptions) ([]archive if err != nil { return nil, err } + params, err := options.ToParams() + if err != nil { + return nil, err + } + response, err := conn.DoRequest(nil, http.MethodGet, "/images/%s/changes", params, nil, nameOrID) - response, err := conn.DoRequest(nil, http.MethodGet, "/images/%s/changes", nil, nil, nameOrID) if err != nil { return nil, err } diff --git a/pkg/bindings/images/types.go b/pkg/bindings/images/types.go index 1f3e46729f..1bb2cd5106 100644 --- a/pkg/bindings/images/types.go +++ b/pkg/bindings/images/types.go @@ -16,6 +16,7 @@ type RemoveOptions struct { //go:generate go run ../generator/generator.go DiffOptions // DiffOptions are optional options image diffs type DiffOptions struct { + OtherImg string } //go:generate go run ../generator/generator.go ListOptions diff --git a/pkg/bindings/images/types_diff_options.go b/pkg/bindings/images/types_diff_options.go index f15a9a6962..fb578cc299 100644 --- a/pkg/bindings/images/types_diff_options.go +++ b/pkg/bindings/images/types_diff_options.go @@ -19,3 +19,19 @@ func (o *DiffOptions) Changed(fieldName string) bool { func (o *DiffOptions) ToParams() (url.Values, error) { return util.ToParams(o) } + +// WithOtherImg +func (o *DiffOptions) WithOtherImg(value string) *DiffOptions { + v := &value + o.OtherImg = v + return o +} + +// GetOtherImg +func (o *DiffOptions) GetOtherImg() string { + var otherImg string + if o.OtherImg == nil { + return otherImg + } + return *o.OtherImg +} diff --git a/pkg/domain/entities/types.go b/pkg/domain/entities/types.go index 02e3741118..6c5cccf319 100644 --- a/pkg/domain/entities/types.go +++ b/pkg/domain/entities/types.go @@ -65,6 +65,7 @@ type DiffOptions struct { Format string `json:",omitempty"` // CLI only Latest bool `json:",omitempty"` // API and CLI, only supported by containers Archive bool `json:",omitempty"` // CLI only + OtherImg string } // DiffReport provides changes for object diff --git a/pkg/domain/infra/abi/images.go b/pkg/domain/infra/abi/images.go index 0835662012..f40da59a75 100644 --- a/pkg/domain/infra/abi/images.go +++ b/pkg/domain/infra/abi/images.go @@ -400,12 +400,22 @@ func (ir *ImageEngine) Import(ctx context.Context, options entities.ImageImportO return &entities.ImageImportReport{Id: imageID}, nil } +func (ir *ImageEngine) Diff(_ context.Context, nameOrID string, options entities.DiffOptions) (*entities.DiffReport, error) { + var ( + parent string + child string + ) + if options.OtherImg == "" { + parent, child = "", nameOrID + } else { + parent, child = nameOrID, options.OtherImg + } -func (ir *ImageEngine) Diff(_ context.Context, nameOrID string, _ entities.DiffOptions) (*entities.DiffReport, error) { - changes, err := ir.Libpod.GetDiff("", nameOrID) + changes, err := ir.Libpod.GetDiff(parent, child) if err != nil { return nil, err } + return &entities.DiffReport{Changes: changes}, nil } diff --git a/pkg/domain/infra/tunnel/images.go b/pkg/domain/infra/tunnel/images.go index 3fd9a755d3..be9379786d 100644 --- a/pkg/domain/infra/tunnel/images.go +++ b/pkg/domain/infra/tunnel/images.go @@ -300,8 +300,9 @@ func (ir *ImageEngine) Save(ctx context.Context, nameOrID string, tags []string, } // Diff reports the changes to the given image -func (ir *ImageEngine) Diff(ctx context.Context, nameOrID string, _ entities.DiffOptions) (*entities.DiffReport, error) { +func (ir *ImageEngine) Diff(ctx context.Context, nameOrID string, opts entities.DiffOptions) (*entities.DiffReport, error) { options := new(images.DiffOptions) + options.OtherImg = opts.OtherImg changes, err := images.Diff(ir.ClientCtx, nameOrID, options) if err != nil { return nil, err diff --git a/test/e2e/diff_test.go b/test/e2e/diff_test.go index 4370a2127b..b6e2a70de1 100644 --- a/test/e2e/diff_test.go +++ b/test/e2e/diff_test.go @@ -92,4 +92,32 @@ var _ = Describe("Podman diff", func() { Expect(session.LineInOutputContains("A /tmp/diff-test")).To(BeTrue()) Expect(session.ExitCode()).To(Equal(0)) }) + + It("podman image diff of image", func() { + session := podmanTest.Podman([]string{"image", "diff", ALPINE, BB}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + Expect(len(session.OutputToStringArray())).To(BeNumerically(">", 0)) + }) + + It("podman image diff of single image", func() { + session := podmanTest.Podman([]string{"image", "diff", BB}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + Expect(len(session.OutputToStringArray())).To(BeNumerically(">", 0)) + }) + + It("podman diff bogus image", func() { + session := podmanTest.Podman([]string{"image", "diff", "1234", ALPINE}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(125)) + }) + + It("podman image diff of the same image", func() { + session := podmanTest.Podman([]string{"image", "diff", ALPINE, ALPINE}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + Expect(len(session.OutputToStringArray())).To(BeNumerically("==", 0)) + }) + })