Skip to content

introduce ResourceResolver to accept remote resources#435

Merged
ndeloof merged 1 commit intocompose-spec:masterfrom
ndeloof:remote_resource
Aug 9, 2023
Merged

introduce ResourceResolver to accept remote resources#435
ndeloof merged 1 commit intocompose-spec:masterfrom
ndeloof:remote_resource

Conversation

@ndeloof
Copy link
Copy Markdown
Collaborator

@ndeloof ndeloof commented Jul 13, 2023

ResourceLoaders can be configured by Compose implementation to support remote resources with extends and include. This will allow users to rely on compose.yaml files published by others, without the need for a mono-repo.

illustration example:

include:
   - git@github.com:acme/commons.git#v2.0:compose.yaml

If this feature demonstrates some significant use for a specific protocol (git, http, oci-artifacts ?) we could make those part of the compose specification and offer a default loader implementation in compose-go

We also could extend this support to other places compose loads files, typically with env_file and secret.file but I'd prefer we keep this focussed on a simpler use-case for a first round.

https://docker.atlassian.net/browse/ENV-251

@ndeloof ndeloof force-pushed the remote_resource branch 6 times, most recently from e63912e to 6d059a4 Compare July 17, 2023 08:40
Copy link
Copy Markdown
Member

@laurazard laurazard left a comment

Choose a reason for hiding this comment

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

LGTM overall, just left a couple nits/a question

@ndeloof ndeloof force-pushed the remote_resource branch 2 times, most recently from ec2ed71 to 61a94cb Compare July 17, 2023 12:48
@ndeloof
Copy link
Copy Markdown
Collaborator Author

ndeloof commented Jul 17, 2023

added example code using this feature to support git resources: docker/compose#10811

// Accept returns `true` is the resource reference matches ResourceLoader supported protocol(s)
Accept(path string) bool
// Load returns the path to a local copy of remote resource identified by `path`.
Load(ctx context.Context, path string) (string, error)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Would it make sense to actually return the contents as []byte here? Internally, loader implementations could do on-disk caching for performance, but externally it could be more of a "store"/VFS interface.

That'd let us use this consistently in all code-paths, aka have a FilesystemLoader as the default/fallback. (Not suggesting that as part of this PR, just looking forward.)

That'd make testing easier in some cases, and hopefully help address some of the implicit direct I/O that happens, e.g. include / extends / file references in secrets, env_file, etc

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

I had this in mind first, but there are many places we also load sibling content, and as such we really need a path so we can search within parent folder.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Right, I had the same thought and then ended up looking around and deciding that returning a local path might make more sense in the long run. Okay with both implementations though.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Joining @milas on this, I would actually love to see some Afero in action here.
It looks like the CopyOnWriteFs would look great for this use case.
And it would handle the case of sibling files too.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Ah yeah the sibling content makes sense and needs more thought. I guess a good first step (independent of this) would be to virtualize/abstract the direct filesystem operations happening and could then offer an updated loader interface that works with that.

@ulyssessouza Good reminder about Afero, we could definitely make interfaces compatible with them in compose-go so it's easy to plug their implementations in. There's also the newer io.FS stuff in Go which might work since compose-go only reads but never writes.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

I agree it would be nice we could rely on some higher level abstraction like the io.fs package, but as this all results into a types.ConfigDetails which uses file paths as strings this won't be very relevant afaict (not to mention the required refactoring is far from being trivial)

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

@ulyssessouza @milas we can't use such an abstraction as we need an actual file path to populate attributes we pass directly to engine API, like build context or bind mount source.

Copy link
Copy Markdown
Collaborator

@glours glours left a comment

Choose a reason for hiding this comment

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

Sounds good to me 👍

Copy link
Copy Markdown
Member

@milas milas left a comment

Choose a reason for hiding this comment

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

As a POC, it LGTM, but this does go against the spec: https://docs.docker.com/compose/compose-file/05-services/#finding-referenced-service

file value can be:

  • Not present. This indicates that another service within the same Compose file is being referenced.
  • File path, which can be either:
    • Relative path. This path is considered as relative to the location of the main Compose file.
    • Absolute path.

Everything in the spec is about file paths currently and currently compose-go is all that's needed to load any arbitrary Compose file.

With this change, if a Compose file gets loaded that uses remote resources, if the caller doesn't have an appropriate loader in place, it will silently fallback to trying to make things file paths, e.g. https://example.com/compose.yaml -> /Users/milas/myproject/https://example.com/compose.yaml and then fail.

At a minimum, I think we need to define an unambiguous distinction in the spec between local file paths and remote resources, e.g. remote resource must start with a protocol ([a-z]+://), and if no loader is registered for the desired protocol, an error is returned. Values without a protocol (or an explicit file://) could continue to be treated as file paths.

extends.file could be the first part then updated to reference "a resource path" as a generic concept, for example.

Beyond that, I'd also argue we should consider having a standard set of remote loaders (http(s), git) live in SUBmodules of compose-go so that they're usable outside of docker/compose.

}

imported, err := load(types.ConfigDetails{
imported, err := load(nil, types.ConfigDetails{
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
imported, err := load(nil, types.ConfigDetails{
imported, err := load(ctx, types.ConfigDetails{

loader/loader.go Outdated
}

// Load reads a ConfigDetails and returns a fully loaded configuration
// Load deprecated, prefer LoadWithContext
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
// Load deprecated, prefer LoadWithContext
// Load reads a ConfigDetails and returns a fully loaded configuration.
//
// Deprecated: use LoadWithContext.

This should make it show up as deprecated in IDEs and hide it on pkg.dev

@ndeloof ndeloof force-pushed the remote_resource branch 2 times, most recently from 3a240cc to 88eace5 Compare August 7, 2023 06:29
Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
@ndeloof ndeloof requested a review from milas August 8, 2023 14:02
@ndeloof ndeloof merged commit 339d49d into compose-spec:master Aug 9, 2023
ndeloof added a commit to ndeloof/compose-go that referenced this pull request Aug 10, 2023
Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants