#Does Dagger support Jobs?

1 messages · Page 1 of 1 (latest)

spare atlas
#

I know about services (long-running containers) but what about jobs (containers that complete a task and exit)?

It would be an equivalent to a Kubernetes Job. When Dagger catches the appropriate container exit code it would exit itself.

warped valve
#

Hey Kenneth!

You mean the engine itself would exit or are you talking about a dagger call?

spare atlas
#

ok so Ive been digging around in the Service docs and I saw this:

package main

import (
    "context"
)

type MyModule struct{}

// Start and return an HTTP service
func (m *MyModule) HttpService() *Service {
    return dag.Container().
        From("python").
        WithWorkdir("/srv").
        WithNewFile("index.html", ContainerWithNewFileOpts{
            Contents: "Hello, world!",
        }).
        WithExec([]string{"python", "-m", "http.server", "8080"}).
        WithExposedPort(8080).
        AsService()
}

// Send a request to an HTTP service and return the response
func (m *MyModule) Get(ctx context.Context) (string, error) {
    return dag.Container().
        From("alpine").
        WithServiceBinding("www", m.HttpService()).
        WithExec([]string{"wget", "-O-", "http://www:8080"}).
        Stdout(ctx)
}
#

The Dagger function Get executes the wget command in the canonical dagger way it seems. During build time, right?

abstract ledge
spare atlas
abstract ledge
#

@spare atlas OK understood. A very understandable question.

#

Think of Dagger as a very specialized container engine. Instead of running applications, it runs pipelines. It doesn't matter if it's a build pipeline, test pipeline, deployment pipeline, or weird-mix-of-things pipeline. Dagger doesn't differentiate: you make calls to the Dagger API, to model your pipeline as a graph (DAG) of steps, with artifacts flowing between them. Then Dagger orchestrates all the steps by running them in containers in the correct sequence, and moving the artifacts around. And then you get the result

#

TLDR: from Dagger's point of view, your "build" is just another pipeline to "run"

#

this comes in particularly handy because, almost always, your build pipeline itself has dependencies, and those dependencies also need to be built, and so on. With more rigid systems, which force you to make a strong distinction between what is "run" and what is "build", that's where things become really complicated. But with Dagger it's just a bigger DAG. No fundamental difference.

#

For example, say in your example above, you decide that instead of pulling a python image from Docker hub (From("Python")) you want to build a custom python image yourself. Normally you would have to worry about that out of band, in a different pipeline: build a python image; push it to a registry; then pull it in this pipeline. But instead you can just do it all on the fly:

package main

import (
    "context"
)

type MyModule struct{}

// Build a custom python container
func (m *MyModule) Python(version string) *Container {
  return dag.
    Container().
    From("alpine:latest").
    WithExec([]string{"apk", "add", "python=" + version}).
    WithExec([]string{"pip", "install", "stuff", "morestuff"})
}

// Start and return an HTTP service
func (m *MyModule) HttpService() *Service {
    return m.
        Python().
        WithWorkdir("/srv").
        WithNewFile("index.html", ContainerWithNewFileOpts{
            Contents: "Hello, world!",
        }).
        WithExec([]string{"python", "-m", "http.server", "8080"}).
        WithExposedPort(8080).
        AsService()
}

// Send a request to an HTTP service and return the response
func (m *MyModule) Get(ctx context.Context) (string, error) {
    return dag.Container().
        From("alpine").
        WithServiceBinding("www", m.HttpService()).
        WithExec([]string{"wget", "-O-", "http://www:8080"}).
        Stdout(ctx)
}
abstract ledge
#

It's pretty addictive