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

[8.x] functionaltests: add first test case (backport #14935) #15284

Merged
merged 2 commits into from
Jan 20, 2025
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
66 changes: 66 additions & 0 deletions .github/workflows/functional-tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
---
name: functional-tests

on:
workflow_dispatch: ~
schedule:
- cron: '0 3 * * 1-5'

permissions:
contents: read
id-token: write

env:
TF_VAR_BRANCH: ${{ github.ref_name }}
TF_VAR_BUILD_ID: ${{ github.run_id }}
TF_VAR_ENVIRONMENT: 'ci'
TF_VAR_REPO: ${{ github.repository }}
TERRAFORM_VERSION: 1.10.2

jobs:
run:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
environment:
- 'qa'
- 'pro'
steps:
- uses: actions/checkout@v4

- uses: hashicorp/setup-terraform@b9cd54a3c349d3f38e8881555d616ced269862dd # v3.1.2
with:
terraform_version: "${{ env.TERRAFORM_VERSION }}"

- uses: actions/setup-go@v5
with:
go-version-file: 'functionaltests/go.mod'

- uses: elastic/oblt-actions/google/auth@v1

- uses: google-github-actions/get-secretmanager-secrets@e5bb06c2ca53b244f978d33348d18317a7f263ce # v2.2.2
with:
export_to_environment: true
secrets: |-
EC_API_KEY:elastic-observability/elastic-cloud-observability-team-${{ matrix.environment }}-api-key

- run: |
export TF_VAR_CREATED_DATE=$(date +%s)
cd functionaltests && go test -v -timeout=20m -target "${{ matrix.environment }}" ./

notify:
if: always()
runs-on: ubuntu-latest
needs:
- run
steps:
- id: check
uses: elastic/oblt-actions/check-dependent-jobs@v1
with:
jobs: ${{ toJSON(needs) }}
- uses: elastic/oblt-actions/slack/notify-result@v1
with:
bot-token: ${{ secrets.SLACK_BOT_TOKEN }}
channel-id: "#apm-server"
status: ${{ steps.check.outputs.status }}
152 changes: 152 additions & 0 deletions functionaltests/8_15_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
// Licensed to Elasticsearch B.V. under one or more contributor
// license agreements. See the NOTICE file distributed with
// this work for additional information regarding copyright
// ownership. Elasticsearch B.V. licenses this file to you under
// the Apache License, Version 2.0 (the "License"); you may
// not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.

package functionaltests

import (
"context"
"testing"
"time"

"go.uber.org/zap"
"go.uber.org/zap/zaptest"

"github.com/elastic/apm-server/functionaltests/internal/esclient"
"github.com/elastic/apm-server/functionaltests/internal/gen"
"github.com/elastic/apm-server/functionaltests/internal/terraform"
"github.com/elastic/go-elasticsearch/v8/typedapi/types"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

func TestUpgrade_8_15_4_to_8_16_0(t *testing.T) {
ecAPICheck(t)

start := time.Now()
ctx := context.Background()

t.Log("creating deploment with terraform")
tf, err := terraform.New(t, t.Name())
require.NoError(t, err)
ecTarget := terraform.Var("ec_target", *target)
ecRegion := terraform.Var("ec_region", regionFrom(*target))
version := terraform.Var("stack_version", "8.15.4")
name := terraform.Var("name", t.Name())
require.NoError(t, tf.Apply(ctx, ecTarget, ecRegion, version, name))
t.Logf("time elapsed: %s", time.Now().Sub(start))

t.Cleanup(func() {
if !t.Failed() || (t.Failed() && *cleanupOnFailure) {
t.Log("cleanup terraform resources")
require.NoError(t, tf.Destroy(ctx, ecTarget, ecRegion, name, version))
} else {
t.Log("test failed and cleanup-on-failure is false, skipping cleanup")
}
})

var escfg esclient.Config
tf.Output("apm_url", &escfg.APMServerURL)
tf.Output("es_url", &escfg.ElasticsearchURL)
tf.Output("username", &escfg.Username)
tf.Output("password", &escfg.Password)
tf.Output("kb_url", &escfg.KibanaURL)

t.Logf("created deployment %s", escfg.KibanaURL)

ecc, err := esclient.New(escfg)
require.NoError(t, err)

t.Log("creating APM API key")
apikey, err := ecc.CreateAPMAPIKey(ctx, t.Name())
require.NoError(t, err)

g := gen.New(escfg.APMServerURL, apikey)
g.Logger = zaptest.NewLogger(t, zaptest.Level(zap.InfoLevel))

previous, err := getDocsCountPerDS(t, ctx, ecc)
require.NoError(t, err)

g.RunBlockingWait(ctx, ecc, expectedIngestForASingleRun(), previous, 1*time.Minute)

beforeUpgradeCount, err := getDocsCountPerDS(t, ctx, ecc)
require.NoError(t, err)
assertDocCount(t, beforeUpgradeCount, previous, expectedIngestForASingleRun())

t.Log("check data streams")
var dss []types.DataStream
dss, err = ecc.GetDataStream(ctx, "*apm*")
require.NoError(t, err)
assertDatastreams(t, checkDatastreamWant{
Quantity: 8,
PreferIlm: false,
DSManagedBy: "Data stream lifecycle",
IndicesPerDs: 1,
IndicesManagedBy: []string{"Data stream lifecycle"},
}, dss)
t.Logf("time elapsed: %s", time.Now().Sub(start))

t.Log("upgrade to 8.16.0")
require.NoError(t, tf.Apply(ctx, ecTarget, ecRegion, name, terraform.Var("stack_version", "8.16.0")))
t.Logf("time elapsed: %s", time.Now().Sub(start))

t.Log("check number of documents after upgrade")
afterUpgradeCount, err := getDocsCountPerDS(t, ctx, ecc)
require.NoError(t, err)
// We assert that no changes happened in the number of documents after upgrade
// to ensure the state didn't change before running the next ingestion round
// and further assertions.
// We don't expect any change here unless something broke during the upgrade.
assertDocCount(t, afterUpgradeCount, esclient.APMDataStreamsDocCount{}, beforeUpgradeCount)

t.Log("check data streams after upgrade, no rollover expected")
dss, err = ecc.GetDataStream(ctx, "*apm*")
require.NoError(t, err)
assertDatastreams(t, checkDatastreamWant{
Quantity: 8,
PreferIlm: false,
DSManagedBy: "Data stream lifecycle",
IndicesPerDs: 1,
IndicesManagedBy: []string{"Data stream lifecycle"},
}, dss)

g.RunBlockingWait(ctx, ecc, expectedIngestForASingleRun(), previous, 1*time.Minute)

t.Log("check number of documents")
afterUpgradeIngestionCount, err := getDocsCountPerDS(t, ctx, ecc)
require.NoError(t, err)
assertDocCount(t, afterUpgradeIngestionCount, afterUpgradeCount, expectedIngestForASingleRun())

// Confirm datastreams are
// v managed by DSL if created after 8.15.0
// x managed by ILM if created before 8.15.0
t.Log("check data streams and verify lazy rollover happened")
dss2, err := ecc.GetDataStream(ctx, "*apm*")
require.NoError(t, err)
assertDatastreams(t, checkDatastreamWant{
Quantity: 8,
PreferIlm: false,
DSManagedBy: "Data stream lifecycle",
IndicesPerDs: 2,
IndicesManagedBy: []string{"Data stream lifecycle", "Data stream lifecycle"},
}, dss2)
t.Logf("time elapsed: %s", time.Now().Sub(start))

res, err := ecc.GetESErrorLogs(ctx)
require.NoError(t, err)
assert.Zero(t, res.Hits.Total.Value)
}
18 changes: 18 additions & 0 deletions functionaltests/TestUpgrade_8_15_4_to_8_16_0/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
module "ec_deployment" {
source = "../../testing/infra/terraform/modules/ec_deployment"
region = var.ec_region

deployment_template = "aws-storage-optimized"
deployment_name_prefix = var.name

// self monitoring is enabled so we can inspect Elasticsearch
// logs from tests.
observability_deployment = "self"

apm_server_size = "1g"

elasticsearch_size = "4g"
elasticsearch_zone_count = 1

stack_version = var.stack_version
}
19 changes: 19 additions & 0 deletions functionaltests/TestUpgrade_8_15_4_to_8_16_0/outputs.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
output "apm_url" {
value = module.ec_deployment.apm_url
}

output "es_url" {
value = module.ec_deployment.elasticsearch_url
}

output "username" {
value = module.ec_deployment.elasticsearch_username
}
output "password" {
value = module.ec_deployment.elasticsearch_password
sensitive = true
}

output "kb_url" {
value = module.ec_deployment.kibana_url
}
20 changes: 20 additions & 0 deletions functionaltests/TestUpgrade_8_15_4_to_8_16_0/tags.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
resource "time_static" "created_date" {}

locals {
ci_tags = {
environment = var.ENVIRONMENT
repo = var.REPO
branch = var.BRANCH
build = var.BUILD_ID
created_date = coalesce(var.CREATED_DATE, time_static.created_date.unix)
}
project = "apm-server-functionaltest"
}

module "tags" {
source = "../../testing/infra/terraform/modules/tags"
# use the convention for team/shared owned resources if we are running in CI.
# assume this is an individually owned resource otherwise.
project = local.project
}

21 changes: 21 additions & 0 deletions functionaltests/TestUpgrade_8_15_4_to_8_16_0/terraform.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
terraform {
required_version = ">= 0.12.29"

required_providers {
ec = {
source = "elastic/ec"
version = "0.5.1"
}
}
}

locals {
api_endpoints = {
qa = "https://public-api.qa.cld.elstc.co"
pro = "https://api.elastic-cloud.com"
}
}

provider "ec" {
endpoint = local.api_endpoints[var.ec_target]
}
47 changes: 47 additions & 0 deletions functionaltests/TestUpgrade_8_15_4_to_8_16_0/vars.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
variable "ec_target" {
type = string
description = "The Elastic Cloud environment to target"
validation {
condition = contains(["qa", "pro"], var.ec_target)
error_message = "Valid values are (qa, pro)."
}
}

variable "ec_region" {
type = string
description = "The Elastic Cloud region to target"
}

variable "name" {
type = string
description = "The deployment name"
}

variable "stack_version" {
type = string
description = "The Elasticsearch version to bootstrap"
}

# CI variables
variable "BRANCH" {
description = "Branch name or pull request for tagging purposes"
default = "unknown-branch"
}

variable "BUILD_ID" {
description = "Build ID in the CI for tagging purposes"
default = "unknown-build"
}

variable "CREATED_DATE" {
description = "Creation date in epoch time for tagging purposes"
default = ""
}

variable "ENVIRONMENT" {
default = "unknown-environment"
}

variable "REPO" {
default = "unknown-repo-name"
}
41 changes: 41 additions & 0 deletions functionaltests/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
module github.com/elastic/apm-server/functionaltests

go 1.23.2

require (
github.com/elastic/apm-perf v0.0.0-20241230130730-2ad47482b731
github.com/elastic/go-elasticsearch/v8 v8.16.0
github.com/hashicorp/terraform-exec v0.21.0
github.com/stretchr/testify v1.10.0
go.uber.org/zap v1.27.0
)

require (
github.com/Microsoft/go-winio v0.6.2 // indirect
github.com/apparentlymart/go-textseg/v15 v15.0.0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/elastic/elastic-transport-go/v8 v8.6.0 // indirect
github.com/go-logr/logr v1.4.2 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/hashicorp/go-version v1.6.0 // indirect
github.com/hashicorp/terraform-json v0.22.1 // indirect
github.com/klauspost/compress v1.17.11 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/tidwall/gjson v1.18.0 // indirect
github.com/tidwall/match v1.1.1 // indirect
github.com/tidwall/pretty v1.2.1 // indirect
github.com/tidwall/sjson v1.2.5 // indirect
github.com/zclconf/go-cty v1.14.4 // indirect
go.elastic.co/apm/v2 v2.6.2 // indirect
go.elastic.co/fastjson v1.4.0 // indirect
go.opentelemetry.io/otel v1.32.0 // indirect
go.opentelemetry.io/otel/metric v1.32.0 // indirect
go.opentelemetry.io/otel/trace v1.32.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
golang.org/x/crypto v0.28.0 // indirect
golang.org/x/sync v0.10.0 // indirect
golang.org/x/text v0.20.0 // indirect
golang.org/x/time v0.8.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
Loading
Loading