-
Notifications
You must be signed in to change notification settings - Fork 42
feat: sync Docker Compose files with Beats Integrations #84
Conversation
We'll create adirectory per service/integration, which will need a modification of the current behavior for fetching services: instead of using its name as compose file, we will use that name as directory in where a docker-compose.yml file will be located
We are going to copy the docker-compose.yml file AND the _meta directory for each service
We downgraded from 3 to 2.3 because Beats' iintegratioins use that version. It's not possible to upgrade theirs, because they leverage 'depends_on' and 'extends', which are noot supported by 3.x
Those service in the file system take precedence over those boxed in the binary
Let's use the default ones, until the user syncs the integrations with the `sync integrations` command
We do not want to read from the packr box: use the available services struct
Retrieving a docker-compose file from the configuration should not expose whether it's located in the file system or boxed in the binary
A run is an execution of the tool, be it a stack or a service. With the tool we can add or remove services to a run The .run file will contain the stack (optional) and the services in the run, including the environment used for the ran, which will allow to restore that state for future updates in the run. We also support recovering and desttroying the state for a run
@@ -23,6 +23,9 @@ make -C metricbeat-tests fetch-binary | |||
# Build runtime dependencies | |||
STACK_VERSION=${STACK_VERSION} make -C metricbeat-tests run-elastic-stack | |||
|
|||
# Sync integrations | |||
make -C metricbeat-tests sync-integrations |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is forcing the CI to get the compose files from Beats
func GetPackedCompose(isStack bool, composeName string) (string, error) { | ||
composeFileName := composeName + ".yml" | ||
func GetComposeFile(isStack bool, composeName string) (string, error) { | ||
composeFileName := "docker-compose.yml" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because of the layout change, we can keep the name as the default one
// PutServiceEnvironment puts the environment variables for the service, replacing "SERVICE_" | ||
// with service name in uppercase. The variables are: | ||
// - SERVICE_VERSION: where it represents the version of the service (i.e. APACHE_VERSION) | ||
// - SERVICE_PATH: where it represents the path to its compose file (i.e. APACHE_PATH) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Follow-up: we won't need the *_PATH after updating the fetched compose files to remove the build
section.
"service": service, | ||
}).Warn("Could not find compose file") | ||
} else { | ||
env[serviceUpper+"_PATH"] = filepath.Dir(srv.Path) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Follow-up: we won't need the *_PATH after updating the fetched compose files to remove the build
section.
c9e2719
to
5dc4cb0
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great job here, I have added some comments, they can probably be follow ups.
// - SERVICE_VARIANT: where SERVICE is the name of the service (i.e. APACHE_VARIANT) | ||
// - SERVICE_VERSION: where it represents the version of the service (i.e. APACHE_VERSION) | ||
func PutServiceVariantEnvironment(env map[string]string, service string, serviceVariant string, serviceVersion string) map[string]string { | ||
type EnvVar interface{} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you can safely assume that this is going to be an string to string map.
type EnvVar interface{} | |
type EnvVar map[string]string |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What does this PR do?
This PR syncs the docker compose files from the project with the existing ones in Beats for metricbeat's integrations.
To achieve that, we added a new command to the CLI (
sync integrations [--remove, --remote]
) which fetches the default Beats repo (elastic/beats:master) to the tool's workspace:~/.op/git/beats
. It's possible to instrument this command with two flags:Once the Beats repo is cloned, we will copy the compose files into the tool's workspace, alongside the other compose files:
~/.op/compose/services
.To make this possible, we had to change the layout of the services and stacks. In the past, there was a YML file representing the service/stack to deploy, where its name was the service name. Now we are going to use the service name as a directory, in which we will copy the
docker-compose.yml
file coming from the Beats repo. Besides that, we downgraded the spec version of the files from '3.0' to '2.3', to match the spec version Beats files use.Alongside with the compose files, we are copying the
_meta
directory from Beats repo, where there exists asupported-versions.yml
file, which is responsible for the versions to support (as obvious). This will be mapped as environment variables into the running services to be able to define properly the variants for those services needing it. These files will be important, because ONLY those services with the file will be copied to the tool.Talking about variants, we had to create two different Gherkin steps to cover this scenario, which is used by MySQL. It was super easy to create them and reuse common functionality.
Once the docker-compose files have been fetched from the git repo, they will be discoverable by the CLI tool, so any subcommand (i.e.
run, stop, deploy, undeploy
will know about them.Because we want to match Beats integrations files, we also removed the default services that came bundled with the CLI. They will not be present for first time, and a sync must be done if we want to use them.
Another improvement we did in this PR is to address #36. With each run of the CLI will create a state file under tool's workspace (i.e.
~/.op/apache-service.run
. These state files will hold information about the run: which environment variables were added to the run, including its version, and the services in the run in the case we deployed services to a stack. This file will be in YML format, and will contain a suffix in its name setting if the run if for a service or a stack. The CLI will update the state when needed, destroying it with the Down. On the other hand, the CLI will read the state to simplify its usage, and not forcing the user to pass again more variables (i.e. the version) with each command. As an example: if you run an apache service v2.4, then it's not needed to pass the version again when stopping it.As a consequence of above requirements, we created several specialised Go files:
io.go, shell.go, git.go, state.go
, which will represent internal functionality for the CLI.To finish, we used 7.6.0 as the default version for the stack and metricbeat, to match with current release (remember it's possible to modify it using environment variables:
OP_STACK_VERSION
andOP_METRICBEAT_VERSION
.Author's checklist
Follow-up
As a result of elastic/beats#16311, we are going to massage the fetched docker-compose files to remove the
build
section, which requires accessing a relative path which was not present at the first docker-compose file. This will be done in next commits in this PR, but I wanted to publish this work for you to review it 🙏Related issues