diff --git a/.ci/Jenkinsfile b/.ci/Jenkinsfile index ec80a6dfce..26f1aaf778 100644 --- a/.ci/Jenkinsfile +++ b/.ci/Jenkinsfile @@ -46,6 +46,7 @@ pipeline { booleanParam(name: "BEATS_USE_CI_SNAPSHOTS", defaultValue: false, description: "If it's needed to use the binary snapshots produced by Beats CI instead of the official releases") choice(name: 'LOG_LEVEL', choices: ['DEBUG', 'TRACE', 'INFO'], description: 'Log level to be used') choice(name: 'TIMEOUT_FACTOR', choices: ['5', '3', '7', '11'], description: 'Max number of minutes for timeout backoff strategies') + string(name: 'KIBANA_VERSION', defaultValue: '', description: 'Docker tag of the kibana to be used for the tests. It will refer to an image related to a Kibana PR, under the Observability-CI namespace') string(name: 'STACK_VERSION', defaultValue: '8.0.0-SNAPSHOT', description: 'SemVer version of the stack to be used for the tests.') string(name: 'HELM_CHART_VERSION', defaultValue: '7.11.2', description: 'SemVer version of Helm chart to be used.') string(name: 'HELM_VERSION', defaultValue: '3.5.2', description: 'SemVer version of Helm to be used.') @@ -53,7 +54,7 @@ pipeline { string(name: 'HELM_KUBERNETES_VERSION', defaultValue: '1.18.2', description: 'SemVer version of Kubernetes to be used.') string(name: 'GITHUB_CHECK_NAME', defaultValue: '', description: 'Name of the GitHub check to be updated. Only if this build is triggered from another parent stream.') string(name: 'GITHUB_CHECK_REPO', defaultValue: '', description: 'Name of the GitHub repo to be updated. Only if this build is triggered from another parent stream.') - string(name: 'GITHUB_CHECK_SHA1', defaultValue: '', description: 'Name of the GitHub repo to be updated. Only if this build is triggered from another parent stream.') + string(name: 'GITHUB_CHECK_SHA1', defaultValue: '', description: 'Git SHA for the Beats upstream project (branch or PR)') } stages { stage('Initializing'){ @@ -69,6 +70,7 @@ pipeline { ELASTIC_AGENT_DOWNLOAD_URL = "${params.ELASTIC_AGENT_DOWNLOAD_URL.trim()}" BEAT_VERSION = "${params.BEAT_VERSION.trim()}" BEATS_USE_CI_SNAPSHOTS = "${params.BEATS_USE_CI_SNAPSHOTS}" + KIBANA_VERSION = "${params.KIBANA_VERSION.trim()}" STACK_VERSION = "${params.STACK_VERSION.trim()}" FORCE_SKIP_GIT_CHECKS = "${params.forceSkipGitChecks}" FORCE_SKIP_PRESUBMIT = "${params.forceSkipPresubmit}" diff --git a/.ci/e2eKibana.groovy b/.ci/e2eKibana.groovy new file mode 100644 index 0000000000..9cd828b9f1 --- /dev/null +++ b/.ci/e2eKibana.groovy @@ -0,0 +1,139 @@ +#!/usr/bin/env groovy + +@Library('apm@current') _ + +pipeline { + agent none + environment { + REPO = 'kibana' + BASE_DIR = "src/github.com/elastic/${env.REPO}" + GITHUB_APP_SECRET = 'secret/observability-team/ci/github-app' + GITHUB_CHECK_E2E_TESTS_NAME = 'E2E Tests' + PIPELINE_LOG_LEVEL = "INFO" + } + options { + timeout(time: 3, unit: 'HOURS') + buildDiscarder(logRotator(numToKeepStr: '20', artifactNumToKeepStr: '20', daysToKeepStr: '30')) + timestamps() + ansiColor('xterm') + disableResume() + durabilityHint('PERFORMANCE_OPTIMIZED') + disableConcurrentBuilds() + } + // http://JENKINS_URL/generic-webhook-trigger/invoke + // Pull requests events: https://docs.github.com/en/developers/webhooks-and-events/github-event-types#pullrequestevent + triggers { + GenericTrigger( + genericVariables: [ + [key: 'GT_REPO', value: '$.repository.full_name'], + [key: 'GT_PR', value: '$.issue.number'], + [key: 'GT_BODY', value: '$.comment.body'], + [key: 'GT_COMMENT_ID', value: '$.comment.id'] + [key: 'GT_PAYLOAD', value: '$'] + ], + genericHeaderVariables: [ + [key: 'x-github-event', regexpFilter: 'comment'] + ], + causeString: 'Triggered on #$GT_PR via comment: $GT_BODY', + printContributedVariables: false, + printPostContent: false, + silentResponse: true, + regexpFilterText: '$GT_REPO$GT_BODY', + regexpFilterExpression: '^elastic/kibana/run-fleet-e2e-tests$' + ) + } + parameters { + string(name: 'kibana_pr', defaultValue: "master", description: "PR ID to use to build the Docker image. (e.g 10000)") + } + stages { + stage('Process GitHub Event') { + agent { label 'ubuntu-20' } + environment { + HOME = "${env.WORKSPACE}/${BASE_DIR}" + PATH = "${env.HOME}/bin:${env.HOME}/node_modules:${env.HOME}/node_modules/.bin:${env.PATH}" + } + steps { + echo(message: "$env.GT_PAYLOAD") + checkPermissions() + buildKibanaDockerImage(refspec: getBranch()) + catchError(buildResult: 'UNSTABLE', message: 'Unable to run e2e tests', stageResult: 'FAILURE') { + runE2ETests('fleet') + } + } + } + } +} + +def checkPermissions(){ + if(env.GT_PR){ + if(!githubPrCheckApproved(changeId: "${env.GT_PR}", org: 'elastic', repo: 'kibana')){ + error("Only PRs from Elasticians can be tested with Fleet E2E tests") + } + + if(!hasCommentAuthorWritePermissions(repoName: 'elastic/kibana', commentId: env.GT_COMMENT_ID)){ + error("Only Elasticians can trigger Fleet E2E tests") + } + } +} + +def getBranch(){ + return "PR/" + getID() +} + +def getID(){ + if(env.GT_PR){ + return "${env.GT_PR}" + } + + return "${params.kibana_pr}" +} + +def runE2ETests(String suite) { + // we need a second API request, as the issue_comment API does not retrieve data about the pull request + // See https://docs.github.com/en/developers/webhooks-and-events/webhook-events-and-payloads#issue_comment + def prID = getID() + def token = githubAppToken(secret: "${env.GITHUB_APP_SECRET}") + + def pullRequest = githubApiCall(token: token, url: "https://api.github.com/repos/${env.$GT_REPO}/pulls/${prID}") + def baseRef = pullRequest?.base?.ref + def headSha = pullRequest?.head?.sha + + // we are going to use the 'pr12345' tag as default + def dockerTag = "pr${params.kibana_pr}" + if(env.GT_PR){ + // it's a PR: we are going to use its head SHA as tag + dockerTag = headSha + } + + log(level: 'DEBUG', text: "Triggering '${suite}' E2E tests for PR-${prID} using '${dockerTag}' as Docker tag") + + // Kibana's maintenance branches follow the 7.11, 7.12 schema. + def branchName = "${baseRef}" + if (branchName != "master") { + branchName += ".x" + } + def e2eTestsPipeline = "e2e-tests/e2e-testing-mbp/${branchName}" + + def parameters = [ + booleanParam(name: 'forceSkipGitChecks', value: true), + booleanParam(name: 'forceSkipPresubmit', value: true), + booleanParam(name: 'notifyOnGreenBuilds', value: false), + booleanParam(name: 'BEATS_USE_CI_SNAPSHOTS', value: true), + string(name: 'runTestsSuites', value: suite), + string(name: 'GITHUB_CHECK_NAME', value: env.GITHUB_CHECK_E2E_TESTS_NAME), + string(name: 'GITHUB_CHECK_REPO', value: env.REPO), + string(name: 'KIBANA_VERSION', value: dockerTag), + ] + + build(job: "${e2eTestsPipeline}", + parameters: parameters, + propagate: false, + wait: false + ) + +/* + // commented out to avoid sending Github statuses to Kibana PRs + def notifyContext = "${env.pr_head_sha}" + githubNotify(context: "${notifyContext}", description: "${notifyContext} ...", status: 'PENDING', targetUrl: "${env.JENKINS_URL}search/?q=${e2eTestsPipeline.replaceAll('/','+')}") +*/ +} diff --git a/.ci/jobs/kibana-e2e-tests.yml b/.ci/jobs/kibana-e2e-tests.yml new file mode 100644 index 0000000000..c068568929 --- /dev/null +++ b/.ci/jobs/kibana-e2e-tests.yml @@ -0,0 +1,18 @@ +--- +- job: + name: e2e-tests/e2e-testing-kibana-fleet + display-name: Fleet UI e2e tests Pipeline + description: Jenkins pipeline to run the end2end tests for the Fleet UI + project-type: pipeline + pipeline-scm: + script-path: .ci/e2eKibana.groovy + scm: + - git: + url: git@github.com:elastic/e2e-testing.git + wipe-workspace: 'True' + name: origin + shallow-clone: true + credentials-id: f6c7695a-671e-4f4f-a331-acdce44ff9ba + branches: + - "master" + triggers: [] diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index faba19305d..b1aa86f90a 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -56,28 +56,28 @@ Link related issues below. Insert the issue link or reference after the word "Cl --> - + + + + diff --git a/.mergify.yml b/.mergify.yml index bb7dba3e68..d11dae93c7 100644 --- a/.mergify.yml +++ b/.mergify.yml @@ -15,25 +15,34 @@ pull_request_rules: ``` - name: backport patches to 7.x branch conditions: + - merged - base=master - label=v7.13.0 actions: backport: + assignees: + - "{{ author }}" branches: - "7.x" - name: backport patches to 7.12 branch conditions: + - merged - base=master - label=v7.12.0 actions: backport: + assignees: + - "{{ author }}" branches: - "7.12.x" - name: backport patches to 7.11 branch conditions: + - merged - base=master - label=v7.11.0 actions: backport: + assignees: + - "{{ author }}" branches: - "7.11.x" diff --git a/cli/config/compose/profiles/fleet/docker-compose.yml b/cli/config/compose/profiles/fleet/docker-compose.yml index 5d22bf2088..2a740c3335 100644 --- a/cli/config/compose/profiles/fleet/docker-compose.yml +++ b/cli/config/compose/profiles/fleet/docker-compose.yml @@ -29,7 +29,7 @@ services: test: "curl -f http://localhost:5601/login | grep kbn-injected-metadata 2>&1 >/dev/null" retries: 600 interval: 1s - image: "docker.elastic.co/kibana/kibana:${stackVersion:-8.0.0-SNAPSHOT}" + image: "docker.elastic.co/${kibanaDockerNamespace:-beats}/kibana:${kibanaVersion:-8.0.0-SNAPSHOT}" ports: - "5601:5601" volumes: diff --git a/cli/config/compose/services/elastic-agent/docker-compose.yml b/cli/config/compose/services/elastic-agent/docker-compose.yml index c5c0180254..1f04538ef3 100644 --- a/cli/config/compose/services/elastic-agent/docker-compose.yml +++ b/cli/config/compose/services/elastic-agent/docker-compose.yml @@ -9,15 +9,12 @@ services: kibana: condition: service_healthy environment: - - "KIBANA_HOST=http://${kibanaHost:-kibana}:${kibanaPort:-5601}" + - "FLEET_SERVER_ELASTICSEARCH_HOST=http://${elasticsearchHost:-elasticsearch}:${elasticsearchPort:-9200}" - "FLEET_SERVER_ENABLE=${fleetServerMode:-0}" - "FLEET_SERVER_INSECURE_HTTP=${fleetServerMode:-0}" - - "KIBANA_FLEET_SETUP=${fleetServerMode:-0}" - "FLEET_SERVER_HOST=0.0.0.0" - - "KIBANA_USERNAME=elastic" - - "KIBANA_PASSWORD=changeme" + - "FLEET_SERVER_ELASTICSEARCH_USERNAME=elastic" + - "FLEET_SERVER_ELASTICSEARCH_PASSWORD=changeme" platform: ${elasticAgentPlatform:-linux/amd64} ports: - "127.0.0.1:8220:8220" - volumes: - - "${elasticAgentConfigFile}:/usr/share/elastic-agent/elastic-agent.yml" diff --git a/e2e/README.md b/e2e/README.md index af1c88d35d..f833d64aa3 100644 --- a/e2e/README.md +++ b/e2e/README.md @@ -147,7 +147,8 @@ The following environment variables affect how the tests are run in both the CI - `BEATS_USE_CI_SNAPSHOTS`: Set this environment variable to `true` if it's needed to use the binary snapshots produced by Beats CI instead of the official releases. The snapshots will be downloaded from a bucket in Google Cloud Storage. This variable is used by the Beats repository, when testing the artifacts generated by the packaging job. Default: `false`. - `LOG_LEVEL`: Set this environment variable to `TRACE`, `DEBUG`, `INFO`, `WARN`, `ERROR` or `FATAL` to set the log level in the project. Default: `INFO`. - `DEVELOPER_MODE`: Set this environment variable to `true` to activate developer mode, which means not destroying the services provisioned by the test framework. Default: `false`. -- `STACK_VERSION`. Set this environment variable to the proper version of the Elastic Stack (Elasticsearch and Kibana) to be used in the current execution. The default value depens on the branch you are targeting your work. +- `KIBANA_VERSION`. Set this environment variable to the proper version of the Kibana instance to be used in the current execution, which should be used for the Docker tag of the kibana instance. It will refer to an image related to a Kibana PR, under the Observability-CI namespace. Default is empty +- `STACK_VERSION`. Set this environment variable to the proper version of the Elasticsearch to be used in the current execution. The default value depens on the branch you are targeting your work. - **master (Fleet):** https://github.com/elastic/e2e-testing/blob/0446248bae1ff604219735998841a21a7576bfdd/e2e/_suites/fleet/ingest-manager_test.go#L39 - **master (Integrations):** https://github.com/elastic/e2e-testing/blob/0446248bae1ff604219735998841a21a7576bfdd/e2e/_suites/metricbeat/metricbeat_test.go#L30 - `TIMEOUT_FACTOR`: Set this environment variable to an integer number, which represents the factor to be used while waiting for resources within the tests. I.e. waiting for Kibana needs around 30 seconds. Instead of hardcoding 30 seconds, or 3 minutes, in the code, we use a backoff strategy to wait until an amount of time, specific per situation, multiplying it by the timeout factor. With that in mind, we are able to set a higher factor on CI without changing the code, and the developer is able to locally set specific conditions when running the tests on slower machines. Default: `3`. diff --git a/e2e/_suites/fleet/README.md b/e2e/_suites/fleet/README.md index 030fa2f497..94cf727cdd 100644 --- a/e2e/_suites/fleet/README.md +++ b/e2e/_suites/fleet/README.md @@ -44,8 +44,10 @@ To change it, please use Docker UI, go to `Preferences > Resources > File Sharin This is an example of the optional configuration: ```shell - # There should be a Docker image for the runtime dependencies (elasticsearch, kibana, package registry) + # There should be a Docker image for the runtime dependencies (elasticsearch, package registry) export STACK_VERSION=8.0.0-SNAPSHOT + # There should be a Docker image for the runtime dependencies (kibana) + export KIBANA_VERSION=pr12345 # (Fleet mode) This environment variable will use a fixed version of the Elastic agent binary, obtained from # https://artifacts-api.elastic.co/v1/search/8.0.0-SNAPSHOT/elastic-agent export ELASTIC_AGENT_DOWNLOAD_URL="https://snapshots.elastic.co/8.0.0-59098054/downloads/beats/elastic-agent/elastic-agent-8.0.0-SNAPSHOT-linux-x86_64.tar.gz" diff --git a/e2e/_suites/fleet/features/fleet_mode_agent.feature b/e2e/_suites/fleet/features/fleet_mode_agent.feature index 31eab5853e..65c5962460 100644 --- a/e2e/_suites/fleet/features/fleet_mode_agent.feature +++ b/e2e/_suites/fleet/features/fleet_mode_agent.feature @@ -122,7 +122,6 @@ Scenario Outline: Un-installing the installed agent Given a "" agent is deployed to Fleet with "tar" installer When the "elastic-agent" process is "uninstalled" on the host Then the file system Agent folder is empty - And the agent is listed in Fleet as "offline" @centos Examples: Centos diff --git a/e2e/_suites/fleet/features/stand_alone_agent.feature b/e2e/_suites/fleet/features/stand_alone_agent.feature index af05676a92..171705c957 100644 --- a/e2e/_suites/fleet/features/stand_alone_agent.feature +++ b/e2e/_suites/fleet/features/stand_alone_agent.feature @@ -54,9 +54,14 @@ Examples: Ubi8 @run_fleet_server Scenario Outline: Deploying a stand-alone agent with fleet server mode When a "" stand-alone agent is deployed with fleet server mode - Then the agent is listed in Fleet as "online" + Then the stand-alone agent is listed in Fleet as "online" @default Examples: default | image | | default | + +@ubi8 +Examples: Ubi8 + | image | + | ubi8 | diff --git a/e2e/_suites/fleet/fleet.go b/e2e/_suites/fleet/fleet.go index 23801fadec..5a770b18a0 100644 --- a/e2e/_suites/fleet/fleet.go +++ b/e2e/_suites/fleet/fleet.go @@ -15,6 +15,7 @@ import ( "github.com/cucumber/godog" "github.com/elastic/e2e-testing/cli/services" curl "github.com/elastic/e2e-testing/cli/shell" + shell "github.com/elastic/e2e-testing/cli/shell" "github.com/elastic/e2e-testing/e2e" "github.com/elastic/e2e-testing/e2e/steps" "github.com/google/uuid" @@ -169,6 +170,23 @@ func (fts *FleetTestSuite) anStaleAgentIsDeployedToFleetWithInstaller(image, ver agentVersionBackup := fts.Version defer func() { fts.Version = agentVersionBackup }() + agentStaleVersion = shell.GetEnv("ELASTIC_AGENT_STALE_VERSION", agentStaleVersion) + // check if stale version is an alias + v, err := e2e.GetElasticArtifactVersion(agentStaleVersion) + if err != nil { + log.WithFields(log.Fields{ + "error": err, + "version": agentStaleVersion, + }).Error("Failed to get stale version") + return err + } + agentStaleVersion = v + + useCISnapshots := shell.GetEnvBool("BEATS_USE_CI_SNAPSHOTS") + if useCISnapshots && !strings.HasSuffix(agentStaleVersion, "-SNAPSHOT") { + agentStaleVersion += "-SNAPSHOT" + } + switch version { case "stale": version = agentStaleVersion diff --git a/e2e/_suites/fleet/ingest_manager_test.go b/e2e/_suites/fleet/ingest_manager_test.go index ea8a411b93..105ccc1131 100644 --- a/e2e/_suites/fleet/ingest_manager_test.go +++ b/e2e/_suites/fleet/ingest_manager_test.go @@ -32,25 +32,44 @@ func setUpSuite() { } // check if base version is an alias - agentVersionBase = e2e.GetElasticArtifactVersion(agentVersionBase) + v, err := e2e.GetElasticArtifactVersion(agentVersionBase) + if err != nil { + log.WithFields(log.Fields{ + "error": err, + "version": agentVersionBase, + }).Fatal("Failed to get agent base version, aborting") + } + agentVersionBase = v timeoutFactor = shell.GetEnvInteger("TIMEOUT_FACTOR", timeoutFactor) agentVersion = shell.GetEnv("BEAT_VERSION", agentVersionBase) - agentStaleVersion = shell.GetEnv("ELASTIC_AGENT_STALE_VERSION", agentStaleVersion) - // check if stale version is an alias - agentStaleVersion = e2e.GetElasticArtifactVersion(agentStaleVersion) - - useCISnapshots := shell.GetEnvBool("BEATS_USE_CI_SNAPSHOTS") - if useCISnapshots && !strings.HasSuffix(agentStaleVersion, "-SNAPSHOT") { - agentStaleVersion += "-SNAPSHOT" - } - // check if version is an alias - agentVersion = e2e.GetElasticArtifactVersion(agentVersion) + v, err = e2e.GetElasticArtifactVersion(agentVersion) + if err != nil { + log.WithFields(log.Fields{ + "error": err, + "version": agentVersion, + }).Fatal("Failed to get agent version, aborting") + } + agentVersion = v stackVersion = shell.GetEnv("STACK_VERSION", stackVersion) - stackVersion = e2e.GetElasticArtifactVersion(stackVersion) + v, err = e2e.GetElasticArtifactVersion(stackVersion) + if err != nil { + log.WithFields(log.Fields{ + "error": err, + "version": stackVersion, + }).Fatal("Failed to get stack version, aborting") + } + stackVersion = v + + kibanaVersion = shell.GetEnv("KIBANA_VERSION", "") + if kibanaVersion == "" { + // we want to deploy a released version for Kibana + // if not set, let's use stackVersion + kibanaVersion = stackVersion + } imts = IngestManagerTestSuite{ Fleet: &FleetTestSuite{ @@ -96,7 +115,14 @@ func InitializeIngestManagerTestSuite(ctx *godog.TestSuiteContext) { log.Trace("Installing Fleet runtime dependencies") profileEnv = map[string]string{ - "stackVersion": stackVersion, + "kibanaVersion": kibanaVersion, + "stackVersion": stackVersion, + } + + profileEnv["kibanaDockerNamespace"] = "kibana" + if strings.HasPrefix(kibanaVersion, "pr") { + // because it comes from a PR + profileEnv["kibanaDockerNamespace"] = "observability-ci" } profile := FleetProfileName diff --git a/e2e/_suites/fleet/stand-alone.go b/e2e/_suites/fleet/stand-alone.go index 9f219ee323..ba1c658bd3 100644 --- a/e2e/_suites/fleet/stand-alone.go +++ b/e2e/_suites/fleet/stand-alone.go @@ -7,7 +7,6 @@ package main import ( "context" "fmt" - "os" "strings" "time" @@ -22,10 +21,9 @@ import ( // StandAloneTestSuite represents the scenarios for Stand-alone-mode type StandAloneTestSuite struct { - AgentConfigFilePath string - Cleanup bool - Hostname string - Image string + Cleanup bool + Hostname string + Image string // date controls for queries AgentStoppedDate time.Time RuntimeDependenciesStartDate time.Time @@ -45,21 +43,6 @@ func (sats *StandAloneTestSuite) afterScenario() { } else { log.WithField("service", serviceName).Info("Because we are running in development mode, the service won't be stopped") } - - if _, err := os.Stat(sats.AgentConfigFilePath); err == nil { - beatsLocalPath := shell.GetEnv("BEATS_LOCAL_PATH", "") - if beatsLocalPath == "" { - os.Remove(sats.AgentConfigFilePath) - - log.WithFields(log.Fields{ - "path": sats.AgentConfigFilePath, - }).Trace("Elastic Agent configuration file removed.") - } else { - log.WithFields(log.Fields{ - "path": sats.AgentConfigFilePath, - }).Trace("Elastic Agent configuration file not removed because it's part of a repository.") - } - } } func (sats *StandAloneTestSuite) contributeSteps(s *godog.ScenarioContext) { @@ -68,7 +51,7 @@ func (sats *StandAloneTestSuite) contributeSteps(s *godog.ScenarioContext) { s.Step(`^there is new data in the index from agent$`, sats.thereIsNewDataInTheIndexFromAgent) s.Step(`^the "([^"]*)" docker container is stopped$`, sats.theDockerContainerIsStopped) s.Step(`^there is no new data in the index after agent shuts down$`, sats.thereIsNoNewDataInTheIndexAfterAgentShutsDown) - s.Step(`^the agent is listed in Fleet as "([^"]*)"$`, sats.theAgentIsListedInFleetWithStatus) + s.Step(`^the stand-alone agent is listed in Fleet as "([^"]*)"$`, sats.theAgentIsListedInFleetWithStatus) } func (sats *StandAloneTestSuite) theAgentIsListedInFleetWithStatus(desiredStatus string) error { @@ -102,11 +85,6 @@ func (sats *StandAloneTestSuite) startAgent(image string, env map[string]string) dockerImageTag += "-amd64" } - configurationFilePath, err := steps.FetchBeatConfiguration(true, "elastic-agent", "elastic-agent.docker.yml") - if err != nil { - return err - } - serviceManager := services.NewServiceManager() profileEnv["elasticAgentDockerImageSuffix"] = "" @@ -114,14 +92,11 @@ func (sats *StandAloneTestSuite) startAgent(image string, env map[string]string) profileEnv["elasticAgentDockerImageSuffix"] = "-" + image } - profileEnv["elasticAgentDockerNamespace"] = e2e.GetDockerNamespaceEnvVar() + profileEnv["elasticAgentDockerNamespace"] = e2e.GetDockerNamespaceEnvVar("beats") containerName := fmt.Sprintf("%s_%s_%d", FleetProfileName, ElasticAgentServiceName, 1) - sats.AgentConfigFilePath = configurationFilePath - profileEnv["elasticAgentContainerName"] = containerName - profileEnv["elasticAgentConfigFile"] = sats.AgentConfigFilePath profileEnv["elasticAgentPlatform"] = "linux/amd64" profileEnv["elasticAgentTag"] = dockerImageTag @@ -129,7 +104,7 @@ func (sats *StandAloneTestSuite) startAgent(image string, env map[string]string) profileEnv[k] = v } - err = serviceManager.AddServicesToCompose(context.Background(), FleetProfileName, []string{ElasticAgentServiceName}, profileEnv) + err := serviceManager.AddServicesToCompose(context.Background(), FleetProfileName, []string{ElasticAgentServiceName}, profileEnv) if err != nil { log.Error("Could not deploy the elastic-agent") return err diff --git a/e2e/_suites/fleet/world.go b/e2e/_suites/fleet/world.go index 4d28ccfcdf..c62233f296 100644 --- a/e2e/_suites/fleet/world.go +++ b/e2e/_suites/fleet/world.go @@ -36,6 +36,10 @@ var agentVersion = agentVersionBase // It can be overriden by ELASTIC_AGENT_STALE_VERSION env var. Using latest GA as a default. var agentStaleVersion = "7.11-SNAPSHOT" +// kibanaVersion is the version of the kibana to use +// It can be overriden by KIBANA_VERSION env var +var kibanaVersion = agentVersionBase + // stackVersion is the version of the stack to use // It can be overriden by STACK_VERSION env var var stackVersion = agentVersionBase diff --git a/e2e/_suites/helm/helm_charts_test.go b/e2e/_suites/helm/helm_charts_test.go index a6c6ab7114..53eacd3fb8 100644 --- a/e2e/_suites/helm/helm_charts_test.go +++ b/e2e/_suites/helm/helm_charts_test.go @@ -81,7 +81,14 @@ func setupSuite() { timeoutFactor = shell.GetEnvInteger("TIMEOUT_FACTOR", timeoutFactor) stackVersion = shell.GetEnv("STACK_VERSION", stackVersion) - stackVersion = e2e.GetElasticArtifactVersion(stackVersion) + v, err := e2e.GetElasticArtifactVersion(stackVersion) + if err != nil { + log.WithFields(log.Fields{ + "error": err, + "version": stackVersion, + }).Fatal("Failed to get stack version, aborting") + } + stackVersion = v h, err := k8s.HelmFactory(helmVersion) if err != nil { diff --git a/e2e/_suites/metricbeat/README.md b/e2e/_suites/metricbeat/README.md index f9f2be6388..0c36e002b2 100644 --- a/e2e/_suites/metricbeat/README.md +++ b/e2e/_suites/metricbeat/README.md @@ -44,7 +44,7 @@ To change it, please use Docker UI, go to `Preferences > Resources > File Sharin This is an example of the optional configuration: ```shell - # There should be a Docker image for the runtime dependencies (elasticsearch, kibana, package registry) + # There should be a Docker image for the runtime dependencies (elasticsearch) export STACK_VERSION="8.0.0-SNAPSHOT" export BEAT_VERSION="8.0.0-SNAPSHOT" # or diff --git a/e2e/_suites/metricbeat/metricbeat_test.go b/e2e/_suites/metricbeat/metricbeat_test.go index 6d3b4ed831..a8d14cce17 100644 --- a/e2e/_suites/metricbeat/metricbeat_test.go +++ b/e2e/_suites/metricbeat/metricbeat_test.go @@ -69,13 +69,27 @@ func setupSuite() { } // check if base version is an alias - metricbeatVersionBase = e2e.GetElasticArtifactVersion(metricbeatVersionBase) + v, err := e2e.GetElasticArtifactVersion(metricbeatVersionBase) + if err != nil { + log.WithFields(log.Fields{ + "error": err, + "version": metricbeatVersionBase, + }).Fatal("Failed to get metricbeat base version, aborting") + } + metricbeatVersionBase = v metricbeatVersion = shell.GetEnv("BEAT_VERSION", metricbeatVersionBase) timeoutFactor = shell.GetEnvInteger("TIMEOUT_FACTOR", timeoutFactor) stackVersion = shell.GetEnv("STACK_VERSION", stackVersion) - stackVersion = e2e.GetElasticArtifactVersion(stackVersion) + v, err = e2e.GetElasticArtifactVersion(stackVersion) + if err != nil { + log.WithFields(log.Fields{ + "error": err, + "version": stackVersion, + }).Fatal("Failed to get stack version, aborting") + } + stackVersion = v serviceManager = services.NewServiceManager() @@ -446,7 +460,7 @@ func (mts *MetricbeatTestSuite) runMetricbeatService() error { "serviceName": mts.ServiceName, } - env["metricbeatDockerNamespace"] = e2e.GetDockerNamespaceEnvVar() + env["metricbeatDockerNamespace"] = e2e.GetDockerNamespaceEnvVar("beats") env["metricbeatPlatform"] = "linux/amd64" err := serviceManager.AddServicesToCompose(testSuite.currentContext, "metricbeat", []string{"metricbeat"}, env) diff --git a/e2e/utils.go b/e2e/utils.go index 3cc414e456..1d67b7ca32 100644 --- a/e2e/utils.go +++ b/e2e/utils.go @@ -194,7 +194,7 @@ func GetExponentialBackOff(elapsedTime time.Duration) *backoff.ExponentialBackOf // 1. Elastic's artifact repository, building the JSON path query based // If the version is a PR, then it will return the version without checking the artifacts API // i.e. GetElasticArtifactVersion("$VERSION") -func GetElasticArtifactVersion(version string) string { +func GetElasticArtifactVersion(version string) (string, error) { exp := GetExponentialBackOff(time.Minute) retryCount := 1 @@ -233,11 +233,7 @@ func GetElasticArtifactVersion(version string) string { err := backoff.Retry(apiStatus, exp) if err != nil { - log.WithFields(log.Fields{ - "error": err, - "version": version, - }).Fatal("Failed to get version, aborting") - return "" + return "", err } jsonParsed, err := gabs.ParseJSON([]byte(body)) @@ -245,8 +241,8 @@ func GetElasticArtifactVersion(version string) string { log.WithFields(log.Fields{ "error": err, "version": version, - }).Fatal("Could not parse the response body to retrieve the version, aborting") - return "" + }).Error("Could not parse the response body to retrieve the version") + return "", err } builds := jsonParsed.Path("version.builds") @@ -259,7 +255,7 @@ func GetElasticArtifactVersion(version string) string { "version": latestVersion, }).Debug("Latest version for current version obtained") - return latestVersion + return latestVersion, nil } // GetElasticArtifactURL returns the URL of a released artifact, which its full name is defined in the first argument, @@ -578,14 +574,14 @@ func Sleep(duration time.Duration) error { // GetDockerNamespaceEnvVar returns the Docker namespace whether we use one of the CI snapshots or // the images produced by local Beats build, or not. -// If an error occurred reading the environment, wil return 'beats' as fallback -func GetDockerNamespaceEnvVar() string { +// If an error occurred reading the environment, will return the passed namespace as fallback +func GetDockerNamespaceEnvVar(fallback string) string { beatsLocalPath := shell.GetEnv("BEATS_LOCAL_PATH", "") useCISnapshots := shell.GetEnvBool("BEATS_USE_CI_SNAPSHOTS") if useCISnapshots || beatsLocalPath != "" { return "observability-ci" } - return "beats" + return fallback } // WaitForProcess polls a container executing "ps" command until the process is in the desired state (present or not), diff --git a/e2e/utils_test.go b/e2e/utils_test.go index 7e04790511..0d1d154c43 100644 --- a/e2e/utils_test.go +++ b/e2e/utils_test.go @@ -225,6 +225,21 @@ func TestGetBucketSearchNextPageParam_HasNoMorePages(t *testing.T) { assert.True(t, param == "") } +func TestGetDockerNamespaceEnvVar(t *testing.T) { + t.Run("Returns fallback when environment variable is not set", func(t *testing.T) { + namespace := GetDockerNamespaceEnvVar("beats") + assert.True(t, namespace == "beats") + }) + + t.Run("Returns Observability CI when environment variable is set", func(t *testing.T) { + defer os.Unsetenv("BEATS_USE_CI_SNAPSHOTS") + os.Setenv("BEATS_USE_CI_SNAPSHOTS", "true") + + namespace := GetDockerNamespaceEnvVar("beats") + assert.True(t, namespace == "observability-ci") + }) +} + func TestGetGCPBucketCoordinates_Commits(t *testing.T) { artifact := "elastic-agent" version := testVersion