#Write file back to host
1 messages · Page 1 of 1 (latest)
With the new dagger this is how my method looks like
func (m *Chainloop) InitAttestation(ctx context.Context) (*Container, error) {
c := dag.Container().
From(cliImage).
WithDirectory("/tmp", dag.Host().Directory(".")).
WithExec([]string{"attestation", "init"})
ok, err := c.Directory("/tmp").Export(ctx, ".")
if err != nil {
return nil, fmt.Errorf("exporting container: %w", err)
}
if !ok {
return nil, fmt.Errorf("exporting container: failed")
}
return c, nil
}
I can attest that the contain in fact can read the host path but I do not see it written back in my host.
Export doesn't seem to fail either
Write file back to host
also, what's the best way to debug this? I tried dagger shell init-attestation but that one returns instantly. Is it because my container image (cliImage) uses scratch container? TBH I am not sure if the shell command shells into my container or to the Dagger engine. Sorry I am new to this
In the new world, you wouldn't export from within the function. You can return a Directory or a File from the function and use the --output flag of the dagger CLI to save something to host.
dagger call -m mymod init-attestation -o .
Dagger calls are also chainable with the core API, so if you exported a container, you can do something like
dagger call -m mymod init-attestation directory --path "/tmp/mystate.json" -o "./mystatefolder"
I find it helpful to look at the CLI --help for each function to know what I can invoke. Since your function returns a container, if you do
dagger call -m mymod init-attestation --help
You'll see what I mean.
For zenith specific docs go here - https://docs.dagger.io/zenith/
thanks @covert coral for the answer. OK, so that confirms my suspicion. Let me check the chaining alternative you mentioned but it seems that to offer similar UX to our users (than the one we have with our native CLI today) we might need to do some state handling on our end.
I tested chaining and it works, it's a cool feature btw!
just a minor tweak on your comment, instead of
dagger call -m mymod init-attestation directory --path "/tmp/mystate.json" -o "./mystatefolder"
you seem to need to chain the export method too
dagger call -m mymod init-attestation directory --path "/tmp/mystate.json" export -path "./mystatefolder"
huh.. Which version of dagger are you on? I am on latest v0.9.8 and my code works. You don't have to do an export on the directory.
0.9.7, let me upgrade because this is what I get
$ dagger call init-attestation directory --path /tmp -o .
✘ load call ERROR [0.79s]
├ [0.55s] loading module
├ [0.25s] loading objects
├ [0.00s] traversing arguments
┃ Error: unknown shorthand flag: 'o' in -o
┃ Run 'dagger call init-attestation directory --help' for usage.
I am upgrading to latest, it seems that I need to change some code in my go module., like dag.Host() not available anymore.
Sorry for my ignorance, but where can I see the breaking changes in this new version, I can't seem to spot it in the GitHub release
Zenith breaking changes aren't well documented yet afaik. They are making improvements for the release though. I've been following new PRs to understand breaking changes myself.
@covert coral I am a bit reticent to upgrade my version since there are usually breakages. but given this amended function ```
@func
async addHostFile(directoryArg: Directory): Promise<Directory> {
const filename = ${Date.now().toString()}-foo.json;
const container = dag
.container()
.from("alpine:latest")
.withMountedDirectory("/mnt", directoryArg)
.withWorkdir("/mnt")
.withExec(["echo", `${crypto.randomBytes(7).toString("hex")}`, ">>", filename]);
const dir = container.directory("/mnt");
return dir;
}
I should be able to do something like this dagger call addHostFile --directory-arg /tmp/foo directory --path /mnt export --path /tmp/foo
So the change to chain the download command came in a later version. Have you tried
dagger download addHostFile --directory-arg /tmp/foo directory --path /mnt
By default --output is "." but you can specify a different path. Even in this case I don't think you need export.
I suggest updating to 0.9.8 though as there are some nice chaining conveniences. One of them being --output others being shell and up
ok so simplified function is now ``` @func
async addHostFile(): Promise<Directory> {
const filename = ${Date.now().toString()}-foo.json;
const container = dag
.container()
.from("alpine:latest")
.withWorkdir("/mnt")
.withEnvVariable("CACHEBUSTER", Date.now().toString())
.withExec(["sh", "-c", "echo", ${crypto.randomBytes(7).toString("hex")}, ">>", filename]);
return container.directory("/mnt");
}```
I don't need to mount the host folder since I'm just exporting
but when I run dagger download addHostFile directory --path /mnt
I get ✘ dagger download add-host-file directory ERROR [2.25s] ┃ Error: response from query: input: resolve: hostmod: addHostFile: directory: lstat /mnt/mnt: no suc ┃ h file or directory ┃ input: resolve: hostmod: addHostFile: directory: lstat /mnt/mnt: no such file or directory ✘ directory ERROR [0.00s] • Engine: e25b554b244d (version v0.9.7) ⧗ 5.73s ✔ 166 ∅ 43 ✘ 2
the --path flag is for the path of the exported dir?
I guess it's only for sub-directories, but it's weird that it's a required flag since you have to set an explicit path on the return value
Since you are already returning a Directory you don't have to chain the directory command in your CLI. All you have to do is dagger download add-host-file
If you were returning a Container and wanted to extract a directory via CLI you'd do something like dagger download add-host-file directory --path "path/of/file/in/container"
out of curiosity, is there any equivalent to this stanza that used to work pre 0.9.8?
WithDirectory("/tmp", dag.Host().Directory(".")).
basically loading some state from the host automatically, without requiring to pass it explicitly in the path. Is it possible?
No, from 0.9.8 onwards the only way to access a directory on the host is to pass it in, either as a function arg or CLI. Recent discussion around same - https://discord.com/channels/707636530424053791/1204498856339963904
ok! Makes sense
lastly, I am trying to pass a single file to the function, so I was thinking about using the File dagger primitive.
Getting a signature similar to
func (m *Chainloop) AttestationAdd(ctx context.Context, name string, value *File) *Container {
but I am trying to retrieve the file name, but it seems to have all props nil except q, and c.
&{q:0xc00011c840 c:{Client:0xc0000a08d0} contents:<nil> export:<nil> id:<nil> name:<nil> size:<nil> sync:<nil>}
Do I need to resolve this file or smth to know it's filename?
hmm, how did you pass the file in?
are you able to cat the contents of it within the container? The name field was added fairly recently - https://github.com/dagger/dagger/pull/6431