Skip to content

Commit 23f853e

Browse files
v1vmergify[bot]
authored andcommitted
automate the ironbank docker context generation (#679)
(cherry picked from commit b0e9623)
1 parent f1897a5 commit 23f853e

File tree

8 files changed

+601
-2
lines changed

8 files changed

+601
-2
lines changed

.ci/Jenkinsfile

+1-1
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,7 @@ pipeline {
175175
withMageEnv(){
176176
dir("${BASE_DIR}"){
177177
withPackageEnv("${PLATFORM}") {
178-
cmd(label: 'Go package', script: 'mage package')
178+
cmd(label: 'Go package', script: 'mage package ironbank')
179179
uploadPackagesToGoogleBucket(
180180
credentialsId: env.JOB_GCS_EXT_CREDENTIALS,
181181
repo: env.REPO,

.gitignore

-1
Original file line numberDiff line numberDiff line change
@@ -62,4 +62,3 @@ internal/pkg/agent/transpiler/tests/exec-1.0-darwin-x86_64/exec
6262

6363
# VSCode
6464
/.vscode
65-

dev-tools/packaging/files/ironbank/LICENSE

+280
Large diffs are not rendered by default.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
#!/bin/bash
2+
3+
set -eo pipefail
4+
5+
# For information on the possible environment variables that can be passed into the container. Run the following
6+
# command for information on the options that are available.
7+
#
8+
# `./elastic-agent container --help`
9+
#
10+
11+
elastic-agent container "$@"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
################################################################################
2+
# Build stage 0
3+
# Extract Elastic Agent and make various file manipulations.
4+
################################################################################
5+
ARG BASE_REGISTRY=registry1.dsop.io
6+
ARG BASE_IMAGE=ironbank/redhat/ubi/ubi8
7+
ARG BASE_TAG=8.6
8+
9+
FROM ${BASE_REGISTRY}/${BASE_IMAGE}:${BASE_TAG} as prep_files
10+
11+
ARG ELASTIC_STACK={{ beat_version }}
12+
ARG ELASTIC_PRODUCT=elastic-agent
13+
ARG OS_AND_ARCH=linux-x86_64
14+
15+
RUN mkdir /usr/share/${ELASTIC_PRODUCT}
16+
WORKDIR /usr/share/${ELASTIC_PRODUCT}
17+
COPY --chown=1000:0 ${ELASTIC_PRODUCT}-${ELASTIC_STACK}-${OS_AND_ARCH}.tar.gz .
18+
RUN tar --strip-components=1 -zxf ${ELASTIC_PRODUCT}-${ELASTIC_STACK}-${OS_AND_ARCH}.tar.gz \
19+
&& rm ${ELASTIC_PRODUCT}-${ELASTIC_STACK}-${OS_AND_ARCH}.tar.gz
20+
21+
# Support arbitrary user ids
22+
# Ensure that group permissions are the same as user permissions.
23+
# This will help when relying on GID-0 to run Kibana, rather than UID-1000.
24+
# OpenShift does this, for example.
25+
# REF: https://docs.okd.io/latest/openshift_images/create-images.html
26+
RUN chmod -R g=u /usr/share/${ELASTIC_PRODUCT}
27+
28+
# Create auxiliary folders and assigning default permissions.
29+
RUN mkdir -p /usr/share/${ELASTIC_PRODUCT}/data /usr/share/${ELASTIC_PRODUCT}/logs && \
30+
chown -R root:root /usr/share/${ELASTIC_PRODUCT} && \
31+
find /usr/share/${ELASTIC_PRODUCT} -type d -exec chmod 0750 {} \; && \
32+
find /usr/share/${ELASTIC_PRODUCT} -type f -exec chmod 0640 {} \; && \
33+
chmod 0750 /usr/share/${ELASTIC_PRODUCT}/${ELASTIC_PRODUCT} && \
34+
chmod 0770 /usr/share/${ELASTIC_PRODUCT}/data /usr/share/${ELASTIC_PRODUCT}/logs
35+
36+
################################################################################
37+
# Build stage 1
38+
# Copy prepared files from the previous stage and complete the image.
39+
################################################################################
40+
FROM ${BASE_REGISTRY}/${BASE_IMAGE}:${BASE_TAG}
41+
42+
ARG ELASTIC_PRODUCT=elastic-agent
43+
44+
COPY LICENSE /licenses/elastic-${ELASTIC_PRODUCT}
45+
46+
# Add a dumb init process
47+
COPY tinit /tinit
48+
RUN chmod +x /tinit
49+
50+
# Bring in product from the initial stage.
51+
COPY --from=prep_files --chown=1000:0 /usr/share/${ELASTIC_PRODUCT} /usr/share/${ELASTIC_PRODUCT}
52+
WORKDIR /usr/share/${ELASTIC_PRODUCT}
53+
RUN ln -s /usr/share/${ELASTIC_PRODUCT} /opt/${ELASTIC_PRODUCT}
54+
55+
ENV ELASTIC_CONTAINER="true"
56+
RUN ln -s /usr/share/${ELASTIC_PRODUCT}/${ELASTIC_PRODUCT} /usr/bin/${ELASTIC_PRODUCT}
57+
58+
# Support arbitrary user ids
59+
# Ensure gid 0 write permissions for OpenShift.
60+
RUN chmod -R g+w /usr/share/${ELASTIC_PRODUCT}
61+
62+
# config file ("${ELASTIC_PRODUCT}.yml") can only be writable by the root and group root
63+
# it is needed on some configurations where the container needs to run as root
64+
RUN chown root:root /usr/share/${ELASTIC_PRODUCT}/${ELASTIC_PRODUCT}.yml \
65+
&& chmod go-w /usr/share/${ELASTIC_PRODUCT}/${ELASTIC_PRODUCT}.yml
66+
67+
# Remove the suid bit everywhere to mitigate "Stack Clash"
68+
RUN find / -xdev -perm -4000 -exec chmod u-s {} +
69+
70+
# Provide a non-root user to run the process.
71+
RUN groupadd --gid 1000 ${ELASTIC_PRODUCT} && useradd --uid 1000 --gid 1000 --groups 0 --home-dir /usr/share/${ELASTIC_PRODUCT} --no-create-home ${ELASTIC_PRODUCT}
72+
73+
# Elastic Agent permissions
74+
RUN find /usr/share//elastic-agent/data -type d -exec chmod 0770 {} \; && \
75+
find /usr/share//elastic-agent/data -type f -exec chmod 0660 {} \; && \
76+
chmod +x /usr/share//elastic-agent/data/elastic-agent-*/elastic-agent
77+
78+
COPY jq /usr/local/bin
79+
RUN chown root:root /usr/local/bin/jq && chmod 0755 /usr/local/bin/jq
80+
81+
COPY config/docker-entrypoint /usr/local/bin/docker-entrypoint
82+
RUN chmod 755 /usr/local/bin/docker-entrypoint
83+
84+
USER ${ELASTIC_PRODUCT}
85+
ENV ELASTIC_PRODUCT=${ELASTIC_PRODUCT}
86+
87+
ENTRYPOINT ["/tinit", "--", "/usr/local/bin/docker-entrypoint"]
88+
CMD [""]
89+
90+
HEALTHCHECK --interval=10s --timeout=5s --start-period=1m --retries=5 CMD test -w '/tmp/elastic-agent/elastic-agent.sock'
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
# elastic-agent
2+
3+
**elastic-agent** is a single, unified way to add monitoring for logs, metrics, and other types of data to each host. A single agent makes it easier and faster to deploy monitoring across your infrastructure. The agent’s single, unified configuration makes it easier to add integrations for new data sources.
4+
5+
For more information about elastic-agent, please visit
6+
https://www.elastic.co/guide/en/ingest-management/7.17/index.html.
7+
8+
---
9+
10+
**NOTE**
11+
12+
This functionality is in beta and is subject to change. The design and code is less mature than official GA features and is being provided as-is with no warranties. Beta features are not subject to the support SLA of official GA features.
13+
14+
---
15+
16+
### Installation instructions
17+
18+
Please follow the documentation on [Quick start](https://www.elastic.co/guide/en/fleet/{{ .MajorMinor }}/fleet-elastic-agent-quick-start.html).
19+
20+
### Where to file issues and PRs
21+
22+
- [Issues](https://github.com/elastic/elastic-agent/issues)
23+
- [PRs](https://github.com/elastic/elastic-agent/pulls)
24+
25+
### DoD Restrictions
26+
27+
### Where to get help
28+
29+
- [elastic-agent Discuss Forums](https://discuss.elastic.co/tags/c/elastic-stack/beats/28/elastic-agent)
30+
- [elastic-agent Documentation](https://www.elastic.co/guide/en/ingest-management/current/index.html)
31+
32+
### Still need help?
33+
34+
You can learn more about the Elastic Community and also understand how to get more help
35+
visiting [Elastic Community](https://www.elastic.co/community).
36+
37+
This software is governed by the [Elastic
38+
License](https://github.com/elastic/beats/blob/{{ .MajorMinor }}/licenses/ELASTIC-LICENSE.txt),
39+
and includes the full set of [free
40+
features](https://www.elastic.co/subscriptions).
41+
42+
View the detailed release notes
43+
[here](https://www.elastic.co/guide/en/beats/libbeat/current/release-notes-{{ beat_version }}.html).
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
---
2+
apiVersion: v1
3+
4+
# The repository name in registry1, excluding /ironbank/
5+
name: "elastic/beats/elastic-agent"
6+
7+
# List of tags to push for the repository in registry1
8+
# The most specific version should be the first tag and will be shown
9+
# on ironbank.dsop.io
10+
tags:
11+
- "{{ beat_version }}"
12+
- "latest"
13+
14+
# Build args passed to Dockerfile ARGs
15+
args:
16+
BASE_IMAGE: "redhat/ubi/ubi8"
17+
BASE_TAG: "8.6"
18+
ELASTIC_STACK: "{{ beat_version }}"
19+
ELASTIC_PRODUCT: "elastic-agent"
20+
21+
# Docker image labels
22+
labels:
23+
org.opencontainers.image.title: "elastic-agent"
24+
## Human-readable description of the software packaged in the image
25+
org.opencontainers.image.description: "elastic-agent is a single, unified way to add monitoring for logs, metrics, and other types of data to each host"
26+
## License(s) under which contained software is distributed
27+
org.opencontainers.image.licenses: "Elastic License"
28+
## URL to find more information on the image
29+
org.opencontainers.image.url: "https://www.elastic.co/products/beats/elastic-agent"
30+
## Name of the distributing entity, organization or individual
31+
org.opencontainers.image.vendor: "Elastic"
32+
org.opencontainers.image.version: "{{ beat_version }}"
33+
## Keywords to help with search (ex. "cicd,gitops,golang")
34+
mil.dso.ironbank.image.keywords: "log,metrics,monitoring,observabilty,o11y,oblt,beats,elastic,elasticsearch,golang"
35+
## This value can be "opensource" or "commercial"
36+
mil.dso.ironbank.image.type: "commercial"
37+
## Product the image belongs to for grouping multiple images
38+
mil.dso.ironbank.product.name: "beats"
39+
40+
# List of resources to make available to the offline build context
41+
resources:
42+
- filename: "elastic-agent-{{ beat_version }}-linux-x86_64.tar.gz"
43+
url: "<artifact_path>/elastic-agent-{{ beat_version }}-linux-x86_64.tar.gz"
44+
validation:
45+
type: "sha512"
46+
value: "<insert SHA 512 here>"
47+
- filename: tinit
48+
url: https://github.com/krallin/tini/releases/download/v0.19.0/tini-amd64
49+
validation:
50+
type: sha256
51+
value: 93dcc18adc78c65a028a84799ecf8ad40c936fdfc5f2a57b1acda5a8117fa82c
52+
- filename: jq
53+
url: https://github.com/stedolan/jq/releases/download/jq-1.6/jq-linux64
54+
validation:
55+
type: sha256
56+
value: af986793a515d500ab2d35f8d2aecd656e764504b789b66d7e1a0b727a124c44
57+
58+
# List of project maintainers
59+
maintainers:
60+
- email: "[email protected]"
61+
name: "Nassim Kammah"
62+
username: "nassim.kammah"
63+
- email: "[email protected]"
64+
name: "Ivan Fernandez Calvo"
65+
username: "ivan.fernandez"
66+
- email: "[email protected]"
67+
name: "Victor Martinez"
68+
username: "victor.martinez"

magefile.go

+108
Original file line numberDiff line numberDiff line change
@@ -827,3 +827,111 @@ func injectBuildVars(m map[string]string) {
827827
m[k] = v
828828
}
829829
}
830+
831+
// Package packages elastic-agent for the IronBank distribution, relying on the
832+
// binaries having already been built.
833+
//
834+
// Use SNAPSHOT=true to build snapshots.
835+
func Ironbank() error {
836+
if runtime.GOARCH != "amd64" {
837+
fmt.Printf(">> IronBank images are only supported for amd64 arch (%s is not supported)\n", runtime.GOARCH)
838+
return nil
839+
}
840+
if err := prepareIronbankBuild(); err != nil {
841+
return errors.Wrap(err, "failed to prepare the IronBank context")
842+
}
843+
if err := saveIronbank(); err != nil {
844+
return errors.Wrap(err, "failed to save artifacts for IronBank")
845+
}
846+
return nil
847+
}
848+
849+
func saveIronbank() error {
850+
fmt.Println(">> saveIronbank: save the IronBank container context.")
851+
852+
ironbank := getIronbankContextName()
853+
buildDir := filepath.Join("build", ironbank)
854+
if _, err := os.Stat(buildDir); os.IsNotExist(err) {
855+
return fmt.Errorf("cannot find the folder with the ironbank context: %+v", err)
856+
}
857+
858+
distributionsDir := "build/distributions"
859+
if _, err := os.Stat(distributionsDir); os.IsNotExist(err) {
860+
err := os.MkdirAll(distributionsDir, 0750)
861+
if err != nil {
862+
return fmt.Errorf("cannot create folder for docker artifacts: %+v", err)
863+
}
864+
}
865+
866+
// change dir to the buildDir location where the ironbank folder exists
867+
// this will generate a tar.gz without some nested folders.
868+
wd, _ := os.Getwd()
869+
os.Chdir(buildDir)
870+
defer os.Chdir(wd)
871+
872+
// move the folder to the parent folder, there are two parent folder since
873+
// buildDir contains a two folders dir.
874+
tarGzFile := filepath.Join("..", "..", distributionsDir, ironbank+".tar.gz")
875+
876+
// Save the build context as tar.gz artifact
877+
err := devtools.Tar("./", tarGzFile)
878+
if err != nil {
879+
return fmt.Errorf("cannot compress the tar.gz file: %+v", err)
880+
}
881+
882+
return errors.Wrap(devtools.CreateSHA512File(tarGzFile), "failed to create .sha512 file")
883+
}
884+
885+
func getIronbankContextName() string {
886+
version, _ := devtools.BeatQualifiedVersion()
887+
defaultBinaryName := "{{.Name}}-ironbank-{{.Version}}{{if .Snapshot}}-SNAPSHOT{{end}}"
888+
outputDir, _ := devtools.Expand(defaultBinaryName+"-docker-build-context", map[string]interface{}{
889+
"Name": "elastic-agent",
890+
"Version": version,
891+
})
892+
return outputDir
893+
}
894+
895+
func prepareIronbankBuild() error {
896+
fmt.Println(">> prepareIronbankBuild: prepare the IronBank container context.")
897+
buildDir := filepath.Join("build", getIronbankContextName())
898+
templatesDir := filepath.Join("dev-tools", "packaging", "templates", "ironbank")
899+
900+
data := map[string]interface{}{
901+
"MajorMinor": majorMinor(),
902+
}
903+
904+
err := filepath.Walk(templatesDir, func(path string, info os.FileInfo, _ error) error {
905+
if !info.IsDir() {
906+
target := strings.TrimSuffix(
907+
filepath.Join(buildDir, filepath.Base(path)),
908+
".tmpl",
909+
)
910+
911+
err := devtools.ExpandFile(path, target, data)
912+
if err != nil {
913+
return errors.Wrapf(err, "expanding template '%s' to '%s'", path, target)
914+
}
915+
}
916+
return nil
917+
})
918+
919+
if err != nil {
920+
return fmt.Errorf("cannot create templates for the IronBank: %+v", err)
921+
}
922+
923+
// copy files
924+
sourcePath := filepath.Join("dev-tools", "packaging", "files", "ironbank")
925+
if err := devtools.Copy(sourcePath, buildDir); err != nil {
926+
return fmt.Errorf("cannot create files for the IronBank: %+v", err)
927+
}
928+
return nil
929+
}
930+
931+
func majorMinor() string {
932+
if v, _ := devtools.BeatQualifiedVersion(); v != "" {
933+
parts := strings.SplitN(v, ".", 3)
934+
return parts[0] + "." + parts[1]
935+
}
936+
return ""
937+
}

0 commit comments

Comments
 (0)