Skip to content

Commit b6e6fc1

Browse files
authored
[beatreceiver] Add e2e test for azure blob storage (#51738)
* [beatreceiver] Add e2e test for azure blob storage
1 parent 8f4bbab commit b6e6fc1

6 files changed

Lines changed: 328 additions & 328 deletions

File tree

Lines changed: 205 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,205 @@
1+
// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
2+
// or more contributor license agreements. Licensed under the Elastic License;
3+
// you may not use this file except in compliance with the Elastic License.
4+
5+
//go:build integration
6+
7+
package integration
8+
9+
import (
10+
"bytes"
11+
"context"
12+
"fmt"
13+
"net/http/httptest"
14+
"strings"
15+
"testing"
16+
"text/template"
17+
"time"
18+
19+
"github.com/gofrs/uuid/v5"
20+
"github.com/stretchr/testify/assert"
21+
"github.com/stretchr/testify/require"
22+
23+
"github.com/elastic/beats/v7/libbeat/tests/integration"
24+
"github.com/elastic/beats/v7/x-pack/filebeat/input/azureblobstorage/mock"
25+
"github.com/elastic/beats/v7/x-pack/otel/oteltest"
26+
"github.com/elastic/beats/v7/x-pack/otel/oteltestcol"
27+
"github.com/elastic/elastic-agent-libs/testing/estools"
28+
)
29+
30+
const (
31+
azureBlobTestAccountName = "beatsblobnew"
32+
azureBlobTestAccountKey = "7pfLm1betGiRyyABEM/RFrLYlafLZHbLtGhB52LkWVeBxE7la9mIvk6YYAbQKYE/f0GdhiaOZeV8+AStsAdr/Q=="
33+
azureBlobTestContainer = "beatscontainer"
34+
azureBlobTestBlob = "ata.json"
35+
azureBlobTestMessage = "iPhone 9"
36+
)
37+
38+
func startAzureBlobMockStorageServer(t *testing.T) string {
39+
t.Helper()
40+
41+
srv := httptest.NewServer(mock.AzureStorageServer())
42+
t.Cleanup(srv.Close)
43+
44+
return srv.URL + "/"
45+
}
46+
47+
func TestAzureBlobStorageInputOTelE2E(t *testing.T) {
48+
integration.EnsureESIsRunning(t)
49+
50+
storageURL := startAzureBlobMockStorageServer(t)
51+
otelHome := t.TempDir()
52+
53+
host := integration.GetESURL(t, "http")
54+
user := host.User.Username()
55+
password, _ := host.User.Password()
56+
57+
otelNamespace := strings.ReplaceAll(uuid.Must(uuid.NewV4()).String(), "-", "")
58+
fbNamespace := strings.ReplaceAll(uuid.Must(uuid.NewV4()).String(), "-", "")
59+
60+
otelIndex := "logs-integration-" + otelNamespace
61+
fbIndex := "logs-integration-" + fbNamespace
62+
63+
type options struct {
64+
Index string
65+
ESURL string
66+
Username string
67+
Password string
68+
StorageURL string
69+
PathHome string
70+
AccountName string
71+
AccountKey string
72+
}
73+
74+
filebeatConfig := `filebeat.inputs:
75+
- type: azure-blob-storage
76+
id: azure-blob-storage-input-e2e
77+
account_name: {{ .AccountName }}
78+
storage_url: {{ .StorageURL }}
79+
auth:
80+
shared_credentials:
81+
account_key: {{ .AccountKey }}
82+
poll: false
83+
max_workers: 1
84+
containers:
85+
- name: ` + azureBlobTestContainer + `
86+
file_selectors:
87+
- regex: '^` + azureBlobTestBlob + `$'
88+
89+
output:
90+
elasticsearch:
91+
hosts:
92+
- {{ .ESURL }}
93+
username: {{ .Username }}
94+
password: {{ .Password }}
95+
index: {{ .Index }}
96+
97+
queue.mem.flush.timeout: 0s
98+
setup.template.enabled: false
99+
processors:
100+
- add_host_metadata: ~
101+
- add_cloud_metadata: ~
102+
- add_docker_metadata: ~
103+
- add_kubernetes_metadata: ~
104+
`
105+
106+
otelConfig := otelElasticsearchExporterYAML + `receivers:
107+
filebeatreceiver:
108+
filebeat:
109+
inputs:
110+
- type: azure-blob-storage
111+
id: azure-blob-storage-input-e2e
112+
account_name: {{ .AccountName }}
113+
storage_url: {{ .StorageURL }}
114+
auth:
115+
shared_credentials:
116+
account_key: {{ .AccountKey }}
117+
poll: false
118+
max_workers: 1
119+
containers:
120+
- name: ` + azureBlobTestContainer + `
121+
file_selectors:
122+
- regex: '^` + azureBlobTestBlob + `$'
123+
processors:
124+
- add_host_metadata: ~
125+
- add_cloud_metadata: ~
126+
- add_docker_metadata: ~
127+
- add_kubernetes_metadata: ~
128+
queue.mem.flush.timeout: 0s
129+
setup.template.enabled: false
130+
path.home: {{ .PathHome }}
131+
` + otelElasticsearchServiceYAML
132+
133+
optionsValue := options{
134+
ESURL: fmt.Sprintf("%s://%s", host.Scheme, host.Host),
135+
Username: user,
136+
Password: password,
137+
StorageURL: storageURL,
138+
PathHome: otelHome,
139+
AccountName: azureBlobTestAccountName,
140+
AccountKey: azureBlobTestAccountKey,
141+
}
142+
143+
var configBuffer bytes.Buffer
144+
optionsValue.Index = otelIndex
145+
require.NoError(t, template.Must(template.New("config").Parse(otelConfig)).Execute(&configBuffer, optionsValue))
146+
147+
oteltestcol.New(t, configBuffer.String())
148+
149+
configBuffer.Reset()
150+
151+
optionsValue.Index = fbIndex
152+
require.NoError(t, template.Must(template.New("config").Parse(filebeatConfig)).Execute(&configBuffer, optionsValue))
153+
154+
filebeat := integration.NewBeat(
155+
t,
156+
"filebeat",
157+
"../../filebeat.test",
158+
)
159+
filebeat.WriteConfigFile(configBuffer.String())
160+
filebeat.Start()
161+
defer filebeat.Stop()
162+
163+
filebeat.WaitLogsContains(
164+
"filebeat start running",
165+
20*time.Second,
166+
"filebeat did not run",
167+
)
168+
169+
es := integration.GetESClient(t, "http")
170+
171+
t.Cleanup(func() {
172+
deleteDataStreamsFromES(t, es, []string{otelIndex, fbIndex})
173+
})
174+
175+
rawQuery := otelE2ERawQueryForInputTypeAndMessage("azure-blob-storage", azureBlobTestMessage)
176+
177+
var filebeatDocs estools.Documents
178+
var otelDocs estools.Documents
179+
var err error
180+
181+
require.EventuallyWithTf(t,
182+
func(ct *assert.CollectT) {
183+
findCtx, findCancel := context.WithTimeout(t.Context(), 900*time.Millisecond)
184+
defer findCancel()
185+
186+
otelDocs, err = estools.PerformQueryForRawQuery(findCtx, rawQuery, ".ds-"+otelIndex+"*", es)
187+
assert.NoError(ct, err)
188+
assert.GreaterOrEqual(ct, otelDocs.Hits.Total.Value, 1, "expected at least 1 otel document, got %d", otelDocs.Hits.Total.Value)
189+
190+
filebeatDocs, err = estools.PerformQueryForRawQuery(findCtx, rawQuery, ".ds-"+fbIndex+"*", es)
191+
assert.NoError(ct, err)
192+
assert.GreaterOrEqual(ct, filebeatDocs.Hits.Total.Value, 1, "expected at least 1 filebeat document, got %d", filebeatDocs.Hits.Total.Value)
193+
},
194+
3*time.Minute, 1*time.Second, "expected at least 1 document for both filebeat and otel modes")
195+
196+
filebeatDoc := filebeatDocs.Hits.Hits[0].Source
197+
otelDoc := otelDocs.Hits.Hits[0].Source
198+
ignoredFields := []string{
199+
"@timestamp",
200+
"agent.ephemeral_id",
201+
"agent.id",
202+
}
203+
204+
oteltest.AssertMapsEqual(t, filebeatDoc, otelDoc, ignoredFields, "expected documents to be equal")
205+
}

x-pack/filebeat/tests/integration/otel_filebeat_input_test.go

Lines changed: 10 additions & 119 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ func TestCELInputOTelE2E(t *testing.T) {
5151
fbIndex := "logs-integration-" + fbNamespace
5252

5353
type options struct {
54-
Namespace string
54+
Index string
5555
ESURL string
5656
Username string
5757
Password string
@@ -72,7 +72,7 @@ output:
7272
- {{ .ESURL }}
7373
username: {{ .Username }}
7474
password: {{ .Password }}
75-
index: logs-integration-{{ .Namespace }}
75+
index: {{ .Index }}
7676
7777
queue.mem.flush.timeout: 0s
7878
setup.template.enabled: false
@@ -83,40 +83,8 @@ processors:
8383
- add_kubernetes_metadata: ~
8484
`
8585

86-
celOTelConfig := `exporters:
87-
elasticsearch:
88-
auth:
89-
authenticator: beatsauth
90-
compression: gzip
91-
compression_params:
92-
level: 1
93-
endpoints:
94-
- {{ .ESURL }}
95-
logs_index: logs-integration-{{ .Namespace }}
96-
max_conns_per_host: 1
97-
password: {{ .Password }}
98-
retry:
99-
enabled: true
100-
initial_interval: 1s
101-
max_interval: 1m0s
102-
max_retries: 3
103-
sending_queue:
104-
batch:
105-
flush_timeout: 10s
106-
max_size: 1600
107-
min_size: 0
108-
sizer: items
109-
block_on_overflow: true
110-
enabled: true
111-
num_consumers: 1
112-
queue_size: 3200
113-
wait_for_result: true
114-
user: {{ .Username }}
115-
extensions:
116-
beatsauth:
117-
idle_connection_timeout: 3s
118-
proxy_disable: false
119-
timeout: 1m30s
86+
celOTelConfig := otelElasticsearchExporterYAML +
87+
`
12088
receivers:
12189
filebeatreceiver:
12290
filebeat:
@@ -134,19 +102,7 @@ receivers:
134102
queue.mem.flush.timeout: 0s
135103
setup.template.enabled: false
136104
management.otel.enabled: true
137-
service:
138-
extensions:
139-
- beatsauth
140-
pipelines:
141-
logs:
142-
exporters:
143-
- elasticsearch
144-
receivers:
145-
- filebeatreceiver
146-
telemetry:
147-
metrics:
148-
level: none
149-
`
105+
` + otelElasticsearchServiceYAML
150106

151107
var configBuffer bytes.Buffer
152108
require.NoError(t, template.Must(template.New("config").Parse(celOTelConfig)).Execute(&configBuffer, options{
@@ -155,7 +111,7 @@ service:
155111
Password: password,
156112
ResourceURL: celSrv.URL,
157113
Program: celProgram,
158-
Namespace: otelNamespace,
114+
Index: otelIndex,
159115
}))
160116

161117
oteltestcol.New(t, configBuffer.String())
@@ -168,7 +124,7 @@ service:
168124
Password: password,
169125
ResourceURL: celSrv.URL,
170126
Program: celProgram,
171-
Namespace: fbNamespace,
127+
Index: fbIndex,
172128
}))
173129

174130
filebeat := integration.NewBeat(
@@ -690,40 +646,7 @@ processors:
690646
- add_kubernetes_metadata: ~
691647
`
692648

693-
mqttOTelConfig := `exporters:
694-
elasticsearch:
695-
auth:
696-
authenticator: beatsauth
697-
compression: gzip
698-
compression_params:
699-
level: 1
700-
endpoints:
701-
- {{ .ESURL }}
702-
logs_index: {{ .Index }}
703-
max_conns_per_host: 1
704-
password: {{ .Password }}
705-
retry:
706-
enabled: true
707-
initial_interval: 1s
708-
max_interval: 1m0s
709-
max_retries: 3
710-
sending_queue:
711-
batch:
712-
flush_timeout: 10s
713-
max_size: 1600
714-
min_size: 0
715-
sizer: items
716-
block_on_overflow: true
717-
enabled: true
718-
num_consumers: 1
719-
queue_size: 3200
720-
wait_for_result: true
721-
user: {{ .Username }}
722-
extensions:
723-
beatsauth:
724-
idle_connection_timeout: 3s
725-
proxy_disable: false
726-
timeout: 1m30s
649+
mqttOTelConfig := otelElasticsearchExporterYAML + `
727650
receivers:
728651
filebeatreceiver:
729652
filebeat:
@@ -744,19 +667,7 @@ receivers:
744667
setup.template.enabled: false
745668
path.home: {{ .PathHome }}
746669
management.otel.enabled: true
747-
service:
748-
extensions:
749-
- beatsauth
750-
pipelines:
751-
logs:
752-
exporters:
753-
- elasticsearch
754-
receivers:
755-
- filebeatreceiver
756-
telemetry:
757-
metrics:
758-
level: none
759-
`
670+
` + otelElasticsearchServiceYAML
760671

761672
optionsValue := options{
762673
ESURL: fmt.Sprintf("%s://%s", host.Scheme, host.Host),
@@ -798,27 +709,7 @@ service:
798709
})
799710
})
800711

801-
rawQuery := map[string]any{
802-
"query": map[string]any{
803-
"bool": map[string]any{
804-
"must": []map[string]any{
805-
{
806-
"match_phrase": map[string]any{
807-
"input.type": "mqtt",
808-
},
809-
},
810-
{
811-
"match_phrase": map[string]any{
812-
"message": mqttInputTestMsg,
813-
},
814-
},
815-
},
816-
},
817-
},
818-
"sort": []map[string]any{
819-
{"@timestamp": map[string]any{"order": "asc"}},
820-
},
821-
}
712+
rawQuery := otelE2ERawQueryForInputTypeAndMessage("mqtt", mqttInputTestMsg)
822713

823714
var filebeatDocs estools.Documents
824715
var otelDocs estools.Documents

0 commit comments

Comments
 (0)