Skip to main content

Custom Types

A Dagger Module can have multiple object types defined. It's important to understand though, that they are only accessible through chaining, starting from a function in the main object.

Here is an example of a "github" module, with a function named dagger_organization that returns a custom Organization type, itself containing a collection of Account types:

import dagger
from dagger import dag, field, function, object_type


@object_type
class Account:
username: str = field()
email: str = field()
url: str = field(init=False)

def __post_init__(self):
self.url = f"https://github.com/{self.username}"


@object_type
class Organization:
name: str = field()
url: str = field()
repositories: list[dagger.GitRepository] = field(default=list)
members: list[Account] = field(default=list)

@classmethod
def create(cls, name: str, repositories: list[str], members: list[Account]):
url = f"https://github.com/{name}"
return cls(
name=name,
url=url,
repositories=[dag.git(f"{url}/{repo}") for repo in repositories],
members=members,
)


@object_type
class Github:
@function
def dagger_organization(self) -> Organization:
return Organization.create(
name="dagger",
repositories=["dagger"],
members=[
Account(username="jane", email="jane@example.com"),
Account(username="john", email="john@example.com"),
],
)

Remember that the dagger.field descriptors expose getter functions without arguments, for their attributes.

note

When the Dagger Engine extends the Dagger API schema with these types, it prefixes their names with the name of the main object:

  • Github
  • GithubAccount
  • GithubOrganization

This is to prevent possible naming conflicts when loading multiple modules, which is reflected in code generation (for example, when using this module in another one as a dependency).

Here's an example of calling this module to get all member URLs:

dagger call dagger-organization members url

The result will be:

https://github.com/jane
https://github.com/john