Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions dev-tools/mage/crossbuild.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@ var Platforms = BuildPlatforms.Defaults()
// are considered to be selected (see isPackageTypeSelected).
var SelectedPackageTypes []PackageType

// SelectedDockerVariants is the list of docker variants. If empty, all docker variants
// are considered to be selected (see isDockerVariantSelected).
var SelectedDockerVariants []DockerVariant

func init() {
// Allow overriding via PLATFORMS.
if expression := os.Getenv("PLATFORMS"); len(expression) > 0 {
Expand All @@ -50,6 +54,18 @@ func init() {
SelectedPackageTypes = append(SelectedPackageTypes, p)
}
}

// Allow overriding via DOCKER_VARIANTS.
if dockerVariants := os.Getenv("DOCKER_VARIANTS"); len(dockerVariants) > 0 {
for _, docvariant := range strings.Split(dockerVariants, ",") {
var v DockerVariant
err := v.UnmarshalText([]byte(docvariant))
if err != nil {
continue
}
SelectedDockerVariants = append(SelectedDockerVariants, v)
}
}
}

// CrossBuildOption defines an option to the CrossBuild target.
Expand Down
8 changes: 2 additions & 6 deletions dev-tools/mage/dockerbuilder.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,17 +28,12 @@ type dockerBuilder struct {
}

func newDockerBuilder(spec PackageSpec) (*dockerBuilder, error) {
imageName, err := spec.ImageName()
if err != nil {
return nil, err
}

buildDir := filepath.Join(spec.packageDir, "docker-build")
beatDir := filepath.Join(buildDir, "beat")

return &dockerBuilder{
PackageSpec: spec,
imageName: imageName,
imageName: spec.ImageName(),
buildDir: buildDir,
beatDir: beatDir,
}, nil
Expand Down Expand Up @@ -117,6 +112,7 @@ func (b *dockerBuilder) prepareBuild() error {
data := map[string]interface{}{
"ExposePorts": b.exposePorts(),
"ModulesDirs": b.modulesDirs(),
"Variant": b.DockerVariant.String(),
}

err = filepath.Walk(templatesDir, func(path string, info os.FileInfo, _ error) error {
Expand Down
78 changes: 78 additions & 0 deletions dev-tools/mage/dockervariants.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
// or more contributor license agreements. Licensed under the Elastic License;
// you may not use this file except in compliance with the Elastic License.

package mage

import (
"fmt"
"strings"
)

const (
undefined = "undefined"
basic = "basic"
ubi = "ubi"
wolfi = "wolfi"
complete = "complete"
cloud = "cloud"
)

// DockerVariant defines the docker variant to build.
type DockerVariant int

// List of possible docker variants.
const (
Undefined = iota
Basic
UBI
Wolfi
Complete
Cloud
)

// String returns the name of the docker variant type.
func (typ DockerVariant) String() string {
switch typ {
case Undefined:
return undefined
case Basic:
return basic
case UBI:
return ubi
case Wolfi:
return wolfi
case Complete:
return complete
case Cloud:
return cloud
default:
return invalid
}
}

// MarshalText returns the text representation of DockerVariant.
func (typ DockerVariant) MarshalText() ([]byte, error) {
return []byte(typ.String()), nil
}

// UnmarshalText returns a DockerVariant based on the given text.
func (typ *DockerVariant) UnmarshalText(text []byte) error {
switch strings.ToLower(string(text)) {
case "":
*typ = Undefined
case basic:
*typ = Basic
case ubi:
*typ = UBI
case wolfi:
*typ = Wolfi
case complete:
*typ = Complete
case cloud:
*typ = Cloud
default:
return fmt.Errorf("unknown docker variant: %v", string(text))
}
return nil
}
20 changes: 20 additions & 0 deletions dev-tools/mage/pkg.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,11 @@ func Package() error {
continue
}

if pkgType == Docker && !isDockerVariantSelected(pkg.Spec.DockerVariant) {
log.Printf("Skipping %s docker variant type because it is not selected", pkg.Spec.DockerVariant)
continue
}

if target.Name == "linux/arm64" && pkgType == Docker && runtime.GOARCH != "arm64" {
log.Printf("Skipping Docker package type because build host isn't arm")
continue
Expand Down Expand Up @@ -121,6 +126,21 @@ func isPackageTypeSelected(pkgType PackageType) bool {
return false
}

// isDockerVariantSelected returns true if SelectedDockerVariants is empty or if
// docVariant is present on SelectedDockerVariants. It returns false otherwise.
func isDockerVariantSelected(docVariant DockerVariant) bool {
if len(SelectedDockerVariants) == 0 {
return true
}

for _, v := range SelectedDockerVariants {
if v == docVariant {
return true
}
}
return false
Comment on lines +136 to +141
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: we can use something more compact:

Suggested change
for _, v := range SelectedDockerVariants {
if v == docVariant {
return true
}
}
return false
return slices.Contains(SelectedDockerVariants, docVariant)

https://pkg.go.dev/slices#Contains

}

type packageBuilder struct {
Platform BuildPlatform
Spec PackageSpec
Expand Down
11 changes: 11 additions & 0 deletions dev-tools/mage/pkgspecs.go
Original file line number Diff line number Diff line change
Expand Up @@ -154,5 +154,16 @@ func LoadSpecs(files ...string) (map[string][]OSPackageArgs, error) {
return nil, fmt.Errorf("failed to unmarshal spec data: %w", err)
}

// verify that the package specification sets the docker variant
for specName, specs := range packages.Specs {
for _, spec := range specs {
for _, pkgType := range spec.Types {
if pkgType == Docker && spec.Spec.DockerVariant == Undefined {
return nil, fmt.Errorf("%s defined a package spec for docker without a docker_variant set", specName)
}
}
}
}

return packages.Specs, nil
}
23 changes: 8 additions & 15 deletions dev-tools/mage/pkgtypes.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ type PackageSpec struct {
License string `yaml:"license,omitempty"`
URL string `yaml:"url,omitempty"`
Description string `yaml:"description,omitempty"`
DockerVariant DockerVariant `yaml:"docker_variant,omitempty"`
PreInstallScript string `yaml:"pre_install_script,omitempty"`
PostInstallScript string `yaml:"post_install_script,omitempty"`
PostRmScript string `yaml:"post_rm_script,omitempty"`
Expand Down Expand Up @@ -271,11 +272,7 @@ func (typ PackageType) AddFileExtension(file string) string {
func (typ PackageType) PackagingDir(home string, target BuildPlatform, spec PackageSpec) (string, error) {
root := home
if typ == Docker {
imageName, err := spec.ImageName()
if err != nil {
return "", err
}
root = filepath.Join(root, imageName)
root = filepath.Join(root, spec.ImageName())
}

targetPath := typ.AddFileExtension(spec.Name + "-" + target.GOOS() + "-" + target.Arch())
Expand Down Expand Up @@ -467,17 +464,13 @@ func (s PackageSpec) Evaluate(args ...map[string]interface{}) PackageSpec {
return s
}

// ImageName computes the image name from the spec. A template for the image
// name can be configured by adding image_name to extra_vars.
func (s PackageSpec) ImageName() (string, error) {
if name := s.ExtraVars["image_name"]; name != "" {
imageName, err := s.Expand(name)
if err != nil {
return "", fmt.Errorf("failed to expand image_name: %w", err)
}
return imageName, nil
// ImageName computes the image name from the spec.
func (s PackageSpec) ImageName() string {
if s.DockerVariant == Basic {
// no suffix for basic docker variant
return s.Name
}
return s.Name, nil
return fmt.Sprintf("%s-%s", s.Name, s.DockerVariant)
}

func copyInstallScript(spec PackageSpec, script string, local *string) error {
Expand Down
20 changes: 10 additions & 10 deletions dev-tools/packaging/packages.yml
Original file line number Diff line number Diff line change
Expand Up @@ -223,31 +223,31 @@ shared:
buildFrom: '--platform=linux/arm64 cgr.dev/chainguard/wolfi-base'

- &docker_ubuntu_spec
docker_variant: 'basic'
extra_vars:
from: '--platform=linux/amd64 ubuntu:20.04'
image_name: '{{.BeatName}}'
- &docker_ubuntu_arm_spec
docker_variant: 'basic'
extra_vars:
from: '--platform=linux/arm64 ubuntu:20.04'
image_name: '{{.BeatName}}'

- &docker_ubi_spec
docker_variant: 'ubi'
extra_vars:
from: '--platform=linux/amd64 docker.elastic.co/ubi9/ubi-minimal'
image_name: '{{.BeatName}}-ubi'
- &docker_ubi_arm_spec
docker_variant: 'ubi'
extra_vars:
from: '--platform=linux/arm64 docker.elastic.co/ubi9/ubi-minimal'
image_name: '{{.BeatName}}-ubi'

- &docker_wolfi_spec
docker_variant: 'wolfi'
extra_vars:
from: '--platform=linux/amd64 cgr.dev/chainguard/wolfi-base'
image_name: '{{.BeatName}}-wolfi'
- &docker_wolfi_arm_spec
docker_variant: 'wolfi'
extra_vars:
from: '--platform=linux/arm64 cgr.dev/chainguard/wolfi-base'
image_name: '{{.BeatName}}-wolfi'

- &docker_elastic_spec
extra_vars:
Expand Down Expand Up @@ -275,9 +275,10 @@ shared:
{{ commit }}
mode: 0644

# cloud build to beats-ci repository
- &agent_docker_cloud_spec
docker_variant: 'cloud'
extra_vars:
image_name: '{{.BeatName}}-cloud'
repository: 'docker.elastic.co/beats-ci'
files:
'data/cloud_downloads/filebeat.sh':
Expand All @@ -290,11 +291,10 @@ shared:
source: '{{.AgentDropPath}}/archives/{{.GOOS}}-{{.AgentArchName}}.tar.gz/agentbeat-{{ beat_version }}{{if .Snapshot}}-SNAPSHOT{{end}}-{{.GOOS}}-{{.AgentArchName}}.tar.gz'
mode: 0755

# not different to the default image, kept for backwards-compatibility
# includes nodejs with @elastic/synthetics
- &agent_docker_complete_spec
<<: *agent_docker_spec
extra_vars:
image_name: '{{.BeatName}}-complete'
docker_variant: 'complete'

# Deb/RPM spec for community beats.
- &deb_rpm_spec
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ RUN true && \
chmod 0775 {{ $beatHome}}/{{ $modulesd }} && \
{{- end }}

{{- if contains .image_name "-cloud" }}
{{- if eq .Variant "cloud" }}
mkdir -p /opt/agentbeat /opt/filebeat /opt/metricbeat && \
cp -f {{ $beatHome }}/data/cloud_downloads/filebeat.sh /opt/filebeat/filebeat && \
chmod +x /opt/filebeat/filebeat && \
Expand Down Expand Up @@ -170,14 +170,14 @@ RUN mkdir /licenses
COPY --from=home {{ $beatHome }}/LICENSE.txt /licenses
COPY --from=home {{ $beatHome }}/NOTICE.txt /licenses

{{- if contains .image_name "-cloud" }}
{{- if eq .Variant "cloud" }}
COPY --from=home /opt /opt
# Generate folder for a stub command that will be overwritten at runtime
RUN mkdir /app && \
chown {{ .user }}:{{ .user }} /app
{{- end }}

{{- if (and (contains .image_name "-complete") (contains .from "ubuntu")) }}
{{- if (and (eq .Variant "complete") (contains .from "ubuntu")) }}
USER root
ENV NODE_PATH={{ $beatHome }}/.node
RUN echo \
Expand Down Expand Up @@ -254,7 +254,7 @@ ENV LIBBEAT_MONITORING_CGROUPS_HIERARCHY_OVERRIDE=/

WORKDIR {{ $beatHome }}

{{- if contains .image_name "-cloud" }}
{{- if eq .Variant "cloud" }}
ENTRYPOINT ["/usr/bin/tini", "--"]
CMD ["/app/apm.sh"]
# Generate a stub command that will be overwritten at runtime
Expand Down