#I'm trying to grok the consequences of having merged interface support.
1 messages · Page 1 of 1 (latest)
Can't do that yet, what's merged is the most basic possible support. Goal was to get the plumbing in place and solve some immediate basic problems, but we haven't updated the core API to use interfaces anywhere yet.
Right now what you can do is define an interface when authoring a Go sdk module and use that in your argument/return types. Docs are a TODO but you can look at the Example section of the PR's description: https://github.com/dagger/dagger/pull/6254
So right now its main utility is that it allows you to author modules that can accept/return types from outside your own module's schema (was impossible before this) and without being specific to one implementation of those types.
But we do have a path to start using it in the core API now too, which I agree would be great for Service and a bunch of other use cases like that
I'm trying to grok the consequences of having merged interface support.
Can DaggerObject be used with custom structs as well?
Interfaces are useful for reusability, but they are not very useful in internal pipelines.
DaggerObject is only meant for including in interfaces; it's required there because we can't accept completely arbitrary go structs, they have to be dagger api objects. But I don't think it would be useful to use outside of that since the only methods it defines are ones used internally by the SDK (stuff around IDs + serialization).
Interfaces are useful for reusability, but they are not very useful in internal pipelines.
Yeah the primary goal to start out here was to unblock certain use cases around module interop that were previously impossible:
- Modules can accept objects from arbitrary other modules (without the need for an explicit dependency on the module implementing them)
- Modules can return objects from arbitrary other modules without exposing the transitive dependency to the caller (which unleashes dependency hell problems).
But we went with the interface approach because it solves those problems and enables a bunch of more stuff down the line. We have a few follow up issues around that already, but curious what use cases you had in mind around "internal pipelines". Can make sure it's covered in the follow up issues or open new ones if not.
Currently I'm working on a release pipeline that replaces roughly what goreleaser is today (I'm not trying to rebuild goreleaser, just the parts that are useful to us)
Currently the whole thing is in a single CI module in a project. In the future, it might be useful to share pieces of the code, but not right now.
one of the "challenges" I have is passing platform specific release assets around in the pipeline. My current approach is an interface like this:
type PlatformAssets interface {
DaggerObject
Platform()
Files() []*File
}
The fact that it's an interface is not very useful in my case though, since the code lives in a single module. (Well, not anymore, because interfaces can't be used in the same module at the moment)
In any case, besides the limitations of the current implementation, using an interface is just not very useful and introduces additional complexity (namely, having to create two entities for the same thing)
It's not the end of the world, but it does introduce some mental and technical overhead in the beginning. I'm not used to introducing abstractions until necessary or an API seems to emerge from a particular use case and Dagger forces me to change the way I usually write software in this instance.
FYI I'm going to present my current pipeline to Jenn, Marcos and others tomorrow to look at some caching issues I have, but the pipeline is the same, so I can show you what I'm working on if you are interested.
Would it make sense to use pragmas instead of interface embedding?
// +object
type Builder interface {
}
@ashen ridge in your case I would just use a struct, I think
but maybe another module might define an interface for an abstract artifact, and you might choose to implement that interface. Then that module could use your asset type without knowing its underlying type. At least that's what comes to mind
Well, I would definitely return a struct. My understanding is that you can't even return an interface defined in a different module right now.
The problem is, from what I can tell, is that you cannot pass in a custom struct to a function.
So that's what I'm trying right now.
@nimble mesa should this work for structs returned from modules as well?
For example:
dag.Archiver().Tar().AsArchiverr() ?
This is the interface:
type Archiverr interface {
DaggerObject
Archive(ctx context.Context, name string, source *Directory) *File
}
Tried every combination of adding/removing context and error.
This is the other module:
// Archiver provides methods to create and extract archives.
type Archiver struct {}
// Create and extract ".tar" archives.
func (m *Archiver) Tar() *Tar {
return &Tar{}
}
// Create and extract ".tar" archives.
type Tar struct{}
func (m *Tar) Archive(name string, source *Directory) *File {
return arc().ArchiveDirectory(name, source).Tar()
}
Tar in theory implements the interface.