Skip to content

Commit d0dc8b2

Browse files
ArturSantosTDChrsMarkedmocosta
authored
[mongodbatlasreceiver] Add baseURL config (#39345)
<!--Ex. Fixing a bug - Describe the bug and how this fixes the issue. Ex. Adding a feature - Explain what this achieves.--> #### Description Adding a feature - On mongodbatlas receiver, allow the use of cloud.mongodbgov.com instead of only the default cloud.mongodb.com, adding a new config <!--Describe the documentation added.--> #### Documentation Update mongodbatlas documentation to reflect new config setting <!--Please delete paragraphs that you did not use before submitting.--> --------- Co-authored-by: Christos Markou <[email protected]> Co-authored-by: Edmo Vamerlatti Costa <[email protected]>
1 parent d23e351 commit d0dc8b2

File tree

13 files changed

+163
-26
lines changed

13 files changed

+163
-26
lines changed
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# Use this changelog template to create an entry for release notes.
2+
3+
# One of 'breaking', 'deprecation', 'new_component', 'enhancement', 'bug_fix'
4+
change_type: enhancement
5+
6+
# The name of the component, or a single word describing the area of concern, (e.g. filelogreceiver)
7+
component: mongodbatlasreceiver
8+
9+
# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`).
10+
note: "Add support for setting custom base URL for the MongoDB Atlas API"
11+
12+
# Mandatory: One or more tracking issues related to the change. You can use the PR number here if no issue exists.
13+
issues: [39345]
14+
15+
# (Optional) One or more lines of additional information to render under the primary note.
16+
# These lines will be padded with 2 spaces and then inserted directly into the document.
17+
# Use pipe (|) for multiline entries.
18+
subtext:
19+
20+
# If your change doesn't affect end users or the exported elements of any package,
21+
# you should instead start your pull request title with [chore] or use the "Skip Changelog" label.
22+
# Optional: The change log or logs in which this entry should be included.
23+
# e.g. '[user]' or '[user, api]'
24+
# Include 'user' if the change is relevant to end users.
25+
# Include 'api' if there is a change to a library API.
26+
# Default: '[user]'
27+
change_logs: [user]

receiver/mongodbatlasreceiver/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ In order to collect access logs, the requesting API key needs the appropriate pe
3434

3535
MongoDB Atlas [Documentation](https://www.mongodb.com/docs/atlas/reference/api/logs/#logs) recommends a polling interval of 5 minutes.
3636

37+
- `base_url` (default https://cloud.mongodb.com/) set the base URL to connect to to Atlas Cloud
3738
- `public_key` (required for metrics, logs, or alerts in `poll` mode)
3839
- `private_key` (required for metrics, logs, or alerts in `poll` mode)
3940
- `granularity` (default `PT1M` - See [MongoDB Atlas Documentation](https://docs.atlas.mongodb.com/reference/api/process-measurements/))

receiver/mongodbatlasreceiver/access_logs.go

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,10 +53,15 @@ type accessLogsReceiver struct {
5353
cancel context.CancelFunc
5454
}
5555

56-
func newAccessLogsReceiver(settings rcvr.Settings, cfg *Config, consumer consumer.Logs) *accessLogsReceiver {
56+
func newAccessLogsReceiver(settings rcvr.Settings, cfg *Config, consumer consumer.Logs) (*accessLogsReceiver, error) {
57+
client, err := internal.NewMongoDBAtlasClient(cfg.BaseURL, cfg.PublicKey, string(cfg.PrivateKey), cfg.BackOffConfig, settings.Logger)
58+
if err != nil {
59+
return nil, fmt.Errorf("failed to create MongoDB Atlas client for access logs receiver: %w", err)
60+
}
61+
5762
r := &accessLogsReceiver{
5863
cancel: func() {},
59-
client: internal.NewMongoDBAtlasClient(cfg.PublicKey, string(cfg.PrivateKey), cfg.BackOffConfig, settings.Logger),
64+
client: client,
6065
cfg: cfg,
6166
logger: settings.Logger,
6267
consumer: consumer,
@@ -80,7 +85,7 @@ func newAccessLogsReceiver(settings rcvr.Settings, cfg *Config, consumer consume
8085
}
8186
}
8287

83-
return r
88+
return r, nil
8489
}
8590

8691
func (alr *accessLogsReceiver) Start(ctx context.Context, _ component.Host, storageClient storage.Client) error {

receiver/mongodbatlasreceiver/access_logs_test.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -277,7 +277,8 @@ func TestAccessLogsRetrieval(t *testing.T) {
277277
for _, tc := range cases {
278278
t.Run(tc.name, func(t *testing.T) {
279279
logSink := &consumertest.LogsSink{}
280-
rcvr := newAccessLogsReceiver(receivertest.NewNopSettings(metadata.Type), tc.config(), logSink)
280+
rcvr, e := newAccessLogsReceiver(receivertest.NewNopSettings(metadata.Type), tc.config(), logSink)
281+
require.NoError(t, e)
281282
tc.setup(rcvr)
282283

283284
err := rcvr.Start(context.Background(), componenttest.NewNopHost(), storage.NewNopClient())
@@ -314,7 +315,8 @@ func TestCheckpointing(t *testing.T) {
314315
}
315316

316317
logSink := &consumertest.LogsSink{}
317-
rcvr := newAccessLogsReceiver(receivertest.NewNopSettings(metadata.Type), config, logSink)
318+
rcvr, e := newAccessLogsReceiver(receivertest.NewNopSettings(metadata.Type), config, logSink)
319+
require.NoError(t, e)
318320
rcvr.client = simpleAccessLogClient()
319321

320322
// First cluster checkpoint should be nil

receiver/mongodbatlasreceiver/alerts.go

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ type alertsReceiver struct {
7171
// only relevant in `poll` mode
7272
projects []*ProjectConfig
7373
client alertsClient
74+
baseURL string
7475
privateKey string
7576
publicKey string
7677
backoffConfig configretry.BackOffConfig
@@ -108,6 +109,7 @@ func newAlertsReceiver(params rcvr.Settings, baseConfig *Config, consumer consum
108109
mode: cfg.Mode,
109110
projects: cfg.Projects,
110111
backoffConfig: baseConfig.BackOffConfig,
112+
baseURL: baseConfig.BaseURL,
111113
publicKey: baseConfig.PublicKey,
112114
privateKey: string(baseConfig.PrivateKey),
113115
wg: &sync.WaitGroup{},
@@ -119,7 +121,12 @@ func newAlertsReceiver(params rcvr.Settings, baseConfig *Config, consumer consum
119121
}
120122

121123
if recv.mode == alertModePoll {
122-
recv.client = internal.NewMongoDBAtlasClient(recv.publicKey, recv.privateKey, recv.backoffConfig, recv.telemetrySettings.Logger)
124+
client, err := internal.NewMongoDBAtlasClient(recv.baseURL, recv.publicKey, recv.privateKey, recv.backoffConfig, recv.telemetrySettings.Logger)
125+
if err != nil {
126+
return nil, fmt.Errorf("failed to create MongoDB Atlas client for alerts receiver: %w", err)
127+
}
128+
129+
recv.client = client
123130
return recv, nil
124131
}
125132
s := &http.Server{

receiver/mongodbatlasreceiver/config.go

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"errors"
88
"fmt"
99
"net"
10+
"net/url"
1011
"strings"
1112
"time"
1213

@@ -24,6 +25,7 @@ var _ component.Config = (*Config)(nil)
2425

2526
type Config struct {
2627
scraperhelper.ControllerConfig `mapstructure:",squash"`
28+
BaseURL string `mapstructure:"base_url"`
2729
PublicKey string `mapstructure:"public_key"`
2830
PrivateKey configopaque.String `mapstructure:"private_key"`
2931
Granularity string `mapstructure:"granularity"`
@@ -129,11 +131,18 @@ var (
129131

130132
// Access Logs Errors
131133
errMaxPageSize = errors.New("the maximum value for 'page_size' is 20000")
134+
135+
// Config Errors
136+
errConfigEmptyEndpoint = errors.New("baseurl must not be empty")
132137
)
133138

134139
func (c *Config) Validate() error {
135140
var errs error
136141

142+
if err := validateEndpoint(c.BaseURL); err != nil {
143+
return fmt.Errorf("invalid base_url %q: %w", c.BaseURL, err)
144+
}
145+
137146
for _, project := range c.Projects {
138147
if len(project.ExcludeClusters) != 0 && len(project.IncludeClusters) != 0 {
139148
errs = multierr.Append(errs, errClusterConfig)
@@ -243,3 +252,23 @@ func (e EventsConfig) validate() error {
243252
}
244253
return nil
245254
}
255+
256+
func validateEndpoint(endpoint string) error {
257+
if endpoint == "" {
258+
return errConfigEmptyEndpoint
259+
}
260+
261+
u, err := url.Parse(endpoint)
262+
if err != nil {
263+
return err
264+
}
265+
switch u.Scheme {
266+
case "http", "https":
267+
default:
268+
return fmt.Errorf(`invalid scheme %q, expected "http" or "https"`, u.Scheme)
269+
}
270+
if u.Host == "" {
271+
return errors.New("host must not be empty")
272+
}
273+
return nil
274+
}

receiver/mongodbatlasreceiver/config_test.go

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"time"
1010

1111
"github.com/stretchr/testify/require"
12+
"go.mongodb.org/atlas/mongodbatlas"
1213
"go.opentelemetry.io/collector/component"
1314
"go.opentelemetry.io/collector/config/configtls"
1415
"go.opentelemetry.io/collector/confmap/confmaptest"
@@ -28,12 +29,14 @@ func TestValidate(t *testing.T) {
2829
{
2930
name: "Empty config",
3031
input: Config{
32+
BaseURL: mongodbatlas.CloudURL,
3133
ControllerConfig: scraperhelper.NewDefaultControllerConfig(),
3234
},
3335
},
3436
{
3537
name: "Valid alerts config",
3638
input: Config{
39+
BaseURL: mongodbatlas.CloudURL,
3740
Alerts: AlertConfig{
3841
Enabled: true,
3942
Endpoint: "0.0.0.0:7706",
@@ -46,6 +49,7 @@ func TestValidate(t *testing.T) {
4649
{
4750
name: "Alerts missing endpoint",
4851
input: Config{
52+
BaseURL: mongodbatlas.CloudURL,
4953
Alerts: AlertConfig{
5054
Enabled: true,
5155
Secret: "some_secret",
@@ -58,6 +62,7 @@ func TestValidate(t *testing.T) {
5862
{
5963
name: "Alerts missing secret",
6064
input: Config{
65+
BaseURL: mongodbatlas.CloudURL,
6166
Alerts: AlertConfig{
6267
Enabled: true,
6368
Endpoint: "0.0.0.0:7706",
@@ -70,6 +75,7 @@ func TestValidate(t *testing.T) {
7075
{
7176
name: "Invalid endpoint",
7277
input: Config{
78+
BaseURL: mongodbatlas.CloudURL,
7379
Alerts: AlertConfig{
7480
Enabled: true,
7581
Endpoint: "7706",
@@ -83,6 +89,7 @@ func TestValidate(t *testing.T) {
8389
{
8490
name: "TLS config missing key",
8591
input: Config{
92+
BaseURL: mongodbatlas.CloudURL,
8693
Alerts: AlertConfig{
8794
Enabled: true,
8895
Endpoint: "0.0.0.0:7706",
@@ -101,6 +108,7 @@ func TestValidate(t *testing.T) {
101108
{
102109
name: "TLS config missing cert",
103110
input: Config{
111+
BaseURL: mongodbatlas.CloudURL,
104112
Alerts: AlertConfig{
105113
Enabled: true,
106114
Endpoint: "0.0.0.0:7706",
@@ -119,6 +127,7 @@ func TestValidate(t *testing.T) {
119127
{
120128
name: "Valid Metrics Config",
121129
input: Config{
130+
BaseURL: mongodbatlas.CloudURL,
122131
Projects: []*ProjectConfig{
123132
{
124133
Name: "Project1",
@@ -130,6 +139,7 @@ func TestValidate(t *testing.T) {
130139
{
131140
name: "Valid Metrics Config with multiple projects with an inclusion or exclusion",
132141
input: Config{
142+
BaseURL: mongodbatlas.CloudURL,
133143
Projects: []*ProjectConfig{
134144
{
135145
Name: "Project1",
@@ -146,6 +156,7 @@ func TestValidate(t *testing.T) {
146156
{
147157
name: "invalid Metrics Config",
148158
input: Config{
159+
BaseURL: mongodbatlas.CloudURL,
149160
Projects: []*ProjectConfig{
150161
{
151162
Name: "Project1",
@@ -160,6 +171,7 @@ func TestValidate(t *testing.T) {
160171
{
161172
name: "Valid Logs Config",
162173
input: Config{
174+
BaseURL: mongodbatlas.CloudURL,
163175
Logs: LogConfig{
164176
Enabled: true,
165177
Projects: []*LogsProjectConfig{
@@ -177,6 +189,7 @@ func TestValidate(t *testing.T) {
177189
{
178190
name: "Invalid Logs Config",
179191
input: Config{
192+
BaseURL: mongodbatlas.CloudURL,
180193
Logs: LogConfig{
181194
Enabled: true,
182195
},
@@ -187,6 +200,7 @@ func TestValidate(t *testing.T) {
187200
{
188201
name: "Invalid ProjectConfig",
189202
input: Config{
203+
BaseURL: mongodbatlas.CloudURL,
190204
Logs: LogConfig{
191205
Enabled: true,
192206
Projects: []*LogsProjectConfig{
@@ -207,6 +221,7 @@ func TestValidate(t *testing.T) {
207221
{
208222
name: "Invalid Alerts Retrieval ProjectConfig",
209223
input: Config{
224+
BaseURL: mongodbatlas.CloudURL,
210225
Alerts: AlertConfig{
211226
Enabled: true,
212227
Mode: alertModePoll,
@@ -226,6 +241,7 @@ func TestValidate(t *testing.T) {
226241
{
227242
name: "Invalid Alerts Poll No Projects",
228243
input: Config{
244+
BaseURL: mongodbatlas.CloudURL,
229245
Alerts: AlertConfig{
230246
Enabled: true,
231247
Mode: alertModePoll,
@@ -239,6 +255,7 @@ func TestValidate(t *testing.T) {
239255
{
240256
name: "Valid Alerts Config",
241257
input: Config{
258+
BaseURL: mongodbatlas.CloudURL,
242259
Alerts: AlertConfig{
243260
Enabled: true,
244261
Mode: alertModePoll,
@@ -255,6 +272,7 @@ func TestValidate(t *testing.T) {
255272
{
256273
name: "Invalid Alerts Mode",
257274
input: Config{
275+
BaseURL: mongodbatlas.CloudURL,
258276
Alerts: AlertConfig{
259277
Enabled: true,
260278
Mode: "invalid type",
@@ -267,6 +285,7 @@ func TestValidate(t *testing.T) {
267285
{
268286
name: "Invalid Page Size",
269287
input: Config{
288+
BaseURL: mongodbatlas.CloudURL,
270289
Alerts: AlertConfig{
271290
Enabled: true,
272291
Mode: alertModePoll,
@@ -284,6 +303,7 @@ func TestValidate(t *testing.T) {
284303
{
285304
name: "Invalid events config - no projects",
286305
input: Config{
306+
BaseURL: mongodbatlas.CloudURL,
287307
Events: &EventsConfig{
288308
Projects: []*ProjectConfig{},
289309
},
@@ -294,6 +314,7 @@ func TestValidate(t *testing.T) {
294314
{
295315
name: "Valid Access Logs Config",
296316
input: Config{
317+
BaseURL: mongodbatlas.CloudURL,
297318
Logs: LogConfig{
298319
Projects: []*LogsProjectConfig{
299320
{
@@ -314,6 +335,7 @@ func TestValidate(t *testing.T) {
314335
{
315336
name: "Invalid Access Logs Config - bad project config",
316337
input: Config{
338+
BaseURL: mongodbatlas.CloudURL,
317339
Logs: LogConfig{
318340
Enabled: true,
319341
Projects: []*LogsProjectConfig{
@@ -361,6 +383,7 @@ func TestLoadConfig(t *testing.T) {
361383

362384
expected := factory.CreateDefaultConfig().(*Config)
363385
expected.MetricsBuilderConfig = metadata.DefaultMetricsBuilderConfig()
386+
expected.BaseURL = "https://cloud.mongodb.com/"
364387
expected.PrivateKey = "my-private-key"
365388
expected.PublicKey = "my-public-key"
366389
expected.Logs = LogConfig{

receiver/mongodbatlasreceiver/events.go

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,9 +57,14 @@ type eventRecord struct {
5757
NextStartTime *time.Time `mapstructure:"next_start_time"`
5858
}
5959

60-
func newEventsReceiver(settings rcvr.Settings, c *Config, consumer consumer.Logs) *eventsReceiver {
60+
func newEventsReceiver(settings rcvr.Settings, c *Config, consumer consumer.Logs) (*eventsReceiver, error) {
61+
client, err := internal.NewMongoDBAtlasClient(c.BaseURL, c.PublicKey, string(c.PrivateKey), c.BackOffConfig, settings.Logger)
62+
if err != nil {
63+
return nil, fmt.Errorf("failed to create MongoDB Atlas client for events receiver: %w", err)
64+
}
65+
6166
r := &eventsReceiver{
62-
client: internal.NewMongoDBAtlasClient(c.PublicKey, string(c.PrivateKey), c.BackOffConfig, settings.Logger),
67+
client: client,
6368
cfg: c,
6469
logger: settings.Logger,
6570
consumer: consumer,
@@ -82,7 +87,7 @@ func newEventsReceiver(settings rcvr.Settings, c *Config, consumer consumer.Logs
8287
r.pollInterval = time.Minute
8388
}
8489

85-
return r
90+
return r, nil
8691
}
8792

8893
func (er *eventsReceiver) Start(ctx context.Context, _ component.Host, storageClient storage.Client) error {

0 commit comments

Comments
 (0)