#Write file back to host

1 messages · Page 1 of 1 (latest)

sudden depot
#

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

covert coral
#

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.

sudden depot
#

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.

sudden depot
#

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"
covert coral
#

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.

sudden depot
#

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

covert coral
#

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.

mortal copper
#

@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

covert coral
#

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

mortal copper
#

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

covert coral
#

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"

sudden depot
#

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?

covert coral
sudden depot
#

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?

covert coral
#

hmm, how did you pass the file in?

sudden depot
#

my bad! I was calling file.name instead of the method file.Name(ctx)

#

having all these helpers as part of the same package, which in hence allows me to see unexported props is what confused me