Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Agent] Docker image for integration tests #16898

Merged
merged 6 commits into from
Mar 16, 2020
Merged
Show file tree
Hide file tree
Changes from 3 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
50 changes: 48 additions & 2 deletions dev-tools/mage/dockerbuilder.go
Original file line number Diff line number Diff line change
Expand Up @@ -120,8 +120,8 @@ func (b *dockerBuilder) prepareBuild() error {
"ModulesDirs": b.modulesDirs(),
}

return filepath.Walk(templatesDir, func(path string, info os.FileInfo, _ error) error {
if !info.IsDir() {
err = filepath.Walk(templatesDir, func(path string, info os.FileInfo, _ error) error {
if !info.IsDir() && !isDockerFile(path) {
target := strings.TrimSuffix(
filepath.Join(b.buildDir, filepath.Base(path)),
".tmpl",
Expand All @@ -134,6 +134,52 @@ func (b *dockerBuilder) prepareBuild() error {
}
return nil
})

if err != nil {
return err
}

return b.expandDockerfile(templatesDir, data)
}

func isDockerFile(path string) bool {
path = filepath.Base(path)
return strings.HasPrefix(path, "Dockerfile") || strings.HasPrefix(path, "docker-entrypoint")
}

func (b *dockerBuilder) expandDockerfile(templatesDir string, data map[string]interface{}) error {
// has specific dockerfile
dockerfile := fmt.Sprintf("Dockerfile.%s.tmpl", b.imageName)
_, err := os.Stat(filepath.Join(templatesDir, dockerfile))
if err != nil {
// specific missing fallback to generic
dockerfile = "Dockerfile.tmpl"
}

entrypoint := fmt.Sprintf("docker-entrypoint.%s.tmpl", b.imageName)
_, err = os.Stat(filepath.Join(templatesDir, entrypoint))
if err != nil {
// specific missing fallback to generic
entrypoint = "docker-entrypoint.tmpl"
}

type fileExpansion struct {
source string
target string
}
for _, file := range []fileExpansion{{dockerfile, "Dockerfile.tmpl"}, {entrypoint, "docker-entrypoint.tmpl"}} {
target := strings.TrimSuffix(
filepath.Join(b.buildDir, file.target),
".tmpl",
)
path := filepath.Join(templatesDir, file.source)
err = b.ExpandFile(path, target, data)
if err != nil {
return errors.Wrapf(err, "expanding template '%s' to '%s'", path, target)
}
}

return nil
}

func (b *dockerBuilder) dockerBuild() (string, error) {
Expand Down
2 changes: 1 addition & 1 deletion dev-tools/packaging/packages.yml
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ shared:
<<: *agent_binary_spec
extra_vars:
from: 'centos:7'
user: '{{ .BeatName }}'
user: 'root'
Copy link
Contributor

Choose a reason for hiding this comment

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

@michalpristas @ph @andrewkroh @urso Just stumbled over this change. I wonder if this could become a problem or is ok?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

this one was done on purpose as agent needs root permissions, the specification here is used for agent only so no beat is affected

linux_capabilities: ''
files:
'agent.yml':
Expand Down
52 changes: 52 additions & 0 deletions dev-tools/packaging/templates/docker/Dockerfile.agent.tmpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
{{- $beatHome := printf "%s/%s" "/usr/share" .BeatName }}
{{- $beatBinary := printf "%s/%s" $beatHome .BeatName }}
{{- $repoInfo := repo }}

FROM {{ .from }}

LABEL \
org.label-schema.build-date="{{ date }}" \
org.label-schema.schema-version="1.0" \
org.label-schema.vendor="{{ .BeatVendor }}" \
org.label-schema.license="{{ .License }}" \
org.label-schema.name="{{ .BeatName }}" \
org.label-schema.version="{{ beat_version }}" \
org.label-schema.url="{{ .BeatURL }}" \
org.label-schema.vcs-url="{{ $repoInfo.RootImportPath }}" \
org.label-schema.vcs-ref="{{ commit }}" \
license="{{ .License }}" \
description="{{ .BeatDescription }}"

ENV ELASTIC_CONTAINER "true"
ENV PATH={{ $beatHome }}:$PATH

COPY beat {{ $beatHome }}
COPY docker-entrypoint /usr/local/bin/docker-entrypoint
RUN chmod 755 /usr/local/bin/docker-entrypoint

RUN groupadd --gid 1000 {{ .BeatName }}

RUN mkdir {{ $beatHome }}/data {{ $beatHome }}/logs && \
chown -R root:{{ .BeatName }} {{ $beatHome }} && \
find {{ $beatHome }} -type d -exec chmod 0750 {} \; && \
find {{ $beatHome }} -type f -exec chmod 0640 {} \; && \
chmod 0750 {{ $beatBinary }} && \
{{- if .linux_capabilities }}
setcap {{ .linux_capabilities }} {{ $beatBinary }} && \
{{- end }}
{{- range $i, $modulesd := .ModulesDirs }}
chmod 0770 {{ $beatHome}}/{{ $modulesd }} && \
{{- end }}
chmod 0770 {{ $beatHome }}/data {{ $beatHome }}/logs

{{- if ne .user "root" }}
RUN useradd -M --uid 1000 --gid 1000 --home {{ $beatHome }} {{ .user }}
{{- end }}
USER {{ .user }}

{{- range $i, $port := .ExposePorts }}
EXPOSE {{ $port }}
{{- end }}

WORKDIR {{ $beatHome }}
ENTRYPOINT ["/usr/local/bin/docker-entrypoint"]
55 changes: 55 additions & 0 deletions dev-tools/packaging/templates/docker/docker-entrypoint.agent.tmpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
#!/bin/bash

set -eo pipefail

# Environment variables used
# FLEET_ADMIN_PASSWORD - used for new fleet user [elastic]
# FLEET_ADMIN_USERNAME - used for new fleet user [changeme]
# FLEET_CONFIG_ID - config related to new token [defaul]
# FLEET_ENROLLMENT_TOKEN - existing enrollment token to be used for enroll
# FLEET_ENROLL - if set to 1 enroll will be performed
# FLEET_SETUP - if set to 1 fleet setup will be performed
# FLEET_TOKEN_NAME - token name for a token to be created
# KIBANA_HOST - actual kibana host [http://localhost:5601]
# KIBANA_PASSWORD - password for accessing kibana API [changeme]
# KIBANA_USERNAME - username for accessing kibana API [elastic]

function setup(){
curl -X POST ${KIBANA_HOST:-http://localhost:5601}/api/ingest_manager/setup -H 'kbn-xsrf: true' -u ${KIBANA_USERNAME:-elastic}:${KIBANA_PASSWORD:-changeme}
curl -X POST ${KIBANA_HOST:-http://localhost:5601}/api/ingest_manager/fleet/setup \
-H 'Content-Type: application/json' \
-H 'kbn-xsrf: true' \
-d '{"admin_username":"'"${FLEET_ADMIN_USERNAME:-elastic}"'","admin_password":"'"${FLEET_ADMIN_PASSWORD:-changeme}"'"}' \
-u ${KIBANA_USERNAME:-elastic}:${KIBANA_PASSWORD:-changeme}
}

function enroll(){
local enrollResp
local apiKey

if [[ -n "${FLEET_ENROLLMENT_TOKEN}" ]] && [[ ${FLEET_ENROLLMENT_TOKEN} == 1 ]]; then
apikey = "${FLEET_ENROLLMENT_TOKEN}"
else
enrollResp=$(curl -X POST ${KIBANA_HOST:-http://localhost:5601}/api/ingest_manager/fleet/enrollment-api-keys \
-H 'Content-Type: application/json' \
-H 'kbn-xsrf: true' \
-u ${KIBANA_USERNAME:-elastic}:${KIBANA_PASSWORD:-changeme} \
-d '{"name":"'"${FLEET_TOKEN_NAME:-demotoken}"'","config_id":"'"${FLEET_CONFIG_ID:-default}"'"}')

local exitCode=$?
if [ $exitCode -ne 0 ]; then
exit $exitCode
fi

apikey=$(echo $enrollResp | jq -r '.item.api_key')
fi

./{{ .BeatName }} enroll ${KIBANA_HOST:-http://localhost:5601} $apikey -f
}
yum install -y epel-release
yum install -y jq

if [[ -n "${FLEET_SETUP}" ]] && [[ ${FLEET_SETUP} == 1 ]]; then setup; fi
if [[ -n "${FLEET_ENROLL}" ]] && [[ ${FLEET_ENROLL} == 1 ]]; then enroll; fi

exec {{ .BeatName }} run "$@"
Copy link
Contributor

Choose a reason for hiding this comment

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

I think there is a small problem here, for testing using a docker container this work great, the setup + enroll using credentials but in the normal scenario we would use an enrollment key and nothing else, no?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

yes this container serves testing first, to be usable in a normal use cases it needs some tweaking. i was thinking about different options such as using flags to determine if we're testing or not or setting env variable like SETUP_KIBANA or PERFORM_ENROLL to perform any additional steps. without variables it would just do run.

Copy link
Contributor

Choose a reason for hiding this comment

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

I have mixed feeling here, having something quickly working and adding a bit more work to make it behave with enroll? Do you think it is a lot of work to add it now?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

no i dont' but i'm not sure about which approach to take. flags vs env vars vs something else i dont see

Copy link
Contributor

@ph ph Mar 10, 2020

Choose a reason for hiding this comment

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

I think environment variables is fine for first version, I prefer to have the functionality right and we can change the flags until we move to GA.

14 changes: 11 additions & 3 deletions x-pack/agent/_meta/agent.docker.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,24 @@
outputs:
default:
type: elasticsearch
hosts: [127.0.0.1:9200, 127.0.0.1:9300]
username: elastic
password: changeme
hosts: '${ELASTICSEARCH_HOSTS:http://elasticsearch:9200}'
username: '${ELASTICSEARCH_USERNAME:elastic}'
password: '${ELASTICSEARCH_PASSWORD:changeme}'

streams:
- type: event/file
enabled: true
paths:
- /var/log/hello1.log
- /var/log/hello2.log
- type: metric/system
metricsets:
- cpu
- memory
enabled: true
period: 10s
processes: ['.*']
cpu.metrics: ["percentages"]

management:
# Mode of management, the agent support two modes of operation:
Expand Down
14 changes: 11 additions & 3 deletions x-pack/agent/agent.docker.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,24 @@
outputs:
default:
type: elasticsearch
hosts: [127.0.0.1:9200, 127.0.0.1:9300]
username: elastic
password: changeme
hosts: '${ELASTICSEARCH_HOSTS:http://elasticsearch:9200}'
username: '${ELASTICSEARCH_USERNAME:elastic}'
password: '${ELASTICSEARCH_PASSWORD:changeme}'

streams:
- type: event/file
enabled: true
paths:
- /var/log/hello1.log
- /var/log/hello2.log
- type: metric/system
metricsets:
- cpu
- memory
enabled: true
period: 10s
processes: ['.*']
cpu.metrics: ["percentages"]

management:
# Mode of management, the agent support two modes of operation:
Expand Down