dalec

package module
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 23, 2024 License: MIT Imports: 23 Imported by: 1

README

Dalec

Dalec is a project aimed at providing a declarative format for building system packages and containers from those packages. Dalec is still under heavy development and the spec format is not currently considered stable.

Currently only support for Azure Linux (CBL-Mariner 2.0) is available but support for other Linux distributions and operating systems is planned and is already pluggable.

Usage

Dalec is currently provided as a buildkit frontend which enables you to use dalec with tools like docker build. You can find the JSON schema for the dalec spec in docs/spec.schema.json.

You will need to add a syntax directive at the top of your spec file to enable the dalec frontend:

# syntax=ghcr.io/azure/dalec/frontend:latest
Exmples:

You can look at the test/fixtures directory for examples of dalec specs.

Build an rpm for mariner2:

$ docker build -f test/fixtures/moby-runc.yml --target mariner2/rpm --output=_output .
<output truncated>

With this command you should have a _output/RPMS/<arch>, _output/RPMS/noarch, and _output/SRPMS directories with the built RPM and SRPM files.

Build a container for mariner2:

$ docker build -f test/fixtures/moby-runc.yml --target mariner2/container -t test-runc-container:example .

This container will have the rpm along with all its dependencies installed. The base image used for the container is determined by the target. For mariner2 this is mcr.microsoft.com/cbl-mariner/distroless/base:2.0. This can be customized in your yaml spec for the target. Example:

targets:
    mariner2:
        image:
            base: mcr.microsoft.com/cbl-mariner/base/core:2.0

Dalec will try to detect if the image is a "distroless" image by checking if the rpm binary is present. If it is present then dalec assumes the image is not distroless and installs the rpm like normal. When the image is distroless the rpm is installed and then the rpm database is cleaned up and rpm manifests are created at /var/lib/rpmmanifest.

To print a list of available build targets:

$ BUILDX_EXPERIMENTAL=1 docker build --print=targets -f test/fixtures/moby-runc.yml .
debug/resolve                Outputs the resolved dalec spec file with build args applied.
mariner2                     Alias for target mariner2/container
mariner2/container (default) Builds a container with the RPM installed.
mariner2/rpm                 Builds an rpm and src.rpm for mariner2.
mariner2/rpm/buildroot       Outputs an rpm buildroot suitable for passing to rpmbuild.
mariner2/rpm/sources         Outputs all the sources specified in the spec file.
mariner2/rpm/spec            Outputs the generated RPM spec file

Support for other OSes and Linux distributions

Dalec can never hope to bake in support for every OS and Linux distribution. Dalec is designed to be pluggable. Even if the base dalec frontend does not support your distro/OS of choice, the spec format is designed to allow referencing a custom frontend. This way you can support other distros/OSes without having to fork dalec, wait for a new release, or even change the syntax directive in your spec file.

Additionally, the structure of dalec is such that you can use dalec as a library to build your frontend. In the frontend package you can register your build targets with frontend.RegisterTarget and then use frontend.Build as the buildkit BuildFunc See ./cmd/frontend/main.go for how this is used.

Example
# ...
targets:
  custom_distro:
    frontend:
        image: <frontend image>
# ...

Contributing

This project welcomes contributions and suggestions. Most contributions require you to agree to a Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us the rights to use your contribution. For details, visit https://cla.opensource.microsoft.com.

When you submit a pull request, a CLA bot will automatically determine whether you need to provide a CLA and decorate the PR appropriately (e.g., status check, comment). Simply follow the instructions provided by the bot. You will only need to do this once across all repos using our CLA.

This project has adopted the Microsoft Open Source Code of Conduct. For more information see the Code of Conduct FAQ or contact opencode@microsoft.com with any additional questions or comments.

Trademarks

This project may contain trademarks or logos for projects, products, or services. Authorized use of Microsoft trademarks or logos is subject to and must follow Microsoft's Trademark & Brand Guidelines. Use of Microsoft trademarks or logos in modified versions of this project must not cause confusion or imply Microsoft sponsorship. Any use of third-party trademarks or logos are subject to those third-party's policies.

Documentation

Index

Constants

View Source
const DefaultPatchStrip int = 1

Variables

This section is empty.

Functions

func CacheDirsToRunOpt

func CacheDirsToRunOpt(mounts map[string]CacheDirConfig, distroKey, archKey string) llb.RunOption

CacheDirsToRunOpt converts the given cache directories into a RunOption.

func DisableDiffMerge

func DisableDiffMerge(v bool)

DisableDiffMerge allows disabling the use of llb.Diff and llb.Merge in favor of llb.Copy. This is needed when the buildkit version does not support llb.Diff and llb.Merge.

Mainly this would be to allow dockerd with the (current) standard setup of dockerd which uses "graphdrivers" to work as these ops are not supported by the graphdriver backend. When this is false and the graphdriver backend is used, the build will fail when buildkit checks the capabilities of the backend.

func DuplicateMap

func DuplicateMap[K comparable, V any](m map[K]V) map[K]V

func MergeAtPath

func MergeAtPath(input llb.State, states []llb.State, dest string) llb.State

MergeAtPath merges the given states into the given destination path in the given input state.

func PatchSources

func PatchSources(worker llb.State, spec *Spec, sourceToState map[string]llb.State, opts ...llb.ConstraintsOpt) map[string]llb.State

`sourceToState` must be a complete map from source name -> llb state for each source in the dalec spec. `worker` must be an LLB state with a `patch` binary present. PatchSources returns a new map containing the patched LLB state for each source in the source map.

func ProgressGroup

func ProgressGroup(name string) llb.ConstraintsOpt

ProgressGroup creates a progress group with the given name. If a progress group is already set in the constraints the id is reused. If no progress group is set a new id is generated.

func SortMapKeys

func SortMapKeys[T any](m map[string]T) []string

SortMapKeys is a convenience generic function to sort the keys of a map[string]T

func SourceIsDir

func SourceIsDir(src Source) (bool, error)

func WithConstraints

func WithConstraints(ls ...llb.ConstraintsOpt) llb.ConstraintsOpt

func WithCreateDestPath

func WithCreateDestPath() llb.CopyOption

func WithDirContentsOnly

func WithDirContentsOnly() llb.CopyOption

func WithExcludes

func WithExcludes(patterns []string) llb.CopyOption

func WithIncludes

func WithIncludes(patterns []string) llb.CopyOption

Types

type ArtifactBuild

type ArtifactBuild struct {
	// Steps is the list of commands to run to build the artifact(s).
	// Each step is run sequentially and will be cached accordingly depending on the frontend implementation.
	Steps []BuildStep `yaml:"steps" json:"steps" jsonschema:"required"`
	// Env is the list of environment variables to set for all commands in this step group.
	Env map[string]string `yaml:"env,omitempty" json:"env,omitempty"`
}

ArtifactBuild configures a group of steps that are run sequentially along with their outputs to build the artifact(s).

type ArtifactConfig

type ArtifactConfig struct {
	// Subpath is the subpath to use in the package for the artifact type.
	//
	// As an example, binaries are typically placed in /usr/bin when installed.
	// If you want to nest them in a subdirectory, you can specify it here.
	SubPath string `yaml:"subpath,omitempty" json:"subpath,omitempty"`
	// Name is file or dir name to use for the artifact in the package.
	// If empty, the file or dir name from the produced artifact will be used.
	Name string `yaml:"name,omitempty" json:"name,omitempty"`
}

ArtifactConfig is the configuration for a given artifact type. This is used to customize where an artifact will be placed when installed.

type Artifacts

type Artifacts struct {
	// Binaries is the list of binaries to include in the package.
	Binaries map[string]ArtifactConfig `yaml:"binaries,omitempty" json:"binaries,omitempty"`
	// Manpages is the list of manpages to include in the package.
	Manpages map[string]ArtifactConfig `yaml:"manpages,omitempty" json:"manpages,omitempty"`
}

Artifacts describes all the artifacts to include in the package. Artifacts are broken down into types, e.g. binaries, manpages, etc. This differentiation is used to determine where to place the artifact on install.

func (*Artifacts) IsEmpty

func (a *Artifacts) IsEmpty() bool

IsEmpty is used to determine if there are any artifacts to include in the package.

type BuildStep

type BuildStep struct {
	// Command is the command to run to build the artifact(s).
	// This will always be wrapped as /bin/sh -c "<command>", or whatever the equivalent is for the target distro.
	Command string `yaml:"command" json:"command" jsonschema:"required"`
	// Env is the list of environment variables to set for the command.
	Env map[string]string `yaml:"env,omitempty" json:"env,omitempty"`
}

BuildStep is used to execute a command to build the artifact(s).

type CacheDirConfig

type CacheDirConfig struct {
	// Mode is the locking mode to set on the cache directory
	// values: shared, private, locked
	// default: shared
	Mode string `yaml:"mode,omitempty" json:"mode,omitempty" jsonschema:"enum=shared,enum=private,enum=locked"`
	// Key is the cache key to use to cache the directory
	// default: Value of `Path`
	Key string `yaml:"key,omitempty" json:"key,omitempty"`
	// IncludeDistroKey is used to include the distro key as part of the cache key
	// What this key is depends on the frontend implementation
	// Example for Debian Buster may be "buster"
	//
	// An example use for this is with a Go(lang) build cache when CGO is included.
	// Go is unable to invalidate cgo and re-using the same cache across different distros may cause issues.
	IncludeDistroKey bool `yaml:"include_distro_key,omitempty" json:"include_distro_key,omitempty"`
	// IncludeArchKey is used to include the architecture key as part of the cache key
	// What this key is depends on the frontend implementation
	// Frontends SHOULD use the buildkit platform arch
	//
	// As with [IncludeDistroKey], this is useful for Go(lang) builds with CGO.
	IncludeArchKey bool `yaml:"include_arch_key,omitempty" json:"include_arch_key,omitempty"`
}

CacheDirConfig configures a persistent cache to be used across builds.

type ChangelogEntry

type ChangelogEntry struct {
	// Date is the date of the changelog entry.
	Date time.Time `yaml:"date" json:"date" jsonschema:"oneof_required=date"`
	// Author is the author of the changelog entry. e.g. `John Smith <john.smith@example.com>`
	Author string `yaml:"author" json:"author"`
	// Changes is the list of changes in the changelog entry.
	Changes []string `yaml:"changes" json:"changes"`
}

ChangelogEntry is an entry in the changelog. This is used to generate the changelog for the package.

type CheckOutput

type CheckOutput struct {
	// Equals is the exact string to compare the output to.
	Equals string `yaml:"equals,omitempty" json:"equals,omitempty"`
	// Contains is the list of strings to check if they are contained in the output.
	Contains []string `yaml:"contains,omitempty" json:"contains,omitempty"`
	// Matches is the regular expression to match the output against.
	Matches string `yaml:"matches,omitempty" json:"matches,omitempty"`
	// StartsWith is the string to check if the output starts with.
	StartsWith string `yaml:"starts_with,omitempty" json:"starts_with,omitempty"`
	// EndsWith is the string to check if the output ends with.
	EndsWith string `yaml:"ends_with,omitempty" json:"ends_with,omitempty"`
	// Empty is used to check if the output is empty.
	Empty bool `yaml:"empty,omitempty" json:"empty,omitempty"`
}

CheckOutput is used to specify the exepcted output of a check, such as stdout/stderr or a file. All non-empty fields will be checked.

func (CheckOutput) Check

func (c CheckOutput) Check(dt string, p string) (retErr error)

Check is used to check the output stream.

func (CheckOutput) IsEmpty

func (c CheckOutput) IsEmpty() bool

IsEmpty is used to determine if there are any checks to perform.

type CheckOutputError

type CheckOutputError struct {
	Kind     string
	Expected string
	Actual   string
	Path     string
}

CheckOutputError is used to build an error message for a failed output check for a test case.

func (*CheckOutputError) Error

func (c *CheckOutputError) Error() string

type Command

type Command struct {
	// Dir is the working directory to run the command in.
	Dir string `yaml:"dir,omitempty" json:"dir,omitempty"`

	// Mounts is the list of sources to mount into the build steps.
	Mounts []SourceMount `yaml:"mounts,omitempty" json:"mounts,omitempty"`

	// List of CacheDirs which will be used across all Steps
	CacheDirs map[string]CacheDirConfig `yaml:"cache_dirs,omitempty" json:"cache_dirs,omitempty"`

	// Env is the list of environment variables to set for all commands in this step group.
	Env map[string]string `yaml:"env,omitempty" json:"env,omitempty"`

	// Steps is the list of commands to run to generate the source.
	// Steps are run sequentially and results of each step should be cached.
	Steps []*BuildStep `yaml:"steps" json:"steps" jsonschema:"required"`
}

Command is used to execute a command to generate a source from a docker image.

type FileCheckOutput

type FileCheckOutput struct {
	CheckOutput `yaml:",inline"`
	// Permissions is the expected permissions of the file.
	Permissions fs.FileMode `yaml:"permissions,omitempty" json:"permissions,omitempty"`
	// IsDir is used to set the expected file mode to a directory.
	IsDir bool `yaml:"is_dir,omitempty" json:"is_dir,omitempty"`
	// NotExist is used to check that the file does not exist.
	NotExist bool `yaml:"not_exist,omitempty" json:"not_exist,omitempty"`
}

FileCheckOutput is used to specify the expected output of a file.

func (FileCheckOutput) Check

func (c FileCheckOutput) Check(dt string, mode fs.FileMode, isDir bool, p string) error

Check is used to check the output file.

type ForwarderFunc

type ForwarderFunc func(llb.State, *SourceBuild) (llb.State, error)

type Frontend

type Frontend struct {
	// Image specifies the frontend image to forward the build to.
	// This can be left unspecified *if* the original frontend has builtin support for the distro.
	//
	// If the original frontend does not have builtin support for the distro, this must be specified or the build will fail.
	// If this is specified then it MUST be used.
	Image string `yaml:"image,omitempty" json:"image,omitempty" jsonschema:"required,example=docker.io/my/frontend:latest"`
	// CmdLine is the command line to use to forward the build to the frontend.
	// By default the frontend image's entrypoint/cmd is used.
	CmdLine string `yaml:"cmdline,omitempty" json:"cmdline,omitempty"`
}

Frontend encapsulates the configuration for a frontend to forward a build target to.

type ImageConfig

type ImageConfig struct {
	// Entrypoint sets the image's "entrypoint" field.
	// This is used to control the default command to run when the image is run.
	Entrypoint string `yaml:"entrypoint,omitempty" json:"entrypoint,omitempty"`
	// Cmd sets the image's "cmd" field.
	// When entrypoint is set, this is used as the default arguments to the entrypoint.
	// When entrypoint is not set, this is used as the default command to run.
	Cmd string `yaml:"cmd,omitempty" json:"cmd,omitempty"`
	// Env is the list of environment variables to set in the image.
	Env []string `yaml:"env,omitempty" json:"env,omitempty"`
	// Labels is the list of labels to set in the image metadata.
	Labels map[string]string `yaml:"labels,omitempty" json:"labels,omitempty"`
	// Volumes is the list of volumes for the image.
	// Volumes instruct the runtime to bypass the any copy-on-write filesystems and mount the volume directly to the container.
	Volumes map[string]struct{} `yaml:"volumes,omitempty" json:"volumes,omitempty"`
	// WorkingDir is the working directory to set in the image.
	// This sets the directory the container will start in.
	WorkingDir string `yaml:"working_dir,omitempty" json:"working_dir,omitempty"`
	// StopSignal is the signal to send to the container to stop it.
	// This is used to stop the container gracefully.
	StopSignal string `yaml:"stop_signal,omitempty" json:"stop_signal,omitempty" jsonschema:"example=SIGTERM"`
	// Base is the base image to use for the output image.
	// This only affects the output image, not the intermediate build image.
	Base string `yaml:"base,omitempty" json:"base,omitempty"`

	// Post is the post install configuration for the image.
	// This allows making additional modifications to the container rootfs after the package(s) are installed.
	//
	// Use this to perform actions that would otherwise require additional tooling inside the container that is not relavent to
	// the resulting container and makes a post-install script as part of the package unnecessary.
	Post *PostInstall `yaml:"post,omitempty" json:"post,omitempty"`
}

ImageConfig is the configuration for the output image. When the target output is a container image, this is used to configure the image.

type InvalidSourceError

type InvalidSourceError struct {
	Name string
	Err  error
}

InvalidSourceError is an error type returned when a source is invalid.

func (*InvalidSourceError) Error

func (s *InvalidSourceError) Error() string

func (*InvalidSourceError) Unwrap

func (s *InvalidSourceError) Unwrap() error

type LLBGetter

type LLBGetter func(sOpts SourceOpts, opts ...llb.ConstraintsOpt) (llb.State, error)

func Source2LLBGetter

func Source2LLBGetter(s *Spec, src Source, name string) LLBGetter

type PackageDependencies

type PackageDependencies struct {
	// Build is the list of packagese required to build the package.
	Build map[string][]string `yaml:"build,omitempty" json:"build,omitempty"`
	// Runtime is the list of packages required to install/run the package.
	Runtime map[string][]string `yaml:"runtime,omitempty" json:"runtime,omitempty"`
	// Recommends is the list of packages recommended to install with the generated package.
	// Note: Not all package managers support this (e.g. rpm)
	Recommends map[string][]string `yaml:"recommends,omitempty" json:"recommends,omitempty"`

	// Test lists any extra packages required for running tests
	Test []string `yaml:"test,omitempty" json:"test,omitempty"`
}

PackageDependencies is a list of dependencies for a package. This will be included in the package metadata so that the package manager can install the dependencies. It also includes build-time dedendencies, which we'll install before running any build steps.

type PatchSpec

type PatchSpec struct {
	// Source is the name of the source that contains the patch to apply.
	Source string `yaml:"source" json:"source" jsonschema:"required"`
	// Strip is the number of leading path components to strip from the patch.
	// The default is 1 which is typical of a git diff.
	Strip *int `yaml:"strip,omitempty" json:"strip,omitempty"`
}

PatchSpec is used to apply a patch to a source with a given set of options. This is used in [Spec.Patches]

type PostInstall

type PostInstall struct {
	// Symlinks is the list of symlinks to create in the container rootfs after the package(s) are installed.
	// The key is the path the symlink should point to.
	Symlinks map[string]SymlinkTarget `yaml:"symlinks,omitempty" json:"symlinks,omitempty"`
}

PostInstall is the post install configuration for the image.

type Source

type Source struct {
	// This is an embedded union representing all of the possible source types.
	// Exactly one must be non-nil, with all other cases being errors.
	//
	// === Begin Source Variants ===
	DockerImage *SourceDockerImage `yaml:"image,omitempty" json:"image,omitempty"`
	Git         *SourceGit         `yaml:"git,omitempty" json:"git,omitempty"`
	HTTP        *SourceHTTP        `yaml:"http,omitempty" json:"http,omitempty"`
	Context     *SourceContext     `yaml:"context,omitempty" json:"context,omitempty"`
	Build       *SourceBuild       `yaml:"build,omitempty" json:"build,omitempty"`
	Inline      *SourceInline      `yaml:"inline,omitempty" json:"inline,omitempty"`

	// Path is the path to the source after fetching it based on the identifier.
	Path string `yaml:"path,omitempty" json:"path,omitempty"`

	// Includes is a list of paths underneath `Path` to include, everything else is execluded
	// If empty, everything is included (minus the excludes)
	Includes []string `yaml:"includes,omitempty" json:"includes,omitempty"`
	// Excludes is a list of paths underneath `Path` to exclude, everything else is included
	Excludes []string `yaml:"excludes,omitempty" json:"excludes,omitempty"`
}

Source defines a source to be used in the build. A source can be a local directory, a git repositoryt, http(s) URL, etc.

func (Source) Doc

func (s Source) Doc(name string) (io.Reader, error)

Doc returns the details of how the source was created. This should be included, where applicable, in build in build specs (such as RPM spec files) so that others can reproduce the build.

type SourceBuild

type SourceBuild struct {
	// A source specification to use as the context for the Dockerfile build
	Source Source `yaml:"source,omitempty" json:"source,omitempty"`

	// DockerFile is the path to the build file in the build context
	// If not set the default is assumed by buildkit to be `Dockerfile` at the root of the context.
	// This is exclusive with [Inline]
	DockerFile string `yaml:"dockerfile,omitempty" json:"dockerfile,omitempty"`
	// Inline is an inline build spec to use.
	// This can be used to specify a dockerfile instead of using one in the build context
	// This is exclusive with [File]
	Inline string `yaml:"inline,omitempty" json:"inline,omitempty" jsonschema:"example=FROM busybox\nRUN echo hello world"`

	// Target specifies the build target to use.
	// If unset, the default target is determined by the frontend implementation
	// (e.g. the dockerfile frontend uses the last build stage as the default).
	Target string `yaml:"target,omitempty" json:"target,omitempty"`
	// Args are the build args to pass to the build.
	Args map[string]string `yaml:"args,omitempty" json:"args,omitempty"`
}

SourceBuild is used to generate source from a DockerFile build, either inline or from a local file.

type SourceContext

type SourceContext struct {
	// Name is the name of the build context. By default, it is the magic name
	// `context`, recognized by Docker as the default context.
	Name string `yaml:"name,omitempty" json:"name,omitempty"`
}

SourceContext is used to generate a source from a build context. The path to the build context is provided to the `Path` field of the owning `Source`.

type SourceDockerImage

type SourceDockerImage struct {
	Ref string   `yaml:"ref" json:"ref"`
	Cmd *Command `yaml:"cmd,omitempty" json:"cmd,omitempty"`
}

type SourceGit

type SourceGit struct {
	URL        string `yaml:"url" json:"url"`
	Commit     string `yaml:"commit" json:"commit"`
	KeepGitDir bool   `yaml:"keepGitDir" json:"keepGitDir"`
}

type SourceHTTP

type SourceHTTP struct {
	URL string `yaml:"url" json:"url"`
}

No longer supports `.git` URLs as git repos. That has to be done with `SourceGit`

type SourceInline

type SourceInline struct {
	// File is the inline file to generate.
	// File is treated as a literal single file.
	// [SourceIsDir] will return false when this is set.
	// This is mutally exclusive with [Dir]
	File *SourceInlineFile `yaml:"file,omitempty" json:"file,omitempty"`
	// Dir creates a directory with the given files and directories.
	// [SourceIsDir] will return true when this is set.
	// This is mutally exclusive with [File]
	Dir *SourceInlineDir `yaml:"dir,omitempty" json:"dir,omitempty"`
}

SourceInline is used to generate a source from inline content.

func (*SourceInline) Doc

func (s *SourceInline) Doc(w io.Writer, name string)

type SourceInlineDir

type SourceInlineDir struct {
	// Files is the list of files to include in the directory.
	// The map key is the name of the file.
	//
	// Files with path separators in the key will be rejected.
	Files map[string]*SourceInlineFile `yaml:"files,omitempty" json:"files,omitempty"`
	// Permissions is the octal permissions to set on the directory.
	Permissions fs.FileMode `yaml:"permissions,omitempty" json:"permissions,omitempty"`

	// UID is the user ID to set on the directory and all files and directories within it.
	// UID must be greater than or equal to 0
	UID int `yaml:"uid,omitempty" json:"uid,omitempty"`
	// GID is the group ID to set on the directory and all files and directories within it.
	// UID must be greater than or equal to 0
	GID int `yaml:"gid,omitempty" json:"gid,omitempty"`
}

SourceInlineDir is used by by SourceInline to represent a filesystem directory.

func (*SourceInlineDir) Doc

func (s *SourceInlineDir) Doc(w io.Writer, name string)

func (*SourceInlineDir) PopulateAt

func (d *SourceInlineDir) PopulateAt(p string) llb.StateOption

type SourceInlineFile

type SourceInlineFile struct {
	// Contents is the content.
	Contents string `yaml:"contents,omitempty" json:"contents,omitempty"`
	// Permissions is the octal file permissions to set on the file.
	Permissions fs.FileMode `yaml:"permissions,omitempty" json:"permissions,omitempty"`
	// UID is the user ID to set on the directory and all files and directories within it.
	// UID must be greater than or equal to 0
	UID int `yaml:"uid,omitempty" json:"uid,omitempty"`
	// GID is the group ID to set on the directory and all files and directories within it.
	// UID must be greater than or equal to 0
	GID int `yaml:"gid,omitempty" json:"gid,omitempty"`
}

SourceInlineFile is used to specify the content of an inline source.

func (*SourceInlineFile) Doc

func (s *SourceInlineFile) Doc(w io.Writer, name string)

func (*SourceInlineFile) PopulateAt

func (f *SourceInlineFile) PopulateAt(p string) llb.StateOption

type SourceMount

type SourceMount struct {
	// Dest is the destination directory to mount to
	Dest string `yaml:"dest" json:"dest" jsonschema:"required"`
	// Spec specifies the source to mount
	Spec Source `yaml:"spec" json:"spec" jsonschema:"required"`
}

SourceMount is used to take a Source and mount it into a build step.

type SourceOpts

type SourceOpts struct {
	Resolver   llb.ImageMetaResolver
	Forward    ForwarderFunc
	GetContext func(string, ...llb.LocalOption) (*llb.State, error)
}

type Spec

type Spec struct {
	// Name is the name of the package.
	Name string `yaml:"name" json:"name" jsonschema:"required"`
	// Description is a short description of the package.
	Description string `yaml:"description" json:"description" jsonschema:"required"`
	// Website is the URL to store in the metadata of the package.
	Website string `yaml:"website" json:"website"`

	// Version setst he version of the package.
	Version string `yaml:"version" json:"version" jsonschema:"required"`
	// Revision sets the package revision.
	// This will generally get merged into the package version when generating the package.
	Revision string `yaml:"revision" json:"revision" jsonschema:"required,oneof_type=string;integer"`

	// Marks the package as architecture independent.
	// It is up to the package author to ensure that the package is actually architecture independent.
	// This is metadata only.
	NoArch bool `yaml:"noarch,omitempty" json:"noarch,omitempty"`

	// Conflicts is the list of packages that conflict with the generated package.
	// This will prevent the package from being installed if any of these packages are already installed or vice versa.
	Conflicts map[string][]string `yaml:"conflicts,omitempty" json:"conflicts,omitempty"`
	// Replaces is the list of packages that are replaced by the generated package.
	Replaces map[string][]string `yaml:"replaces,omitempty" json:"replaces,omitempty"`
	// Provides is the list of things that the generated package provides.
	// This can be used to satisfy dependencies of other packages.
	// As an example, the moby-runc package provides "runc", other packages could depend on "runc" and be satisfied by moby-runc.
	// This is an advanced use case and consideration should be taken to ensure that the package actually provides the thing it claims to provide.
	Provides []string `yaml:"provides,omitempty" json:"provides,omitempty"`

	// Sources is the list of sources to use to build the artifact(s).
	// The map key is the name of the source and the value is the source configuration.
	// The source configuration is used to fetch the source and filter the files to include/exclude.
	// This can be mounted into the build using the "Mounts" field in the StepGroup.
	//
	// Sources can be embedded in the main spec as here or overriden in a build request.
	Sources map[string]Source `yaml:"sources,omitempty" json:"sources,omitempty"`

	// Patches is the list of patches to apply to the sources.
	// The map key is the name of the source to apply the patches to.
	// The value is the list of patches to apply to the source.
	// The patch must be present in the `Sources` map.
	// Each patch is applied in order and the result is used as the source for the build.
	Patches map[string][]PatchSpec `yaml:"patches,omitempty" json:"patches,omitempty"`

	// Build is the configuration for building the artifacts in the package.
	Build ArtifactBuild `yaml:"build,omitempty" json:"build,omitempty"`

	// Args is the list of arguments that can be used for shell-style expansion in (certain fields of) the spec.
	// Any arg supplied in the build request which does not appear in this list will cause an error.
	// Attempts to use an arg in the spec which is not specified here will assume to be a literal string.
	// The map value is the default value to use if the arg is not supplied in the build request.
	Args map[string]string `yaml:"args,omitempty" json:"args,omitempty"`

	// License is the license of the package.
	License string `yaml:"license" json:"license"`
	// Vendor is the vendor of the package.
	Vendor string `yaml:"vendor" json:"vendor"`
	// Packager is the name of the person,team,company that packaged the package.
	Packager string `yaml:"packager" json:"packager"`

	// Artifacts is the list of artifacts to include in the package.
	Artifacts Artifacts `yaml:"artifacts,omitempty" json:"artifacts,omitempty"`

	// The list of distro targets to build the package for.
	Targets map[string]Target `yaml:"targets,omitempty" json:"targets,omitempty"`

	// Dependencies are the different dependencies that need to be specified in the package.
	// Dependencies are overwritten if specified in the target map for the requested distro.
	Dependencies *PackageDependencies `yaml:"dependencies,omitempty" json:"dependencies,omitempty"`
	// Image is the image configuration when the target output is a container image.
	// This is overwritten if specified in the target map for the requested distro.
	Image *ImageConfig `yaml:"image,omitempty" json:"image,omitempty"`

	// Changelog is the list of changes to the package.
	Changelog []ChangelogEntry `yaml:"changelog,omitempty" json:"changelog,omitempty"`

	// Tests are the list of tests to run for the package that should work regardless of target OS
	// Each item in this list is run with a separate rootfs and cannot interact with other tests.
	// Each [TestSpec] is run with a separate rootfs, asyncronously from other [TestSpec].
	Tests []*TestSpec `yaml:"tests,omitempty" json:"tests,omitempty"`
}

Spec is the specification for a package build.

func LoadSpec

func LoadSpec(dt []byte) (*Spec, error)

LoadSpec loads a spec from the given data.

func (*Spec) FillDefaults

func (s *Spec) FillDefaults()

func (*Spec) SubstituteArgs

func (s *Spec) SubstituteArgs(env map[string]string) error

func (Spec) Validate

func (s Spec) Validate() error

type SymlinkTarget

type SymlinkTarget struct {
	// Path is the path where the symlink should be placed
	Path string `yaml:"path" json:"path" jsonschema:"required"`
}

SymlinkTarget specifies the properties of a symlink

type Target

type Target struct {
	// Dependencies are the different dependencies that need to be specified in the package.
	Dependencies *PackageDependencies `yaml:"dependencies,omitempty" json:"dependencies,omitempty"`

	// Image is the image configuration when the target output is a container image.
	Image *ImageConfig `yaml:"image,omitempty" json:"image,omitempty"`

	// Frontend is the frontend configuration to use for the target.
	// This is used to forward the build to a different, dalec-compatabile frontend.
	// This can be useful when testing out new distros or using a different version of the frontend for a given distro.
	Frontend *Frontend `yaml:"frontend,omitempty" json:"frontend,omitempty"`

	// Tests are the list of tests to run which are specific to the target.
	// Tests are appended to the list of tests in the main [Spec]
	Tests []*TestSpec `yaml:"tests,omitempty" json:"tests,omitempty"`
}

Target defines a distro-specific build target. This is used in Spec to specify the build target for a distro.

type TestSpec

type TestSpec struct {
	// Name is the name of the test
	// This will be used to output the test results
	Name string `yaml:"name" json:"name" jsonschema:"required"`

	// Dir is the working directory to run the command in.
	Dir string `yaml:"dir,omitempty" json:"dir,omitempty"`

	// Mounts is the list of sources to mount into the build steps.
	Mounts []SourceMount `yaml:"mounts,omitempty" json:"mounts,omitempty"`

	// List of CacheDirs which will be used across all Steps
	CacheDirs map[string]CacheDirConfig `yaml:"cache_dirs,omitempty" json:"cache_dirs,omitempty"`

	// Env is the list of environment variables to set for all commands in this step group.
	Env map[string]string `yaml:"env,omitempty" json:"env,omitempty"`

	// Steps is the list of commands to run to test the package.
	Steps []TestStep `yaml:"steps" json:"steps" jsonschema:"required"`

	// Files is the list of files to check after running the steps.
	Files map[string]FileCheckOutput `yaml:"files,omitempty" json:"files,omitempty"`
}

TestSpec is used to execute tests against a container with the package installed in it.

type TestStep

type TestStep struct {
	// Command is the command to run to build the artifact(s).
	// This will always be wrapped as /bin/sh -c "<command>", or whatever the equivalent is for the target distro.
	Command string `yaml:"command" json:"command" jsonschema:"required"`
	// Env is the list of environment variables to set for the command.
	Env map[string]string `yaml:"env,omitempty" json:"env,omitempty"`
	// Stdout is the expected output on stdout
	Stdout CheckOutput `yaml:"stdout,omitempty" json:"stdout,omitempty"`
	// Stderr is the expected output on stderr
	Stderr CheckOutput `yaml:"stderr,omitempty" json:"stderr,omitempty"`
	// Stdin is the input to pass to stdin for the command
	Stdin string `yaml:"stdin,omitempty" json:"stdin,omitempty"`
}

TestStep is a wrapper for BuildStep to include checks on stdio streams

Directories

Path Synopsis
cmd
rpm
test
website module

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL