-
Notifications
You must be signed in to change notification settings - Fork 395
Pre-layer copy hook #218
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
Pre-layer copy hook #218
Conversation
|
I've not yet done a full code review but high level concept sounds really good to me. Maybe we can use the callback to also skip layers we're not interested in (or the other way around). I like it. @mtrmac WDYT? I'm not totally sure about the implications this code could have to the way we work with signatures. |
|
https://erikh.github.io/box/user-guide/functions/#skip is a practical
application of this function and does exactly what you're describing.
…On Thu, Jan 19, 2017 at 5:45 AM, Antonio Murdaca ***@***.***> wrote:
I've not yet done a full code review but high level concept sounds really
good to me. Maybe we can use the callback to also *skip* layers we're not
interested in (or the other way around). I like it. @mtrmac
<https://github.com/mtrmac> WDYT?
—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub
<#218 (comment)>, or mute
the thread
<https://github.com/notifications/unsubscribe-auth/AABJ6yJm39Pn6rdYfFk8ZB9MdQnzy7rWks5rT2jigaJpZM4LoGoZ>
.
|
mtrmac
left a comment
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 is very similar to #159 , except that it uses a function instead of a prescribed set, and that it tries to update the manifest as well, whereas #159 just punts on that.
At a high level, there’s only so far copy.Image can go as a generic image editing system, without it becoming a completely unmanageable mess (and it is fairly close to that already, and it will get worse with things like #105 ). I don’t really know how flexible we can or want to make it…
For example, a plausible alternative could be that we would instead make some part of imageCopier public (the top-level copylayers, which would in the future handle parallelization? Almost certainly the non-trivial copyLayer should be made available.), and leave it to the callers to coordinate getting the necessary information for types.Image.UpdatedImage.
OTOH it does make sense for UpdatedImage to support adding/removing layers, and that’s, probably, the most difficult part of this.
Overall, I really don’t know right now.
copy/copy.go
Outdated
| // Please keep this policy check BEFORE reading any other information about the image. | ||
| if allowed, err := policyContext.IsRunningImageAllowed(unparsedImage); !allowed || err != nil { // Be paranoid and fail if either return value indicates so. | ||
| return errors.Wrap(err, "Source image rejected") | ||
| } |
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’d rather force the caller to provide a policy. It is… not too difficult… to do:
signature.Policy{Default: []signature.PolicyRequirement{signature.NewPRInsecureAcceptAnything()}}and passing nil here by mistake could be disastrous.
copy/copy.go
Outdated
| } | ||
|
|
||
| canModifyManifest := len(sigs) == 0 | ||
| canModifyManifest := len(sigs) == 0 || options.RemoveSignatures |
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 necessary? Per
var sigs [][]byte
if options != nil && options.RemoveSignatures {
sigs = [][]byte{}above, this seems redundant.
(Also, options can be nil.)
| copy := *m // NOTE: This is not a deep copy, it still shares slices etc. | ||
|
|
||
| if options.LayerInfos != nil { | ||
| if len(copy.LayersDescriptors) != len(options.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.
If we do add support for this, it should land for all manifest schemas simultaneously.
image/docker_schema2.go
Outdated
| // Edits the layers in the manifest when called by replacing them with the | ||
| // appropriate infos provided. This is metadata-only -- the actual layers still | ||
| // have to get to the image. | ||
| func (m *manifestSchema2) performEdits(infos []types.BlobInfo) error { |
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.
performEdits is too generic a name for this limited operation.
image/docker_schema2.go
Outdated
| m.LayersDescriptors = make([]descriptor, infolen) | ||
| for i, info := range infos { | ||
| imageConfig.History[i] = imageHistory{} | ||
| imageConfig.RootFS.DiffIDs[i] = info.Digest |
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 is incorrect if the layer is compressed. DiffID values must be the digests of the compressedEDIT uncompressed layers.
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.
(See also the UpdatedImageNeedsLayerDiffIDs hack. That decision mechanism would obviously not work with the “anything can be returned” hook, and it is also too late by that time; so “should we compute DiffIDs” would need a complete rethinking.)
image/docker_schema2.go
Outdated
| m.LayersDescriptors[i].Size = info.Size | ||
| m.LayersDescriptors[i].URLs = info.URLs | ||
| } | ||
| imageConfig.RootFS.BaseLayer = m.LayersDescriptors[0].Digest.String() |
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.
(Note to self: I didn’t review the config.json edits in detail here, … but this is inconsistent with what manifestSchema1.convertToManifestSchema2 does.)
copy/copy.go
Outdated
| ReportWriter io.Writer | ||
| SourceCtx *types.SystemContext | ||
| DestinationCtx *types.SystemContext | ||
| LayerCopyHook func(types.BlobInfo) bool |
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 should really have a more descriptive name; shouldLayerBeCopied or something shorter to that effect; “hook” does not describe the function at all.
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.
… and does this really have to be a function? Could this be a set, as per #159 ?
Or, more generally, if we add “delete layer” here, pretty soon we will be adding an “add a layer at this index”. What would that interface look like, and can we define that instead right now? (Yeah, that would be making this PR more complex. Perhaps we should just merge this, or the “layer subset” non-hook variant, right now, with a // Warning: API likely to change, and not block on the higher-level discussions?)
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.
we pass the layer id so really you could do anything you want, including keeping a table of images you want to keep, which is exactly what box does.
image/docker_schema2.go
Outdated
| } | ||
|
|
||
| // regurgitate the image configuration for recalculation of layers in the event the layer list has been edited. | ||
| imageConfig := &image{} |
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.
There is a fairly high risk that this would drop any fields of config.json added in the future.
|
The two security changes I made seemed necessary at the time but I will back them out. |
|
Ok. I will not close this while you decide. I realize the code is not in the best shape; it's merely meant as a discussion-starter. For the rest of it, I'm focused on it being doable; we accomplish this in box with a layer list we manage outside of the layer list in the image (and then repackage at the end) so there's no reason we couldn't do it that way too -- I just felt a function was a safer bet given how generic they can be. No objection to doing it the other way. |
Yeah; this strongly depends on how you want to use it in general. Vaguely, the two major directions I see (but I may well be missing something)
Does any of this make sense? Are there other options I have missed? @runcom ? (And would the |
|
(admittedly the |
|
Shooting from the hip; the presence of the hook during the run should be
enough to describe a capability to the appropriate image destination that
it can reject if it discovers the hook and can't process it. Requires
knowledge though, and will need to be maintained as destinations grow as a
canonical part of the API.
I don't think doing this just in schema2 is the right answer, if that's
what you were suggesting.
I need to mull over the rest. Will reply in a few hours.
…On Thu, Jan 19, 2017 at 11:53 AM, Miloslav Trmač ***@***.***> wrote:
(admittedly the LayerEditor name doesn’t mean anything and in general
sucks.)
—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub
<#218 (comment)>, or mute
the thread
<https://github.com/notifications/unsubscribe-auth/AABJ6yzVr0eyM3ZR_sQNUawrm3wDmnZnks5rT78egaJpZM4LoGoZ>
.
|
To be fair, my initial comment on the |
|
agree entirely.
…On Thu, Jan 19, 2017 at 12:16 PM, Miloslav Trmač ***@***.***> wrote:
I don't think doing this just in schema2 is the right answer, if that's
what you were suggesting.
To be fair, my initial comment on the docker_schema2.go file was probably
too strong. It would definitely not be the first case where some
types.Image.UpdatedImage functionality is only available for some schemas
or schema combinations, and if nobody cared to implement this for
$obscure_format, well, nobody would exactly be *hurt*. But it does make
the interface confusing when we can’t easily explain to users what is and
is not supposed to work.
—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub
<#218 (comment)>, or mute
the thread
<https://github.com/notifications/unsubscribe-auth/AABJ64qY-Yf4Am5Ga8kz58WVeidfGu2Rks5rT8SdgaJpZM4LoGoZ>
.
|
|
Hmm; maybe make the hook a part of the interface somehow, so it has to at least be considered when implementing a destination? |
|
Also please note that I have elided the security changes, so we can focus on the meat. :) |
As far as layers go, it seems to me that |
|
Sure; I'm talking about the requirement for the hook to be implemented (or at least, considered when implementing a destination). Unrelated, is there an irc or slack I can join to collaborate with you folks? |
|
I'm sorry, I'm not being clear. For a destination to work with copy, I think it should at least implement or at minimum, do something (perhaps by return an error) to indicate that it cannot do layer edits. This could be done by satisfying an interface. I hope that's clearer, sorry. |
|
@mtrmac I'm going to try implementing option #2 in #218 (comment) tonight -- please let me know if you'd prefer I do it some other way. I am already running with a fork with this PR in erikh/box so I could get moving, but I want to realign as soon as we can come to a conclusion of how to implement this. |
|
... the layer editing hook, to be precise. |
No, I continue to think that an interface vaguely like that would be general and flexible enough to be useful long-term. And it is quite acceptable to implement this kind of editing only for one of the image manifest formats in the initial PR, as long as an attempt to do it with the unsupported formats is clearly rejected. |
|
Well ideally I'd like to set it up in a way that all (or at least, almost
all) editing capabilities are added to image formats across the library; it
wasn't my intent just to affect docker images this way. I need this for OCI
and friends too.
…On Wed, Feb 15, 2017 at 9:45 AM, Miloslav Trmač ***@***.***> wrote:
@mtrmac <https://github.com/mtrmac> I'm going to try implementing option
#2 <#2> in #218
<#218> (comment) tonight --
please let me know if you'd prefer I do it some other way.
No, I continue to think that an interface vaguely like that would be
general and flexible enough to be useful long-term.
And it is quite acceptable to implement this kind of editing only for one
of the image manifest formats in the initial PR, as long as an attempt to
do it with the unsupported formats is clearly rejected.
—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub
<#218 (comment)>, or mute
the thread
<https://github.com/notifications/unsubscribe-auth/AABJ64ZcHPf0rfuFDY768WdZLMQeZ2r_ks5rczmggaJpZM4LoGoZ>
.
|
|
I'm going to leave the new layer reader off for now. I really think this would be better done as a separate method on the src that accepts a reader for each layer. The rest I'm working on now. |
798114b to
1a0fcb4
Compare
|
I've taken a stab at this (which I have overwritten the previous patch with) Looking for some suggestions on how to resolve this. |
| if err := dest.PutSignatures(sigs); err != nil { | ||
| return errors.Wrap(err, "Error writing signatures") | ||
| } | ||
| */ |
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?
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.
no idea what happened here. I'll investigate.
| srcInfos := ic.src.LayerInfos() | ||
|
|
||
| if ic.layerEditor != nil { | ||
| srcInfos = ic.layerEditor(ic.src.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.
Calling LayerInfos three times is a bit much… at the very least srcInfos = ic.layerEditor(srcInfos)
| retval := types.BlobInfo{Digest: digester.Digest(), Size: inputInfo.Size} | ||
|
|
||
| d.blobs[inputInfo.Digest] = retval | ||
| return retval, nil |
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.
(WRT this, comment changes, empty lines, etc…) I guess, why not, but please, in the final version, one idea per commit. It should be clear why every change was introduced, and in big commits it is often difficult whether a small change is essential for the primary task of the commit or really a typo in an unrelated cleanup which was not supposed to change behavior.
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.
… OTOH, in the extreme, having 10 one-line commits is just fine with me. Obviously correct, easy to review.
Yeah. Still doing that is really necessary. A possible step towards making this possible could be to replace the existing And then, we do need to figure out what the required config updates are. Right now, when the layers must come from the original The more general case, with arbitrary new layers being introduced, is noticeably harder; luckily we do have the |
|
The problem is not editing the config, it's converting the config to the new layers; which means it has to be unmarshalled first and its properties changed and remarshalled, but to what format? At that level there's no indicator of what format to use, much less convert to. |
I guess I don’t understand the problem; is there any ambiguity about config formats? We are already parsing / creating Or are you perhaps saying that a schema2 manifest could refer to an OCI config, or an OCi manifest could refer to a schema1 config? |
|
Yes but the abstraction doesn't support that, unless I'm missing something,
by the time you're in ConfigBlob() you don't have access to the manifest
format to unmarshal/marshal it. It's a straight byte read.
…On Wed, Feb 22, 2017 at 11:39 AM, Miloslav Trmač ***@***.***> wrote:
At that level there's no indicator of what format to use, much less
convert to.
I guess I don’t understand the problem; is there any ambiguity about
config formats? We are already parsing / creating config.json files in
manifestSchema[12].convertToManifestSchema[12]. It’s somewhat hairy but
it seems perfectly doable.
Or are you perhaps saying that a schema2 manifest could refer to an OCI
config, or an OCi manifest could refer to a schema1 config?
—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub
<#218 (comment)>, or mute
the thread
<https://github.com/notifications/unsubscribe-auth/AABJ60477Un_63TTBNQ_Eah9CXV_nZZaks5rfI71gaJpZM4LoGoZ>
.
|
|
… On Wed, Feb 22, 2017 at 11:42 AM, Erik Hollensbe ***@***.***> wrote:
Yes but the abstraction doesn't support that, unless I'm missing
something, by the time you're in ConfigBlob() you don't have access to the
manifest format to unmarshal/marshal it. It's a straight byte read.
On Wed, Feb 22, 2017 at 11:39 AM, Miloslav Trmač ***@***.***
> wrote:
> At that level there's no indicator of what format to use, much less
> convert to.
>
> I guess I don’t understand the problem; is there any ambiguity about
> config formats? We are already parsing / creating config.json files in
> manifestSchema[12].convertToManifestSchema[12]. It’s somewhat hairy but
> it seems perfectly doable.
>
> Or are you perhaps saying that a schema2 manifest could refer to an OCI
> config, or an OCi manifest could refer to a schema1 config?
>
> —
> You are receiving this because you authored the thread.
> Reply to this email directly, view it on GitHub
> <#218 (comment)>,
> or mute the thread
> <https://github.com/notifications/unsubscribe-auth/AABJ60477Un_63TTBNQ_Eah9CXV_nZZaks5rfI71gaJpZM4LoGoZ>
> .
>
|
What happens is that the copy code, after supplying all needed data, calls (And of course the abstraction is not set in stone, |
|
Right, but if you read that code, it takes it right out of the original
image. Or does the getblob in the code I linked from above take from the
memory image?
…On Wed, Feb 22, 2017 at 12:01 PM, Miloslav Trmač ***@***.***> wrote:
Yes but the abstraction doesn't support that, unless I'm missing
something, by the time you're in ConfigBlob() you don't have access to the
manifest format to unmarshal/marshal it.
What happens is that the copy code, after supplying all needed data, calls
.UpdatedImage; that creates an in-memory-only variant of the original
manifest (a memoryImage with a new manifest object); that new manifest
object is initialized with an edited version of configBlob from the
start. Follow e.g. https://github.com/containers/image/blob/master/image/
docker_schema1.go#L171 → https://github.com/containers/
image/blob/master/image/docker_schema1.go#L284 →
https://github.com/containers/image/blob/master/image/
docker_schema2.go#L56 .
(And of course the abstraction is not set in stone, image.genericManifest
is a private type perfectly subject to change, and even the public types in
types.go have been modified fairly frequently in the past. The existing
structure does seem to be more or less suitable for this in principle,
concentrating all the true complexity in .UpdatedImage and its helper
methods, and leaving the rest as fairly simple parsers / getters. It can
very likely be improved.)
—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub
<#218 (comment)>, or mute
the thread
<https://github.com/notifications/unsubscribe-auth/AABJ6-ePD3fL7js2CPCb86rltRqMDAo7ks5rfJP-gaJpZM4LoGoZ>
.
|
|
I should admit that I have tested this and the manifest is not updated.
…On Wed, Feb 22, 2017 at 12:15 PM, Erik Hollensbe ***@***.***> wrote:
Right, but if you read that code, it takes it right out of the original
image. Or does the getblob in the code I linked from above take from the
memory image?
On Wed, Feb 22, 2017 at 12:01 PM, Miloslav Trmač ***@***.***
> wrote:
> Yes but the abstraction doesn't support that, unless I'm missing
> something, by the time you're in ConfigBlob() you don't have access to the
> manifest format to unmarshal/marshal it.
>
> What happens is that the copy code, after supplying all needed data,
> calls .UpdatedImage; that creates an in-memory-only variant of the
> original manifest (a memoryImage with a new manifest object); that new
> manifest object is initialized with an edited version of configBlob from
> the start. Follow e.g. https://github.com/containers/
> image/blob/master/image/docker_schema1.go#L171 →
> https://github.com/containers/image/blob/master/image/docker
> _schema1.go#L284 → https://github.com/containers/
> image/blob/master/image/docker_schema2.go#L56 .
>
> (And of course the abstraction is not set in stone, image.genericManifest
> is a private type perfectly subject to change, and even the public types in
> types.go have been modified fairly frequently in the past. The existing
> structure does seem to be more or less suitable for this in principle,
> concentrating all the true complexity in .UpdatedImage and its helper
> methods, and leaving the rest as fairly simple parsers / getters. It can
> very likely be improved.)
>
> —
> You are receiving this because you authored the thread.
> Reply to this email directly, view it on GitHub
> <#218 (comment)>,
> or mute the thread
> <https://github.com/notifications/unsubscribe-auth/AABJ6-ePD3fL7js2CPCb86rltRqMDAo7ks5rfJP-gaJpZM4LoGoZ>
> .
>
|
What path exactly? In the conversion case I have demonstrated above, https://github.com/containers/image/blob/master/image/docker_schema2.go#L84 uses the |
|
I can check again, but I've printed that config right at that point. It's
not updated and gets processed right before uploading to docker. The layers
after editing do not save to docker because of this. This is literally the
only thing keeping it from working.
I'll amend the PR.
…On Wed, Feb 22, 2017 at 12:18 PM, Miloslav Trmač ***@***.***> wrote:
Right, but if you read that code, it takes it right out of the original
image
What path exactly? In the conversion case I have demonstrated above,
https://github.com/containers/image/blob/master/image/
docker_schema2.go#L84 uses the m.configBlob != nil path, with m.configBlob
prepopulated with a memory-only version which does not exist in the source
(obviously, when the source is not a schema2 image and there is no separate
config.json in the original at all).
—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub
<#218 (comment)>, or mute
the thread
<https://github.com/notifications/unsubscribe-auth/AABJ62ZleWWEGEulv5IHu1Y5N3z0Pc0Xks5rfJgdgaJpZM4LoGoZ>
.
|
|
I've amended the PR with the print statement and a test.go which will
exhibit the issue in the root directory of the repository. Can you validate
that I am seeing what I am seeing?
…On Wed, Feb 22, 2017 at 12:24 PM, Erik Hollensbe ***@***.***> wrote:
I can check again, but I've printed that config right at that point. It's
not updated and gets processed right before uploading to docker. The layers
after editing do not save to docker because of this. This is literally the
only thing keeping it from working.
I'll amend the PR.
On Wed, Feb 22, 2017 at 12:18 PM, Miloslav Trmač ***@***.***
> wrote:
> Right, but if you read that code, it takes it right out of the original
> image
>
> What path exactly? In the conversion case I have demonstrated above,
> https://github.com/containers/image/blob/master/image/docker
> _schema2.go#L84 uses the m.configBlob != nil path, with m.configBlob
> prepopulated with a memory-only version which does not exist in the source
> (obviously, when the source is not a schema2 image and there is no separate
> config.json in the original at all).
>
> —
> You are receiving this because you authored the thread.
> Reply to this email directly, view it on GitHub
> <#218 (comment)>,
> or mute the thread
> <https://github.com/notifications/unsubscribe-auth/AABJ62ZleWWEGEulv5IHu1Y5N3z0Pc0Xks5rfJgdgaJpZM4LoGoZ>
> .
>
|
|
That added If that’s not the case, I’m not immediately sure what is going on. Here’s what I have used to test that I am not going crazy: diff --git a/vendor/github.com/containers/image/copy/copy.go b/vendor/github.com/containers/image/copy/copy.go
index d27e634..a0f3f8a 100644
--- a/vendor/github.com/containers/image/copy/copy.go
+++ b/vendor/github.com/containers/image/copy/copy.go
@@ -180,7 +180,7 @@ func Image(policyContext *signature.PolicyContext, destRef, srcRef types.ImageRe
}
pendingImage := src
- if !reflect.DeepEqual(manifestUpdates, types.ManifestUpdateOptions{InformationOnly: manifestUpdates.InformationOnly}) {
+ if _ = reflect.DeepEqual; true { //} !reflect.DeepEqual(manifestUpdates, types.ManifestUpdateOptions{InformationOnly: manifestUpdates.InformationOnly}) {
if !canModifyManifest {
return errors.Errorf("Internal error: copy needs an updated manifest but that was known to be forbidden")
}
diff --git a/vendor/github.com/containers/image/image/docker_schema2.go b/vendor/github.com/containers/image/image/docker_schema2.go
index 76ceea7..1188cd9 100644
--- a/vendor/github.com/containers/image/image/docker_schema2.go
+++ b/vendor/github.com/containers/image/image/docker_schema2.go
@@ -151,6 +151,24 @@ func (m *manifestSchema2) UpdatedImageNeedsLayerDiffIDs(options types.ManifestUp
// This does not change the state of the original Image object.
func (m *manifestSchema2) UpdatedImage(options types.ManifestUpdateOptions) (types.Image, error) {
copy := *m // NOTE: This is not a deep copy, it still shares slices etc.
+
+ if true {
+ logrus.Errorf("HERE")
+ blob, err := copy.ConfigBlob()
+ if err != nil {
+ return nil, err
+ }
+ configJSON := bytes.Join([][]byte{[]byte("INVALIDPREFIX"), blob}, nil)
+ configDescriptor := descriptor{
+ MediaType: "application/vnd.docker.container.image.v1+json",
+ Size: int64(len(configJSON)),
+ Digest: digest.FromBytes(configJSON),
+ }
+
+ m2 := manifestSchema2FromComponents(configDescriptor, nil, configJSON, copy.LayersDescriptors)
+ return memoryImageFromManifest(m2), nil
+ }
+
if options.LayerInfos != nil {
if len(copy.LayersDescriptors) != len(options.LayerInfos) {
return nil, errors.Errorf("Error preparing updated manifest: layer count changed from %d to %d", len(copy.LayersDescriptors), len(options.LayerInfos))and My best guess (but just a guess) is that the |
|
… actually, let’s step back: This PR, as far as manifest/config editing goes, only updates |
|
run the code! It's reached, trust me.
…On Wed, Feb 22, 2017 at 12:45 PM, Miloslav Trmač ***@***.***> wrote:
… actually, let’s step back: This PR, as far as manifest/config editing
goes, *only* updates ManifestUpdateOptions.LayerInfos. That of course
does not edit config.json simply because that code doesn’t exist.
.LayerInfos has been created to update the manifest after blobs are
compressed (changing their digests but not DiffIDs). Editing the config as
necessary would be a new functionality which needs to be written. It isn’t *already
there* just to enable.
—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub
<#218 (comment)>, or mute
the thread
<https://github.com/notifications/unsubscribe-auth/AABJ6zrdNnkg-Fy9UQkKvQHcyFlvl1l5ks5rfJ5rgaJpZM4LoGoZ>
.
|
Signed-off-by: Erik Hollensbe <github@hollensbe.org>
Specifically, with the layer editing changes. The layers are variable and unvalidated now so this test will no longer pass. Signed-off-by: Erik Hollensbe <github@hollensbe.org>
|
it's ok, thanks and sorry to keep this hanging up things for so long |
This is a proof-of-concept and still needs tests and other completeness changes
(like for things that are not docker). Please let me know if you'd like to
accept the feature so I know to continue work towards getting this fleshed out
in the other image systems, tests, etc.
erikh/box has a layer editor inside it that allows it to filter out layers as
necessary. This is made possible currently with some hand-rolled image code.
I'd love to move to containers/image but it has a very coarse copy
implementation.
This adds a simple hook that provides the source layer information to a hook in
the copier which returns bool on whether to proceed to continue to copy
(contrast with
filepath.Walk).Here is some example code that demonstrates how it can be used: in this case,
the
golangimage is pulled from the host docker, the first layer is clippedoff the top and pushed to a new image named
erikh/test. The other layerrelationships have been removed and naturally the image is much smaller.
This has proven useful for building minimal images of containers in the past.