Skip to content

[mongodbatlasreceiver] Add baseURL config #39345

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

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
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
27 changes: 27 additions & 0 deletions .chloggen/feat--Add-support-for-atlasgov.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Use this changelog template to create an entry for release notes.

# One of 'breaking', 'deprecation', 'new_component', 'enhancement', 'bug_fix'
change_type: enhancement

# The name of the component, or a single word describing the area of concern, (e.g. filelogreceiver)
component: mongodbatlasreceiver

# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`).
note: "Add support for setting custom base URL for the MongoDB Atlas API"

# Mandatory: One or more tracking issues related to the change. You can use the PR number here if no issue exists.
issues: [39345]

# (Optional) One or more lines of additional information to render under the primary note.
# These lines will be padded with 2 spaces and then inserted directly into the document.
# Use pipe (|) for multiline entries.
subtext:

# If your change doesn't affect end users or the exported elements of any package,
# you should instead start your pull request title with [chore] or use the "Skip Changelog" label.
# Optional: The change log or logs in which this entry should be included.
# e.g. '[user]' or '[user, api]'
# Include 'user' if the change is relevant to end users.
# Include 'api' if there is a change to a library API.
# Default: '[user]'
change_logs: [user]
1 change: 1 addition & 0 deletions receiver/mongodbatlasreceiver/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ In order to collect access logs, the requesting API key needs the appropriate pe

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

- `base_url` (default https://cloud.mongodb.com/) set the base URL to connect to to Atlas Cloud
- `public_key` (required for metrics, logs, or alerts in `poll` mode)
- `private_key` (required for metrics, logs, or alerts in `poll` mode)
- `granularity` (default `PT1M` - See [MongoDB Atlas Documentation](https://docs.atlas.mongodb.com/reference/api/process-measurements/))
Expand Down
11 changes: 8 additions & 3 deletions receiver/mongodbatlasreceiver/access_logs.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,15 @@ type accessLogsReceiver struct {
cancel context.CancelFunc
}

func newAccessLogsReceiver(settings rcvr.Settings, cfg *Config, consumer consumer.Logs) *accessLogsReceiver {
func newAccessLogsReceiver(settings rcvr.Settings, cfg *Config, consumer consumer.Logs) (*accessLogsReceiver, error) {
client, err := internal.NewMongoDBAtlasClient(cfg.BaseURL, cfg.PublicKey, string(cfg.PrivateKey), cfg.BackOffConfig, settings.Logger)
if err != nil {
return nil, fmt.Errorf("failed to create MongoDB Atlas client for access logs receiver: %w", err)
}

r := &accessLogsReceiver{
cancel: func() {},
client: internal.NewMongoDBAtlasClient(cfg.PublicKey, string(cfg.PrivateKey), cfg.BackOffConfig, settings.Logger),
client: client,
cfg: cfg,
logger: settings.Logger,
consumer: consumer,
Expand All @@ -80,7 +85,7 @@ func newAccessLogsReceiver(settings rcvr.Settings, cfg *Config, consumer consume
}
}

return r
return r, nil
}

func (alr *accessLogsReceiver) Start(ctx context.Context, _ component.Host, storageClient storage.Client) error {
Expand Down
6 changes: 4 additions & 2 deletions receiver/mongodbatlasreceiver/access_logs_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -277,7 +277,8 @@ func TestAccessLogsRetrieval(t *testing.T) {
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
logSink := &consumertest.LogsSink{}
rcvr := newAccessLogsReceiver(receivertest.NewNopSettings(metadata.Type), tc.config(), logSink)
rcvr, e := newAccessLogsReceiver(receivertest.NewNopSettings(metadata.Type), tc.config(), logSink)
require.NoError(t, e)
tc.setup(rcvr)

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

logSink := &consumertest.LogsSink{}
rcvr := newAccessLogsReceiver(receivertest.NewNopSettings(metadata.Type), config, logSink)
rcvr, e := newAccessLogsReceiver(receivertest.NewNopSettings(metadata.Type), config, logSink)
require.NoError(t, e)
rcvr.client = simpleAccessLogClient()

// First cluster checkpoint should be nil
Expand Down
9 changes: 8 additions & 1 deletion receiver/mongodbatlasreceiver/alerts.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ type alertsReceiver struct {
// only relevant in `poll` mode
projects []*ProjectConfig
client alertsClient
baseURL string
privateKey string
publicKey string
backoffConfig configretry.BackOffConfig
Expand Down Expand Up @@ -108,6 +109,7 @@ func newAlertsReceiver(params rcvr.Settings, baseConfig *Config, consumer consum
mode: cfg.Mode,
projects: cfg.Projects,
backoffConfig: baseConfig.BackOffConfig,
baseURL: baseConfig.BaseURL,
publicKey: baseConfig.PublicKey,
privateKey: string(baseConfig.PrivateKey),
wg: &sync.WaitGroup{},
Expand All @@ -119,7 +121,12 @@ func newAlertsReceiver(params rcvr.Settings, baseConfig *Config, consumer consum
}

if recv.mode == alertModePoll {
recv.client = internal.NewMongoDBAtlasClient(recv.publicKey, recv.privateKey, recv.backoffConfig, recv.telemetrySettings.Logger)
client, err := internal.NewMongoDBAtlasClient(recv.baseURL, recv.publicKey, recv.privateKey, recv.backoffConfig, recv.telemetrySettings.Logger)
if err != nil {
return nil, fmt.Errorf("failed to create MongoDB Atlas client for alerts receiver: %w", err)
}

recv.client = client
return recv, nil
}
s := &http.Server{
Expand Down
29 changes: 29 additions & 0 deletions receiver/mongodbatlasreceiver/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"errors"
"fmt"
"net"
"net/url"
"strings"
"time"

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

type Config struct {
scraperhelper.ControllerConfig `mapstructure:",squash"`
BaseURL string `mapstructure:"base_url"`
PublicKey string `mapstructure:"public_key"`
PrivateKey configopaque.String `mapstructure:"private_key"`
Granularity string `mapstructure:"granularity"`
Expand Down Expand Up @@ -129,11 +131,18 @@ var (

// Access Logs Errors
errMaxPageSize = errors.New("the maximum value for 'page_size' is 20000")

// Config Errors
errConfigEmptyEndpoint = errors.New("baseurl must not be empty")
)

func (c *Config) Validate() error {
var errs error

if err := validateEndpoint(c.BaseURL); err != nil {
return fmt.Errorf("invalid base_url %q: %w", c.BaseURL, err)
}

for _, project := range c.Projects {
if len(project.ExcludeClusters) != 0 && len(project.IncludeClusters) != 0 {
errs = multierr.Append(errs, errClusterConfig)
Expand Down Expand Up @@ -243,3 +252,23 @@ func (e EventsConfig) validate() error {
}
return nil
}

func validateEndpoint(endpoint string) error {
if endpoint == "" {
return errConfigEmptyEndpoint
}

u, err := url.Parse(endpoint)
if err != nil {
return err
}
switch u.Scheme {
case "http", "https":
default:
return fmt.Errorf(`invalid scheme %q, expected "http" or "https"`, u.Scheme)
}
if u.Host == "" {
return errors.New("host must not be empty")
}
return nil
}
23 changes: 23 additions & 0 deletions receiver/mongodbatlasreceiver/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"time"

"github.com/stretchr/testify/require"
"go.mongodb.org/atlas/mongodbatlas"
"go.opentelemetry.io/collector/component"
"go.opentelemetry.io/collector/config/configtls"
"go.opentelemetry.io/collector/confmap/confmaptest"
Expand All @@ -28,12 +29,14 @@ func TestValidate(t *testing.T) {
{
name: "Empty config",
input: Config{
BaseURL: mongodbatlas.CloudURL,
ControllerConfig: scraperhelper.NewDefaultControllerConfig(),
},
},
{
name: "Valid alerts config",
input: Config{
BaseURL: mongodbatlas.CloudURL,
Alerts: AlertConfig{
Enabled: true,
Endpoint: "0.0.0.0:7706",
Expand All @@ -46,6 +49,7 @@ func TestValidate(t *testing.T) {
{
name: "Alerts missing endpoint",
input: Config{
BaseURL: mongodbatlas.CloudURL,
Alerts: AlertConfig{
Enabled: true,
Secret: "some_secret",
Expand All @@ -58,6 +62,7 @@ func TestValidate(t *testing.T) {
{
name: "Alerts missing secret",
input: Config{
BaseURL: mongodbatlas.CloudURL,
Alerts: AlertConfig{
Enabled: true,
Endpoint: "0.0.0.0:7706",
Expand All @@ -70,6 +75,7 @@ func TestValidate(t *testing.T) {
{
name: "Invalid endpoint",
input: Config{
BaseURL: mongodbatlas.CloudURL,
Alerts: AlertConfig{
Enabled: true,
Endpoint: "7706",
Expand All @@ -83,6 +89,7 @@ func TestValidate(t *testing.T) {
{
name: "TLS config missing key",
input: Config{
BaseURL: mongodbatlas.CloudURL,
Alerts: AlertConfig{
Enabled: true,
Endpoint: "0.0.0.0:7706",
Expand All @@ -101,6 +108,7 @@ func TestValidate(t *testing.T) {
{
name: "TLS config missing cert",
input: Config{
BaseURL: mongodbatlas.CloudURL,
Alerts: AlertConfig{
Enabled: true,
Endpoint: "0.0.0.0:7706",
Expand All @@ -119,6 +127,7 @@ func TestValidate(t *testing.T) {
{
name: "Valid Metrics Config",
input: Config{
BaseURL: mongodbatlas.CloudURL,
Projects: []*ProjectConfig{
{
Name: "Project1",
Expand All @@ -130,6 +139,7 @@ func TestValidate(t *testing.T) {
{
name: "Valid Metrics Config with multiple projects with an inclusion or exclusion",
input: Config{
BaseURL: mongodbatlas.CloudURL,
Projects: []*ProjectConfig{
{
Name: "Project1",
Expand All @@ -146,6 +156,7 @@ func TestValidate(t *testing.T) {
{
name: "invalid Metrics Config",
input: Config{
BaseURL: mongodbatlas.CloudURL,
Projects: []*ProjectConfig{
{
Name: "Project1",
Expand All @@ -160,6 +171,7 @@ func TestValidate(t *testing.T) {
{
name: "Valid Logs Config",
input: Config{
BaseURL: mongodbatlas.CloudURL,
Logs: LogConfig{
Enabled: true,
Projects: []*LogsProjectConfig{
Expand All @@ -177,6 +189,7 @@ func TestValidate(t *testing.T) {
{
name: "Invalid Logs Config",
input: Config{
BaseURL: mongodbatlas.CloudURL,
Logs: LogConfig{
Enabled: true,
},
Expand All @@ -187,6 +200,7 @@ func TestValidate(t *testing.T) {
{
name: "Invalid ProjectConfig",
input: Config{
BaseURL: mongodbatlas.CloudURL,
Logs: LogConfig{
Enabled: true,
Projects: []*LogsProjectConfig{
Expand All @@ -207,6 +221,7 @@ func TestValidate(t *testing.T) {
{
name: "Invalid Alerts Retrieval ProjectConfig",
input: Config{
BaseURL: mongodbatlas.CloudURL,
Alerts: AlertConfig{
Enabled: true,
Mode: alertModePoll,
Expand All @@ -226,6 +241,7 @@ func TestValidate(t *testing.T) {
{
name: "Invalid Alerts Poll No Projects",
input: Config{
BaseURL: mongodbatlas.CloudURL,
Alerts: AlertConfig{
Enabled: true,
Mode: alertModePoll,
Expand All @@ -239,6 +255,7 @@ func TestValidate(t *testing.T) {
{
name: "Valid Alerts Config",
input: Config{
BaseURL: mongodbatlas.CloudURL,
Alerts: AlertConfig{
Enabled: true,
Mode: alertModePoll,
Expand All @@ -255,6 +272,7 @@ func TestValidate(t *testing.T) {
{
name: "Invalid Alerts Mode",
input: Config{
BaseURL: mongodbatlas.CloudURL,
Alerts: AlertConfig{
Enabled: true,
Mode: "invalid type",
Expand All @@ -267,6 +285,7 @@ func TestValidate(t *testing.T) {
{
name: "Invalid Page Size",
input: Config{
BaseURL: mongodbatlas.CloudURL,
Alerts: AlertConfig{
Enabled: true,
Mode: alertModePoll,
Expand All @@ -284,6 +303,7 @@ func TestValidate(t *testing.T) {
{
name: "Invalid events config - no projects",
input: Config{
BaseURL: mongodbatlas.CloudURL,
Events: &EventsConfig{
Projects: []*ProjectConfig{},
},
Expand All @@ -294,6 +314,7 @@ func TestValidate(t *testing.T) {
{
name: "Valid Access Logs Config",
input: Config{
BaseURL: mongodbatlas.CloudURL,
Logs: LogConfig{
Projects: []*LogsProjectConfig{
{
Expand All @@ -314,6 +335,7 @@ func TestValidate(t *testing.T) {
{
name: "Invalid Access Logs Config - bad project config",
input: Config{
BaseURL: mongodbatlas.CloudURL,
Logs: LogConfig{
Enabled: true,
Projects: []*LogsProjectConfig{
Expand Down Expand Up @@ -361,6 +383,7 @@ func TestLoadConfig(t *testing.T) {

expected := factory.CreateDefaultConfig().(*Config)
expected.MetricsBuilderConfig = metadata.DefaultMetricsBuilderConfig()
expected.BaseURL = "https://cloud.mongodb.com/"
expected.PrivateKey = "my-private-key"
expected.PublicKey = "my-public-key"
expected.Logs = LogConfig{
Expand Down
11 changes: 8 additions & 3 deletions receiver/mongodbatlasreceiver/events.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,14 @@ type eventRecord struct {
NextStartTime *time.Time `mapstructure:"next_start_time"`
}

func newEventsReceiver(settings rcvr.Settings, c *Config, consumer consumer.Logs) *eventsReceiver {
func newEventsReceiver(settings rcvr.Settings, c *Config, consumer consumer.Logs) (*eventsReceiver, error) {
client, err := internal.NewMongoDBAtlasClient(c.BaseURL, c.PublicKey, string(c.PrivateKey), c.BackOffConfig, settings.Logger)
if err != nil {
return nil, fmt.Errorf("failed to create MongoDB Atlas client for events receiver: %w", err)
}

r := &eventsReceiver{
client: internal.NewMongoDBAtlasClient(c.PublicKey, string(c.PrivateKey), c.BackOffConfig, settings.Logger),
client: client,
cfg: c,
logger: settings.Logger,
consumer: consumer,
Expand All @@ -82,7 +87,7 @@ func newEventsReceiver(settings rcvr.Settings, c *Config, consumer consumer.Logs
r.pollInterval = time.Minute
}

return r
return r, nil
}

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