Skip to main content

Constructors

Every Dagger module has a constructor. The default one is generated automatically and has no arguments.

It's possible to write a custom constructor. The mechanism to do this is SDK-specific.

This is a simple way to accept module-wide configuration, or just to set a few attributes without having to create setter functions for them.

Simple constructor

The default constructor for a module can be overridden by registering a custom constructor. Its parameters are available as flags in the dagger call command directly.

important

Dagger modules have only one constructors. Constructors of custom types are not registered; they are constructed by the function that chains them.

Here is an example module with a custom constructor:

// A Dagger module for saying hello world!

package main

import (
"fmt"
)

func New(
// +optional
// +default="Hello"
greeting string,
// +optional
// +default="World"
name string,
) *MyModule {
return &MyModule{
Greeting: greeting,
Name: name,
}
}

type MyModule struct {
Greeting string
Name string
}

func (hello *MyModule) Message() string {
return fmt.Sprintf("%s, %s!", hello.Greeting, hello.Name)
}

Here is an example call for this Dagger Function:

dagger call --name=Foo message

The result will be:

Hello, Foo!
important

If you plan to use constructor fields in other module functions, ensure that they are declared as public (in Go and TypeScript). This is because Dagger stores fields using serialization and private fields are omitted during the serialization process. As a result, if a field is not declared as public, calling methods that use it will produce unexpected results.

Default values for complex types

Constructors can be passed both simple and complex types (such as Container, Directory, Service etc.) as arguments. Default values can be assigned in both cases.

Here is an example of a Dagger module with a default constructor argument of type Container:

package main

import (
"context"

"main/internal/dagger"
)

func New(
// +optional
ctr *dagger.Container,
) *MyModule {
if ctr == nil {
ctr = dag.Container().From("alpine:3.14.0")
}
return &MyModule{
Ctr: *ctr,
}
}

type MyModule struct {
Ctr dagger.Container
}

func (m *MyModule) Version(ctx context.Context) (string, error) {
c := m.Ctr
return c.
WithExec([]string{"/bin/sh", "-c", "cat /etc/os-release | grep VERSION_ID"}).
Stdout(ctx)
}

It is necessary to explicitly declare the type even when a default value is assigned, so that the Dagger SDK can extend the GraphQL schema correctly.

Here is an example call for this Dagger Function:

dagger call version

The result will be:

VERSION_ID=3.14.0