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

[cmd/opampsupervisor] Handle OpAMP connection settings #30237

Merged
merged 24 commits into from
Apr 9, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
Next Next commit
Implement Collector bootstrapping in the Supervisor
  • Loading branch information
evan-bradley committed Dec 14, 2023
commit 826f6133ba087631b140e0c283bbc8e0e0f7a66f
92 changes: 88 additions & 4 deletions cmd/opampsupervisor/e2e_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (
"net/http"
"net/http/httptest"
"os"
"os/exec"
"path"
"runtime"
"strings"
Expand All @@ -23,12 +24,18 @@ import (
"text/template"
"time"

"github.com/knadh/koanf/parsers/yaml"
"github.com/knadh/koanf/providers/file"
"github.com/knadh/koanf/providers/rawbytes"
"github.com/knadh/koanf/v2"
"github.com/open-telemetry/opamp-go/protobufs"
"github.com/open-telemetry/opamp-go/server"
"github.com/open-telemetry/opamp-go/server/types"
"github.com/open-telemetry/opentelemetry-collector-contrib/cmd/opampsupervisor/supervisor"
"github.com/open-telemetry/opentelemetry-collector-contrib/cmd/opampsupervisor/supervisor/config"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
semconv "go.opentelemetry.io/collector/semconv/v1.21.0"
"go.uber.org/zap"
)

Expand Down Expand Up @@ -122,6 +129,14 @@ func newOpAMPServer(t *testing.T, connectingCallback onConnectingFuncFactory, ca
}

func newSupervisor(t *testing.T, configType string, extraConfigData map[string]string) *supervisor.Supervisor {
cfgFile := getSupervisorConfig(t, configType, extraConfigData)
s, err := supervisor.NewSupervisor(zap.NewNop(), cfgFile.Name())
require.NoError(t, err)

return s
}

func getSupervisorConfig(t *testing.T, configType string, extraConfigData map[string]string) *os.File {
tpl, err := os.ReadFile(path.Join("testdata", "supervisor", "supervisor_"+configType+".yaml"))
require.NoError(t, err)

Expand All @@ -148,10 +163,7 @@ func newSupervisor(t *testing.T, configType string, extraConfigData map[string]s
_, err = cfgFile.Write(buf.Bytes())
require.NoError(t, err)

s, err := supervisor.NewSupervisor(zap.NewNop(), cfgFile.Name())
require.NoError(t, err)

return s
return cfgFile
}

func TestSupervisorStartsCollectorWithRemoteConfig(t *testing.T) {
Expand Down Expand Up @@ -323,6 +335,78 @@ func TestSupervisorConfiguresCapabilities(t *testing.T) {
}, 5*time.Second, 250*time.Millisecond)
}

func TestSupervisorBootstrapsCollector(t *testing.T) {
agentDescription := atomic.Value{}

// Load the Supervisor config so we can get the location of
// the Collector that will be run.
var cfg config.Supervisor
cfgFile := getSupervisorConfig(t, "nocap", map[string]string{})
k := koanf.New("::")
err := k.Load(file.Provider(cfgFile.Name()), yaml.Parser())
require.NoError(t, err)
err = k.UnmarshalWithConf("", &cfg, koanf.UnmarshalConf{
Tag: "mapstructure",
})
require.NoError(t, err)

// Get the binary name and version from the Collector binary
// using the `components` command that prints a YAML-encoded
// map of information about the Collector build. Some of this
// information will be used as defaults for the telemetry
// attributes.
agentPath := cfg.Agent.Executable
componentsInfo, err := exec.Command(agentPath, "components").Output()
require.NoError(t, err)
k = koanf.New("::")
err = k.Load(rawbytes.Provider(componentsInfo), yaml.Parser())
require.NoError(t, err)
buildinfo := k.StringMap("buildinfo")
command := buildinfo["command"]
version := buildinfo["version"]

server := newOpAMPServer(
t,
defaultConnectingHandler,
server.ConnectionCallbacksStruct{
OnMessageFunc: func(_ types.Connection, message *protobufs.AgentToServer) *protobufs.ServerToAgent {
if message.AgentDescription != nil {
agentDescription.Store(message.AgentDescription)
}

return &protobufs.ServerToAgent{}
},
})

s := newSupervisor(t, "nocap", map[string]string{"url": server.addr})
defer s.Shutdown()

waitForSupervisorConnection(server.supervisorConnected, true)

require.Eventually(t, func() bool {
ad, ok := agentDescription.Load().(*protobufs.AgentDescription)
if !ok {
return false
}

var agentName, agentVersion string
identAttr := ad.IdentifyingAttributes
for _, attr := range identAttr {
switch attr.Key {
case semconv.AttributeServiceName:
agentName = attr.Value.GetStringValue()
case semconv.AttributeServiceVersion:
agentVersion = attr.Value.GetStringValue()
}
}

// By default the Collector should report its name and version
// from the component.BuildInfo struct built into the Collector
// binary.
return agentName == command && agentVersion == version
}, 5*time.Second, 250*time.Millisecond)
}

// Creates a Collector config that reads and writes logs to files and provides
// file descriptors for I/O operations to those files. The files are placed
// in a unique temp directory that is cleaned up after the test's completion.
Expand Down
1 change: 1 addition & 0 deletions cmd/opampsupervisor/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ require (
github.com/open-telemetry/opamp-go v0.10.0
github.com/stretchr/testify v1.8.4
go.opentelemetry.io/collector/config/configtls v0.91.0
go.opentelemetry.io/collector/semconv v0.91.0
go.uber.org/zap v1.26.0
)

Expand Down
2 changes: 2 additions & 0 deletions cmd/opampsupervisor/go.sum

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions cmd/opampsupervisor/specification/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -220,8 +220,8 @@ configuration.
To overcome this problem the Supervisor starts the Collector with an
"noop" configuration that collects nothing but allows the opamp
extension to be started. The "noop" configuration is a single pipeline
with a filelog receiver that points to a non-existing file and a logging
exporter and the opamp extension. The purpose of the "noop"
with an OTLP receiver that listens on a random port and a debug
exporter, and the opamp extension. The purpose of the "noop"
configuration is to make sure the Collector starts and the opamp
extension communicates with the Supervisor.

Expand Down
Loading