Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cmd/list: Make listing of containers/images more robust #503

Merged
merged 4 commits into from
Jul 24, 2020

Conversation

HarryMichal
Copy link
Member

@HarryMichal HarryMichal commented Jul 14, 2020

Every time Podman changes their JSON API Toolbox breaks horribly. That
is caused by the complete lack of type guards. With this, the verbosity
of the code goes up a bit but it should be much more resistant to API
changes.

If a field is of a not-expected type, the field is set to "" and
an error message is printed after the rest of the table is printed into
the console.

An alternative to this solution is to unmarshal the JSON response to a
strongly typed structure, as pointed out by @owtaylor.

Closes: #502

@softwarefactory-project-zuul
Copy link

Build failed.

@softwarefactory-project-zuul
Copy link

Build failed.

@owtaylor
Copy link
Contributor

I think that the approach that toolbox is taking to parsing json output is generally not optimal - and not the way that pretty much every golang project I've looked at does it. Unmarshaling to a map of interfaces puts the checking (and error handling as is added here) at the point of use, which is both error-prone and hard to maintain.

We talked to the libpod maintainers some, and their recommendation was to use the libpod bindings that talk over a local http socket. Using this requires the fedora packaging to be updated to automatically create the socket for all users using a systemd user preset, and also would be a pretty major refactoring.

I think a short term fix would be, to, e.g. change GetContainers to return []Container where the Container type has just the fields that you actually care about, and unmarshal directly to that list. Then the json package will do the type checking upfront. It even has some ability to skip fields with a type mismatch:

If a JSON value is not appropriate for a given target type, or if a JSON number overflows the target type, Unmarshal skips that field and completes the unmarshaling as best it can. If no more serious errors are encountered, Unmarshal returns an UnmarshalTypeError describing the earliest such error. In any case, it's not guaranteed that all the remaining fields following the problematic one will be unmarshaled into the target object.

@softwarefactory-project-zuul
Copy link

Build failed.

@softwarefactory-project-zuul
Copy link

Build failed.

src/cmd/list.go Show resolved Hide resolved
src/cmd/list.go Outdated Show resolved Hide resolved
@HarryMichal HarryMichal added this to the Release 0.1.0 milestone Jul 15, 2020
@HarryMichal HarryMichal added 3. Enhancement Improvement to an existing feature 6. Major Change May cause breakage labels Jul 15, 2020
@softwarefactory-project-zuul
Copy link

Build failed.

Copy link
Contributor

@owtaylor owtaylor left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be slightly better to structure this as a commit that just switches around the structure to use JSON unmarshaling and tries to keep the logic the same as before, followed by another commit that adds the additional compat handling for the new 'podman images' breakage. But that's entirely optional - up to how comfortable you are restructuring git commits.

src/cmd/list.go Outdated Show resolved Hide resolved
src/cmd/list.go Outdated Show resolved Hide resolved
src/cmd/list.go Outdated Show resolved Hide resolved
src/cmd/list.go Outdated
c.Name = raw.Names[0]
}

if raw.Status != "" {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From the discussion in containers/podman#6980 I think this is an exception to old => new - a human Status is what we want and it sounds like it will be added back.

src/cmd/list.go Show resolved Hide resolved
@HarryMichal HarryMichal changed the title cmd/list: Add type assertions and error reporter cmd/list: Make listing of containers/images more robust Jul 23, 2020
@softwarefactory-project-zuul
Copy link

Build failed.

@HarryMichal
Copy link
Member Author

System tests are still failing on Fedora Rawhide but that is due to a different issue, not #502 that is fixed by this PR.

@HarryMichal
Copy link
Member Author

I just tried this with Podman v1.9.3 and there's a problem with listing containers due to:

failed to unmarshal container: json: cannot unmarshal number into Go struct field .State of type string

I'll adjust this accordingly.

@softwarefactory-project-zuul
Copy link

Build failed.

@owtaylor
Copy link
Contributor

Latest version looks good to me!

@HarryMichal HarryMichal added the 3. Bugfix Fixes a bug label Jul 23, 2020
HarryMichal added a commit to HarryMichal/toolbox that referenced this pull request Jul 24, 2020
This package will be used for generating a human-readable representation
of elapsed time (e.g., "5 minutes").

containers#503
HarryMichal added a commit to HarryMichal/toolbox that referenced this pull request Jul 24, 2020
HarryMichal added a commit to HarryMichal/toolbox that referenced this pull request Jul 24, 2020
Every time Podman changes their JSON API Toolbox breaks horribly. That
is caused by the combination of decoding the JSON purely by hand and by
the complete lack of type assertions to make the process stable.

I previously didn't know that unmarshalling with Go works on the 'do the
best job it can' logic (thank you Owen!). This makes the need to check
for subtle changes in the names of fields go away and type checking a
bit more bareable (marking the questioned field as interface{} and then
immediatelly type switch).

If even now an existing field does not hold an expected value the field
will remain blank.

To take this a bit further, I created two types (toolboxImage and
toolboxContainer) that are used by both functions for returning the list
of images and containers. Instead of using getters for properties that
need some checks or adjustments this uses a custom unmarshaling function
(Owen's idea; thanks!).

The work around populating the two new types is a bit hacky (marshalling
and already unmarshalled JSON - that was unmarshalled to
[]map[string]interface{} - that is then unmarshalled to either
toolboxImage or toolboxContainer. This is done to prevent a major
refactoring before the 0.1.0 release. This should be changed for the
0.2.0 release.

containers#503
HarryMichal added a commit to HarryMichal/toolbox that referenced this pull request Jul 24, 2020
Since Podman 2.1 the field 'Created' of `podman images --format json` no
longer holds a string with human-readable string in format "5 minutes
ago" but holds a Unix time integer[0].

[0] containers/podman#6815

containers#503
@softwarefactory-project-zuul
Copy link

Merge Failed.

This change or one of its cross-repo dependencies was unable to be automatically merged with the current state of its repository. Please rebase the change and upload a new patchset.

HarryMichal added a commit to HarryMichal/toolbox that referenced this pull request Jul 24, 2020
This package will be used for generating a human-readable representation
of elapsed time (e.g., "5 minutes").

containers#503
HarryMichal added a commit to HarryMichal/toolbox that referenced this pull request Jul 24, 2020
HarryMichal added a commit to HarryMichal/toolbox that referenced this pull request Jul 24, 2020
Every time Podman changes their JSON API Toolbox breaks horribly. That
is caused by the combination of decoding the JSON purely by hand and by
the complete lack of type assertions to make the process stable.

I previously didn't know that unmarshalling with Go works on the 'do the
best job it can' logic (thank you Owen!). This makes the need to check
for subtle changes in the names of fields go away and type checking a
bit more bareable (marking the questioned field as interface{} and then
immediatelly type switch).

If even now an existing field does not hold an expected value the field
will remain blank.

To take this a bit further, I created two types (toolboxImage and
toolboxContainer) that are used by both functions for returning the list
of images and containers. Instead of using getters for properties that
need some checks or adjustments this uses a custom unmarshaling function
(Owen's idea; thanks!).

The work around populating the two new types is a bit hacky (marshalling
and already unmarshalled JSON - that was unmarshalled to
[]map[string]interface{} - that is then unmarshalled to either
toolboxImage or toolboxContainer. This is done to prevent a major
refactoring before the 0.1.0 release. This should be changed for the
0.2.0 release.

containers#503
HarryMichal added a commit to HarryMichal/toolbox that referenced this pull request Jul 24, 2020
Since Podman 2.1 the field 'Created' of `podman images --format json` no
longer holds a string with human-readable string in format "5 minutes
ago" but holds a Unix time integer[0].

[0] containers/podman#6815

containers#503
@softwarefactory-project-zuul
Copy link

Build failed.

This package will be used for generating a human-readable
representation of elapsed time (e.g., "5 minutes").

containers#503
Every time Podman changes their JSON API Toolbox breaks horribly. That
is caused by the combination of decoding the JSON purely by hand and by
the complete lack of type assertions to make the process stable.

I previously didn't know that unmarshalling with Go works on the 'do
the best job it can' logic (thank you Owen!). This makes the need to
check for subtle changes in the names of fields go away and type
checking a bit more bearable (marking the questioned field as
interface{} and then immediatelly type switch).

If even now an existing field does not hold an expected value the field
will remain blank.

To take this a bit further, I created two types (toolboxImage and
toolboxContainer) that are used by both functions for returning the
list of images and containers. Instead of using getters for properties
that need some checks or adjustments this uses a custom unmarshaling
function (Owen's idea; thanks!).

The work around populating the two new types is a bit hacky
(marshalling and already unmarshalled JSON - that was unmarshalled to
[]map[string]interface{} - that is then unmarshalled to either
toolboxImage or toolboxContainer. This is done to prevent a major
refactoring before the 0.1.0 release. This should be changed for the
0.2.0 release.

containers#503
Since Podman 2.1 the field 'Created' of `podman images --format json`
no longer holds a string with human-readable string but holds a Unix
time integer[0].

[0] containers/podman#6815

containers#503
@debarshiray debarshiray merged commit 8168e0f into containers:master Jul 24, 2020
@debarshiray
Copy link
Member

Thanks for all your work on this, @HarryMichal

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
3. Bugfix Fixes a bug 3. Enhancement Improvement to an existing feature 6. Major Change May cause breakage
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Listing images panics
3 participants