Skip to content

Commit

Permalink
Add discoverybundler, initial embedded bundle.d, and enabled properties
Browse files Browse the repository at this point in the history
  • Loading branch information
rmfitzpatrick committed Feb 27, 2023
1 parent a809186 commit 53c15ed
Show file tree
Hide file tree
Showing 29 changed files with 999 additions and 95 deletions.
4 changes: 4 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,10 @@ migratecheckpoint:
GO111MODULE=on CGO_ENABLED=0 go build -trimpath -o ./bin/migratecheckpoint_$(GOOS)_$(GOARCH)$(EXTENSION) $(BUILD_INFO) ./cmd/migratecheckpoint
ln -sf migratecheckpoint_$(GOOS)_$(GOARCH)$(EXTENSION) ./bin/migratecheckpoint

.PHONY: bundle.d
bundle.d:
go generate -tags bundle.d ./...

.PHONY: add-tag
add-tag:
@[ "${TAG}" ] || ( echo ">> env var TAG is not set"; exit 1 )
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -471,7 +471,7 @@ require (
gopkg.in/natefinch/lumberjack.v2 v2.0.0 // indirect
gopkg.in/square/go-jose.v2 v2.6.0 // indirect
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
gopkg.in/yaml.v3 v3.0.1
k8s.io/api v0.26.1 // indirect
k8s.io/apimachinery v0.26.1 // indirect
k8s.io/client-go v0.26.1 // indirect
Expand Down
69 changes: 60 additions & 9 deletions internal/confmapprovider/discovery/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,17 +35,68 @@ graph LR
config.d --> 5[/receivers/]
subgraph 5a[receivers]
5 --> 5a1>otlp.yaml]
5a1 --> 5b1[[otlp:<br>protocols:<br>grpc]]
5a1 --> 5b1[[otlp:<br>protocols:<br>grpc:]]
end
```

This component is currently exposed in the Collector via the `--configd` option with corresponding
`--config-dir <config.d path>` and `SPLUNK_CONFIG_DIR` option and environment variable to load
This component is currently supported in the Collector settings via the `--configd` option with corresponding
`--config-dir <config.d path>` option and `SPLUNK_CONFIG_DIR` environment variable to load
additional components and service configuration from the specified `config.d` directory (`/etc/otel/collector/config.d`
by default).
by default). You can use the terminating `--dry-run` flag to report the final assembled Collector config contents to
stdout before exiting.

This component is also exposed in the Collector via the `--discovery [--dry-run]` option that also uses the
`--config-dir <config.d path>` and `SPLUNK_CONFIG_DIR` option and environment variable that attempts to
instantiate any `.discovery.yaml` receivers using corresponding `.discovery.yaml` observers in a "preflight"
Collector service, using any successfully discovered entities in the final config, or writing it to stdout
if `--dry-run` was specified.
At this time, if you want to only use `config.d` for Collector config content and not an additional configuration file,
you must set the `--config` option or `SPLUNK_CONFIG` environment variable to `/dev/null` or any empty file:

```bash
$ # run the Collector without a config file using components from a local ./config.d config directory,
$ # printing the config to stdout before exiting immediately:
$ bin/otelcol --config /dev/null --configd --config-dir ./config.d --dry-run
2023/02/24 19:54:23 settings.go:331: Set config to [/dev/null]
2023/02/24 19:54:23 settings.go:384: Set ballast to 168 MiB
2023/02/24 19:54:23 settings.go:400: Set memory limit to 460 MiB
exporters:
logging:
loglevel: debug
otlp:
endpoint: 1.2.3.4:2345
extensions:
health_check:
path: /health
zpages:
endpoint: 0.0.0.0:1234
processors:
batch: {}
resourcedetection:
detectors:
- system
receivers:
otlp:
protocols:
grpc: null
service:
pipelines:
metrics:
exporters:
- logging
receivers:
- otlp
```

## Discovery Mode

This component also provides a `--discovery [--dry-run]` option compatible with `config.d` that attempts to instantiate
any `.discovery.yaml` receivers using corresponding `.discovery.yaml` observers in a "preflight" Collector service.
Discovery mode will:

1. Load and attempt to start any observers in `config.d/extensions/<name>.discovery.yaml`.
1. Load and attempt to start any receiver blocks in `config.d/receivers/<name>.discovery.yaml` in a
[Discovery Receiver](../../receiver/discoveryreceiver/README.md)` instance receiver events from all
successfully started observers.
1. Wait 10s or the configured `SPLUNK_DISCOVERY_DURATION` environment variable [`time.Duration`](https://pkg.go.dev/time#ParseDuration).
1. Embed any receiver instances' configs resulting in a `discovery.status` of `successful` inside a `receiver_creator/discovery` receiver's configuration to be passed to the final Collector service config (or outputted w/ `--dry-run`).
1. Log any receiver resulting in a `discovery.status` of `partial` with the configured guidance for setting any relevant discovery properties.
1. Stop all temporary components before continuing on to the actual Collector service (or exiting early with `--dry-run`).


By default the Discovery mode is provided with premade discovery config components in [`bundle.d`](./bundle/README.md).
72 changes: 72 additions & 0 deletions internal/confmapprovider/discovery/bundle/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
## bundle.d

`bundle.d` refers to the [`embed.FS`](https://pkg.go.dev/embed#hdr-File_Systems) config directory made available by the
[`bundle.BundledFS`](./bundle.go). It currently consists of all `./bundle.d/extensions/*.discovery.yaml` and
`./bundle.d/receivers/*.discovery.yaml` files that are generated by the `discoverybundler` cmd as used by `go:generate`
directives in [bundle_gen.go](./bundle_gen.go).

To construct the latest bundle.d contents before building the collector run:

```bash
$ make bundle.d
```

### *.discovery.yaml.tmpl

All discovery config component discovery.yaml files are generated from [`text/template`](https://pkg.go.dev/text/template)
`discovery.yaml.tmpl` files using built-in validators and property guidance helpers:

Example `redis.discovery.yaml.tmpl`:

```yaml
{{ receiver "redis" }}:
rule:
docker_observer: type == "container" and port == 6379
<...>
status:
<...>
statements:
partial:
- regexp: 'ERR AUTH.*'
first_only: true
log_record:
severity_text: info
body: >-
Please ensure your redis password is correctly specified with
`--set {{ configProperty "password" "<password>" }}` or
`{{ configPropertyEnvVar "password" "<username>" }}` environment variable.
```
After adding the required generate directive to `bundle_gen.go` and running `make bundle.d`:

```go
//go:generate discoverybundler -r -t bundle.d/receivers/redis.discovery.yaml.tmpl
```

There is now a corresponding `bundle.d/receiver/redis.discovery.yaml`:

```yaml
#####################################################################################
# This file is generated by the Splunk Distribution of the OpenTelemetry Collector. #
#####################################################################################
redis:
rule:
docker_observer: type == "container" and port == 6379
<...>
status:
<...>
statements:
partial:
- regexp: 'ERR AUTH.*'
first_only: true
log_record:
severity_text: info
body: >-
Please ensure your redis password is correctly specified with
`--set splunk.discovery.receivers.redis.config.password="<password>"` or
`SPLUNK_DISCOVERY_RECEIVERS_redis_CONFIG_password="<username>"` environment variable.
```

When building the collector afterward, this redis receiver discovery config is now made available to discovery mode, and
it can be disabled by `--set splunk.discovery.receivers.redis.enabled=false` or
`SPLUNK_DISCOVERY_RECEIVERS_redis_ENABLED=false`.
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#####################################################################################
# This file is generated by the Splunk Distribution of the OpenTelemetry Collector. #
#####################################################################################
docker_observer:
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{{ extension "docker_observer" }}:
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#####################################################################################
# This file is generated by the Splunk Distribution of the OpenTelemetry Collector. #
#####################################################################################
host_observer:
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{{ extension "host_observer" }}:
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#####################################################################################
# This file is generated by the Splunk Distribution of the OpenTelemetry Collector. #
#####################################################################################
k8s_observer:
auth_type: serviceAccount
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
{{ extension "k8s_observer" }}:
auth_type: serviceAccount
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
#####################################################################################
# This file is generated by the Splunk Distribution of the OpenTelemetry Collector. #
#####################################################################################
smartagent/postgresql:
rule:
docker_observer: type == "container" and port == 5432
host_observer: type == "hostport" and command contains "pg" and port == 5432
config:
default:
type: postgresql
connectionString: 'sslmode=disable user={{.username}} password={{.password}}'
params:
username: bundle.default
password: bundle.default
masterDBName: postgres
status:
metrics:
successful:
- strict: postgres_block_hit_ratio
first_only: true
log_record:
severity_text: info
body: postgresql SA receiver working!
statements:
failed:
- regexp: '.* connect: connection refused'
first_only: true
log_record:
severity_text: info
body: container appears to not be accepting postgres connections
partial:
- regexp: '.*pq: password authentication failed for user.*'
first_only: true
log_record:
severity_text: info
body: >-
Please ensure your user credentials are correctly specified with
`--set splunk.discovery.receivers.smartagent/postgresql.config.params::username="<username>"` and
`--set splunk.discovery.receivers.smartagent/postgresql.config.params::password="<password>"` or
`SPLUNK_DISCOVERY_RECEIVERS_smartagent_x2f_postgresql_CONFIG_params_x3a__x3a_username="<username>"` and
`SPLUNK_DISCOVERY_RECEIVERS_smartagent_x2f_postgresql_CONFIG_params_x3a__x3a_password="<password>"` environment variables.
- regexp: '.*pq: database ".*" does not exist.*'
first_only: true
log_record:
severity_text: info
body: >-
Please ensure your target database is correctly specified with
`--set splunk.discovery.receivers.smartagent/postgresql.config.masterDBName="<db>"` or
`SPLUNK_DISCOVERY_RECEIVERS_smartagent_x2f_postgresql_CONFIG_masterDBName="<db>"` environment variable.
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
{{ receiver "smartagent/postgresql" }}:
rule:
docker_observer: type == "container" and port == 5432
host_observer: type == "hostport" and command contains "pg" and port == 5432
config:
default:
type: postgresql
connectionString: 'sslmode=disable user={{ "{{.username}}" }} password={{ "{{.password}}" }}'
params:
username: bundle.default
password: bundle.default
masterDBName: postgres
status:
metrics:
successful:
- strict: postgres_block_hit_ratio
first_only: true
log_record:
severity_text: info
body: postgresql SA receiver working!
statements:
failed:
- regexp: '.* connect: connection refused'
first_only: true
log_record:
severity_text: info
body: container appears to not be accepting postgres connections
partial:
- regexp: '.*pq: password authentication failed for user.*'
first_only: true
log_record:
severity_text: info
body: >-
Please ensure your user credentials are correctly specified with
`--set {{ configProperty "params" "username" "<username>" }}` and
`--set {{ configProperty "params" "password" "<password>" }}` or
`{{ configPropertyEnvVar "params" "username" "<username>" }}` and
`{{ configPropertyEnvVar "params" "password" "<password>" }}` environment variables.
- regexp: '.*pq: database ".*" does not exist.*'
first_only: true
log_record:
severity_text: info
body: >-
Please ensure your target database is correctly specified with
`--set {{ configProperty "masterDBName" "<db>" }}` or
`{{ configPropertyEnvVar "masterDBName" "<db>" }}` environment variable.
29 changes: 29 additions & 0 deletions internal/confmapprovider/discovery/bundle/bundle.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// Copyright Splunk, Inc.
//
// Licensed 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 bundle

import (
"embed"
)

// BundledFS is the in-executable filesystem that contains all bundled discovery config.d components.
//
// If you are bootstrapping bundle_gen.go or the `discoverybundler` cmd without any rendered files in bundle.d,
// comment out the below embed directives before installing to prevent "no matching files found"
// build errors.
//
//go:embed bundle.d/extensions/*.discovery.yaml
//go:embed bundle.d/receivers/*.discovery.yaml
var BundledFS embed.FS
27 changes: 27 additions & 0 deletions internal/confmapprovider/discovery/bundle/bundle_gen.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// Copyright Splunk, Inc.
//
// Licensed 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.

//go:build bundle.d

// These are the discovery config component generating statements.
// In order to update run go generate -tags bundle.d ./...
//go:generate go install github.com/signalfx/splunk-otel-collector/internal/confmapprovider/discovery/bundle/cmd/discoverybundler

//go:generate discoverybundler -r -t bundle.d/receivers/smartagent-postgresql.discovery.yaml.tmpl

//go:generate discoverybundler -r -t bundle.d/extensions/docker-observer.discovery.yaml.tmpl
//go:generate discoverybundler -r -t bundle.d/extensions/host-observer.discovery.yaml.tmpl
//go:generate discoverybundler -r -t bundle.d/extensions/k8s-observer.discovery.yaml.tmpl

package bundle
38 changes: 38 additions & 0 deletions internal/confmapprovider/discovery/bundle/bundle_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// Copyright Splunk, Inc.
//
// Licensed 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 bundle

import (
"io/fs"
"testing"

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

func TestBundleDir(t *testing.T) {
receivers, err := fs.Glob(BundledFS, "bundle.d/receivers/*.discovery.yaml")
require.NoError(t, err)
require.Equal(t, []string{
"bundle.d/receivers/smartagent-postgresql.discovery.yaml",
}, receivers)

extensions, err := fs.Glob(BundledFS, "bundle.d/extensions/*.discovery.yaml")
require.NoError(t, err)
require.Equal(t, []string{
"bundle.d/extensions/docker-observer.discovery.yaml",
"bundle.d/extensions/host-observer.discovery.yaml",
"bundle.d/extensions/k8s-observer.discovery.yaml",
}, extensions)
}
Loading

0 comments on commit 53c15ed

Please sign in to comment.