Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. Weā€™ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

šŸ–ļø Is it possible to access Host() from a dagger function? (Go SDK) #6955

Closed
tonirvega opened this issue Mar 27, 2024 · 13 comments
Closed

Comments

@tonirvega
Copy link

tonirvega commented Mar 27, 2024

How can I get access to the host from a dagger function?

I miss the Host() , Is there any way to do this?

package main
 
import (
 "context"
)
 
type MyModule struct{}
 
func (m *MyModule) Test(
 
 ctx context.Context,
 
) string {
 
       // Host() does not exist
 myDir := dag.Host().Directory("/tmp/my-directory")
 
 content, err := myDir.File("my-file").Contents(ctx)
 
        if err != nil {
  panic(err)
 }
 
       return content
  
}
 
@tonirvega tonirvega changed the title šŸ–ļø Is it possible to access `Host() from a dagger function? (Go SDK) šŸ–ļø Is it possible to access Host() from a dagger function? (Go SDK) Mar 27, 2024
@lsibilla
Copy link

I just installed dagger 0.10.3 this morning and have the same issue with Python SDK.

@tonirvega
Copy link
Author

I just installed dagger 0.10.3 this morning and have the same issue with Python SDK.

I'm in the 0.10.2

@purpleclay
Copy link
Contributor

I just installed dagger 0.10.3 this morning and have the same issue with Python SDK.

I'm in the 0.10.2

The approach to writing a Dagger module has changed since v10. If you need a directory from the host you can pass one in when invoking your function:

package main

import (
	"context"
)

type MyModule struct{}

func (m *MyModule) Test(ctx context.Context, dir *Directory) (string, error) {
	return dir.File("my-file").Contents(ctx)
}

Then you would call it by:

dagger call test --dir /tmp/my-directory

@tonirvega
Copy link
Author

I just installed dagger 0.10.3 this morning and have the same issue with Python SDK.

I'm in the 0.10.2

The approach to writing a Dagger module has changed since v10. If you need a directory from the host you can pass one in when invoking your function:

package main

import (
	"context"
)

type MyModule struct{}

func (m *MyModule) Test(ctx context.Context, dir *Directory) (string, error) {
	return dir.File("my-file").Contents(ctx)
}

Then you would call it by:

dagger call test --dir /tmp/my-directory

Thank you for your response.

So if I want to do it through code instead of a param I have to use a "standard" dagger workflow instead of a module function, right?

Greetings.

@purpleclay
Copy link
Contributor

@tonirvega That is my understanding of the difference between writing Dagger Modules and using a "standard" Dagger workflow. I am happy to be corrected by someone from the community šŸ˜„

@by-nelson
Copy link

I'm having some issues with this, I ran dagger init --sdk python with dagger version 0.10.3 but the documentation and code in the release don't match with the one I have in my sdk folder. Am I using a different sdk version or why is the Host class missing?

@helderco
Copy link
Contributor

helderco commented Apr 1, 2024

the documentation and code in the release don't match with the one I have in my sdk folder

@by-nelson, can you be more specific on what you mean?

Some APIs are only accessible in modules, and others may be the opposite. That's the case with Host. See https://docs.dagger.io/manuals/developer/overview/942201/execution-environment for more on this.

@by-nelson
Copy link

by-nelson commented Apr 1, 2024

@helderco sure, what I mean is that looking at the docs for the python SDK I see that there is a Host class and also that the Client class has a host() method for v0.10.3. But when I try it then I get that there is no host() property for Client.

Thanks!

@helderco
Copy link
Contributor

helderco commented Apr 2, 2024

Ok, great! šŸ™‚

I'm going to close as being answered.

  • In Dagger Functions, you need to explicitly accept a directory as argument, and provide it via the CLI which does have access to Host().
  • If the directory (or file) is inside the module's source directory, you can access it within the function (i.e., don't need an argument for it) with dag.CurrentModule().Source().
  • See the documentation on the Execution Environment for more on this.

@helderco helderco closed this as completed Apr 2, 2024
@noah-troncoso
Copy link

I came here looking for the same information as the OP. If we have to accept a Directory as a path, we lose the ability to setup include/exclude rules.

And based on all the documentation, it seems like modules and functions are the way to write dagger scripts now. If there is a normal Dagger workflow (as @purpleclay called it) where is this in the documentation?

@helderco
Copy link
Contributor

I came here looking for the same information as the OP. If we have to accept a Directory as a path, we lose the ability to setup include/exclude rules.

Not quite, we have a feature called views:

Itā€™s not yet documented because we need to polish the DX for managing it with the CLI:

We use it in our CI:

dagger/dagger.json

Lines 6 to 17 in e678cdd

"views": [
{
"name": "default",
"patterns": [
"!bin",
"!.git",
"!**/node_modules",
"!**/.venv",
"!**/__pycache__"
]
}
]

And we call it like:

dagger call --source=.:default test all

To be clear, this is only needed for files outside of the moduleā€™s source directory ("source" in dagger.json; defaults to the directory where dagger.json is). For that, you have:

dag.CurrentModule().Source()

And thereā€™s filters for limiting the files uploaded when loading a module. Example:

"include": [
"**/*.py",
"**/*.typed",
"**/pyproject.toml",
"**/*ruff.toml",
"LICENSE",
"README.md",
"hatch.toml",
"requirements/*.txt",
"docs/**/*.rst",
"dev/dagger.json"
],
"exclude": [
"docs/_build",
"**/.envrc",
"**/.direnv",
"**/.venv",
"*/sdk"
],

However, weā€™re discussing a change for how modules are loaded:

So that in the common case of needing access to the parent directory, you wonā€™t need to pass it as an argument and set up views. Youā€™ll be able to access it and filter from code:

func (m *MyModule) Source() *Directory {
 return dag.
  Context().
  Directory(ContextDirectoryOpts{Include: []string{"*.go"})
}

And based on all the documentation, it seems like modules and functions are the way to write dagger scripts now. If there is a normal Dagger workflow (as @purpleclay called it) where is this in the documentation?

The term ā€œnormalā€ here is only in the same sense of ā€œusualā€, but only for users that have used dagger for a while, before modules were released in v0.10.

We think that using Functions has many benefits over what came before but to clarify a few things:

  • Weā€™re not deprecating custom clients (dagger run), weā€™re considering it an advanced or niche use case. Sometimes itā€™s necessary. Everything should still work as before. Functions work on top of that, to improve the DX, but itā€™s the same API and works the same underneath, just more sandboxed. That's why there's more limitations when accessing host resources, but it's also more secure, reusable and portable (less boilerplate too).
  • We donā€™t want fragmentation in the ecosystem so itā€™s important to us that users with custom clients can call modules seamlessly. You can do it today, but you have to lower into making GraphQL queries rather than using the generated dagger.Client that all SDKs have. That work is scoped in: Call Dagger Functions from an external clientĀ #5993
  • For new users it would be too much to try to explain the two approaches so we decided to rewrite the docs in v0.10 to focus on the new approach. The previous docs are still available at https://archive.docs.dagger.io/0.9/ for those that are using that version. You may notice that link is featured on every page of the current docs, in a blue bar a the very top.
  • We didnā€™t have time to migrate all the content over to the new docs, but weā€™re currently very active in doing that. The priority is for documenting Functions, but eventually, weā€™ll probably have a guide for the custom client use case and how to interop with modules.

@noah-troncoso
Copy link

noah-troncoso commented May 11, 2024

Thanks for the information. This seems like a pretty fundamental thing that should have been ironed out before releasing these functions. Not to mention the DX for these "views" is awful. I need a single file added to a container, but with the views limited parameters, I can't figure out how.

{
  "name": "flagsmith-scripts",
  "sdk": "typescript",
  "source": "./dagger",
  "engineVersion": "v0.11.2",
  "views": [
    {
      "name": "npmrc",
	  "patterns": [
		"!**/*",
		"$HOME/.npmrc"
	  ]
    }
  ]
}

My assumption is that the projects root acts as the "baseDir". But I need a file in the home directory, as you can see. So based on the implemtation of "views", it seems I want to exclude everything from the "baseDir" and then just include my 1 file, but as you can guess, Dagger doesn't like this

@helderco
Copy link
Contributor

helderco commented May 11, 2024

If you only need a file you can have a dagger.File as a function argument and give the path to it in dagger call. No need for a view here.

But just for completeness, I'd have .npmrc as the only pattern in that view. The way it works is you use a view to filter a directory argument in the CLI, not to provide the directory itself.

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

No branches or pull requests

6 participants