-
Notifications
You must be signed in to change notification settings - Fork 383
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
enhance skopeo inspect #1608
base: main
Are you sure you want to change the base?
enhance skopeo inspect #1608
Conversation
skopeo inspect can't see whether an image's MediaType,I want to use MediaType to check whether it is enctryed. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the PR.
c/image is following the Go semantic versioning rules, so we must not incompatibly change the externally-visible API like this (and we have no appetite for increasing the major version number either).
This needs to be done by adding new fields, without modifying any of the existing ones.
7bf77ee
to
831eccc
Compare
d913113
to
2defada
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This PR keeps growing…
While the additions are certainly valuable, perhaps it might be better to get one feature done, and then add others similarly, in one or more smaller PRs.
types/types.go
Outdated
History []v1.History | ||
Author string | ||
Size int64 | ||
Config v1.ImageConfig |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Adding a full config here is redundant with Image.OCIConfig
, and probably unwanted for the Inspect
caller, who is calling Inspect
exactly not to deal with the details of the config format.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I use podman or docker inspect an image, they will show config, so I think we should stay the same with docker or podman
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But then are other callers like skopeo inspect
, or automation that just wants a single element (like looking up a single label) that don’t need both at the same time. Paying the cost of the full conversion and JSON formatting is not all that great for them.
As a maintainer, I’d also much prefer not to have to maintain logic to convert to OCI format in two separate implementations for each format.
Config v1.ImageConfig | ||
} | ||
|
||
type LayerDetail struct { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ImageInspectLayer
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think ImageInspectLayer and Layers are same meaning, at ImageInspectInfo struct
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The types
subpackage contains quite a few types … and it’s useful to make it clear that the purpose of this struct is only as an inspect output.
We already have types.BlobInfo
(and manifest.LayerInfo
); being clear about the purposes of each (especially when there is no written documentation) is helpful to users of the API.
(Especially when may users are just going to use Inspect().LayersDetail…
without having to name the type, we need the type name more to be unambiguous than we need it to be short.)
types/types.go
Outdated
@@ -466,6 +466,18 @@ type ImageInspectInfo struct { | |||
Os string | |||
Layers []string | |||
Env []string | |||
LayersDetail []LayerDetail | |||
History []v1.History |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As this very PR shows, it’s valuable to be able to add extra fields — so a separate ImageInspectHistory
where we can add fields to would be better than forever tying this to OCIv1, and potentially having to add a HistoryDetail
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you means I should use another func ImageInspectHistory to show history? When I use podman inspect an image, I can see history
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I mean that the type of the field should be History []ImageInpectHistory
.
manifest/oci.go
Outdated
Env: v1.Config.Env, | ||
History: v1.History, | ||
Author: v1.Author, | ||
Size: d1.Size, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Size is not defined in OCI — so the ImageInspectInfo
documentation for the field must document how “unknown” is represented, and this code needs to set that value.
(0
is not a good “unknown” value for a size field, in principle… We typically use -1.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Still outstanding: The -1 value needs documenting.
types/types.go
Outdated
@@ -466,6 +466,18 @@ type ImageInspectInfo struct { | |||
Os string | |||
Layers []string | |||
Env []string | |||
LayersDetail []LayerDetail | |||
History []v1.History |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For History
, we need to worry about promised semantics, if any; e.g. is the number of entries supposed to match the number of layers? (That needs to be very careful about the EmptyLayer
bit in OCI — so the number of non-empty layers?) Is “unknown” a possible value?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Outstanding.
types/types.go
Outdated
LayersDetail []LayerDetail | ||
History []v1.History | ||
Author string | ||
Size int64 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Size of what? The compressed representation? Uncompressed representation? Either, depending on circumstances?
In OCI this can apparently be unknown.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Still outstanding; the added comment doesn’t answer this question.
Unit test coverage, to make sure this does not accidentally break, would also be nice. (And, looking at how the existing tests fail, it’s in a sense unavoidable at least to that little extent.) |
dbf036e
to
7b09f2f
Compare
Signed-off-by: ningmingxiao <[email protected]>
assert.Equal(t, Env, ii.Env) | ||
assert.NotEqual(t, nil, ii.Config) | ||
assert.Equal(t, int64(0), ii.Size) | ||
assert.Equal(t, "", ii.Author) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please maintain the original whole-structure comparison.
A single Equal
over the whole structure is more useful because it ensures that nothing was left out in the tests. Doing this item by item requires much more manual inspection and maintenance.
(In all three formats.)
assert.Equal(t, int64(0), ii.Size) | ||
assert.Equal(t, "", ii.Author) | ||
for _, layer := range ii.LayersDetail { | ||
assert.NotEqual(t, nil, layer) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
AFAICS that’s always true (members of the slice are not pointers at all), and does not test the created contents at all. That’s not useful.
Same for the other loop.
types/types.go
Outdated
History []v1.History | ||
Author string | ||
Size int64 | ||
Config v1.ImageConfig |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But then are other callers like skopeo inspect
, or automation that just wants a single element (like looking up a single label) that don’t need both at the same time. Paying the cost of the full conversion and JSON formatting is not all that great for them.
As a maintainer, I’d also much prefer not to have to maintain logic to convert to OCI format in two separate implementations for each format.
func schema2HistoryToV1History(history []Schema2History) []v1.History { | ||
v1History := make([]v1.History, len(history)) | ||
for index, value := range history { | ||
v1History[index].Created = &value.Created |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
created := value.Created
v1History[index].Created = &created
would be more obviously safe, because the pointer points at an individually-allocated value that will never be modified by whatever owns the input history
value.
i := &types.ImageInspectInfo{ | ||
Tag: "", | ||
Created: v1.Created, | ||
DockerVersion: d1.DockerVersion, | ||
Labels: v1.Config.Labels, | ||
Architecture: v1.Architecture, | ||
Os: v1.OS, | ||
Layers: layerInfosToStrings(m.LayerInfos()), | ||
Layers: layerInfosToStrings(layerInfos), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please keep the order of fields in the initializer the same as in the type definition, to make it easier to tell which fields were / were not set. (Everywhere.)
} | ||
|
||
diffIDs := []digest.Digest{digest.FromString(s1.ID)} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
s1.ID
is not a diffID
, and the single-value array would frequently not even have the right number of elements.
Passing an empty value would at least be consistent with the existing OCIConfig
call.
(This is another reason not to include all of OCIv1 config in the inspect output: the value is not fully valid, and the OCIConfig
API is focused enough on this single thing that it can document that at least a bit more effectively.)
Actually the best thing to do is not to involve the schema2 JSON format at all: refactor the convertedHistory
computation out from ToSchema2Config
into a separate function, and call it here. Then
- We don’t need to invent fake DiffID values
ToSchema2Config
avoids a whole lot of JSON manipulation- This code can just consume convenient Go values instead of having to unmarshal again.
if err != nil { | ||
return nil, err | ||
} | ||
imageConfig := &schema2Image{} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(Why is this using a custom type and not the existing schema2 manifest.Schema2Image
? But see elsewhere, we shouldn’t need to involve JSON for this.)
@@ -466,6 +466,19 @@ type ImageInspectInfo struct { | |||
Os string | |||
Layers []string | |||
Env []string | |||
LayersDetail []LayerDetail |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we can keep LayersDetail
right next to Layers
.
@ningmingxiao needs a rebase |
#1626 follows up on this PR (with a subset of the functionality). |
Signed-off-by: ningmingxiao [email protected]