Initial implementation of storage layer path mapper #729
Initial implementation of storage layer path mapper #729
Conversation
LGTM |
cc @BrianBland |
We've added a path mapper to support simple mapping between path objects used in the storage layer and the underlying file system. The target of this is to ensure that paths are only calculated in a single place and their format is separated from the data that makes up the path components. This commit only includes spec implementation to support layer reads. Further specs will come along with their implementations.
25c79d8
to
8e44c1d
Compare
LGTM |
On Thu, Nov 13, 2014 at 03:42:06PM -0800, Stephen Day wrote:
I'm not sure why we need an “underlying file system” model on top of
For other tasks, we'll want endpoints to:
Those don't need to be registry endpoints though, if the utility can The content-addressable mapping you're proposing is good (just flat It looks like layerindex is addressing the “List repositories that layerindex:tarsum+sha256:589…e03 (where I've used a colon instead of slashes between “layerindex” and layerindex:/: For example: layerindex:tarsum+sha256:589…e03/library/debian:latest You don't even need a value for that key. I don't understand the need for repositories//layers/…. Can't repositories// for storing the manifests. There's also which sounded to me like out-of-manifest certificate |
After I clarify some of the issues you brought up, I think you'll find this layout points the next generation registry in the direction you're looking for. Right now, we are focused on standing up a working registry that implements the V2 API so we can validate the concepts.
This mapping scheme has the very nice property that it doesn't actually leverage file system operations for layer lookup (ie directory listing). While the scheme is hierarchical like a filesystem, all the paths for the main operations are pre-calculated lookups followed by a read, which maps very well to keyed object stores. Currently, the next generation storagedriver effectively implements a VFS. The work I am doing now will definitely expose a higher-level interface and possibly a mid-level interface, both of which could be candidates for future driver interfaces, but not yet.
By exposing the registry layout to out of band clients, we would be effectively exporting a new API, which needs to be versioned and controlled. We are still working on the V2 HTTP registry API and we want to focus on that. Though the use cases (listing repos, layers, etc.) you've listed will likely be added to the registry API to support management tasks, the general concept of safe, application-level registry operations would likely be implemented as part of an extension mechanism.
While it can serve that purpose, this is actually part of the access control methodology and partially a by-product of the v2 image manifest format. The layerindex allows one to lookup up the "owning" repository of the target layer, identified by tarsum, without knowing the name of the repository. If the user doesn't have access to one of the listed repositories, they can't get to the blob id, stored under This scheme supports the use case of two parties uploading identical layers without requiring access to each others repositories. This avoids the pathological case of "claimed tarsums". With this approach, two parties can use the same tarsum for a layer but both parties have to prove they have the content, even if they have the same checksum. If this is not considered, the tarsum effectively becomes a content access key, and any one that knows you're tarsum can get access to your content. Conversely, if one uploads a simple layer, they could claim that tarsum and prevent others using it, even if generated independently. This will become more obvious as we put the access controls in place.
This allows multiple versions of indexes in the directory, referencing the same content, without blowing up directory listing. It also keeps the
Even though the number of repositories with the same tarsum but no mutual access should be small, in accordance with your earlier comments, directory listing should be avoided. Concurrent updates will be problematic, but that is a fine tradeoff. |
On Thu, Nov 13, 2014 at 06:36:19PM -0800, Stephen Day wrote:
That's fair enough; obviously we don't need to have everything
Right, key/value is easy with known keys. The hard part is getting a
I don't want multiple levels of interfaces. If the registry authors
I'm fine with that, but they're not in the v2 HTTP client/registry API
The registry/storage API shouldn't have to care about the
Aren't you just storing consuming :s? You don't need a
Agreed, but I'd handle this in the registry itself (see the “PUT
First, the storage driver is free to optimize this. I just don't
First, you can't just claim a tarsum without content that has that
Why would you need to store multiple indexes to the same content with
They're not filenames, they're keys ;). If the storage driver wants
I'm happy to kick this can down the road. In the event that we need
I'm fine with a single-key: layerindex:tarsum+sha256:589…e03 too 6. I don't think listing this will be a big problem though. If
|
I believe you guys are pretty much saying the same thing, although probably with different words and looking at it from different perspectives. A couple of notes, though:
Hope that helps. |
Initial implementation of storage layer path mapper
On Fri, Nov 14, 2014 at 11:06:13AM -0800, Olivier Gambier wrote:
And both of our schemes mention the tarsum version and hash. I'm just layerindex/tarsum/v1/ we just need to be able to iterate over keys starting with: layerindex:tarsum+sha256:589…e03 (if we take the per-tag entry approach 1). If we take the
I thought the issue was concern about different layers with the same
Escaping that in the registry is fine, but personally, I think that's
Right, and we have an existing abstract storage API. I think the List("blob/sha256/01") and get 01a60e35df88d8b49546cb3f8f4ba4f406870f9b8e1f394c9d48ab73548d748d which would be useful for parallel garbage-collection handlers (one |
On Fri, Nov 14, 2014 at 11:24:58AM -0800, W. Trevor King wrote:
And the more workarounds like this you build into the registry, the |
No it does not need to. |
Simple enough to devise. Likely something like: a-zA-Z0-9_.:- |
On Fri, Nov 14, 2014 at 02:15:57PM -0800, Olivier Gambier wrote:
So: bulk registry code that gives you back clean abstractions in the bulk registry code, but |
On Fri, Nov 14, 2014 at 02:20:03PM -0800, Olivier Gambier wrote:
I agree that that's likely to work, but it's another bit you have to |
Fortunately it's simple enough to test exhaustively (unlike testing exhaustively "some bytes").
Then people don't do the work properly because (insert random reason), and we end-up with a variety of bugs reports for third-party code that we have to carry around. One step further: what about path traversal? or security at large? do we trust the driver authors as well to do that properly?
So we maintain them, recommend that people use them, have to upgrade them and go through all drivers so they keep up with the latest version? Maybe I'm just opinionated :-) but I strongly believe that we do need to own some critical stuff inside the registry and that a great API is a good API that don't let you shoot yourself in the foot. Drivers authors should focus on stuff that has value: provide storage primitives - not implement petty sanity checking. Either way :) |
On Fri, Nov 14, 2014 at 02:53:15PM -0800, Olivier Gambier wrote:
How is it easier? You have an infinite number of possible keys in
You don't have to carry third-party code. Suggested workflow:
With active upstream maintainers you get a.4, and everyone's happy.
Absolutely not. We write a test suite to validate all of the APIs,
No, whoever maintains net/url has you covered on the maintenance side,
Fair enough, I'm opinionated too ;). I'm fine making the
Encoding your keys so your backend can handle them doesn't sound like But all of my pushback hear is just me trying to save you future work |
We've added a path mapper to support simple mapping between path objects used in the storage layer and the underlying file system. The target of this is to ensure that paths are only calculated in a single place and their format is separated from the data that makes up the path components.
This commit only includes spec implementation to support layer reads. Further specs will come along with their implementations.