From f49c5d111fdf6d11505fa97ecd8ed4f42f5bdddf Mon Sep 17 00:00:00 2001 From: Jacob Aronoff Date: Mon, 19 Dec 2022 19:43:47 -0500 Subject: [PATCH 01/16] Begin the journey --- .chloggen/1318-remote-config-service.yaml | 16 + .gitignore | 1 + cmd/remote-configuration/agent/agent.go | 273 ++++++++ cmd/remote-configuration/agent/logger.go | 25 + .../agent/metricreporter.go | 205 ++++++ cmd/remote-configuration/config/config.go | 109 +++ cmd/remote-configuration/go.mod | 72 ++ cmd/remote-configuration/go.sum | 635 ++++++++++++++++++ cmd/remote-configuration/main.go | 34 + 9 files changed, 1370 insertions(+) create mode 100755 .chloggen/1318-remote-config-service.yaml create mode 100644 cmd/remote-configuration/agent/agent.go create mode 100644 cmd/remote-configuration/agent/logger.go create mode 100644 cmd/remote-configuration/agent/metricreporter.go create mode 100644 cmd/remote-configuration/config/config.go create mode 100644 cmd/remote-configuration/go.mod create mode 100644 cmd/remote-configuration/go.sum create mode 100644 cmd/remote-configuration/main.go diff --git a/.chloggen/1318-remote-config-service.yaml b/.chloggen/1318-remote-config-service.yaml new file mode 100755 index 0000000000..2a7a3dca35 --- /dev/null +++ b/.chloggen/1318-remote-config-service.yaml @@ -0,0 +1,16 @@ +# One of 'breaking', 'deprecation', 'new_component', 'enhancement', 'bug_fix' +change_type: new_component + +# The name of the component, or a single word describing the area of concern, (e.g. operator, target allocator, github action) +component: Remote Configuration + +# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`). +note: Introducing the Operator Remote Configuration service, which allows a user to manage OpenTelemetry Collector CRDs via OpAMP + +# One or more tracking issues related to the change +issues: [1318] + +# (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: diff --git a/.gitignore b/.gitignore index 6b11e10253..88abe862c0 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,7 @@ *.dylib bin vendor +.DS_Store # Test binary, build with `go test -c` *.test diff --git a/cmd/remote-configuration/agent/agent.go b/cmd/remote-configuration/agent/agent.go new file mode 100644 index 0000000000..59e335df6d --- /dev/null +++ b/cmd/remote-configuration/agent/agent.go @@ -0,0 +1,273 @@ +package agent + +import ( + "context" + "github.com/open-telemetry/opentelemetry-operator/cmd/remote-configuration/config" + "math/rand" + "os" + "runtime" + "time" + + "github.com/oklog/ulid/v2" + + "github.com/open-telemetry/opamp-go/client" + "github.com/open-telemetry/opamp-go/client/types" + "github.com/open-telemetry/opamp-go/protobufs" +) + +const localConfig = ` +exporters: + otlp: + endpoint: localhost:1111 + +receivers: + otlp: + protocols: + grpc: {} + http: {} + +service: + pipelines: + traces: + receivers: [otlp] + processors: [] + exporters: [otlp] +` + +type Agent struct { + logger types.Logger + + agentType string + agentVersion string + + effectiveConfig string + startTime uint64 + + instanceId ulid.ULID + + agentDescription *protobufs.AgentDescription + + opampClient client.OpAMPClient + + remoteConfigStatus *protobufs.RemoteConfigStatus + + metricReporter *MetricReporter + config config.Config +} + +func NewAgent(logger types.Logger, config config.Config, agentType string, agentVersion string) *Agent { + agent := &Agent{ + config: config, + logger: logger, + agentType: agentType, + agentVersion: agentVersion, + } + + agent.createAgentIdentity() + agent.logger.Debugf("Agent starting, id=%v, type=%s, version=%s.", + agent.instanceId.String(), agentType, agentVersion) + agent.opampClient = agent.createClient() + + return agent +} + +func (agent *Agent) createClient() client.OpAMPClient { + if agent.config.Protocol == "http" { + return client.NewHTTP(agent.logger) + } + return client.NewWebSocket(agent.logger) +} + +func (agent *Agent) getHealth() *protobufs.AgentHealth { + return &protobufs.AgentHealth{ + Healthy: true, + StartTimeUnixNano: agent.startTime, + LastError: "", + } +} + +func (agent *Agent) Start() error { + agent.startTime = uint64(time.Now().UnixNano()) + settings := types.StartSettings{ + OpAMPServerURL: agent.config.Endpoint, + //TLSConfig: &tls.Config{InsecureSkipVerify: true}, + InstanceUid: agent.instanceId.String(), + Callbacks: types.CallbacksStruct{ + OnConnectFunc: func() { + agent.logger.Debugf("Connected to the server.") + }, + OnConnectFailedFunc: func(err error) { + agent.logger.Errorf("Failed to connect to the server: %v", err) + }, + OnErrorFunc: func(err *protobufs.ServerErrorResponse) { + agent.logger.Errorf("Server returned an error response: %v", err.ErrorMessage) + }, + SaveRemoteConfigStatusFunc: func(_ context.Context, status *protobufs.RemoteConfigStatus) { + agent.remoteConfigStatus = status + }, + GetEffectiveConfigFunc: func(ctx context.Context) (*protobufs.EffectiveConfig, error) { + return agent.composeEffectiveConfig(), nil + }, + OnMessageFunc: agent.onMessage, + }, + RemoteConfigStatus: agent.remoteConfigStatus, + PackagesStateProvider: nil, + Capabilities: agent.config.GetCapabilities(), + } + err := agent.opampClient.SetAgentDescription(agent.agentDescription) + if err != nil { + return err + } + err = agent.opampClient.SetHealth(agent.getHealth()) + if err != nil { + return err + } + + agent.logger.Debugf("Starting OpAMP client...") + + err = agent.opampClient.Start(context.Background(), settings) + if err != nil { + return err + } + + agent.logger.Debugf("OpAMP Client started.") + + return nil +} + +func (agent *Agent) createAgentIdentity() { + // Generate instance id. + entropy := ulid.Monotonic(rand.New(rand.NewSource(0)), 0) + agent.instanceId = ulid.MustNew(ulid.Timestamp(time.Now()), entropy) + + hostname, _ := os.Hostname() + + // Create Agent description. + agent.agentDescription = &protobufs.AgentDescription{ + IdentifyingAttributes: []*protobufs.KeyValue{ + { + Key: "service.name", + Value: &protobufs.AnyValue{ + Value: &protobufs.AnyValue_StringValue{StringValue: agent.agentType}, + }, + }, + { + Key: "service.version", + Value: &protobufs.AnyValue{ + Value: &protobufs.AnyValue_StringValue{StringValue: agent.agentVersion}, + }, + }, + }, + NonIdentifyingAttributes: []*protobufs.KeyValue{ + { + Key: "os.family", + Value: &protobufs.AnyValue{ + Value: &protobufs.AnyValue_StringValue{ + StringValue: runtime.GOOS, + }, + }, + }, + { + Key: "host.name", + Value: &protobufs.AnyValue{ + Value: &protobufs.AnyValue_StringValue{ + StringValue: hostname, + }, + }, + }, + }, + } +} + +func (agent *Agent) updateAgentIdentity(instanceId ulid.ULID) { + agent.logger.Debugf("Agent identify is being changed from id=%v to id=%v", + agent.instanceId.String(), + instanceId.String()) + agent.instanceId = instanceId + + if agent.metricReporter != nil { + // TODO: reinit or update meter (possibly using a single function to update all own connection settings + // or with having a common resource factory or so) + } +} + +func (agent *Agent) composeEffectiveConfig() *protobufs.EffectiveConfig { + return &protobufs.EffectiveConfig{ + ConfigMap: &protobufs.AgentConfigMap{ + ConfigMap: map[string]*protobufs.AgentConfigFile{ + "": {Body: []byte(agent.effectiveConfig)}, + }, + }, + } +} + +func (agent *Agent) initMeter(settings *protobufs.TelemetryConnectionSettings) { + reporter, err := NewMetricReporter(agent.logger, settings, agent.agentType, agent.agentVersion, agent.instanceId) + if err != nil { + agent.logger.Errorf("Cannot collect metrics: %v", err) + return + } + + prevReporter := agent.metricReporter + + agent.metricReporter = reporter + + if prevReporter != nil { + prevReporter.Shutdown() + } + return +} + +// Take the remote config, layer it over existing, done +func (agent *Agent) applyRemoteConfig(config *protobufs.AgentRemoteConfig) (configChanged bool, err error) { + if config == nil { + return false, nil + } + return false, nil +} + +func (agent *Agent) Shutdown() { + agent.logger.Debugf("Agent shutting down...") + if agent.opampClient != nil { + _ = agent.opampClient.Stop(context.Background()) + } +} + +func (agent *Agent) onMessage(ctx context.Context, msg *types.MessageData) { + configChanged := false + if msg.RemoteConfig != nil { + var err error + configChanged, err = agent.applyRemoteConfig(msg.RemoteConfig) + if err != nil { + agent.opampClient.SetRemoteConfigStatus(&protobufs.RemoteConfigStatus{ + LastRemoteConfigHash: msg.RemoteConfig.ConfigHash, + Status: protobufs.RemoteConfigStatuses_RemoteConfigStatuses_FAILED, + ErrorMessage: err.Error(), + }) + } else { + agent.opampClient.SetRemoteConfigStatus(&protobufs.RemoteConfigStatus{ + LastRemoteConfigHash: msg.RemoteConfig.ConfigHash, + Status: protobufs.RemoteConfigStatuses_RemoteConfigStatuses_APPLIED, + }) + } + } + + if msg.OwnMetricsConnSettings != nil { + agent.initMeter(msg.OwnMetricsConnSettings) + } + + if msg.AgentIdentification != nil { + newInstanceId, err := ulid.Parse(msg.AgentIdentification.NewInstanceUid) + if err != nil { + agent.logger.Errorf(err.Error()) + } + agent.updateAgentIdentity(newInstanceId) + } + + if configChanged { + err := agent.opampClient.UpdateEffectiveConfig(ctx) + if err != nil { + agent.logger.Errorf(err.Error()) + } + } +} diff --git a/cmd/remote-configuration/agent/logger.go b/cmd/remote-configuration/agent/logger.go new file mode 100644 index 0000000000..1899419eb9 --- /dev/null +++ b/cmd/remote-configuration/agent/logger.go @@ -0,0 +1,25 @@ +package agent + +import ( + "fmt" + "github.com/go-logr/logr" + "github.com/open-telemetry/opamp-go/client/types" +) + +var _ types.Logger = &Logger{} + +type Logger struct { + Logger *logr.Logger +} + +func NewLogger(logger *logr.Logger) *Logger { + return &Logger{Logger: logger} +} + +func (l *Logger) Debugf(format string, v ...interface{}) { + l.Logger.V(4).Info(fmt.Sprintf(format, v...)) +} + +func (l *Logger) Errorf(format string, v ...interface{}) { + l.Logger.V(0).Error(nil, fmt.Sprintf(format, v...)) +} diff --git a/cmd/remote-configuration/agent/metricreporter.go b/cmd/remote-configuration/agent/metricreporter.go new file mode 100644 index 0000000000..524e8dc59b --- /dev/null +++ b/cmd/remote-configuration/agent/metricreporter.go @@ -0,0 +1,205 @@ +package agent + +import ( + "context" + "fmt" + "math" + "math/rand" + "net/url" + "os" + "time" + + "github.com/oklog/ulid/v2" + "github.com/shirou/gopsutil/process" + "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/exporters/otlp/otlpmetric" + "go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp" + "go.opentelemetry.io/otel/metric" + "go.opentelemetry.io/otel/metric/global" + controller "go.opentelemetry.io/otel/sdk/metric/controller/basic" + processor "go.opentelemetry.io/otel/sdk/metric/processor/basic" + "go.opentelemetry.io/otel/sdk/metric/selector/simple" + otelresource "go.opentelemetry.io/otel/sdk/resource" + semconv "go.opentelemetry.io/otel/semconv/v1.4.0" + + "github.com/open-telemetry/opamp-go/client/types" + "github.com/open-telemetry/opamp-go/protobufs" +) + +// MetricReporter is a metric reporter that collects Agent metrics and sends them to an +// OTLP/HTTP destination. +type MetricReporter struct { + logger types.Logger + + meter metric.Meter + meterShutdowner func() + done chan struct{} + + // The Agent's process. + process *process.Process + + // Some example metrics to report. + processMemoryPhysical metric.Int64GaugeObserver + counter metric.Int64Counter + processCpuTime metric.Float64CounterObserver +} + +func NewMetricReporter( + logger types.Logger, + dest *protobufs.TelemetryConnectionSettings, + agentType string, + agentVersion string, + instanceId ulid.ULID, +) (*MetricReporter, error) { + + // Check the destination credentials to make sure they look like a valid OTLP/HTTP + // destination. + + if dest.DestinationEndpoint == "" { + err := fmt.Errorf("metric destination must specify DestinationEndpoint") + return nil, err + } + u, err := url.Parse(dest.DestinationEndpoint) + if err != nil { + err := fmt.Errorf("invalid DestinationEndpoint: %v", err) + return nil, err + } + + // Create OTLP/HTTP metric exporter. + opts := []otlpmetrichttp.Option{ + otlpmetrichttp.WithEndpoint(u.Host), + otlpmetrichttp.WithURLPath(u.Path), + } + + if u.Scheme == "http" { + opts = append(opts, otlpmetrichttp.WithInsecure()) + } + + client := otlpmetrichttp.NewClient(opts...) + + metricExporter, err := otlpmetric.New(context.Background(), client) + if err != nil { + err := fmt.Errorf("failed to initialize stdoutmetric export pipeline: %v", err) + return nil, err + } + + // Define the Resource to be exported with all metrics. Use OpenTelemetry semantic + // conventions as the OpAMP spec requires: + // https://github.com/open-telemetry/opamp-spec/blob/main/specification.md#own-telemetry-reporting + resource, err := otelresource.New(context.Background(), + otelresource.WithAttributes( + semconv.ServiceNameKey.String(agentType), + semconv.ServiceVersionKey.String(agentVersion), + semconv.ServiceInstanceIDKey.String(instanceId.String()), + ), + ) + + // Wire up the Resource and the exporter together. + cont := controller.New( + processor.NewFactory( + simple.NewWithInexpensiveDistribution(), + metricExporter, + ), + controller.WithExporter(metricExporter), + controller.WithCollectPeriod(5*time.Second), + controller.WithResource(resource), + ) + + err = cont.Start(context.Background()) + if err != nil { + err := fmt.Errorf("failed to initialize metric controller: %v", err) + return nil, err + } + + global.SetMeterProvider(cont) + + reporter := &MetricReporter{ + logger: logger, + } + + reporter.done = make(chan struct{}) + + reporter.meter = global.Meter("opamp") + + reporter.process, err = process.NewProcess(int32(os.Getpid())) + if err != nil { + err := fmt.Errorf("cannot query own process: %v", err) + return nil, err + } + + // Create some metrics that will be reported according to OpenTelemetry semantic + // conventions for process metrics (conventions are TBD for now). + reporter.processCpuTime = metric.Must(reporter.meter).NewFloat64CounterObserver( + "process.cpu.time", + reporter.processCpuTimeFunc, + ) + + reporter.processMemoryPhysical = metric.Must(reporter.meter).NewInt64GaugeObserver( + "process.memory.physical_usage", + reporter.processMemoryPhysicalFunc, + ) + + reporter.counter = metric.Must(reporter.meter).NewInt64Counter("custom_metric_ticks") + + reporter.meterShutdowner = func() { _ = cont.Stop(context.Background()) } + + go reporter.sendMetrics() + + return reporter, nil +} + +func (reporter *MetricReporter) processCpuTimeFunc(_ context.Context, result metric.Float64ObserverResult) { + times, err := reporter.process.Times() + if err != nil { + reporter.logger.Errorf("Cannot get process CPU times: %v", err) + } + + // Report process CPU times, but also add some randomness to make it interesting for demo. + result.Observe(math.Min(times.User+rand.Float64(), 1), attribute.String("state", "user")) + result.Observe(math.Min(times.System+rand.Float64(), 1), attribute.String("state", "system")) + result.Observe(math.Min(times.Iowait+rand.Float64(), 1), attribute.String("state", "wait")) +} + +func (reporter *MetricReporter) processMemoryPhysicalFunc(_ context.Context, result metric.Int64ObserverResult) { + memory, err := reporter.process.MemoryInfo() + if err != nil { + reporter.logger.Errorf("Cannot get process memory information: %v", err) + return + } + + // Report the RSS, but also add some randomness to make it interesting for demo. + result.Observe(int64(memory.RSS) + rand.Int63n(10000000)) +} + +func (reporter *MetricReporter) sendMetrics() { + + // Collect metrics every 5 seconds. + t := time.NewTicker(time.Second * 5) + ticks := int64(0) + + for { + select { + case <-reporter.done: + return + + case <-t.C: + ctx := context.Background() + reporter.meter.RecordBatch( + ctx, + []attribute.KeyValue{}, + reporter.counter.Measurement(ticks), + ) + ticks++ + } + } +} + +func (reporter *MetricReporter) Shutdown() { + if reporter.done != nil { + close(reporter.done) + } + + if reporter.meterShutdowner != nil { + reporter.meterShutdowner() + } +} diff --git a/cmd/remote-configuration/config/config.go b/cmd/remote-configuration/config/config.go new file mode 100644 index 0000000000..6d6321e376 --- /dev/null +++ b/cmd/remote-configuration/config/config.go @@ -0,0 +1,109 @@ +package config + +import ( + "errors" + "flag" + "fmt" + "github.com/go-logr/logr" + "github.com/open-telemetry/opamp-go/protobufs" + "github.com/spf13/pflag" + "gopkg.in/yaml.v2" + "io/fs" + "k8s.io/client-go/rest" + "k8s.io/client-go/tools/clientcmd" + "k8s.io/client-go/util/homedir" + "k8s.io/klog/v2" + "os" + "path/filepath" + "sigs.k8s.io/controller-runtime/pkg/log/zap" +) + +const ( + agentType = "io.opentelemetry.remote-configuration" + defaultConfigFilePath = "/conf/remoteconfiguration.yaml" +) + +type Config struct { + Endpoint string `yaml:"endpoint"` + Protocol string `yaml:"protocol"` + Capabilities []string `yaml:"capabilities"` + + // ComponentsAllowed is a list of allowed OpenTelemetry components for each pipeline type (receiver, processor, etc.) + ComponentsAllowed map[string][]string `yaml:"components_allowed,omitempty"` +} + +func (c *Config) GetCapabilities() protobufs.AgentCapabilities { + var capabilities int32 + for _, capability := range c.Capabilities { + // This is a helper so that we don't force consumers to prefix every agent capability + formatted := fmt.Sprintf("AgentCapabilities_%s", capability) + if v, ok := protobufs.AgentCapabilities_value[formatted]; ok { + capabilities = v | capabilities + } + } + return protobufs.AgentCapabilities(capabilities) +} + +type CLIConfig struct { + ListenAddr *string + ConfigFilePath *string + AgentType *string + AgentVersion *string + + ClusterConfig *rest.Config + // KubeConfigFilePath empty if in cluster configuration is in use + KubeConfigFilePath string + RootLogger logr.Logger +} + +func Load(file string) (Config, error) { + var cfg Config + if err := unmarshal(&cfg, file); err != nil { + return Config{}, err + } + return cfg, nil +} + +func unmarshal(cfg *Config, configFile string) error { + yamlFile, err := os.ReadFile(configFile) + if err != nil { + return err + } + if err = yaml.UnmarshalStrict(yamlFile, cfg); err != nil { + return fmt.Errorf("error unmarshaling YAML: %w", err) + } + return nil +} + +func ParseCLI() (CLIConfig, error) { + opts := zap.Options{} + opts.BindFlags(flag.CommandLine) + agentVersion := os.Getenv("OPAMP_VERSION") + cLIConf := CLIConfig{ + ListenAddr: pflag.String("listen-addr", ":8080", "The address where this service serves."), + ConfigFilePath: pflag.String("config-file", defaultConfigFilePath, "The path to the config file."), + AgentType: pflag.String("agent-type", agentType, "The type agent that is connecting."), + AgentVersion: pflag.String("agent-version", agentVersion, "The version of the agent."), + } + kubeconfigPath := pflag.String("kubeconfig-path", filepath.Join(homedir.HomeDir(), ".kube", "config"), "absolute path to the KubeconfigPath file") + pflag.Parse() + + cLIConf.RootLogger = zap.New(zap.UseFlagOptions(&opts)) + klog.SetLogger(cLIConf.RootLogger) + + clusterConfig, err := clientcmd.BuildConfigFromFlags("", *kubeconfigPath) + cLIConf.KubeConfigFilePath = *kubeconfigPath + if err != nil { + pathError := &fs.PathError{} + if ok := errors.As(err, &pathError); !ok { + return CLIConfig{}, err + } + clusterConfig, err = rest.InClusterConfig() + if err != nil { + return CLIConfig{}, err + } + cLIConf.KubeConfigFilePath = "" // reset as we use in cluster configuration + } + cLIConf.ClusterConfig = clusterConfig + return cLIConf, nil +} diff --git a/cmd/remote-configuration/go.mod b/cmd/remote-configuration/go.mod new file mode 100644 index 0000000000..b0dc15fb14 --- /dev/null +++ b/cmd/remote-configuration/go.mod @@ -0,0 +1,72 @@ +module github.com/open-telemetry/opentelemetry-operator/cmd/remote-configuration + +go 1.19 + +require ( + github.com/go-logr/logr v1.2.3 + github.com/knadh/koanf v1.3.3 + github.com/oklog/ulid/v2 v2.0.2 + github.com/open-telemetry/opamp-go v0.5.0 + github.com/shirou/gopsutil v3.21.11+incompatible + github.com/spf13/pflag v1.0.5 + go.opentelemetry.io/otel v1.3.0 + go.opentelemetry.io/otel/exporters/otlp/otlpmetric v0.26.0 + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v0.26.0 + go.opentelemetry.io/otel/metric v0.26.0 + go.opentelemetry.io/otel/sdk v1.3.0 + go.opentelemetry.io/otel/sdk/metric v0.26.0 + gopkg.in/yaml.v2 v2.4.0 + k8s.io/client-go v0.26.0 + k8s.io/klog/v2 v2.80.1 + sigs.k8s.io/controller-runtime v0.14.0 +) + +require ( + github.com/cenkalti/backoff/v4 v4.1.2 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/go-logr/stdr v1.2.0 // indirect + github.com/go-logr/zapr v1.2.3 // indirect + github.com/go-ole/go-ole v1.2.6 // indirect + github.com/gogo/protobuf v1.3.2 // indirect + github.com/golang/protobuf v1.5.2 // indirect + github.com/google/gofuzz v1.1.0 // indirect + github.com/gorilla/websocket v1.4.2 // indirect + github.com/grpc-ecosystem/grpc-gateway v1.16.0 // indirect + github.com/imdario/mergo v0.3.6 // indirect + github.com/json-iterator/go v1.1.12 // indirect + github.com/mitchellh/copystructure v1.2.0 // indirect + github.com/mitchellh/mapstructure v1.4.1 // indirect + github.com/mitchellh/reflectwalk v1.0.2 // indirect + github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect + github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/stretchr/testify v1.8.0 // indirect + github.com/tklauser/go-sysconf v0.3.11 // indirect + github.com/tklauser/numcpus v0.6.0 // indirect + github.com/yusufpapurcu/wmi v1.2.2 // indirect + go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.3.0 // indirect + go.opentelemetry.io/otel/internal/metric v0.26.0 // indirect + go.opentelemetry.io/otel/sdk/export/metric v0.26.0 // indirect + go.opentelemetry.io/otel/trace v1.3.0 // indirect + go.opentelemetry.io/proto/otlp v0.11.0 // indirect + go.uber.org/atomic v1.7.0 // indirect + go.uber.org/multierr v1.6.0 // indirect + go.uber.org/zap v1.24.0 // indirect + golang.org/x/net v0.3.1-0.20221206200815-1e63c2f08a10 // indirect + golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b // indirect + golang.org/x/sys v0.3.0 // indirect + golang.org/x/term v0.3.0 // indirect + golang.org/x/text v0.5.0 // indirect + golang.org/x/time v0.3.0 // indirect + google.golang.org/appengine v1.6.7 // indirect + google.golang.org/genproto v0.0.0-20200825200019-8632dd797987 // indirect + google.golang.org/grpc v1.42.0 // indirect + google.golang.org/protobuf v1.28.1 // indirect + gopkg.in/inf.v0 v0.9.1 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect + k8s.io/apimachinery v0.26.0 // indirect + k8s.io/utils v0.0.0-20221128185143-99ec85e7a448 // indirect + sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2 // indirect + sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect + sigs.k8s.io/yaml v1.3.0 // indirect +) diff --git a/cmd/remote-configuration/go.sum b/cmd/remote-configuration/go.sum new file mode 100644 index 0000000000..367eafb203 --- /dev/null +++ b/cmd/remote-configuration/go.sum @@ -0,0 +1,635 @@ +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= +cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= +cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= +cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= +cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= +cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= +cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= +cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= +cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= +cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= +cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= +cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= +cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= +cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= +cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= +cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= +cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= +cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= +cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= +cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= +cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= +cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= +cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= +cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= +cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= +cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= +cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= +cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= +cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= +cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= +dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= +github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= +github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= +github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= +github.com/aws/aws-sdk-go-v2 v1.9.2/go.mod h1:cK/D0BBs0b/oWPIcX/Z/obahJK1TT7IPVjy53i/mX/4= +github.com/aws/aws-sdk-go-v2/config v1.8.3/go.mod h1:4AEiLtAb8kLs7vgw2ZV3p2VZ1+hBavOc84hqxVNpCyw= +github.com/aws/aws-sdk-go-v2/credentials v1.4.3/go.mod h1:FNNC6nQZQUuyhq5aE5c7ata8o9e4ECGmS4lAXC7o1mQ= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.6.0/go.mod h1:gqlclDEZp4aqJOancXK6TN24aKhT0W0Ae9MHk3wzTMM= +github.com/aws/aws-sdk-go-v2/internal/ini v1.2.4/go.mod h1:ZcBrrI3zBKlhGFNYWvju0I3TR93I7YIgAfy82Fh4lcQ= +github.com/aws/aws-sdk-go-v2/service/appconfig v1.4.2/go.mod h1:FZ3HkCe+b10uFZZkFdvf98LHW21k49W8o8J366lqVKY= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.3.2/go.mod h1:72HRZDLMtmVQiLG2tLfQcaWLCssELvGl+Zf2WVxMmR8= +github.com/aws/aws-sdk-go-v2/service/sso v1.4.2/go.mod h1:NBvT9R1MEF+Ud6ApJKM0G+IkPchKS7p7c2YPKwHmBOk= +github.com/aws/aws-sdk-go-v2/service/sts v1.7.2/go.mod h1:8EzeIqfWt2wWT4rJVu3f21TfrhJ8AEMzVybRNSb/b4g= +github.com/aws/smithy-go v1.8.0/go.mod h1:SObp3lf9smib00L/v3U2eAKG8FyQ7iLrJnQiAmR5n+E= +github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= +github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT8A= +github.com/benbjohnson/clock v1.3.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= +github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= +github.com/cenkalti/backoff/v4 v4.1.2 h1:6Yo7N8UP2K6LWZnW94DLVSSrbobcWdVzAYOisuDPIFo= +github.com/cenkalti/backoff/v4 v4.1.2/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= +github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= +github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= +github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/emicklei/go-restful/v3 v3.9.0 h1:XwGDlfxEnQZzuopoqxwSEllNcCOM9DhhFyhFIIGKwxE= +github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= +github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= +github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= +github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= +github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= +github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= +github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-ldap/ldap v3.0.2+incompatible/go.mod h1:qfd9rJvER9Q0/D/Sqn1DfHRoBp40uXYvFoEVrNEPqRc= +github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.2.1/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0= +github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/stdr v1.2.0 h1:j4LrlVXgrbIWO83mmQUnK0Hi+YnbD+vzrE1z/EphbFE= +github.com/go-logr/stdr v1.2.0/go.mod h1:YkVgnZu1ZjjL7xTxrfm/LLZBfkhTqSR1ydtm6jTKKwI= +github.com/go-logr/zapr v1.2.3 h1:a9vnzlIBPQBBkeaR9IuMUfmVOrQlkoC4YfPoFkX3T7A= +github.com/go-logr/zapr v1.2.3/go.mod h1:eIauM6P8qSvTw5o2ez6UEAfGjQKrxQTl5EoK+Qa2oG4= +github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= +github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= +github.com/go-openapi/jsonpointer v0.19.5 h1:gZr+CIYByUqjcgeLXnQu2gHYQC9o73G2XUeOFYEICuY= +github.com/go-openapi/jsonreference v0.20.0 h1:MYlu0sBgChmCfJxxUKZ8g1cPWFOB37YSZqewK7OKeyA= +github.com/go-openapi/swag v0.19.14 h1:gm3vOOXfiuw5i9p5N9xJvfjvuofpyvLA9Wr6QfK5Fng= +github.com/go-test/deep v1.0.2-0.20181118220953-042da051cf31/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= +github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= +github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= +github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= +github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/gnostic v0.5.7-v3refs h1:FhTMOKj2VhjpouxvWJAV1TL304uMlb9zcDqkl6cEI54= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/gofuzz v1.1.0 h1:Hsa8mG0dQ46ij8Sl2AYJDUv1oA9/d6Vk+3LG99Oe02g= +github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= +github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= +github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= +github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= +github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= +github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo= +github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= +github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= +github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= +github.com/hashicorp/go-hclog v0.0.0-20180709165350-ff2cf002a8dd/go.mod h1:9bjs9uLqI8l75knNv3lV1kA55veR+WUPSiKIWcQHudI= +github.com/hashicorp/go-hclog v0.8.0/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ= +github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= +github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= +github.com/hashicorp/go-plugin v1.0.1/go.mod h1:++UyYGoz3o5w9ZzAdZxtQKrWWP+iqPBn3cQptSMzBuY= +github.com/hashicorp/go-retryablehttp v0.5.4/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs= +github.com/hashicorp/go-rootcerts v1.0.1/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8= +github.com/hashicorp/go-sockaddr v1.0.2/go.mod h1:rB4wwRAUzs07qva3c5SdrY/NEtAUjGlgmH/UkBUC97A= +github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-version v1.1.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= +github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= +github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/hashicorp/vault/api v1.0.4/go.mod h1:gDcqh3WGcR1cpF5AJz/B1UFheUEneMoIospckxBxk6Q= +github.com/hashicorp/vault/sdk v0.1.13/go.mod h1:B+hVj7TpuQY1Y/GPbCpffmgd+tSEwvhkWnjtSYCaS2M= +github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM= +github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM= +github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/imdario/mergo v0.3.6 h1:xTNEAn+kxVO7dTZGu0CegyqKZmoWFI0rF8UxjlB2d28= +github.com/imdario/mergo v0.3.6/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= +github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= +github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= +github.com/joho/godotenv v1.3.0 h1:Zjp+RcGpHhGlrMbJzXTrZZPrWj+1vfm90La1wgB6Bhc= +github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg= +github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= +github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= +github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= +github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= +github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/knadh/koanf v1.3.3 h1:eNtBOzQDzkzIIPRCJCx/Ha3DeD/ZFwCAp8JxyqoVAls= +github.com/knadh/koanf v1.3.3/go.mod h1:1cfH5223ZeZUOs8FU2UdTmaNfHpqgtjV0+NHjRO43gs= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/mailru/easyjson v0.7.6 h1:8yTIVnZgCoiM1TgqoeTl+LfU5Jg6/xL3QhGQnimLYnA= +github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= +github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= +github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw= +github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= +github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= +github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/go-testing-interface v0.0.0-20171004221916-a61a99592b77/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= +github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= +github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo= +github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/mitchellh/mapstructure v1.4.1 h1:CpVNEelQCZBooIPDn+AR3NpivK/TIKU8bDxdASFVQag= +github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= +github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= +github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= +github.com/npillmayer/nestext v0.1.3/go.mod h1:h2lrijH8jpicr25dFY+oAJLyzlya6jhnuG+zWp9L0Uk= +github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= +github.com/oklog/ulid/v2 v2.0.2 h1:r4fFzBm+bv0wNKNh5eXTwU7i85y5x+uwkxCUTNVQqLc= +github.com/oklog/ulid/v2 v2.0.2/go.mod h1:mtBL0Qe/0HAx6/a4Z30qxVIAL1eQDweXq5lxOEiwQ68= +github.com/onsi/ginkgo/v2 v2.6.0 h1:9t9b9vRUbFq3C4qKFCGkVuq/fIHji802N1nrtkh1mNc= +github.com/onsi/gomega v1.24.1 h1:KORJXNNTzJXzu4ScJWssJfJMnJ+2QJqhoQSRwNlze9E= +github.com/open-telemetry/opamp-go v0.1.0 h1:VEeGUZG54X1P6Sabl4Q61yClDmVuDfo/Xsmh/SEFPoo= +github.com/open-telemetry/opamp-go v0.1.0/go.mod h1:IMdeuHGVc5CjKSu5/oNV0o+UmiXuahoHvoZ4GOmAI9M= +github.com/open-telemetry/opamp-go v0.5.0 h1:2YFbb6G4qBkq3yTRdVb5Nfz9hKHW/ldUyex352e1J7g= +github.com/open-telemetry/opamp-go v0.5.0/go.mod h1:IMdeuHGVc5CjKSu5/oNV0o+UmiXuahoHvoZ4GOmAI9M= +github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= +github.com/pborman/getopt v0.0.0-20170112200414-7148bc3a4c30/go.mod h1:85jBQOZwpVEaDAr341tbn15RS4fCAsIst0qp7i8ex1o= +github.com/pelletier/go-toml v1.7.0 h1:7utD74fnzVc/cpcyy8sjrlFr5vYpypUixARcHIMIGuI= +github.com/pelletier/go-toml v1.7.0/go.mod h1:vwGMzjaWMwyfHwgIBhI2YUM4fB6nL6lVAvS1LBMMhTE= +github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= +github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/rhnvrm/simples3 v0.6.1/go.mod h1:Y+3vYm2V7Y4VijFoJHHTrja6OgPrJ2cBti8dPGkC3sA= +github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= +github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= +github.com/ryanuber/go-glob v1.0.0/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc= +github.com/shirou/gopsutil v3.21.11+incompatible h1:+1+c1VGhc88SSonWP6foOcLhvnKlUeu/erjjvaPEYiI= +github.com/shirou/gopsutil v3.21.11+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= +github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= +github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/tklauser/go-sysconf v0.3.11 h1:89WgdJhk5SNwJfu+GKyYveZ4IaJ7xAkecBo+KdJV0CM= +github.com/tklauser/go-sysconf v0.3.11/go.mod h1:GqXfhXY3kiPa0nAXPDIQIWzJbMCB7AmcWpGR8lSZfqI= +github.com/tklauser/numcpus v0.6.0 h1:kebhY2Qt+3U6RNK7UqpYNA+tJ23IBEGKkB7JQBfDYms= +github.com/tklauser/numcpus v0.6.0/go.mod h1:FEZLMke0lhOUG6w2JadTzp0a+Nl8PF/GFkQ5UVIcaL4= +github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yusufpapurcu/wmi v1.2.2 h1:KBNDSne4vP5mbSWnJbO+51IMOXJB67QiYCSBrubbPRg= +github.com/yusufpapurcu/wmi v1.2.2/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= +go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= +go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= +go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opentelemetry.io/otel v1.3.0 h1:APxLf0eiBwLl+SOXiJJCVYzA1OOJNyAoV8C5RNRyy7Y= +go.opentelemetry.io/otel v1.3.0/go.mod h1:PWIKzi6JCp7sM0k9yZ43VX+T345uNbAkDKwHVjb2PTs= +go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.3.0 h1:R/OBkMoGgfy2fLhs2QhkCI1w4HLEQX92GCcJB6SSdNk= +go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.3.0/go.mod h1:VpP4/RMn8bv8gNo9uK7/IMY4mtWLELsS+JIP0inH0h4= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric v0.26.0 h1:dIE9swzwOnkGaJ6OF1QQQdBk2EdrJnD9Ilao2G9DeLU= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric v0.26.0/go.mod h1:1E0NE+3ywwedkOEl3d7nFjyI/bqRECMhI3xTGh13pxY= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v0.26.0 h1:B4KUKYd6VEiqKh0kHf4+RZOhY/kANSvGydrQdE1dNkY= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v0.26.0/go.mod h1:CaqVOcEDDQ1XY7zEJT81c8aUNPju3jRqjva6ROUi+z0= +go.opentelemetry.io/otel/internal/metric v0.26.0 h1:dlrvawyd/A+X8Jp0EBT4wWEe4k5avYaXsXrBr4dbfnY= +go.opentelemetry.io/otel/internal/metric v0.26.0/go.mod h1:CbBP6AxKynRs3QCbhklyLUtpfzbqCLiafV9oY2Zj1Jk= +go.opentelemetry.io/otel/metric v0.26.0 h1:VaPYBTvA13h/FsiWfxa3yZnZEm15BhStD8JZQSA773M= +go.opentelemetry.io/otel/metric v0.26.0/go.mod h1:c6YL0fhRo4YVoNs6GoByzUgBp36hBL523rECoZA5UWg= +go.opentelemetry.io/otel/sdk v1.3.0 h1:3278edCoH89MEJ0Ky8WQXVmDQv3FX4ZJ3Pp+9fJreAI= +go.opentelemetry.io/otel/sdk v1.3.0/go.mod h1:rIo4suHNhQwBIPg9axF8V9CA72Wz2mKF1teNrup8yzs= +go.opentelemetry.io/otel/sdk/export/metric v0.26.0 h1:eNseg5yyZqaAAY+Att3owR3Bl0Is5rCZywqO1OrGx18= +go.opentelemetry.io/otel/sdk/export/metric v0.26.0/go.mod h1:UpqzSnUOjFeSIVQLPp3pYIXfB/MiMFyXXzYT/bercxQ= +go.opentelemetry.io/otel/sdk/metric v0.26.0 h1:7IKp3gc/ObieCtshBeYYVFp3ZP7xIH1OzODi1Wao90Y= +go.opentelemetry.io/otel/sdk/metric v0.26.0/go.mod h1:2VIeK0kS1YvRLFg3J58ptZTXYpiWlkq2n5RQt6w7He8= +go.opentelemetry.io/otel/trace v1.3.0 h1:doy8Hzb1RJ+I3yFhtDmwNc7tIyw1tNMOIsyPzp1NOGY= +go.opentelemetry.io/otel/trace v1.3.0/go.mod h1:c/VDhno8888bvQYmbYLqe41/Ldmr/KKunbvWM4/fEjk= +go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= +go.opentelemetry.io/proto/otlp v0.11.0 h1:cLDgIBTf4lLOlztkhzAEdQsJ4Lj+i5Wc9k6Nn0K1VyU= +go.opentelemetry.io/proto/otlp v0.11.0/go.mod h1:QpEjXPrNQzrFDZgoTo49dgHR9RYRSrg3NAKnUGl9YpQ= +go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw= +go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= +go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk= +go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4= +go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= +go.uber.org/zap v1.19.0/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI= +go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60= +go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= +golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= +golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= +golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= +golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= +golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= +golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= +golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= +golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= +golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= +golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.3.1-0.20221206200815-1e63c2f08a10 h1:Frnccbp+ok2GkUS2tC84yAq/U9Vg+0sIO7aRL3T4Xnc= +golang.org/x/net v0.3.1-0.20221206200815-1e63c2f08a10/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b h1:clP8eMhB30EHdc0bd2Twtq6kgU7yl5ub2cQLSdrv1Dg= +golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190129075346-302c3dd5f1cc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.3.0 h1:w8ZOecv6NaNa/zC8944JTU3vz4u6Lagfk4RPQxv92NQ= +golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.3.0 h1:qoo4akIqOcDME5bhc/NgxUdovd6BSS2uMsVjB56q1xI= +golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA= +golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.1-0.20181227161524-e6919f6577db/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.5.0 h1:OLmvp0KP+FVG99Ct/qFiL/Fhk4zp4QQnZ7b2U+5piUM= +golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= +golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= +golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= +google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= +google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= +google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= +google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= +google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= +google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= +google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190404172233-64821d5d2107/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= +google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= +google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= +google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= +google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200825200019-8632dd797987 h1:PDIOdWxZ8eRizhKa1AAvY53xsvLB1cWorMjslvY3VA8= +google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= +google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= +google.golang.org/grpc v1.22.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= +google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= +google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= +google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= +google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.42.0 h1:XT2/MFpuPFsEX2fWh3YQtHkZ+WYZFQRfaUgLZYj/p6A= +google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= +google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w= +google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d/go.mod h1:cuepJuh7vyXfUyUwEgHQXw849cJrilpS5NeIjOWESAw= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU= +gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= +gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= +gopkg.in/square/go-jose.v2 v2.3.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= +honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +k8s.io/api v0.26.0 h1:IpPlZnxBpV1xl7TGk/X6lFtpgjgntCg8PJ+qrPHAC7I= +k8s.io/apimachinery v0.26.0 h1:1feANjElT7MvPqp0JT6F3Ss6TWDwmcjLypwoPpEf7zg= +k8s.io/apimachinery v0.26.0/go.mod h1:tnPmbONNJ7ByJNz9+n9kMjNP8ON+1qoAIIC70lztu74= +k8s.io/client-go v0.26.0 h1:lT1D3OfO+wIi9UFolCrifbjUUgu7CpLca0AD8ghRLI8= +k8s.io/client-go v0.26.0/go.mod h1:I2Sh57A79EQsDmn7F7ASpmru1cceh3ocVT9KlX2jEZg= +k8s.io/klog/v2 v2.80.1 h1:atnLQ121W371wYYFawwYx1aEY2eUfs4l3J72wtgAwV4= +k8s.io/klog/v2 v2.80.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= +k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280 h1:+70TFaan3hfJzs+7VK2o+OGxg8HsuBr/5f6tVAjDu6E= +k8s.io/utils v0.0.0-20221128185143-99ec85e7a448 h1:KTgPnR10d5zhztWptI952TNtt/4u5h3IzDXkdIMuo2Y= +k8s.io/utils v0.0.0-20221128185143-99ec85e7a448/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= +rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= +rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= +sigs.k8s.io/controller-runtime v0.14.0 h1:ju2xsov5Ara6FoQuddg+az+rAxsUsTYn2IYyEKCTyDc= +sigs.k8s.io/controller-runtime v0.14.0/go.mod h1:GaRkrY8a7UZF0kqFFbUKG7n9ICiTY5T55P1RiE3UZlU= +sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2 h1:iXTIw73aPyC+oRdyqqvVJuloN1p0AC/kzH07hu3NE+k= +sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= +sigs.k8s.io/structured-merge-diff/v4 v4.2.3 h1:PRbqxJClWWYMNV1dhaG4NsibJbArud9kFxnAMREiWFE= +sigs.k8s.io/structured-merge-diff/v4 v4.2.3/go.mod h1:qjx8mGObPmV2aSZepjQjbmb2ihdVs8cGKBraizNC69E= +sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo= +sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8= diff --git a/cmd/remote-configuration/main.go b/cmd/remote-configuration/main.go new file mode 100644 index 0000000000..03b795d92e --- /dev/null +++ b/cmd/remote-configuration/main.go @@ -0,0 +1,34 @@ +package main + +import ( + "github.com/open-telemetry/opentelemetry-operator/cmd/remote-configuration/agent" + "github.com/open-telemetry/opentelemetry-operator/cmd/remote-configuration/config" + "os" + "os/signal" +) + +func main() { + cliConf, err := config.ParseCLI() + if err != nil { + os.Exit(1) + } + cfg, configLoadErr := config.Load(*cliConf.ConfigFilePath) + if configLoadErr != nil { + cliConf.RootLogger.Error(configLoadErr, "Unable to load configuration") + return + } + cliConf.RootLogger.Info("Starting the Remote Configuration service") + agentLogger := cliConf.RootLogger.WithName("agent") + + opampAgent := agent.NewAgent(agent.NewLogger(&agentLogger), cfg, *cliConf.AgentType, *cliConf.AgentVersion) + + if err := opampAgent.Start(); err != nil { + cliConf.RootLogger.Error(err, "Cannot start OpAMP client") + return + } + + interrupt := make(chan os.Signal, 1) + signal.Notify(interrupt, os.Interrupt) + <-interrupt + opampAgent.Shutdown() +} From 2d55fe2121c45a31e6e406437626d169f8c237e8 Mon Sep 17 00:00:00 2001 From: Jacob Aronoff Date: Tue, 20 Dec 2022 22:47:41 -0500 Subject: [PATCH 02/16] Some hacks to functionality --- cmd/remote-configuration/agent/agent.go | 105 +++++- cmd/remote-configuration/agent/logger.go | 1 + .../agent/metricreporter.go | 93 +++--- cmd/remote-configuration/config/config.go | 7 +- cmd/remote-configuration/go.mod | 67 ++-- cmd/remote-configuration/go.sum | 311 +++++++++++------- cmd/remote-configuration/main.go | 12 +- cmd/remote-configuration/operator/client.go | 146 ++++++++ 8 files changed, 532 insertions(+), 210 deletions(-) create mode 100644 cmd/remote-configuration/operator/client.go diff --git a/cmd/remote-configuration/agent/agent.go b/cmd/remote-configuration/agent/agent.go index 59e335df6d..607ef5a687 100644 --- a/cmd/remote-configuration/agent/agent.go +++ b/cmd/remote-configuration/agent/agent.go @@ -1,14 +1,22 @@ package agent import ( + "bytes" "context" - "github.com/open-telemetry/opentelemetry-operator/cmd/remote-configuration/config" + "errors" + "fmt" + "github.com/open-telemetry/opentelemetry-operator/cmd/remote-configuration/operator" + "gopkg.in/yaml.v3" "math/rand" "os" "runtime" + "strings" "time" + "github.com/open-telemetry/opentelemetry-operator/cmd/remote-configuration/config" + "github.com/oklog/ulid/v2" + "go.uber.org/multierr" "github.com/open-telemetry/opamp-go/client" "github.com/open-telemetry/opamp-go/client/types" @@ -40,8 +48,9 @@ type Agent struct { agentType string agentVersion string - effectiveConfig string - startTime uint64 + // A set of the applied object keys (name/namespace) + appliedKeys map[string]bool + startTime uint64 instanceId ulid.ULID @@ -53,14 +62,18 @@ type Agent struct { metricReporter *MetricReporter config config.Config + applier operator.ConfigApplier + lastHash []byte } -func NewAgent(logger types.Logger, config config.Config, agentType string, agentVersion string) *Agent { +func NewAgent(logger types.Logger, applier operator.ConfigApplier, config config.Config, agentType string, agentVersion string) *Agent { agent := &Agent{ config: config, + applier: applier, logger: logger, agentType: agentType, agentVersion: agentVersion, + appliedKeys: map[string]bool{}, } agent.createAgentIdentity() @@ -191,14 +204,45 @@ func (agent *Agent) updateAgentIdentity(instanceId ulid.ULID) { } } +func (agent *Agent) getNameAndNamespace(key string) (string, string, error) { + s := strings.Split(key, "/") + // We expect map keys to be of the form name/namespace + if len(s) != 2 { + return "", "", errors.New("invalid key") + } + return s[0], s[1], nil +} + +func (agent *Agent) makeKeyFromNameNamespace(name string, namespace string) string { + return fmt.Sprintf("%s/%s", name, namespace) +} + func (agent *Agent) composeEffectiveConfig() *protobufs.EffectiveConfig { - return &protobufs.EffectiveConfig{ + effectiveConfig := &protobufs.EffectiveConfig{ ConfigMap: &protobufs.AgentConfigMap{ - ConfigMap: map[string]*protobufs.AgentConfigFile{ - "": {Body: []byte(agent.effectiveConfig)}, - }, + ConfigMap: nil, }, } + instances, err := agent.applier.ListInstances() + if err != nil { + agent.logger.Errorf("couldn't list instances", err) + return effectiveConfig + } + instanceMap := map[string]*protobufs.AgentConfigFile{} + for _, instance := range instances { + marshalled, err := yaml.Marshal(instance) + if err != nil { + agent.logger.Errorf("couldn't marshal collector configuration", err) + continue + } + mapKey := agent.makeKeyFromNameNamespace(instance.GetName(), instance.GetNamespace()) + instanceMap[mapKey] = &protobufs.AgentConfigFile{ + Body: marshalled, + ContentType: "yaml", + } + } + effectiveConfig.ConfigMap.ConfigMap = instanceMap + return effectiveConfig } func (agent *Agent) initMeter(settings *protobufs.TelemetryConnectionSettings) { @@ -219,11 +263,35 @@ func (agent *Agent) initMeter(settings *protobufs.TelemetryConnectionSettings) { } // Take the remote config, layer it over existing, done -func (agent *Agent) applyRemoteConfig(config *protobufs.AgentRemoteConfig) (configChanged bool, err error) { +func (agent *Agent) applyRemoteConfig(config *protobufs.AgentRemoteConfig) (bool, error) { if config == nil { return false, nil } - return false, nil + if bytes.Equal(agent.lastHash, config.ConfigHash) { + return false, nil + } + var multiErr error + for key, file := range config.Config.GetConfigMap() { + if len(key) == 0 || len(file.Body) == 0 { + continue + } + name, namespace, err := agent.getNameAndNamespace(key) + if err != nil { + multiErr = multierr.Append(multiErr, err) + continue + } + err = agent.applier.Apply(name, namespace, file) + if err != nil { + multiErr = multierr.Append(multiErr, err) + continue + } + agent.appliedKeys[key] = true + } + if multiErr != nil { + return false, multiErr + } + agent.lastHash = config.ConfigHash + return true, nil } func (agent *Agent) Shutdown() { @@ -239,22 +307,29 @@ func (agent *Agent) onMessage(ctx context.Context, msg *types.MessageData) { var err error configChanged, err = agent.applyRemoteConfig(msg.RemoteConfig) if err != nil { - agent.opampClient.SetRemoteConfigStatus(&protobufs.RemoteConfigStatus{ + setErr := agent.opampClient.SetRemoteConfigStatus(&protobufs.RemoteConfigStatus{ LastRemoteConfigHash: msg.RemoteConfig.ConfigHash, Status: protobufs.RemoteConfigStatuses_RemoteConfigStatuses_FAILED, ErrorMessage: err.Error(), }) + if setErr != nil { + return + } } else { - agent.opampClient.SetRemoteConfigStatus(&protobufs.RemoteConfigStatus{ + setErr := agent.opampClient.SetRemoteConfigStatus(&protobufs.RemoteConfigStatus{ LastRemoteConfigHash: msg.RemoteConfig.ConfigHash, Status: protobufs.RemoteConfigStatuses_RemoteConfigStatuses_APPLIED, }) + if setErr != nil { + return + } } } - if msg.OwnMetricsConnSettings != nil { - agent.initMeter(msg.OwnMetricsConnSettings) - } + // TODO: figure out why metrics aren't working + //if msg.OwnMetricsConnSettings != nil { + // agent.initMeter(msg.OwnMetricsConnSettings) + //} if msg.AgentIdentification != nil { newInstanceId, err := ulid.Parse(msg.AgentIdentification.NewInstanceUid) diff --git a/cmd/remote-configuration/agent/logger.go b/cmd/remote-configuration/agent/logger.go index 1899419eb9..5c85d3a40b 100644 --- a/cmd/remote-configuration/agent/logger.go +++ b/cmd/remote-configuration/agent/logger.go @@ -2,6 +2,7 @@ package agent import ( "fmt" + "github.com/go-logr/logr" "github.com/open-telemetry/opamp-go/client/types" ) diff --git a/cmd/remote-configuration/agent/metricreporter.go b/cmd/remote-configuration/agent/metricreporter.go index 524e8dc59b..3d74e6f9e4 100644 --- a/cmd/remote-configuration/agent/metricreporter.go +++ b/cmd/remote-configuration/agent/metricreporter.go @@ -12,13 +12,14 @@ import ( "github.com/oklog/ulid/v2" "github.com/shirou/gopsutil/process" "go.opentelemetry.io/otel/attribute" - "go.opentelemetry.io/otel/exporters/otlp/otlpmetric" "go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp" "go.opentelemetry.io/otel/metric" "go.opentelemetry.io/otel/metric/global" - controller "go.opentelemetry.io/otel/sdk/metric/controller/basic" - processor "go.opentelemetry.io/otel/sdk/metric/processor/basic" - "go.opentelemetry.io/otel/sdk/metric/selector/simple" + "go.opentelemetry.io/otel/metric/instrument" + "go.opentelemetry.io/otel/metric/instrument/asyncfloat64" + "go.opentelemetry.io/otel/metric/instrument/asyncint64" + "go.opentelemetry.io/otel/metric/instrument/syncint64" + sdkmetric "go.opentelemetry.io/otel/sdk/metric" otelresource "go.opentelemetry.io/otel/sdk/resource" semconv "go.opentelemetry.io/otel/semconv/v1.4.0" @@ -39,9 +40,9 @@ type MetricReporter struct { process *process.Process // Some example metrics to report. - processMemoryPhysical metric.Int64GaugeObserver - counter metric.Int64Counter - processCpuTime metric.Float64CounterObserver + processMemoryPhysical asyncint64.Gauge + counter syncint64.Counter + processCpuTime asyncfloat64.Counter } func NewMetricReporter( @@ -75,11 +76,9 @@ func NewMetricReporter( opts = append(opts, otlpmetrichttp.WithInsecure()) } - client := otlpmetrichttp.NewClient(opts...) - - metricExporter, err := otlpmetric.New(context.Background(), client) + client, err := otlpmetrichttp.New(context.Background(), opts...) if err != nil { - err := fmt.Errorf("failed to initialize stdoutmetric export pipeline: %v", err) + err := fmt.Errorf("failed to initialize otlp metric http client: %v", err) return nil, err } @@ -94,24 +93,11 @@ func NewMetricReporter( ), ) - // Wire up the Resource and the exporter together. - cont := controller.New( - processor.NewFactory( - simple.NewWithInexpensiveDistribution(), - metricExporter, - ), - controller.WithExporter(metricExporter), - controller.WithCollectPeriod(5*time.Second), - controller.WithResource(resource), - ) - - err = cont.Start(context.Background()) - if err != nil { - err := fmt.Errorf("failed to initialize metric controller: %v", err) - return nil, err - } + provider := sdkmetric.NewMeterProvider( + sdkmetric.WithResource(resource), + sdkmetric.WithReader(sdkmetric.NewPeriodicReader(client))) - global.SetMeterProvider(cont) + global.SetMeterProvider(provider) reporter := &MetricReporter{ logger: logger, @@ -129,38 +115,57 @@ func NewMetricReporter( // Create some metrics that will be reported according to OpenTelemetry semantic // conventions for process metrics (conventions are TBD for now). - reporter.processCpuTime = metric.Must(reporter.meter).NewFloat64CounterObserver( + reporter.processCpuTime, err = reporter.meter.AsyncFloat64().Counter( "process.cpu.time", - reporter.processCpuTimeFunc, ) - - reporter.processMemoryPhysical = metric.Must(reporter.meter).NewInt64GaugeObserver( + if err != nil { + err := fmt.Errorf("can't create process time metric: %v", err) + return nil, err + } + err = reporter.meter.RegisterCallback([]instrument.Asynchronous{reporter.processCpuTime}, reporter.processCpuTimeFunc) + if err != nil { + err := fmt.Errorf("can't create register callback: %v", err) + return nil, err + } + reporter.processMemoryPhysical, err = reporter.meter.AsyncInt64().Gauge( "process.memory.physical_usage", - reporter.processMemoryPhysicalFunc, ) + if err != nil { + err := fmt.Errorf("can't create memory metric: %v", err) + return nil, err + } + err = reporter.meter.RegisterCallback([]instrument.Asynchronous{reporter.processMemoryPhysical}, reporter.processMemoryPhysicalFunc) + if err != nil { + err := fmt.Errorf("can't register callback: %v", err) + return nil, err + } - reporter.counter = metric.Must(reporter.meter).NewInt64Counter("custom_metric_ticks") + reporter.counter, err = reporter.meter.SyncInt64().Counter("custom_metric_ticks") + if err != nil { + err := fmt.Errorf("can't register counter metric: %v", err) + return nil, err + } - reporter.meterShutdowner = func() { _ = cont.Stop(context.Background()) } + reporter.meterShutdowner = func() { _ = provider.Shutdown(context.Background()) } go reporter.sendMetrics() return reporter, nil } -func (reporter *MetricReporter) processCpuTimeFunc(_ context.Context, result metric.Float64ObserverResult) { +func (reporter *MetricReporter) processCpuTimeFunc(c context.Context) { times, err := reporter.process.Times() if err != nil { reporter.logger.Errorf("Cannot get process CPU times: %v", err) } // Report process CPU times, but also add some randomness to make it interesting for demo. - result.Observe(math.Min(times.User+rand.Float64(), 1), attribute.String("state", "user")) - result.Observe(math.Min(times.System+rand.Float64(), 1), attribute.String("state", "system")) - result.Observe(math.Min(times.Iowait+rand.Float64(), 1), attribute.String("state", "wait")) + reporter.processCpuTime.Observe(c, math.Min(times.User+rand.Float64(), 1), attribute.String("state", "user")) + reporter.processCpuTime.Observe(c, math.Min(times.System+rand.Float64(), 1), attribute.String("state", "system")) + reporter.processCpuTime.Observe(c, math.Min(times.Iowait+rand.Float64(), 1), attribute.String("state", "wait")) } -func (reporter *MetricReporter) processMemoryPhysicalFunc(_ context.Context, result metric.Int64ObserverResult) { +func (reporter *MetricReporter) processMemoryPhysicalFunc(ctx context.Context) { memory, err := reporter.process.MemoryInfo() if err != nil { reporter.logger.Errorf("Cannot get process memory information: %v", err) @@ -168,7 +173,7 @@ func (reporter *MetricReporter) processMemoryPhysicalFunc(_ context.Context, res } // Report the RSS, but also add some randomness to make it interesting for demo. - result.Observe(int64(memory.RSS) + rand.Int63n(10000000)) + reporter.processMemoryPhysical.Observe(ctx, int64(memory.RSS)+rand.Int63n(10000000)) } func (reporter *MetricReporter) sendMetrics() { @@ -184,11 +189,7 @@ func (reporter *MetricReporter) sendMetrics() { case <-t.C: ctx := context.Background() - reporter.meter.RecordBatch( - ctx, - []attribute.KeyValue{}, - reporter.counter.Measurement(ticks), - ) + reporter.counter.Add(ctx, ticks) ticks++ } } diff --git a/cmd/remote-configuration/config/config.go b/cmd/remote-configuration/config/config.go index 6d6321e376..66b5e9493b 100644 --- a/cmd/remote-configuration/config/config.go +++ b/cmd/remote-configuration/config/config.go @@ -4,17 +4,18 @@ import ( "errors" "flag" "fmt" + "io/fs" + "os" + "path/filepath" + "github.com/go-logr/logr" "github.com/open-telemetry/opamp-go/protobufs" "github.com/spf13/pflag" "gopkg.in/yaml.v2" - "io/fs" "k8s.io/client-go/rest" "k8s.io/client-go/tools/clientcmd" "k8s.io/client-go/util/homedir" "k8s.io/klog/v2" - "os" - "path/filepath" "sigs.k8s.io/controller-runtime/pkg/log/zap" ) diff --git a/cmd/remote-configuration/go.mod b/cmd/remote-configuration/go.mod index b0dc15fb14..7addcc141e 100644 --- a/cmd/remote-configuration/go.mod +++ b/cmd/remote-configuration/go.mod @@ -4,17 +4,16 @@ go 1.19 require ( github.com/go-logr/logr v1.2.3 - github.com/knadh/koanf v1.3.3 github.com/oklog/ulid/v2 v2.0.2 github.com/open-telemetry/opamp-go v0.5.0 + github.com/open-telemetry/opentelemetry-operator v1.51.0 github.com/shirou/gopsutil v3.21.11+incompatible github.com/spf13/pflag v1.0.5 - go.opentelemetry.io/otel v1.3.0 - go.opentelemetry.io/otel/exporters/otlp/otlpmetric v0.26.0 - go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v0.26.0 - go.opentelemetry.io/otel/metric v0.26.0 - go.opentelemetry.io/otel/sdk v1.3.0 - go.opentelemetry.io/otel/sdk/metric v0.26.0 + go.opentelemetry.io/otel v1.11.2 + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v0.34.0 + go.opentelemetry.io/otel/metric v0.34.0 + go.opentelemetry.io/otel/sdk v1.11.2 + go.opentelemetry.io/otel/sdk/metric v0.34.0 gopkg.in/yaml.v2 v2.4.0 k8s.io/client-go v0.26.0 k8s.io/klog/v2 v2.80.1 @@ -22,34 +21,51 @@ require ( ) require ( - github.com/cenkalti/backoff/v4 v4.1.2 // indirect + github.com/beorn7/perks v1.0.1 // indirect + github.com/cenkalti/backoff/v4 v4.2.0 // indirect + github.com/cespare/xxhash/v2 v2.1.2 // indirect github.com/davecgh/go-spew v1.1.1 // indirect - github.com/go-logr/stdr v1.2.0 // indirect + github.com/emicklei/go-restful/v3 v3.9.0 // indirect + github.com/evanphx/json-patch/v5 v5.6.0 // indirect + github.com/fsnotify/fsnotify v1.6.0 // indirect + github.com/go-logr/stdr v1.2.2 // indirect github.com/go-logr/zapr v1.2.3 // indirect github.com/go-ole/go-ole v1.2.6 // indirect + github.com/go-openapi/jsonpointer v0.19.5 // indirect + github.com/go-openapi/jsonreference v0.20.0 // indirect + github.com/go-openapi/swag v0.19.14 // indirect github.com/gogo/protobuf v1.3.2 // indirect + github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/protobuf v1.5.2 // indirect + github.com/google/gnostic v0.5.7-v3refs // indirect + github.com/google/go-cmp v0.5.9 // indirect github.com/google/gofuzz v1.1.0 // indirect + github.com/google/uuid v1.1.2 // indirect github.com/gorilla/websocket v1.4.2 // indirect - github.com/grpc-ecosystem/grpc-gateway v1.16.0 // indirect - github.com/imdario/mergo v0.3.6 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0 // indirect + github.com/imdario/mergo v0.3.12 // indirect + github.com/josharian/intern v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect - github.com/mitchellh/copystructure v1.2.0 // indirect - github.com/mitchellh/mapstructure v1.4.1 // indirect - github.com/mitchellh/reflectwalk v1.0.2 // indirect + github.com/mailru/easyjson v0.7.6 // indirect + github.com/matttproud/golang_protobuf_extensions v1.0.2 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect + github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/stretchr/testify v1.8.0 // indirect + github.com/prometheus/client_golang v1.14.0 // indirect + github.com/prometheus/client_model v0.3.0 // indirect + github.com/prometheus/common v0.37.0 // indirect + github.com/prometheus/procfs v0.8.0 // indirect + github.com/stretchr/testify v1.8.1 // indirect github.com/tklauser/go-sysconf v0.3.11 // indirect github.com/tklauser/numcpus v0.6.0 // indirect github.com/yusufpapurcu/wmi v1.2.2 // indirect - go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.3.0 // indirect - go.opentelemetry.io/otel/internal/metric v0.26.0 // indirect - go.opentelemetry.io/otel/sdk/export/metric v0.26.0 // indirect - go.opentelemetry.io/otel/trace v1.3.0 // indirect - go.opentelemetry.io/proto/otlp v0.11.0 // indirect - go.uber.org/atomic v1.7.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.11.2 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlpmetric v0.34.0 // indirect + go.opentelemetry.io/otel/trace v1.11.2 // indirect + go.opentelemetry.io/proto/otlp v0.19.0 // indirect + go.uber.org/atomic v1.8.0 // indirect go.uber.org/multierr v1.6.0 // indirect go.uber.org/zap v1.24.0 // indirect golang.org/x/net v0.3.1-0.20221206200815-1e63c2f08a10 // indirect @@ -58,13 +74,18 @@ require ( golang.org/x/term v0.3.0 // indirect golang.org/x/text v0.5.0 // indirect golang.org/x/time v0.3.0 // indirect + gomodules.xyz/jsonpatch/v2 v2.2.0 // indirect google.golang.org/appengine v1.6.7 // indirect - google.golang.org/genproto v0.0.0-20200825200019-8632dd797987 // indirect - google.golang.org/grpc v1.42.0 // indirect + google.golang.org/genproto v0.0.0-20220502173005-c8bf987b8c21 // indirect + google.golang.org/grpc v1.51.0 // indirect google.golang.org/protobuf v1.28.1 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect + k8s.io/api v0.26.0 // indirect + k8s.io/apiextensions-apiserver v0.26.0 // indirect k8s.io/apimachinery v0.26.0 // indirect + k8s.io/component-base v0.26.0 // indirect + k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280 // indirect k8s.io/utils v0.0.0-20221128185143-99ec85e7a448 // indirect sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2 // indirect sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect diff --git a/cmd/remote-configuration/go.sum b/cmd/remote-configuration/go.sum index 367eafb203..c9c4d417c6 100644 --- a/cmd/remote-configuration/go.sum +++ b/cmd/remote-configuration/go.sum @@ -33,27 +33,26 @@ cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9 dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= +github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= +github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= -github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= -github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= -github.com/aws/aws-sdk-go-v2 v1.9.2/go.mod h1:cK/D0BBs0b/oWPIcX/Z/obahJK1TT7IPVjy53i/mX/4= -github.com/aws/aws-sdk-go-v2/config v1.8.3/go.mod h1:4AEiLtAb8kLs7vgw2ZV3p2VZ1+hBavOc84hqxVNpCyw= -github.com/aws/aws-sdk-go-v2/credentials v1.4.3/go.mod h1:FNNC6nQZQUuyhq5aE5c7ata8o9e4ECGmS4lAXC7o1mQ= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.6.0/go.mod h1:gqlclDEZp4aqJOancXK6TN24aKhT0W0Ae9MHk3wzTMM= -github.com/aws/aws-sdk-go-v2/internal/ini v1.2.4/go.mod h1:ZcBrrI3zBKlhGFNYWvju0I3TR93I7YIgAfy82Fh4lcQ= -github.com/aws/aws-sdk-go-v2/service/appconfig v1.4.2/go.mod h1:FZ3HkCe+b10uFZZkFdvf98LHW21k49W8o8J366lqVKY= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.3.2/go.mod h1:72HRZDLMtmVQiLG2tLfQcaWLCssELvGl+Zf2WVxMmR8= -github.com/aws/aws-sdk-go-v2/service/sso v1.4.2/go.mod h1:NBvT9R1MEF+Ud6ApJKM0G+IkPchKS7p7c2YPKwHmBOk= -github.com/aws/aws-sdk-go-v2/service/sts v1.7.2/go.mod h1:8EzeIqfWt2wWT4rJVu3f21TfrhJ8AEMzVybRNSb/b4g= -github.com/aws/smithy-go v1.8.0/go.mod h1:SObp3lf9smib00L/v3U2eAKG8FyQ7iLrJnQiAmR5n+E= +github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= -github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT8A= -github.com/benbjohnson/clock v1.3.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= -github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= -github.com/cenkalti/backoff/v4 v4.1.2 h1:6Yo7N8UP2K6LWZnW94DLVSSrbobcWdVzAYOisuDPIFo= -github.com/cenkalti/backoff/v4 v4.1.2/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= +github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= +github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= +github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/cenkalti/backoff/v4 v4.2.0 h1:HN5dHm3WBOgndBH6E8V0q2jIYIR3s9yglV8k/+MN3u4= +github.com/cenkalti/backoff/v4 v4.2.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE= +github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= @@ -61,49 +60,74 @@ github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDk github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= +github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= github.com/emicklei/go-restful/v3 v3.9.0 h1:XwGDlfxEnQZzuopoqxwSEllNcCOM9DhhFyhFIIGKwxE= +github.com/emicklei/go-restful/v3 v3.9.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= +github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= -github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= -github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= +github.com/evanphx/json-patch v0.5.2/go.mod h1:ZWS5hhDbVDyob71nXKNL0+PWn6ToqBHMikGIFbs31qQ= +github.com/evanphx/json-patch v4.12.0+incompatible h1:4onqiflcdA9EOZ4RxV643DvftH5pOlLGNtQ5lPWQu84= +github.com/evanphx/json-patch/v5 v5.6.0 h1:b91NhWfaz02IuVxO9faSllyAtNXHMPkC5J8sJCLunww= +github.com/evanphx/json-patch/v5 v5.6.0/go.mod h1:G79N1coSVB93tBe7j6PhzjmR3/2VvlbKOFpnXhI9Bw4= github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= +github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-ldap/ldap v3.0.2+incompatible/go.mod h1:qfd9rJvER9Q0/D/Sqn1DfHRoBp40uXYvFoEVrNEPqRc= +github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= +github.com/go-kit/log v0.2.0/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= +github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= +github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= +github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= +github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.2.1/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0= github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/stdr v1.2.0 h1:j4LrlVXgrbIWO83mmQUnK0Hi+YnbD+vzrE1z/EphbFE= -github.com/go-logr/stdr v1.2.0/go.mod h1:YkVgnZu1ZjjL7xTxrfm/LLZBfkhTqSR1ydtm6jTKKwI= +github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-logr/zapr v1.2.3 h1:a9vnzlIBPQBBkeaR9IuMUfmVOrQlkoC4YfPoFkX3T7A= github.com/go-logr/zapr v1.2.3/go.mod h1:eIauM6P8qSvTw5o2ez6UEAfGjQKrxQTl5EoK+Qa2oG4= github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= +github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= github.com/go-openapi/jsonpointer v0.19.5 h1:gZr+CIYByUqjcgeLXnQu2gHYQC9o73G2XUeOFYEICuY= +github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= github.com/go-openapi/jsonreference v0.20.0 h1:MYlu0sBgChmCfJxxUKZ8g1cPWFOB37YSZqewK7OKeyA= +github.com/go-openapi/jsonreference v0.20.0/go.mod h1:Ag74Ico3lPc+zR+qjn4XBUmXymS4zJbYVCZmcgkasdo= +github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= github.com/go-openapi/swag v0.19.14 h1:gm3vOOXfiuw5i9p5N9xJvfjvuofpyvLA9Wr6QfK5Fng= -github.com/go-test/deep v1.0.2-0.20181118220953-042da051cf31/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= +github.com/go-openapi/swag v0.19.14/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= +github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/glog v1.0.0 h1:nfP3RFugxnNRyKgeWd4oI1nYvXpxrx8ck8ZrcizshdQ= +github.com/golang/glog v1.0.0/go.mod h1:EWib/APOK0SL3dFbYqvxE3UYd8E6s1ouQ7iEp/0LWV4= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= @@ -128,10 +152,10 @@ github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/gnostic v0.5.7-v3refs h1:FhTMOKj2VhjpouxvWJAV1TL304uMlb9zcDqkl6cEI54= +github.com/google/gnostic v0.5.7-v3refs/go.mod h1:73MKFl6jIHelAJNaBGFzt3SPtZULs9dYrGFt8OiIsHQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= @@ -143,6 +167,7 @@ github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.1.0 h1:Hsa8mG0dQ46ij8Sl2AYJDUv1oA9/d6Vk+3LG99Oe02g= github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= @@ -156,120 +181,130 @@ github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hf github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= -github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= -github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= -github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= -github.com/hashicorp/go-hclog v0.0.0-20180709165350-ff2cf002a8dd/go.mod h1:9bjs9uLqI8l75knNv3lV1kA55veR+WUPSiKIWcQHudI= -github.com/hashicorp/go-hclog v0.8.0/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ= -github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= -github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= -github.com/hashicorp/go-plugin v1.0.1/go.mod h1:++UyYGoz3o5w9ZzAdZxtQKrWWP+iqPBn3cQptSMzBuY= -github.com/hashicorp/go-retryablehttp v0.5.4/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs= -github.com/hashicorp/go-rootcerts v1.0.1/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8= -github.com/hashicorp/go-sockaddr v1.0.2/go.mod h1:rB4wwRAUzs07qva3c5SdrY/NEtAUjGlgmH/UkBUC97A= -github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= -github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= -github.com/hashicorp/go-version v1.1.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0 h1:BZHcxBETFHIdVyhyEfOvn/RdU/QGdLI4y34qQGjGWO0= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0/go.mod h1:hgWBS7lorOAVIJEQMi4ZsPv9hVvWI6+ch50m39Pf2Ks= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= -github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= -github.com/hashicorp/vault/api v1.0.4/go.mod h1:gDcqh3WGcR1cpF5AJz/B1UFheUEneMoIospckxBxk6Q= -github.com/hashicorp/vault/sdk v0.1.13/go.mod h1:B+hVj7TpuQY1Y/GPbCpffmgd+tSEwvhkWnjtSYCaS2M= -github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM= -github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/imdario/mergo v0.3.6 h1:xTNEAn+kxVO7dTZGu0CegyqKZmoWFI0rF8UxjlB2d28= -github.com/imdario/mergo v0.3.6/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= -github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= -github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= -github.com/joho/godotenv v1.3.0 h1:Zjp+RcGpHhGlrMbJzXTrZZPrWj+1vfm90La1wgB6Bhc= -github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg= +github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU= +github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= +github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= +github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= +github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= +github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= +github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= +github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/knadh/koanf v1.3.3 h1:eNtBOzQDzkzIIPRCJCx/Ha3DeD/ZFwCAp8JxyqoVAls= -github.com/knadh/koanf v1.3.3/go.mod h1:1cfH5223ZeZUOs8FU2UdTmaNfHpqgtjV0+NHjRO43gs= +github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.7.6 h1:8yTIVnZgCoiM1TgqoeTl+LfU5Jg6/xL3QhGQnimLYnA= -github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= -github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= -github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= -github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw= -github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= -github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= -github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -github.com/mitchellh/go-testing-interface v0.0.0-20171004221916-a61a99592b77/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= -github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= -github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo= -github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/mitchellh/mapstructure v1.4.1 h1:CpVNEelQCZBooIPDn+AR3NpivK/TIKU8bDxdASFVQag= -github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= -github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= -github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= -github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= +github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= +github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/matttproud/golang_protobuf_extensions v1.0.2 h1:hAHbPm5IJGijwng3PWk09JkG9WeqChjprR5s9bBZ+OM= +github.com/matttproud/golang_protobuf_extensions v1.0.2/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= +github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= -github.com/npillmayer/nestext v0.1.3/go.mod h1:h2lrijH8jpicr25dFY+oAJLyzlya6jhnuG+zWp9L0Uk= -github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/oklog/ulid/v2 v2.0.2 h1:r4fFzBm+bv0wNKNh5eXTwU7i85y5x+uwkxCUTNVQqLc= github.com/oklog/ulid/v2 v2.0.2/go.mod h1:mtBL0Qe/0HAx6/a4Z30qxVIAL1eQDweXq5lxOEiwQ68= github.com/onsi/ginkgo/v2 v2.6.0 h1:9t9b9vRUbFq3C4qKFCGkVuq/fIHji802N1nrtkh1mNc= github.com/onsi/gomega v1.24.1 h1:KORJXNNTzJXzu4ScJWssJfJMnJ+2QJqhoQSRwNlze9E= -github.com/open-telemetry/opamp-go v0.1.0 h1:VEeGUZG54X1P6Sabl4Q61yClDmVuDfo/Xsmh/SEFPoo= -github.com/open-telemetry/opamp-go v0.1.0/go.mod h1:IMdeuHGVc5CjKSu5/oNV0o+UmiXuahoHvoZ4GOmAI9M= github.com/open-telemetry/opamp-go v0.5.0 h1:2YFbb6G4qBkq3yTRdVb5Nfz9hKHW/ldUyex352e1J7g= github.com/open-telemetry/opamp-go v0.5.0/go.mod h1:IMdeuHGVc5CjKSu5/oNV0o+UmiXuahoHvoZ4GOmAI9M= -github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= +github.com/open-telemetry/opentelemetry-operator v1.51.0 h1:mf6E24jBnv0JvxUH2nOujiqShwA7kJcCFbhd2vdMyQQ= +github.com/open-telemetry/opentelemetry-operator v1.51.0/go.mod h1:2oXRmTlK6/4gc+ipK94KKHEEf6h3PWh2NiG3doAQnwo= github.com/pborman/getopt v0.0.0-20170112200414-7148bc3a4c30/go.mod h1:85jBQOZwpVEaDAr341tbn15RS4fCAsIst0qp7i8ex1o= -github.com/pelletier/go-toml v1.7.0 h1:7utD74fnzVc/cpcyy8sjrlFr5vYpypUixARcHIMIGuI= -github.com/pelletier/go-toml v1.7.0/go.mod h1:vwGMzjaWMwyfHwgIBhI2YUM4fB6nL6lVAvS1LBMMhTE= -github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= +github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= +github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= +github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= +github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= +github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= +github.com/prometheus/client_golang v1.14.0 h1:nJdhIvne2eSX/XRAFV9PcvFFRbrjbcTUj0VP62TMhnw= +github.com/prometheus/client_golang v1.14.0/go.mod h1:8vpkKitgIVNcqrRBWh1C4TIUQgYNtG/XQE4E/Zae36Y= +github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/rhnvrm/simples3 v0.6.1/go.mod h1:Y+3vYm2V7Y4VijFoJHHTrja6OgPrJ2cBti8dPGkC3sA= +github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.3.0 h1:UBgGFHqYdG/TPFD1B1ogZywDqEkwp3fBMvqdiQ7Xew4= +github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w= +github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= +github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= +github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= +github.com/prometheus/common v0.37.0 h1:ccBbHCgIiT9uSoFY0vX8H3zsNR5eLt17/RQLUvn8pXE= +github.com/prometheus/common v0.37.0/go.mod h1:phzohg0JFMnBEFGxTDbfu3QyL5GI8gTQJFhYO5B3mfA= +github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= +github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= +github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= +github.com/prometheus/procfs v0.8.0 h1:ODq8ZFEaYeCaZOJlZZdJA2AbQR98dSHSM1KW/You5mo= +github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= -github.com/ryanuber/go-glob v1.0.0/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc= github.com/shirou/gopsutil v3.21.11+incompatible h1:+1+c1VGhc88SSonWP6foOcLhvnKlUeu/erjjvaPEYiI= github.com/shirou/gopsutil v3.21.11+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= +github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= +github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= +github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= +github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/tklauser/go-sysconf v0.3.11 h1:89WgdJhk5SNwJfu+GKyYveZ4IaJ7xAkecBo+KdJV0CM= github.com/tklauser/go-sysconf v0.3.11/go.mod h1:GqXfhXY3kiPa0nAXPDIQIWzJbMCB7AmcWpGR8lSZfqI= github.com/tklauser/numcpus v0.6.0 h1:kebhY2Qt+3U6RNK7UqpYNA+tJ23IBEGKkB7JQBfDYms= @@ -285,31 +320,28 @@ go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opentelemetry.io/otel v1.3.0 h1:APxLf0eiBwLl+SOXiJJCVYzA1OOJNyAoV8C5RNRyy7Y= -go.opentelemetry.io/otel v1.3.0/go.mod h1:PWIKzi6JCp7sM0k9yZ43VX+T345uNbAkDKwHVjb2PTs= -go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.3.0 h1:R/OBkMoGgfy2fLhs2QhkCI1w4HLEQX92GCcJB6SSdNk= -go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.3.0/go.mod h1:VpP4/RMn8bv8gNo9uK7/IMY4mtWLELsS+JIP0inH0h4= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric v0.26.0 h1:dIE9swzwOnkGaJ6OF1QQQdBk2EdrJnD9Ilao2G9DeLU= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric v0.26.0/go.mod h1:1E0NE+3ywwedkOEl3d7nFjyI/bqRECMhI3xTGh13pxY= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v0.26.0 h1:B4KUKYd6VEiqKh0kHf4+RZOhY/kANSvGydrQdE1dNkY= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v0.26.0/go.mod h1:CaqVOcEDDQ1XY7zEJT81c8aUNPju3jRqjva6ROUi+z0= -go.opentelemetry.io/otel/internal/metric v0.26.0 h1:dlrvawyd/A+X8Jp0EBT4wWEe4k5avYaXsXrBr4dbfnY= -go.opentelemetry.io/otel/internal/metric v0.26.0/go.mod h1:CbBP6AxKynRs3QCbhklyLUtpfzbqCLiafV9oY2Zj1Jk= -go.opentelemetry.io/otel/metric v0.26.0 h1:VaPYBTvA13h/FsiWfxa3yZnZEm15BhStD8JZQSA773M= -go.opentelemetry.io/otel/metric v0.26.0/go.mod h1:c6YL0fhRo4YVoNs6GoByzUgBp36hBL523rECoZA5UWg= -go.opentelemetry.io/otel/sdk v1.3.0 h1:3278edCoH89MEJ0Ky8WQXVmDQv3FX4ZJ3Pp+9fJreAI= -go.opentelemetry.io/otel/sdk v1.3.0/go.mod h1:rIo4suHNhQwBIPg9axF8V9CA72Wz2mKF1teNrup8yzs= -go.opentelemetry.io/otel/sdk/export/metric v0.26.0 h1:eNseg5yyZqaAAY+Att3owR3Bl0Is5rCZywqO1OrGx18= -go.opentelemetry.io/otel/sdk/export/metric v0.26.0/go.mod h1:UpqzSnUOjFeSIVQLPp3pYIXfB/MiMFyXXzYT/bercxQ= -go.opentelemetry.io/otel/sdk/metric v0.26.0 h1:7IKp3gc/ObieCtshBeYYVFp3ZP7xIH1OzODi1Wao90Y= -go.opentelemetry.io/otel/sdk/metric v0.26.0/go.mod h1:2VIeK0kS1YvRLFg3J58ptZTXYpiWlkq2n5RQt6w7He8= -go.opentelemetry.io/otel/trace v1.3.0 h1:doy8Hzb1RJ+I3yFhtDmwNc7tIyw1tNMOIsyPzp1NOGY= -go.opentelemetry.io/otel/trace v1.3.0/go.mod h1:c/VDhno8888bvQYmbYLqe41/Ldmr/KKunbvWM4/fEjk= +go.opentelemetry.io/otel v1.11.2 h1:YBZcQlsVekzFsFbjygXMOXSs6pialIZxcjfO/mBDmR0= +go.opentelemetry.io/otel v1.11.2/go.mod h1:7p4EUV+AqgdlNV9gL97IgUZiVR3yrFXYo53f9BM3tRI= +go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.11.2 h1:htgM8vZIF8oPSCxa341e3IZ4yr/sKxgu8KZYllByiVY= +go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.11.2/go.mod h1:rqbht/LlhVBgn5+k3M5QK96K5Xb0DvXpMJ5SFQpY6uw= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric v0.34.0 h1:kpskzLZ60cJ48SJ4uxWa6waBL+4kSV6nVK8rP+QM8Wg= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric v0.34.0/go.mod h1:4+x3i62TEegDHuzNva0bMcAN8oUi5w4liGb1d/VgPYo= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v0.34.0 h1:t4Ajxj8JGjxkqoBtbkCOY2cDUl9RwiNE9LPQavooi9U= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v0.34.0/go.mod h1:WO7omosl4P7JoanH9NgInxDxEn2F2M5YinIh8EyeT8w= +go.opentelemetry.io/otel/metric v0.34.0 h1:MCPoQxcg/26EuuJwpYN1mZTeCYAUGx8ABxfW07YkjP8= +go.opentelemetry.io/otel/metric v0.34.0/go.mod h1:ZFuI4yQGNCupurTXCwkeD/zHBt+C2bR7bw5JqUm/AP8= +go.opentelemetry.io/otel/sdk v1.11.2 h1:GF4JoaEx7iihdMFu30sOyRx52HDHOkl9xQ8SMqNXUiU= +go.opentelemetry.io/otel/sdk v1.11.2/go.mod h1:wZ1WxImwpq+lVRo4vsmSOxdd+xwoUJ6rqyLc3SyX9aU= +go.opentelemetry.io/otel/sdk/metric v0.34.0 h1:7ElxfQpXCFZlRTvVRTkcUvK8Gt5DC8QzmzsLsO2gdzo= +go.opentelemetry.io/otel/sdk/metric v0.34.0/go.mod h1:l4r16BIqiqPy5rd14kkxllPy/fOI4tWo1jkpD9Z3ffQ= +go.opentelemetry.io/otel/trace v1.11.2 h1:Xf7hWSF2Glv0DE3MH7fBHvtpSBsjcBUe5MYAmZM/+y0= +go.opentelemetry.io/otel/trace v1.11.2/go.mod h1:4N+yC7QEz7TTsG9BSRLNAa63eg5E06ObSbKPmxQ/pKA= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= -go.opentelemetry.io/proto/otlp v0.11.0 h1:cLDgIBTf4lLOlztkhzAEdQsJ4Lj+i5Wc9k6Nn0K1VyU= -go.opentelemetry.io/proto/otlp v0.11.0/go.mod h1:QpEjXPrNQzrFDZgoTo49dgHR9RYRSrg3NAKnUGl9YpQ= -go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw= +go.opentelemetry.io/proto/otlp v0.19.0 h1:IVN6GR+mhC4s5yfcTbmzHYODqvWAp3ZedA2SJPI1Nnw= +go.opentelemetry.io/proto/otlp v0.19.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/atomic v1.8.0 h1:CUhrE4N1rqSE6FM9ecihEjRkLQu8cDfgDyoOs83mEY4= +go.uber.org/atomic v1.8.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk= go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4= @@ -317,6 +349,7 @@ go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9i go.uber.org/zap v1.19.0/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI= go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60= go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg= +golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= @@ -354,6 +387,7 @@ golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= @@ -361,6 +395,7 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -379,7 +414,10 @@ golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81R golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= +golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.3.1-0.20221206200815-1e63c2f08a10 h1:Frnccbp+ok2GkUS2tC84yAq/U9Vg+0sIO7aRL3T4Xnc= golang.org/x/net v0.3.1-0.20221206200815-1e63c2f08a10/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -387,6 +425,8 @@ golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4Iltr golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b h1:clP8eMhB30EHdc0bd2Twtq6kgU7yl5ub2cQLSdrv1Dg= golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -398,13 +438,14 @@ golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190129075346-302c3dd5f1cc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -412,9 +453,9 @@ golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -427,23 +468,35 @@ golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.3.0 h1:w8ZOecv6NaNa/zC8944JTU3vz4u6Lagfk4RPQxv92NQ= golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.3.0 h1:qoo4akIqOcDME5bhc/NgxUdovd6BSS2uMsVjB56q1xI= golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.1-0.20181227161524-e6919f6577db/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.5.0 h1:OLmvp0KP+FVG99Ct/qFiL/Fhk4zp4QQnZ7b2U+5piUM= golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= @@ -499,6 +552,8 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +gomodules.xyz/jsonpatch/v2 v2.2.0 h1:4pT439QV83L+G9FkcCriY6EkpcK6r6bK+A5FBUMI7qY= +gomodules.xyz/jsonpatch/v2 v2.2.0/go.mod h1:WXp+iVDkoLQqPudfQ9GBlwB2eZ5DKOnjQZCYdOS8GPY= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= @@ -525,7 +580,6 @@ google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6 google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190404172233-64821d5d2107/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= @@ -553,13 +607,14 @@ google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEY google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200825200019-8632dd797987 h1:PDIOdWxZ8eRizhKa1AAvY53xsvLB1cWorMjslvY3VA8= google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= +google.golang.org/genproto v0.0.0-20201019141844-1ed22bb0c154/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20220502173005-c8bf987b8c21 h1:hrbNEivu7Zn1pxvHk6MBrq9iE22woVILTHqexqBxe6I= +google.golang.org/genproto v0.0.0-20220502173005-c8bf987b8c21/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= -google.golang.org/grpc v1.22.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= @@ -571,8 +626,11 @@ google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.42.0 h1:XT2/MFpuPFsEX2fWh3YQtHkZ+WYZFQRfaUgLZYj/p6A= +google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= +google.golang.org/grpc v1.46.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= +google.golang.org/grpc v1.51.0 h1:E1eGv1FTqoLIdnBCZufiSHgKjlqG6fKFf6pPWtMTh8U= +google.golang.org/grpc v1.51.0/go.mod h1:wgNDFcnuBGmxLKI/qn4T+m5BtEBYXJPvibbUPsAIPww= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -586,22 +644,29 @@ google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlba google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w= google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d/go.mod h1:cuepJuh7vyXfUyUwEgHQXw849cJrilpS5NeIjOWESAw= +gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU= +gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= -gopkg.in/square/go-jose.v2 v2.3.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= +gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= @@ -613,13 +678,19 @@ honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= k8s.io/api v0.26.0 h1:IpPlZnxBpV1xl7TGk/X6lFtpgjgntCg8PJ+qrPHAC7I= +k8s.io/api v0.26.0/go.mod h1:k6HDTaIFC8yn1i6pSClSqIwLABIcLV9l5Q4EcngKnQg= +k8s.io/apiextensions-apiserver v0.26.0 h1:Gy93Xo1eg2ZIkNX/8vy5xviVSxwQulsnUdQ00nEdpDo= +k8s.io/apiextensions-apiserver v0.26.0/go.mod h1:7ez0LTiyW5nq3vADtK6C3kMESxadD51Bh6uz3JOlqWQ= k8s.io/apimachinery v0.26.0 h1:1feANjElT7MvPqp0JT6F3Ss6TWDwmcjLypwoPpEf7zg= k8s.io/apimachinery v0.26.0/go.mod h1:tnPmbONNJ7ByJNz9+n9kMjNP8ON+1qoAIIC70lztu74= k8s.io/client-go v0.26.0 h1:lT1D3OfO+wIi9UFolCrifbjUUgu7CpLca0AD8ghRLI8= k8s.io/client-go v0.26.0/go.mod h1:I2Sh57A79EQsDmn7F7ASpmru1cceh3ocVT9KlX2jEZg= +k8s.io/component-base v0.26.0 h1:0IkChOCohtDHttmKuz+EP3j3+qKmV55rM9gIFTXA7Vs= +k8s.io/component-base v0.26.0/go.mod h1:lqHwlfV1/haa14F/Z5Zizk5QmzaVf23nQzCwVOQpfC8= k8s.io/klog/v2 v2.80.1 h1:atnLQ121W371wYYFawwYx1aEY2eUfs4l3J72wtgAwV4= k8s.io/klog/v2 v2.80.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280 h1:+70TFaan3hfJzs+7VK2o+OGxg8HsuBr/5f6tVAjDu6E= +k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280/go.mod h1:+Axhij7bCpeqhklhUTe3xmOn6bWxolyZEeyaFpjGtl4= k8s.io/utils v0.0.0-20221128185143-99ec85e7a448 h1:KTgPnR10d5zhztWptI952TNtt/4u5h3IzDXkdIMuo2Y= k8s.io/utils v0.0.0-20221128185143-99ec85e7a448/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= diff --git a/cmd/remote-configuration/main.go b/cmd/remote-configuration/main.go index 03b795d92e..57b2d179a4 100644 --- a/cmd/remote-configuration/main.go +++ b/cmd/remote-configuration/main.go @@ -1,10 +1,12 @@ package main import ( - "github.com/open-telemetry/opentelemetry-operator/cmd/remote-configuration/agent" - "github.com/open-telemetry/opentelemetry-operator/cmd/remote-configuration/config" + "github.com/open-telemetry/opentelemetry-operator/cmd/remote-configuration/operator" "os" "os/signal" + + "github.com/open-telemetry/opentelemetry-operator/cmd/remote-configuration/agent" + "github.com/open-telemetry/opentelemetry-operator/cmd/remote-configuration/config" ) func main() { @@ -20,7 +22,11 @@ func main() { cliConf.RootLogger.Info("Starting the Remote Configuration service") agentLogger := cliConf.RootLogger.WithName("agent") - opampAgent := agent.NewAgent(agent.NewLogger(&agentLogger), cfg, *cliConf.AgentType, *cliConf.AgentVersion) + operatorClient, operatorClientErr := operator.NewClient(cliConf.RootLogger.WithName("operator-client"), cliConf.ClusterConfig) + if operatorClientErr != nil { + cliConf.RootLogger.Error(operatorClientErr, "Couldn't create operator client") + } + opampAgent := agent.NewAgent(agent.NewLogger(&agentLogger), operatorClient, cfg, *cliConf.AgentType, *cliConf.AgentVersion) if err := opampAgent.Start(); err != nil { cliConf.RootLogger.Error(err, "Cannot start OpAMP client") diff --git a/cmd/remote-configuration/operator/client.go b/cmd/remote-configuration/operator/client.go new file mode 100644 index 0000000000..8bd198d311 --- /dev/null +++ b/cmd/remote-configuration/operator/client.go @@ -0,0 +1,146 @@ +package operator + +import ( + "context" + "github.com/go-logr/logr" + "github.com/open-telemetry/opamp-go/protobufs" + "gopkg.in/yaml.v3" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/client-go/kubernetes/scheme" + "k8s.io/client-go/rest" + "sigs.k8s.io/controller-runtime/pkg/client" + + "github.com/open-telemetry/opentelemetry-operator/apis/v1alpha1" +) + +const ( + CollectorResource = "OpenTelemetryCollector" +) + +var ( + schemeBuilder = runtime.NewSchemeBuilder(registerKnownTypes) +) + +func registerKnownTypes(s *runtime.Scheme) error { + s.AddKnownTypes(v1alpha1.GroupVersion, &v1alpha1.OpenTelemetryCollector{}, &v1alpha1.OpenTelemetryCollectorList{}) + metav1.AddToGroupVersion(s, v1alpha1.GroupVersion) + return nil +} + +type ConfigApplier interface { + Apply(name string, namespace string, configmap *protobufs.AgentConfigFile) error + GetInstance(name string, namespace string) (*v1alpha1.OpenTelemetryCollector, error) + ListInstances() ([]v1alpha1.OpenTelemetryCollector, error) +} + +type Client struct { + log logr.Logger + k8sClient client.Client + close chan bool +} + +var _ ConfigApplier = &Client{} + +func NewClient(log logr.Logger, kubeConfig *rest.Config) (*Client, error) { + err := schemeBuilder.AddToScheme(scheme.Scheme) + if err != nil { + return nil, err + } + c, err := client.New(kubeConfig, client.Options{ + Scheme: scheme.Scheme, + }) + if err != nil { + return nil, err + } + return &Client{ + log: log, + k8sClient: c, + close: make(chan bool, 1), + }, nil +} + +func (c Client) create(ctx context.Context, name string, namespace string, collector v1alpha1.OpenTelemetryCollector) error { + // Set the defaults + collector.Default() + collector.TypeMeta.Kind = CollectorResource + collector.TypeMeta.APIVersion = v1alpha1.GroupVersion.String() + collector.ObjectMeta.Name = name + collector.ObjectMeta.Namespace = namespace + + if collector.ObjectMeta.Annotations == nil { + collector.ObjectMeta.Annotations = map[string]string{} + } + collector.ObjectMeta.Annotations["created-by"] = "remote-configuration" + err := collector.ValidateCreate() + if err != nil { + return err + } + c.log.Info("Was given a valid configuration", "collector", collector) + err = c.k8sClient.Create(ctx, &collector) + if err != nil { + c.log.Error(err, "unable to create collector") + return err + } + return nil +} + +func (c Client) Apply(name string, namespace string, configmap *protobufs.AgentConfigFile) error { + c.log.Info("Received new config", name, len(configmap.String())) + var collectorSpec v1alpha1.OpenTelemetryCollectorSpec + err := yaml.Unmarshal(configmap.Body, &collectorSpec) + if err != nil { + return err + } + collector := v1alpha1.OpenTelemetryCollector{Spec: collectorSpec} + ctx := context.Background() + //created := false + instance, err := c.GetInstance(name, namespace) + if err != nil { + return err + } + if instance != nil { + collector.ObjectMeta = instance.ObjectMeta + collector.TypeMeta = instance.TypeMeta + err := collector.ValidateUpdate(instance) + if err != nil { + return err + } + err = c.k8sClient.Update(ctx, &collector) + if err != nil { + return err + } + c.log.Info("Updated collector") + return nil + } + + err = c.create(ctx, name, namespace, collector) + if err != nil { + return err + } + c.log.Info("Created collector") + return nil +} + +func (c Client) ListInstances() ([]v1alpha1.OpenTelemetryCollector, error) { + ctx := context.Background() + result := v1alpha1.OpenTelemetryCollectorList{} + err := c.k8sClient.List(ctx, &result) + if err != nil { + return nil, err + } + return result.Items, nil +} + +func (c Client) GetInstance(name string, namespace string) (*v1alpha1.OpenTelemetryCollector, error) { + ctx := context.Background() + result := v1alpha1.OpenTelemetryCollector{} + err := c.k8sClient.Get(ctx, client.ObjectKey{ + Namespace: namespace, + Name: name, + }, &result) + if err != nil { + return nil, err + } + return &result, nil +} From c5ab004772809851831bf53dc2c719fd159f75e1 Mon Sep 17 00:00:00 2001 From: Jacob Aronoff Date: Wed, 21 Dec 2022 11:33:21 -0500 Subject: [PATCH 03/16] Fix create bug, getting prepped for refactor --- cmd/remote-configuration/operator/client.go | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/cmd/remote-configuration/operator/client.go b/cmd/remote-configuration/operator/client.go index 8bd198d311..61bb6c7cc0 100644 --- a/cmd/remote-configuration/operator/client.go +++ b/cmd/remote-configuration/operator/client.go @@ -5,6 +5,7 @@ import ( "github.com/go-logr/logr" "github.com/open-telemetry/opamp-go/protobufs" "gopkg.in/yaml.v3" + "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/client-go/kubernetes/scheme" @@ -15,7 +16,9 @@ import ( ) const ( - CollectorResource = "OpenTelemetryCollector" + CollectorResource = "OpenTelemetryCollector" + ResourceIdentifierKey = "created-by" + ResourceIdentifierValue = "remote-configuration" ) var ( @@ -68,10 +71,10 @@ func (c Client) create(ctx context.Context, name string, namespace string, colle collector.ObjectMeta.Name = name collector.ObjectMeta.Namespace = namespace - if collector.ObjectMeta.Annotations == nil { - collector.ObjectMeta.Annotations = map[string]string{} + if collector.ObjectMeta.Labels == nil { + collector.ObjectMeta.Labels = map[string]string{} } - collector.ObjectMeta.Annotations["created-by"] = "remote-configuration" + collector.ObjectMeta.Labels[ResourceIdentifierKey] = ResourceIdentifierValue err := collector.ValidateCreate() if err != nil { return err @@ -125,7 +128,9 @@ func (c Client) Apply(name string, namespace string, configmap *protobufs.AgentC func (c Client) ListInstances() ([]v1alpha1.OpenTelemetryCollector, error) { ctx := context.Background() result := v1alpha1.OpenTelemetryCollectorList{} - err := c.k8sClient.List(ctx, &result) + err := c.k8sClient.List(ctx, &result, client.MatchingLabels{ + ResourceIdentifierKey: ResourceIdentifierValue, + }) if err != nil { return nil, err } @@ -139,6 +144,9 @@ func (c Client) GetInstance(name string, namespace string) (*v1alpha1.OpenTeleme Namespace: namespace, Name: name, }, &result) + if errors.IsNotFound(err) { + return nil, nil + } if err != nil { return nil, err } From 8839e94bb1bb082e92eaec3d108ddb060e65276e Mon Sep 17 00:00:00 2001 From: Jacob Aronoff Date: Wed, 21 Dec 2022 18:35:24 -0500 Subject: [PATCH 04/16] Some reorganization and cleaning, added tests --- cmd/remote-configuration/agent/agent.go | 236 +++------- cmd/remote-configuration/agent/agent_test.go | 425 ++++++++++++++++++ .../agent/testdata/agent.yaml | 17 + .../agent/testdata/basic.yaml | 24 + .../agent/testdata/invalid.yaml | 24 + .../agent/testdata/updated.yaml | 25 ++ cmd/remote-configuration/config/cli.go | 80 ++++ cmd/remote-configuration/config/config.go | 108 +++-- cmd/remote-configuration/go.mod | 9 +- cmd/remote-configuration/go.sum | 1 + .../{agent => logger}/logger.go | 2 +- cmd/remote-configuration/main.go | 16 +- .../metricreporter.go => metrics/reporter.go} | 2 +- cmd/remote-configuration/operator/client.go | 73 +-- .../operator/client_test.go | 149 ++++++ .../operator/testdata/collector.yaml | 24 + .../operator/testdata/invalid-collector.yaml | 24 + .../operator/testdata/updated-collector.yaml | 24 + 18 files changed, 979 insertions(+), 284 deletions(-) create mode 100644 cmd/remote-configuration/agent/agent_test.go create mode 100644 cmd/remote-configuration/agent/testdata/agent.yaml create mode 100644 cmd/remote-configuration/agent/testdata/basic.yaml create mode 100644 cmd/remote-configuration/agent/testdata/invalid.yaml create mode 100644 cmd/remote-configuration/agent/testdata/updated.yaml create mode 100644 cmd/remote-configuration/config/cli.go rename cmd/remote-configuration/{agent => logger}/logger.go (96%) rename cmd/remote-configuration/{agent/metricreporter.go => metrics/reporter.go} (99%) create mode 100644 cmd/remote-configuration/operator/client_test.go create mode 100644 cmd/remote-configuration/operator/testdata/collector.yaml create mode 100644 cmd/remote-configuration/operator/testdata/invalid-collector.yaml create mode 100644 cmd/remote-configuration/operator/testdata/updated-collector.yaml diff --git a/cmd/remote-configuration/agent/agent.go b/cmd/remote-configuration/agent/agent.go index 607ef5a687..2cfd4b4333 100644 --- a/cmd/remote-configuration/agent/agent.go +++ b/cmd/remote-configuration/agent/agent.go @@ -5,11 +5,9 @@ import ( "context" "errors" "fmt" + "github.com/open-telemetry/opentelemetry-operator/cmd/remote-configuration/metrics" "github.com/open-telemetry/opentelemetry-operator/cmd/remote-configuration/operator" "gopkg.in/yaml.v3" - "math/rand" - "os" - "runtime" "strings" "time" @@ -23,74 +21,41 @@ import ( "github.com/open-telemetry/opamp-go/protobufs" ) -const localConfig = ` -exporters: - otlp: - endpoint: localhost:1111 - -receivers: - otlp: - protocols: - grpc: {} - http: {} - -service: - pipelines: - traces: - receivers: [otlp] - processors: [] - exporters: [otlp] -` - type Agent struct { logger types.Logger - agentType string - agentVersion string - // A set of the applied object keys (name/namespace) appliedKeys map[string]bool startTime uint64 + lastHash []byte - instanceId ulid.ULID - - agentDescription *protobufs.AgentDescription - - opampClient client.OpAMPClient - + instanceId ulid.ULID + agentDescription *protobufs.AgentDescription remoteConfigStatus *protobufs.RemoteConfigStatus - metricReporter *MetricReporter + opampClient client.OpAMPClient + metricReporter *metrics.MetricReporter config config.Config applier operator.ConfigApplier - lastHash []byte } -func NewAgent(logger types.Logger, applier operator.ConfigApplier, config config.Config, agentType string, agentVersion string) *Agent { +func NewAgent(logger types.Logger, applier operator.ConfigApplier, config config.Config, opampClient client.OpAMPClient) *Agent { agent := &Agent{ - config: config, - applier: applier, - logger: logger, - agentType: agentType, - agentVersion: agentVersion, - appliedKeys: map[string]bool{}, + config: config, + applier: applier, + logger: logger, + appliedKeys: map[string]bool{}, + instanceId: config.GetNewInstanceId(), + agentDescription: config.GetDescription(), + opampClient: opampClient, } - agent.createAgentIdentity() agent.logger.Debugf("Agent starting, id=%v, type=%s, version=%s.", - agent.instanceId.String(), agentType, agentVersion) - agent.opampClient = agent.createClient() + agent.instanceId.String(), config.GetAgentType(), config.GetAgentVersion()) return agent } -func (agent *Agent) createClient() client.OpAMPClient { - if agent.config.Protocol == "http" { - return client.NewHTTP(agent.logger) - } - return client.NewWebSocket(agent.logger) -} - func (agent *Agent) getHealth() *protobufs.AgentHealth { return &protobufs.AgentHealth{ Healthy: true, @@ -99,29 +64,34 @@ func (agent *Agent) getHealth() *protobufs.AgentHealth { } } +func (agent *Agent) onConnect() { + agent.logger.Debugf("Connected to the server.") +} + +func (agent *Agent) onConnectFailed(err error) { + agent.logger.Errorf("Failed to connect to the server: %v", err) +} + +func (agent *Agent) onError(err *protobufs.ServerErrorResponse) { + agent.logger.Errorf("Server returned an error response: %v", err.ErrorMessage) +} + +func (agent *Agent) saveRemoteConfigStatus(_ context.Context, status *protobufs.RemoteConfigStatus) { + agent.remoteConfigStatus = status +} + func (agent *Agent) Start() error { agent.startTime = uint64(time.Now().UnixNano()) settings := types.StartSettings{ OpAMPServerURL: agent.config.Endpoint, - //TLSConfig: &tls.Config{InsecureSkipVerify: true}, - InstanceUid: agent.instanceId.String(), + InstanceUid: agent.instanceId.String(), Callbacks: types.CallbacksStruct{ - OnConnectFunc: func() { - agent.logger.Debugf("Connected to the server.") - }, - OnConnectFailedFunc: func(err error) { - agent.logger.Errorf("Failed to connect to the server: %v", err) - }, - OnErrorFunc: func(err *protobufs.ServerErrorResponse) { - agent.logger.Errorf("Server returned an error response: %v", err.ErrorMessage) - }, - SaveRemoteConfigStatusFunc: func(_ context.Context, status *protobufs.RemoteConfigStatus) { - agent.remoteConfigStatus = status - }, - GetEffectiveConfigFunc: func(ctx context.Context) (*protobufs.EffectiveConfig, error) { - return agent.composeEffectiveConfig(), nil - }, - OnMessageFunc: agent.onMessage, + OnConnectFunc: agent.onConnect, + OnConnectFailedFunc: agent.onConnectFailed, + OnErrorFunc: agent.onError, + SaveRemoteConfigStatusFunc: agent.saveRemoteConfigStatus, + GetEffectiveConfigFunc: agent.getEffectiveConfig, + OnMessageFunc: agent.onMessage, }, RemoteConfigStatus: agent.remoteConfigStatus, PackagesStateProvider: nil, @@ -148,50 +118,6 @@ func (agent *Agent) Start() error { return nil } -func (agent *Agent) createAgentIdentity() { - // Generate instance id. - entropy := ulid.Monotonic(rand.New(rand.NewSource(0)), 0) - agent.instanceId = ulid.MustNew(ulid.Timestamp(time.Now()), entropy) - - hostname, _ := os.Hostname() - - // Create Agent description. - agent.agentDescription = &protobufs.AgentDescription{ - IdentifyingAttributes: []*protobufs.KeyValue{ - { - Key: "service.name", - Value: &protobufs.AnyValue{ - Value: &protobufs.AnyValue_StringValue{StringValue: agent.agentType}, - }, - }, - { - Key: "service.version", - Value: &protobufs.AnyValue{ - Value: &protobufs.AnyValue_StringValue{StringValue: agent.agentVersion}, - }, - }, - }, - NonIdentifyingAttributes: []*protobufs.KeyValue{ - { - Key: "os.family", - Value: &protobufs.AnyValue{ - Value: &protobufs.AnyValue_StringValue{ - StringValue: runtime.GOOS, - }, - }, - }, - { - Key: "host.name", - Value: &protobufs.AnyValue{ - Value: &protobufs.AnyValue_StringValue{ - StringValue: hostname, - }, - }, - }, - }, - } -} - func (agent *Agent) updateAgentIdentity(instanceId ulid.ULID) { agent.logger.Debugf("Agent identify is being changed from id=%v to id=%v", agent.instanceId.String(), @@ -217,23 +143,18 @@ func (agent *Agent) makeKeyFromNameNamespace(name string, namespace string) stri return fmt.Sprintf("%s/%s", name, namespace) } -func (agent *Agent) composeEffectiveConfig() *protobufs.EffectiveConfig { - effectiveConfig := &protobufs.EffectiveConfig{ - ConfigMap: &protobufs.AgentConfigMap{ - ConfigMap: nil, - }, - } +func (agent *Agent) getEffectiveConfig(ctx context.Context) (*protobufs.EffectiveConfig, error) { instances, err := agent.applier.ListInstances() if err != nil { agent.logger.Errorf("couldn't list instances", err) - return effectiveConfig + return nil, err } instanceMap := map[string]*protobufs.AgentConfigFile{} for _, instance := range instances { marshalled, err := yaml.Marshal(instance) if err != nil { agent.logger.Errorf("couldn't marshal collector configuration", err) - continue + return nil, err } mapKey := agent.makeKeyFromNameNamespace(instance.GetName(), instance.GetNamespace()) instanceMap[mapKey] = &protobufs.AgentConfigFile{ @@ -241,35 +162,29 @@ func (agent *Agent) composeEffectiveConfig() *protobufs.EffectiveConfig { ContentType: "yaml", } } - effectiveConfig.ConfigMap.ConfigMap = instanceMap - return effectiveConfig + return &protobufs.EffectiveConfig{ + ConfigMap: &protobufs.AgentConfigMap{ + ConfigMap: instanceMap, + }, + }, nil } func (agent *Agent) initMeter(settings *protobufs.TelemetryConnectionSettings) { - reporter, err := NewMetricReporter(agent.logger, settings, agent.agentType, agent.agentVersion, agent.instanceId) + reporter, err := metrics.NewMetricReporter(agent.logger, settings, agent.config.GetAgentType(), agent.config.GetAgentVersion(), agent.instanceId) if err != nil { agent.logger.Errorf("Cannot collect metrics: %v", err) return } - prevReporter := agent.metricReporter - - agent.metricReporter = reporter - - if prevReporter != nil { - prevReporter.Shutdown() + if agent.metricReporter != nil { + agent.metricReporter.Shutdown() } - return + agent.metricReporter = reporter } // Take the remote config, layer it over existing, done -func (agent *Agent) applyRemoteConfig(config *protobufs.AgentRemoteConfig) (bool, error) { - if config == nil { - return false, nil - } - if bytes.Equal(agent.lastHash, config.ConfigHash) { - return false, nil - } +// INVARIANT: The caller must verify that config isn't nil _and_ the configuration has changed between calls +func (agent *Agent) applyRemoteConfig(config *protobufs.AgentRemoteConfig) (*protobufs.RemoteConfigStatus, error) { var multiErr error for key, file := range config.Config.GetConfigMap() { if len(key) == 0 || len(file.Body) == 0 { @@ -288,10 +203,17 @@ func (agent *Agent) applyRemoteConfig(config *protobufs.AgentRemoteConfig) (bool agent.appliedKeys[key] = true } if multiErr != nil { - return false, multiErr + return &protobufs.RemoteConfigStatus{ + LastRemoteConfigHash: config.GetConfigHash(), + Status: protobufs.RemoteConfigStatuses_RemoteConfigStatuses_FAILED, + ErrorMessage: multiErr.Error(), + }, multiErr } agent.lastHash = config.ConfigHash - return true, nil + return &protobufs.RemoteConfigStatus{ + LastRemoteConfigHash: config.ConfigHash, + Status: protobufs.RemoteConfigStatuses_RemoteConfigStatuses_APPLIED, + }, nil } func (agent *Agent) Shutdown() { @@ -302,27 +224,18 @@ func (agent *Agent) Shutdown() { } func (agent *Agent) onMessage(ctx context.Context, msg *types.MessageData) { - configChanged := false - if msg.RemoteConfig != nil { + + // If we received remote configuration, and it's not the same as the previously applied one + if msg.RemoteConfig != nil && !bytes.Equal(agent.lastHash, msg.RemoteConfig.GetConfigHash()) { var err error - configChanged, err = agent.applyRemoteConfig(msg.RemoteConfig) + status, err := agent.applyRemoteConfig(msg.RemoteConfig) + setErr := agent.opampClient.SetRemoteConfigStatus(status) + if setErr != nil { + return + } + err = agent.opampClient.UpdateEffectiveConfig(ctx) if err != nil { - setErr := agent.opampClient.SetRemoteConfigStatus(&protobufs.RemoteConfigStatus{ - LastRemoteConfigHash: msg.RemoteConfig.ConfigHash, - Status: protobufs.RemoteConfigStatuses_RemoteConfigStatuses_FAILED, - ErrorMessage: err.Error(), - }) - if setErr != nil { - return - } - } else { - setErr := agent.opampClient.SetRemoteConfigStatus(&protobufs.RemoteConfigStatus{ - LastRemoteConfigHash: msg.RemoteConfig.ConfigHash, - Status: protobufs.RemoteConfigStatuses_RemoteConfigStatuses_APPLIED, - }) - if setErr != nil { - return - } + agent.logger.Errorf(err.Error()) } } @@ -338,11 +251,4 @@ func (agent *Agent) onMessage(ctx context.Context, msg *types.MessageData) { } agent.updateAgentIdentity(newInstanceId) } - - if configChanged { - err := agent.opampClient.UpdateEffectiveConfig(ctx) - if err != nil { - agent.logger.Errorf(err.Error()) - } - } } diff --git a/cmd/remote-configuration/agent/agent_test.go b/cmd/remote-configuration/agent/agent_test.go new file mode 100644 index 0000000000..a7c475dfb7 --- /dev/null +++ b/cmd/remote-configuration/agent/agent_test.go @@ -0,0 +1,425 @@ +package agent + +import ( + "context" + "fmt" + "github.com/oklog/ulid/v2" + "github.com/open-telemetry/opamp-go/client" + "github.com/open-telemetry/opamp-go/client/types" + "github.com/open-telemetry/opamp-go/protobufs" + "github.com/open-telemetry/opentelemetry-operator/apis/v1alpha1" + "github.com/open-telemetry/opentelemetry-operator/cmd/remote-configuration/config" + "github.com/open-telemetry/opentelemetry-operator/cmd/remote-configuration/logger" + "github.com/open-telemetry/opentelemetry-operator/cmd/remote-configuration/operator" + "github.com/stretchr/testify/assert" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "math/rand" + "os" + "sigs.k8s.io/controller-runtime/pkg/client/fake" + logf "sigs.k8s.io/controller-runtime/pkg/log" + "testing" +) + +var ( + l = logf.Log.WithName("agent-tests") + clientLogger = logger.NewLogger(&l) + _ client.OpAMPClient = &mockOpampClient{} +) + +type mockOpampClient struct { + lastStatus *protobufs.RemoteConfigStatus + lastEffectiveConfig *protobufs.EffectiveConfig + settings types.StartSettings +} + +func (m *mockOpampClient) Start(ctx context.Context, settings types.StartSettings) error { + m.settings = settings + return nil +} + +func (m *mockOpampClient) Stop(ctx context.Context) error { + return nil +} + +func (m *mockOpampClient) SetAgentDescription(descr *protobufs.AgentDescription) error { + return nil +} + +func (m *mockOpampClient) AgentDescription() *protobufs.AgentDescription { + return nil +} + +func (m *mockOpampClient) SetHealth(health *protobufs.AgentHealth) error { + return nil +} + +func (m *mockOpampClient) UpdateEffectiveConfig(ctx context.Context) error { + effectiveConfig, err := m.settings.Callbacks.GetEffectiveConfig(ctx) + if err != nil { + return err + } + m.lastEffectiveConfig = effectiveConfig + return nil +} + +func (m *mockOpampClient) SetRemoteConfigStatus(status *protobufs.RemoteConfigStatus) error { + m.lastStatus = status + return nil +} + +func (m *mockOpampClient) SetPackageStatuses(statuses *protobufs.PackageStatuses) error { + return nil +} + +func getFakeApplier(t *testing.T) *operator.Client { + schemeBuilder := runtime.NewSchemeBuilder(func(s *runtime.Scheme) error { + s.AddKnownTypes(v1alpha1.GroupVersion, &v1alpha1.OpenTelemetryCollector{}, &v1alpha1.OpenTelemetryCollectorList{}) + metav1.AddToGroupVersion(s, v1alpha1.GroupVersion) + return nil + }) + scheme := runtime.NewScheme() + err := schemeBuilder.AddToScheme(scheme) + assert.NoError(t, err, "Should be able to add custom types") + c := fake.NewClientBuilder().WithScheme(scheme) + return operator.NewClient(l, c.Build()) +} + +func TestAgent_onMessage(t *testing.T) { + type fields struct { + configFile string + } + type args struct { + ctx context.Context + // Mapping from name/namespace to a config in testdata + configFile map[string]string + // Mapping from name/namespace to a config in testdata (for testing updates) + nextConfigFile map[string]string + } + type want struct { + // Mapping from name/namespace to a list of expected contents + contents map[string][]string + // Mapping from name/namespace to a list of updated expected contents + nextContents map[string][]string + // The status after the initial config loading + status *protobufs.RemoteConfigStatus + // The status after the updated config loading + nextStatus *protobufs.RemoteConfigStatus + } + tests := []struct { + name string + fields fields + args args + want want + }{ + { + name: "no data", + fields: fields{ + configFile: "testdata/agent.yaml", + }, + args: args{ + ctx: context.Background(), + configFile: nil, + }, + want: want{ + contents: map[string][]string{}, + status: nil, + }, + }, + { + name: "base case", + fields: fields{ + configFile: "testdata/agent.yaml", + }, + args: args{ + ctx: context.Background(), + configFile: map[string]string{ + "good/testnamespace": "basic.yaml", + }, + }, + want: want{ + contents: map[string][]string{ + "good/testnamespace": { + "kind: OpenTelemetryCollector", + "name: good", + "namespace: testnamespace", + "send_batch_size: 10000", + "receivers: [otlp]", + "status:", + }, + }, + status: &protobufs.RemoteConfigStatus{ + LastRemoteConfigHash: []byte("good/testnamespace405"), + Status: protobufs.RemoteConfigStatuses_RemoteConfigStatuses_APPLIED, + }, + }, + }, + { + name: "failure", + fields: fields{ + configFile: "testdata/agent.yaml", + }, + args: args{ + ctx: context.Background(), + configFile: map[string]string{ + "bad/testnamespace": "invalid.yaml", + }, + }, + want: want{ + contents: nil, + status: &protobufs.RemoteConfigStatus{ + LastRemoteConfigHash: []byte("bad/testnamespace408"), + Status: protobufs.RemoteConfigStatuses_RemoteConfigStatuses_FAILED, + ErrorMessage: "yaml: line 16: could not find expected ':'", + }, + }, + }, + { + name: "can update config and replicas", + fields: fields{ + configFile: "testdata/agent.yaml", + }, + args: args{ + ctx: context.Background(), + configFile: map[string]string{ + "good/testnamespace": "basic.yaml", + }, + nextConfigFile: map[string]string{ + "good/testnamespace": "updated.yaml", + }, + }, + want: want{ + contents: map[string][]string{ + "good/testnamespace": { + "kind: OpenTelemetryCollector", + "name: good", + "namespace: testnamespace", + "send_batch_size: 10000", + "processors: []", + "replicas: 1", + "status:", + }, + }, + status: &protobufs.RemoteConfigStatus{ + LastRemoteConfigHash: []byte("good/testnamespace405"), + Status: protobufs.RemoteConfigStatuses_RemoteConfigStatuses_APPLIED, + }, + nextContents: map[string][]string{ + "good/testnamespace": { + "kind: OpenTelemetryCollector", + "name: good", + "namespace: testnamespace", + "send_batch_size: 10000", + "processors: [memory_limiter, batch]", + "replicas: 3", + "status:", + }, + }, + nextStatus: &protobufs.RemoteConfigStatus{ + LastRemoteConfigHash: []byte("good/testnamespace439"), + Status: protobufs.RemoteConfigStatuses_RemoteConfigStatuses_APPLIED, + }, + }, + }, + { + name: "cannot update with bad config", + fields: fields{ + configFile: "testdata/agent.yaml", + }, + args: args{ + ctx: context.Background(), + configFile: map[string]string{ + "good/testnamespace": "basic.yaml", + }, + nextConfigFile: map[string]string{ + "good/testnamespace": "invalid.yaml", + }, + }, + want: want{ + contents: map[string][]string{ + "good/testnamespace": { + "kind: OpenTelemetryCollector", + "name: good", + "namespace: testnamespace", + "send_batch_size: 10000", + "processors: []", + "replicas: 1", + "status:", + }, + }, + status: &protobufs.RemoteConfigStatus{ + LastRemoteConfigHash: []byte("good/testnamespace405"), + Status: protobufs.RemoteConfigStatuses_RemoteConfigStatuses_APPLIED, + }, + nextContents: map[string][]string{ + "good/testnamespace": { + "kind: OpenTelemetryCollector", + "name: good", + "namespace: testnamespace", + "send_batch_size: 10000", + "processors: []", + "replicas: 1", + "status:", + }, + }, + nextStatus: &protobufs.RemoteConfigStatus{ + LastRemoteConfigHash: []byte("good/testnamespace408"), // The new hash should be of the bad config + Status: protobufs.RemoteConfigStatuses_RemoteConfigStatuses_FAILED, + ErrorMessage: "yaml: line 16: could not find expected ':'", + }, + }, + }, + { + name: "update with new collector", + fields: fields{ + configFile: "testdata/agent.yaml", + }, + args: args{ + ctx: context.Background(), + configFile: map[string]string{ + "good/testnamespace": "basic.yaml", + }, + nextConfigFile: map[string]string{ + "good/testnamespace": "basic.yaml", + "other/testnamespace": "updated.yaml", + }, + }, + want: want{ + contents: map[string][]string{ + "good/testnamespace": { + "kind: OpenTelemetryCollector", + "name: good", + "namespace: testnamespace", + "send_batch_size: 10000", + "processors: []", + "status:", + }, + }, + status: &protobufs.RemoteConfigStatus{ + LastRemoteConfigHash: []byte("good/testnamespace405"), + Status: protobufs.RemoteConfigStatuses_RemoteConfigStatuses_APPLIED, + }, + nextContents: map[string][]string{ + "good/testnamespace": { + "kind: OpenTelemetryCollector", + "name: good", + "namespace: testnamespace", + "send_batch_size: 10000", + "processors: []", + "status:", + }, + "other/testnamespace": { + "kind: OpenTelemetryCollector", + "name: other", + "namespace: testnamespace", + "send_batch_size: 10000", + "processors: [memory_limiter, batch]", + "status:", + }, + }, + nextStatus: &protobufs.RemoteConfigStatus{ + LastRemoteConfigHash: []byte("good/testnamespace405other/testnamespace439"), + Status: protobufs.RemoteConfigStatuses_RemoteConfigStatuses_APPLIED, + }, + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + applier := getFakeApplier(t) + mockClient := &mockOpampClient{} + conf, err := config.Load(tt.fields.configFile) + assert.NoError(t, err, "should be able to load config") + agent := NewAgent(clientLogger, applier, conf, mockClient) + err = agent.Start() + defer agent.Shutdown() + assert.NoError(t, err, "should be able to start agent") + data, err := getMessageDataFromConfigFile(tt.args.configFile) + assert.NoError(t, err, "should be able to load data") + agent.onMessage(tt.args.ctx, data) + effectiveConfig, err := agent.getEffectiveConfig(tt.args.ctx) + assert.NoError(t, err, "should be able to get effective config") + if tt.args.configFile != nil { + // We should only expect this to happen if we supply configuration + assert.Equal(t, effectiveConfig, mockClient.lastEffectiveConfig, "client's config should be updated") + } + assert.NotNilf(t, effectiveConfig.ConfigMap.GetConfigMap(), "configmap should have data") + for colNameNamespace, expectedContents := range tt.want.contents { + assert.Contains(t, effectiveConfig.ConfigMap.GetConfigMap(), colNameNamespace) + for _, content := range expectedContents { + asString := string(effectiveConfig.ConfigMap.GetConfigMap()[colNameNamespace].GetBody()) + assert.Contains(t, asString, content) + } + } + assert.Equal(t, tt.want.status, mockClient.lastStatus) + if tt.args.nextConfigFile == nil { + // Nothing left to do! + return + } + nextData, err := getMessageDataFromConfigFile(tt.args.nextConfigFile) + assert.NoError(t, err, "should be able to load updated data") + agent.onMessage(tt.args.ctx, nextData) + nextEffectiveConfig, err := agent.getEffectiveConfig(tt.args.ctx) + assert.NoError(t, err, "should be able to get updated effective config") + assert.Equal(t, nextEffectiveConfig, mockClient.lastEffectiveConfig, "client's config should be updated") + assert.NotNilf(t, nextEffectiveConfig.ConfigMap.GetConfigMap(), "configmap should have updated data") + for colNameNamespace, expectedContents := range tt.want.nextContents { + assert.Contains(t, nextEffectiveConfig.ConfigMap.GetConfigMap(), colNameNamespace) + for _, content := range expectedContents { + asString := string(nextEffectiveConfig.ConfigMap.GetConfigMap()[colNameNamespace].GetBody()) + assert.Contains(t, asString, content) + } + } + assert.Equal(t, tt.want.nextStatus, mockClient.lastStatus) + }) + } +} + +func Test_CanUpdateIdentity(t *testing.T) { + applier := getFakeApplier(t) + mockClient := &mockOpampClient{} + conf, err := config.Load("testdata/agent.yaml") + assert.NoError(t, err, "should be able to load config") + agent := NewAgent(clientLogger, applier, conf, mockClient) + err = agent.Start() + defer agent.Shutdown() + assert.NoError(t, err, "should be able to start agent") + previousInstanceId := agent.instanceId.String() + entropy := ulid.Monotonic(rand.New(rand.NewSource(10000)), 0) + newId := ulid.MustNew(ulid.MaxTime(), entropy) + agent.onMessage(context.Background(), &types.MessageData{ + AgentIdentification: &protobufs.AgentIdentification{ + NewInstanceUid: newId.String(), + }, + }) + assert.NotEqual(t, previousInstanceId, newId.String()) + assert.Equal(t, agent.instanceId, newId) +} + +func getMessageDataFromConfigFile(filemap map[string]string) (*types.MessageData, error) { + toReturn := &types.MessageData{} + if filemap == nil { + return toReturn, nil + } + configs := map[string]*protobufs.AgentConfigFile{} + hash := "" + for key, filename := range filemap { + yamlFile, err := os.ReadFile(fmt.Sprintf("testdata/%s", filename)) + if err != nil { + return toReturn, err + } + configs[key] = &protobufs.AgentConfigFile{ + Body: yamlFile, + ContentType: "yaml", + } + hash = hash + key + fmt.Sprint(len(yamlFile)) + } + toReturn.RemoteConfig = &protobufs.AgentRemoteConfig{ + Config: &protobufs.AgentConfigMap{ + ConfigMap: configs, + }, + // just use the file name for the hash + ConfigHash: []byte(hash), + } + return toReturn, nil +} diff --git a/cmd/remote-configuration/agent/testdata/agent.yaml b/cmd/remote-configuration/agent/testdata/agent.yaml new file mode 100644 index 0000000000..c1e126aceb --- /dev/null +++ b/cmd/remote-configuration/agent/testdata/agent.yaml @@ -0,0 +1,17 @@ +endpoint: ws://127.0.0.1:4320/v1/opamp +protocol: wss +capabilities: + - Unspecified + - ReportsStatus + - AcceptsRemoteConfig + - ReportsEffectiveConfig + # - AcceptsPackages + # - ReportsPackageStatuses + - ReportsOwnTraces + - ReportsOwnMetrics + - ReportsOwnLogs + - AcceptsOpAMPConnectionSettings + - AcceptsOtherConnectionSettings + - AcceptsRestartCommand + - ReportsHealth + - ReportsRemoteConfig diff --git a/cmd/remote-configuration/agent/testdata/basic.yaml b/cmd/remote-configuration/agent/testdata/basic.yaml new file mode 100644 index 0000000000..1e808b1981 --- /dev/null +++ b/cmd/remote-configuration/agent/testdata/basic.yaml @@ -0,0 +1,24 @@ +config: | + receivers: + otlp: + protocols: + grpc: + http: + processors: + memory_limiter: + check_interval: 1s + limit_percentage: 75 + spike_limit_percentage: 15 + batch: + send_batch_size: 10000 + timeout: 10s + + exporters: + logging: + + service: + pipelines: + traces: + receivers: [otlp] + processors: [] + exporters: [logging] \ No newline at end of file diff --git a/cmd/remote-configuration/agent/testdata/invalid.yaml b/cmd/remote-configuration/agent/testdata/invalid.yaml new file mode 100644 index 0000000000..3d8c6c93ed --- /dev/null +++ b/cmd/remote-configuration/agent/testdata/invalid.yaml @@ -0,0 +1,24 @@ +config: | + receivers: + otlp: + protocols: + grpc: + http: + processors: + memory_limiter: + check_interval: 1s + limit_percentage: 75 + spike_limit_percentage: 15 + batch: + send_batch_size: 10000 + timeout: 10s + +GARBAGE + exporters: + logging: + service: + pipelines: + traces: + receivers: [otlp] + processors: [] + exporters: [logging] \ No newline at end of file diff --git a/cmd/remote-configuration/agent/testdata/updated.yaml b/cmd/remote-configuration/agent/testdata/updated.yaml new file mode 100644 index 0000000000..12eee6c3a0 --- /dev/null +++ b/cmd/remote-configuration/agent/testdata/updated.yaml @@ -0,0 +1,25 @@ +config: | + receivers: + otlp: + protocols: + grpc: + http: + processors: + memory_limiter: + check_interval: 1s + limit_percentage: 75 + spike_limit_percentage: 15 + batch: + send_batch_size: 10000 + timeout: 10s + + exporters: + logging: + + service: + pipelines: + traces: + receivers: [otlp] + processors: [memory_limiter, batch] + exporters: [logging] +replicas: 3 diff --git a/cmd/remote-configuration/config/cli.go b/cmd/remote-configuration/config/cli.go new file mode 100644 index 0000000000..984a811044 --- /dev/null +++ b/cmd/remote-configuration/config/cli.go @@ -0,0 +1,80 @@ +package config + +import ( + "errors" + "flag" + "github.com/go-logr/logr" + "github.com/open-telemetry/opentelemetry-operator/apis/v1alpha1" + "github.com/spf13/pflag" + "io/fs" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/client-go/kubernetes/scheme" + "k8s.io/client-go/rest" + "k8s.io/client-go/tools/clientcmd" + "k8s.io/client-go/util/homedir" + "k8s.io/klog/v2" + "path/filepath" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/log/zap" +) + +var ( + schemeBuilder = runtime.NewSchemeBuilder(registerKnownTypes) +) + +func registerKnownTypes(s *runtime.Scheme) error { + s.AddKnownTypes(v1alpha1.GroupVersion, &v1alpha1.OpenTelemetryCollector{}, &v1alpha1.OpenTelemetryCollectorList{}) + metav1.AddToGroupVersion(s, v1alpha1.GroupVersion) + return nil +} + +type CLIConfig struct { + ListenAddr *string + ConfigFilePath *string + + ClusterConfig *rest.Config + // KubeConfigFilePath empty if in cluster configuration is in use + KubeConfigFilePath string + RootLogger logr.Logger +} + +func ParseCLI() (CLIConfig, error) { + opts := zap.Options{} + opts.BindFlags(flag.CommandLine) + cLIConf := CLIConfig{ + ListenAddr: pflag.String("listen-addr", ":8080", "The address where this service serves."), + ConfigFilePath: pflag.String("config-file", defaultConfigFilePath, "The path to the config file."), + } + kubeconfigPath := pflag.String("kubeconfig-path", filepath.Join(homedir.HomeDir(), ".kube", "config"), "absolute path to the KubeconfigPath file") + pflag.Parse() + + cLIConf.RootLogger = zap.New(zap.UseFlagOptions(&opts)) + klog.SetLogger(cLIConf.RootLogger) + + clusterConfig, err := clientcmd.BuildConfigFromFlags("", *kubeconfigPath) + cLIConf.KubeConfigFilePath = *kubeconfigPath + if err != nil { + pathError := &fs.PathError{} + if ok := errors.As(err, &pathError); !ok { + return CLIConfig{}, err + } + clusterConfig, err = rest.InClusterConfig() + if err != nil { + return CLIConfig{}, err + } + cLIConf.KubeConfigFilePath = "" // reset as we use in cluster configuration + } + cLIConf.ClusterConfig = clusterConfig + return cLIConf, nil +} + +func (cli CLIConfig) GetKubernetesClient() (client.Client, error) { + err := schemeBuilder.AddToScheme(scheme.Scheme) + if err != nil { + return nil, err + } + return client.New(cli.ClusterConfig, client.Options{ + Scheme: scheme.Scheme, + }) +} diff --git a/cmd/remote-configuration/config/config.go b/cmd/remote-configuration/config/config.go index 66b5e9493b..f324003bd6 100644 --- a/cmd/remote-configuration/config/config.go +++ b/cmd/remote-configuration/config/config.go @@ -1,22 +1,16 @@ package config import ( - "errors" - "flag" "fmt" - "io/fs" - "os" - "path/filepath" - - "github.com/go-logr/logr" + "github.com/oklog/ulid/v2" + "github.com/open-telemetry/opamp-go/client" "github.com/open-telemetry/opamp-go/protobufs" - "github.com/spf13/pflag" + "github.com/open-telemetry/opentelemetry-operator/cmd/remote-configuration/logger" "gopkg.in/yaml.v2" - "k8s.io/client-go/rest" - "k8s.io/client-go/tools/clientcmd" - "k8s.io/client-go/util/homedir" - "k8s.io/klog/v2" - "sigs.k8s.io/controller-runtime/pkg/log/zap" + "math/rand" + "os" + "runtime" + "time" ) const ( @@ -24,6 +18,11 @@ const ( defaultConfigFilePath = "/conf/remoteconfiguration.yaml" ) +var ( + agentVersion = os.Getenv("OPAMP_VERSION") + hostname, _ = os.Hostname() +) + type Config struct { Endpoint string `yaml:"endpoint"` Protocol string `yaml:"protocol"` @@ -33,6 +32,13 @@ type Config struct { ComponentsAllowed map[string][]string `yaml:"components_allowed,omitempty"` } +func (c *Config) CreateClient(logger *logger.Logger) client.OpAMPClient { + if c.Protocol == "http" { + return client.NewHTTP(logger) + } + return client.NewWebSocket(logger) +} + func (c *Config) GetCapabilities() protobufs.AgentCapabilities { var capabilities int32 for _, capability := range c.Capabilities { @@ -45,16 +51,41 @@ func (c *Config) GetCapabilities() protobufs.AgentCapabilities { return protobufs.AgentCapabilities(capabilities) } -type CLIConfig struct { - ListenAddr *string - ConfigFilePath *string - AgentType *string - AgentVersion *string +func (c *Config) GetAgentType() string { + return agentType +} + +func (c *Config) GetAgentVersion() string { + return agentVersion +} + +func (c *Config) GetDescription() *protobufs.AgentDescription { + return &protobufs.AgentDescription{ + IdentifyingAttributes: []*protobufs.KeyValue{ + keyValuePair("service.name", c.GetAgentType()), + keyValuePair("service.version", c.GetAgentVersion()), + }, + NonIdentifyingAttributes: []*protobufs.KeyValue{ + keyValuePair("os.family", runtime.GOOS), + keyValuePair("host.name", hostname), + }, + } +} + +func keyValuePair(key string, value string) *protobufs.KeyValue { + return &protobufs.KeyValue{ + Key: key, + Value: &protobufs.AnyValue{ + Value: &protobufs.AnyValue_StringValue{ + StringValue: value, + }, + }, + } +} - ClusterConfig *rest.Config - // KubeConfigFilePath empty if in cluster configuration is in use - KubeConfigFilePath string - RootLogger logr.Logger +func (c *Config) GetNewInstanceId() ulid.ULID { + entropy := ulid.Monotonic(rand.New(rand.NewSource(10000)), 0) + return ulid.MustNew(ulid.Timestamp(time.Now()), entropy) } func Load(file string) (Config, error) { @@ -75,36 +106,3 @@ func unmarshal(cfg *Config, configFile string) error { } return nil } - -func ParseCLI() (CLIConfig, error) { - opts := zap.Options{} - opts.BindFlags(flag.CommandLine) - agentVersion := os.Getenv("OPAMP_VERSION") - cLIConf := CLIConfig{ - ListenAddr: pflag.String("listen-addr", ":8080", "The address where this service serves."), - ConfigFilePath: pflag.String("config-file", defaultConfigFilePath, "The path to the config file."), - AgentType: pflag.String("agent-type", agentType, "The type agent that is connecting."), - AgentVersion: pflag.String("agent-version", agentVersion, "The version of the agent."), - } - kubeconfigPath := pflag.String("kubeconfig-path", filepath.Join(homedir.HomeDir(), ".kube", "config"), "absolute path to the KubeconfigPath file") - pflag.Parse() - - cLIConf.RootLogger = zap.New(zap.UseFlagOptions(&opts)) - klog.SetLogger(cLIConf.RootLogger) - - clusterConfig, err := clientcmd.BuildConfigFromFlags("", *kubeconfigPath) - cLIConf.KubeConfigFilePath = *kubeconfigPath - if err != nil { - pathError := &fs.PathError{} - if ok := errors.As(err, &pathError); !ok { - return CLIConfig{}, err - } - clusterConfig, err = rest.InClusterConfig() - if err != nil { - return CLIConfig{}, err - } - cLIConf.KubeConfigFilePath = "" // reset as we use in cluster configuration - } - cLIConf.ClusterConfig = clusterConfig - return cLIConf, nil -} diff --git a/cmd/remote-configuration/go.mod b/cmd/remote-configuration/go.mod index 7addcc141e..9ebba0e1f9 100644 --- a/cmd/remote-configuration/go.mod +++ b/cmd/remote-configuration/go.mod @@ -9,12 +9,16 @@ require ( github.com/open-telemetry/opentelemetry-operator v1.51.0 github.com/shirou/gopsutil v3.21.11+incompatible github.com/spf13/pflag v1.0.5 + github.com/stretchr/testify v1.8.1 go.opentelemetry.io/otel v1.11.2 go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v0.34.0 go.opentelemetry.io/otel/metric v0.34.0 go.opentelemetry.io/otel/sdk v1.11.2 go.opentelemetry.io/otel/sdk/metric v0.34.0 + go.uber.org/multierr v1.6.0 gopkg.in/yaml.v2 v2.4.0 + gopkg.in/yaml.v3 v3.0.1 + k8s.io/apimachinery v0.26.0 k8s.io/client-go v0.26.0 k8s.io/klog/v2 v2.80.1 sigs.k8s.io/controller-runtime v0.14.0 @@ -26,6 +30,7 @@ require ( github.com/cespare/xxhash/v2 v2.1.2 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/emicklei/go-restful/v3 v3.9.0 // indirect + github.com/evanphx/json-patch v4.12.0+incompatible // indirect github.com/evanphx/json-patch/v5 v5.6.0 // indirect github.com/fsnotify/fsnotify v1.6.0 // indirect github.com/go-logr/stdr v1.2.2 // indirect @@ -57,7 +62,6 @@ require ( github.com/prometheus/client_model v0.3.0 // indirect github.com/prometheus/common v0.37.0 // indirect github.com/prometheus/procfs v0.8.0 // indirect - github.com/stretchr/testify v1.8.1 // indirect github.com/tklauser/go-sysconf v0.3.11 // indirect github.com/tklauser/numcpus v0.6.0 // indirect github.com/yusufpapurcu/wmi v1.2.2 // indirect @@ -66,7 +70,6 @@ require ( go.opentelemetry.io/otel/trace v1.11.2 // indirect go.opentelemetry.io/proto/otlp v0.19.0 // indirect go.uber.org/atomic v1.8.0 // indirect - go.uber.org/multierr v1.6.0 // indirect go.uber.org/zap v1.24.0 // indirect golang.org/x/net v0.3.1-0.20221206200815-1e63c2f08a10 // indirect golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b // indirect @@ -80,10 +83,8 @@ require ( google.golang.org/grpc v1.51.0 // indirect google.golang.org/protobuf v1.28.1 // indirect gopkg.in/inf.v0 v0.9.1 // indirect - gopkg.in/yaml.v3 v3.0.1 // indirect k8s.io/api v0.26.0 // indirect k8s.io/apiextensions-apiserver v0.26.0 // indirect - k8s.io/apimachinery v0.26.0 // indirect k8s.io/component-base v0.26.0 // indirect k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280 // indirect k8s.io/utils v0.0.0-20221128185143-99ec85e7a448 // indirect diff --git a/cmd/remote-configuration/go.sum b/cmd/remote-configuration/go.sum index c9c4d417c6..bdd771b446 100644 --- a/cmd/remote-configuration/go.sum +++ b/cmd/remote-configuration/go.sum @@ -82,6 +82,7 @@ github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go. github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/evanphx/json-patch v0.5.2/go.mod h1:ZWS5hhDbVDyob71nXKNL0+PWn6ToqBHMikGIFbs31qQ= github.com/evanphx/json-patch v4.12.0+incompatible h1:4onqiflcdA9EOZ4RxV643DvftH5pOlLGNtQ5lPWQu84= +github.com/evanphx/json-patch v4.12.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/evanphx/json-patch/v5 v5.6.0 h1:b91NhWfaz02IuVxO9faSllyAtNXHMPkC5J8sJCLunww= github.com/evanphx/json-patch/v5 v5.6.0/go.mod h1:G79N1coSVB93tBe7j6PhzjmR3/2VvlbKOFpnXhI9Bw4= github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= diff --git a/cmd/remote-configuration/agent/logger.go b/cmd/remote-configuration/logger/logger.go similarity index 96% rename from cmd/remote-configuration/agent/logger.go rename to cmd/remote-configuration/logger/logger.go index 5c85d3a40b..6b64619cdd 100644 --- a/cmd/remote-configuration/agent/logger.go +++ b/cmd/remote-configuration/logger/logger.go @@ -1,4 +1,4 @@ -package agent +package logger import ( "fmt" diff --git a/cmd/remote-configuration/main.go b/cmd/remote-configuration/main.go index 57b2d179a4..87da75dcb7 100644 --- a/cmd/remote-configuration/main.go +++ b/cmd/remote-configuration/main.go @@ -1,6 +1,7 @@ package main import ( + "github.com/open-telemetry/opentelemetry-operator/cmd/remote-configuration/logger" "github.com/open-telemetry/opentelemetry-operator/cmd/remote-configuration/operator" "os" "os/signal" @@ -20,13 +21,18 @@ func main() { return } cliConf.RootLogger.Info("Starting the Remote Configuration service") - agentLogger := cliConf.RootLogger.WithName("agent") + agentLogf := cliConf.RootLogger.WithName("agent") + agentLogger := logger.NewLogger(&agentLogf) - operatorClient, operatorClientErr := operator.NewClient(cliConf.RootLogger.WithName("operator-client"), cliConf.ClusterConfig) - if operatorClientErr != nil { - cliConf.RootLogger.Error(operatorClientErr, "Couldn't create operator client") + kubeClient, kubeErr := cliConf.GetKubernetesClient() + if kubeErr != nil { + cliConf.RootLogger.Error(kubeErr, "Couldn't create kubernetes client") + return } - opampAgent := agent.NewAgent(agent.NewLogger(&agentLogger), operatorClient, cfg, *cliConf.AgentType, *cliConf.AgentVersion) + operatorClient := operator.NewClient(cliConf.RootLogger.WithName("operator-client"), kubeClient) + + opampClient := cfg.CreateClient(agentLogger) + opampAgent := agent.NewAgent(agentLogger, operatorClient, cfg, opampClient) if err := opampAgent.Start(); err != nil { cliConf.RootLogger.Error(err, "Cannot start OpAMP client") diff --git a/cmd/remote-configuration/agent/metricreporter.go b/cmd/remote-configuration/metrics/reporter.go similarity index 99% rename from cmd/remote-configuration/agent/metricreporter.go rename to cmd/remote-configuration/metrics/reporter.go index 3d74e6f9e4..b5275f8129 100644 --- a/cmd/remote-configuration/agent/metricreporter.go +++ b/cmd/remote-configuration/metrics/reporter.go @@ -1,4 +1,4 @@ -package agent +package metrics import ( "context" diff --git a/cmd/remote-configuration/operator/client.go b/cmd/remote-configuration/operator/client.go index 61bb6c7cc0..738c3f545f 100644 --- a/cmd/remote-configuration/operator/client.go +++ b/cmd/remote-configuration/operator/client.go @@ -6,10 +6,6 @@ import ( "github.com/open-telemetry/opamp-go/protobufs" "gopkg.in/yaml.v3" "k8s.io/apimachinery/pkg/api/errors" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/client-go/kubernetes/scheme" - "k8s.io/client-go/rest" "sigs.k8s.io/controller-runtime/pkg/client" "github.com/open-telemetry/opentelemetry-operator/apis/v1alpha1" @@ -21,16 +17,6 @@ const ( ResourceIdentifierValue = "remote-configuration" ) -var ( - schemeBuilder = runtime.NewSchemeBuilder(registerKnownTypes) -) - -func registerKnownTypes(s *runtime.Scheme) error { - s.AddKnownTypes(v1alpha1.GroupVersion, &v1alpha1.OpenTelemetryCollector{}, &v1alpha1.OpenTelemetryCollectorList{}) - metav1.AddToGroupVersion(s, v1alpha1.GroupVersion) - return nil -} - type ConfigApplier interface { Apply(name string, namespace string, configmap *protobufs.AgentConfigFile) error GetInstance(name string, namespace string) (*v1alpha1.OpenTelemetryCollector, error) @@ -45,25 +31,15 @@ type Client struct { var _ ConfigApplier = &Client{} -func NewClient(log logr.Logger, kubeConfig *rest.Config) (*Client, error) { - err := schemeBuilder.AddToScheme(scheme.Scheme) - if err != nil { - return nil, err - } - c, err := client.New(kubeConfig, client.Options{ - Scheme: scheme.Scheme, - }) - if err != nil { - return nil, err - } +func NewClient(log logr.Logger, c client.Client) *Client { return &Client{ log: log, k8sClient: c, close: make(chan bool, 1), - }, nil + } } -func (c Client) create(ctx context.Context, name string, namespace string, collector v1alpha1.OpenTelemetryCollector) error { +func (c Client) create(ctx context.Context, name string, namespace string, collector *v1alpha1.OpenTelemetryCollector) error { // Set the defaults collector.Default() collector.TypeMeta.Kind = CollectorResource @@ -79,50 +55,41 @@ func (c Client) create(ctx context.Context, name string, namespace string, colle if err != nil { return err } - c.log.Info("Was given a valid configuration", "collector", collector) - err = c.k8sClient.Create(ctx, &collector) + c.log.Info("Creating collector") + return c.k8sClient.Create(ctx, collector) +} + +func (c Client) update(ctx context.Context, old *v1alpha1.OpenTelemetryCollector, new *v1alpha1.OpenTelemetryCollector) error { + new.ObjectMeta = old.ObjectMeta + new.TypeMeta = old.TypeMeta + err := new.ValidateUpdate(old) if err != nil { - c.log.Error(err, "unable to create collector") return err } - return nil + c.log.Info("Updating collector") + return c.k8sClient.Update(ctx, new) } func (c Client) Apply(name string, namespace string, configmap *protobufs.AgentConfigFile) error { - c.log.Info("Received new config", name, len(configmap.String())) + c.log.Info("Received new config", "name", name, "namespace", namespace) var collectorSpec v1alpha1.OpenTelemetryCollectorSpec err := yaml.Unmarshal(configmap.Body, &collectorSpec) if err != nil { return err } - collector := v1alpha1.OpenTelemetryCollector{Spec: collectorSpec} + if len(collectorSpec.Config) == 0 { + return errors.NewBadRequest("Must supply valid configuration") + } + collector := &v1alpha1.OpenTelemetryCollector{Spec: collectorSpec} ctx := context.Background() - //created := false instance, err := c.GetInstance(name, namespace) if err != nil { return err } if instance != nil { - collector.ObjectMeta = instance.ObjectMeta - collector.TypeMeta = instance.TypeMeta - err := collector.ValidateUpdate(instance) - if err != nil { - return err - } - err = c.k8sClient.Update(ctx, &collector) - if err != nil { - return err - } - c.log.Info("Updated collector") - return nil - } - - err = c.create(ctx, name, namespace, collector) - if err != nil { - return err + return c.update(ctx, instance, collector) } - c.log.Info("Created collector") - return nil + return c.create(ctx, name, namespace, collector) } func (c Client) ListInstances() ([]v1alpha1.OpenTelemetryCollector, error) { diff --git a/cmd/remote-configuration/operator/client_test.go b/cmd/remote-configuration/operator/client_test.go new file mode 100644 index 0000000000..4b55bf6cb9 --- /dev/null +++ b/cmd/remote-configuration/operator/client_test.go @@ -0,0 +1,149 @@ +package operator + +import ( + "github.com/open-telemetry/opamp-go/protobufs" + "github.com/open-telemetry/opentelemetry-operator/apis/v1alpha1" + "github.com/stretchr/testify/assert" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "os" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/client/fake" + logf "sigs.k8s.io/controller-runtime/pkg/log" + "testing" +) + +var ( + clientLogger = logf.Log.WithName("client-tests") +) + +func getFakeClient(t *testing.T) client.WithWatch { + schemeBuilder := runtime.NewSchemeBuilder(func(s *runtime.Scheme) error { + s.AddKnownTypes(v1alpha1.GroupVersion, &v1alpha1.OpenTelemetryCollector{}, &v1alpha1.OpenTelemetryCollectorList{}) + metav1.AddToGroupVersion(s, v1alpha1.GroupVersion) + return nil + }) + scheme := runtime.NewScheme() + err := schemeBuilder.AddToScheme(scheme) + assert.NoError(t, err, "Should be able to add custom types") + c := fake.NewClientBuilder().WithScheme(scheme) + return c.Build() +} + +func TestClient_Apply(t *testing.T) { + type args struct { + name string + namespace string + file string + config string + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "base case", + args: args{ + name: "test", + namespace: "opentelemetry", + file: "testdata/collector.yaml", + }, + wantErr: false, + }, + { + name: "invalid config", + args: args{ + name: "test", + namespace: "opentelemetry", + file: "testdata/invalid-collector.yaml", + }, + wantErr: true, + }, + { + name: "empty config", + args: args{ + name: "test", + namespace: "opentelemetry", + config: "", + }, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + fakeClient := getFakeClient(t) + c := NewClient(clientLogger, fakeClient) + var colConfig []byte + var err error + if len(tt.args.file) > 0 { + colConfig, err = loadConfig(tt.args.file) + assert.NoError(t, err, "Should be no error on loading test configuration") + } else { + colConfig = []byte(tt.args.config) + } + configmap := &protobufs.AgentConfigFile{ + Body: colConfig, + ContentType: "yaml", + } + if err := c.Apply(tt.args.name, tt.args.namespace, configmap); (err != nil) != tt.wantErr { + t.Errorf("Apply() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} + +func Test_collectorUpdate(t *testing.T) { + name := "test" + namespace := "testing" + fakeClient := getFakeClient(t) + c := NewClient(clientLogger, fakeClient) + colConfig, err := loadConfig("testdata/collector.yaml") + assert.NoError(t, err, "Should be no error on loading test configuration") + configmap := &protobufs.AgentConfigFile{ + Body: colConfig, + ContentType: "yaml", + } + // Apply a valid initial configuration + err = c.Apply(name, namespace, configmap) + assert.NoError(t, err, "Should apply base config") + + // Get the newly created collector + instance, err := c.GetInstance(name, namespace) + assert.NoError(t, err, "Should be able to get the newly created instance") + assert.Contains(t, instance.Spec.Config, "processors: []") + + // Try updating with an invalid one + configmap.Body = []byte("empty, invalid!") + err = c.Apply(name, namespace, configmap) + assert.Error(t, err, "Should be unable to update") + + // Update successfully with a valid configuration + newColConfig, err := loadConfig("testdata/updated-collector.yaml") + assert.NoError(t, err, "Should be no error on loading test configuration") + newConfigMap := &protobufs.AgentConfigFile{ + Body: newColConfig, + ContentType: "yaml", + } + err = c.Apply(name, namespace, newConfigMap) + assert.NoError(t, err, "Should be able to update collector") + + // Get the updated collector + updatedInstance, err := c.GetInstance(name, namespace) + assert.NoError(t, err, "Should be able to get the updated instance") + assert.Contains(t, updatedInstance.Spec.Config, "processors: [memory_limiter, batch]") + + allInstances, err := c.ListInstances() + assert.NoError(t, err, "Should be able to list all collectors") + assert.Len(t, allInstances, 1) + assert.Equal(t, allInstances[0], *updatedInstance) + +} + +func loadConfig(file string) ([]byte, error) { + yamlFile, err := os.ReadFile(file) + if err != nil { + return []byte{}, err + } + return yamlFile, nil +} diff --git a/cmd/remote-configuration/operator/testdata/collector.yaml b/cmd/remote-configuration/operator/testdata/collector.yaml new file mode 100644 index 0000000000..1e808b1981 --- /dev/null +++ b/cmd/remote-configuration/operator/testdata/collector.yaml @@ -0,0 +1,24 @@ +config: | + receivers: + otlp: + protocols: + grpc: + http: + processors: + memory_limiter: + check_interval: 1s + limit_percentage: 75 + spike_limit_percentage: 15 + batch: + send_batch_size: 10000 + timeout: 10s + + exporters: + logging: + + service: + pipelines: + traces: + receivers: [otlp] + processors: [] + exporters: [logging] \ No newline at end of file diff --git a/cmd/remote-configuration/operator/testdata/invalid-collector.yaml b/cmd/remote-configuration/operator/testdata/invalid-collector.yaml new file mode 100644 index 0000000000..bfc325a9bd --- /dev/null +++ b/cmd/remote-configuration/operator/testdata/invalid-collector.yaml @@ -0,0 +1,24 @@ +config: | + receivers: + otlp: + protocols: + grpc: + http: + processors: + memory_limiter: + check_interval: 1s + limit_percentage: 75 + spike_limit_percentage: 15 + batch: + send_batch_size: 10000 + timeout: 10s +GARBAGE + exporters: + logging: + + service: + pipelines: + traces: + receivers: [otlp] + processors: [] + exporters: [logging] \ No newline at end of file diff --git a/cmd/remote-configuration/operator/testdata/updated-collector.yaml b/cmd/remote-configuration/operator/testdata/updated-collector.yaml new file mode 100644 index 0000000000..d04399ea07 --- /dev/null +++ b/cmd/remote-configuration/operator/testdata/updated-collector.yaml @@ -0,0 +1,24 @@ +config: | + receivers: + otlp: + protocols: + grpc: + http: + processors: + memory_limiter: + check_interval: 1s + limit_percentage: 75 + spike_limit_percentage: 15 + batch: + send_batch_size: 10000 + timeout: 10s + + exporters: + logging: + + service: + pipelines: + traces: + receivers: [otlp] + processors: [memory_limiter, batch] + exporters: [logging] \ No newline at end of file From 98b5a9c249d4c29c959a088a2ed093ca40538cb6 Mon Sep 17 00:00:00 2001 From: Jacob Aronoff Date: Tue, 3 Jan 2023 13:40:01 -0500 Subject: [PATCH 05/16] Add deletion and dockerfile --- Makefile | 15 ++++++-- cmd/remote-configuration/Dockerfile | 26 ++++++++++++++ cmd/remote-configuration/agent/agent.go | 13 +++++++ cmd/remote-configuration/agent/agent_test.go | 34 +++++++++++++++++++ cmd/remote-configuration/operator/client.go | 17 ++++++++++ .../operator/client_test.go | 29 ++++++++++++++++ 6 files changed, 132 insertions(+), 2 deletions(-) create mode 100644 cmd/remote-configuration/Dockerfile diff --git a/Makefile b/Makefile index 70d94903a6..68439b96ea 100644 --- a/Makefile +++ b/Makefile @@ -21,6 +21,9 @@ BUNDLE_IMG ?= ${IMG_PREFIX}/${IMG_REPO}-bundle:${VERSION} TARGETALLOCATOR_IMG_REPO ?= target-allocator TARGETALLOCATOR_IMG ?= ${IMG_PREFIX}/${TARGETALLOCATOR_IMG_REPO}:$(addprefix v,${VERSION}) +REMOTECONFIGURATION_IMG_REPO ?= remote-configuration +REMOTECONFIGURATION_IMG ?= ${IMG_PREFIX}/${REMOTECONFIGURATION_IMG_REPO}:$(addprefix v,${VERSION}) + # Options for 'bundle-build' ifneq ($(origin CHANNELS), undefined) BUNDLE_CHANNELS := --channels=$(CHANNELS) @@ -171,7 +174,7 @@ e2e-log-operator: kubectl get deploy -A .PHONY: prepare-e2e -prepare-e2e: kuttl set-test-image-vars set-image-controller container container-target-allocator start-kind install-metrics-server install-openshift-routes load-image-all +prepare-e2e: kuttl set-test-image-vars set-image-controller container container-target-allocator container-remote-configuration start-kind install-metrics-server install-openshift-routes load-image-all mkdir -p tests/_build/crds tests/_build/manifests $(KUSTOMIZE) build config/default -o tests/_build/manifests/01-opentelemetry-operator.yaml $(KUSTOMIZE) build config/crd -o tests/_build/crds/ @@ -200,6 +203,10 @@ container-push: container-target-allocator: docker buildx build --platform linux/${ARCH} -t ${TARGETALLOCATOR_IMG} cmd/otel-allocator +.PHONY: container-remote-configuration +container-remote-configuration: + docker buildx build --platform linux/${ARCH} -t ${REMOTECONFIGURATION_IMG} cmd/remote-configuration + .PHONY: start-kind start-kind: kind create cluster --config $(KIND_CONFIG) @@ -213,7 +220,7 @@ install-openshift-routes: ./hack/install-openshift-routes.sh .PHONY: load-image-all -load-image-all: load-image-operator load-image-target-allocator +load-image-all: load-image-operator load-image-target-allocator load-image-remote-configuration .PHONY: load-image-operator load-image-operator: @@ -223,6 +230,10 @@ load-image-operator: load-image-target-allocator: kind load docker-image ${TARGETALLOCATOR_IMG} +.PHONY: load-image-remote-configuration +load-image-remote-configuration: + kind load docker-image ${REMOTECONFIGURATION_IMG} + .PHONY: cert-manager cert-manager: cmctl # Consider using cmctl to install the cert-manager once install command is not experimental diff --git a/cmd/remote-configuration/Dockerfile b/cmd/remote-configuration/Dockerfile new file mode 100644 index 0000000000..dbc121f7b1 --- /dev/null +++ b/cmd/remote-configuration/Dockerfile @@ -0,0 +1,26 @@ +# Build the remote-configuration binary +FROM golang:1.19 as builder + +WORKDIR /app + +# Copy go mod and sum files +COPY go.mod go.sum ./ + +RUN go mod download + +COPY . . + +# Build the Go app +RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o main . + +######## Start a new stage from scratch ####### +FROM alpine:latest + +RUN apk --no-cache add ca-certificates + +WORKDIR /root/ + +# Copy the pre-built binary file from the previous stage +COPY --from=builder /app/main . + +ENTRYPOINT ["./main"] diff --git a/cmd/remote-configuration/agent/agent.go b/cmd/remote-configuration/agent/agent.go index 2cfd4b4333..7f6fd9051c 100644 --- a/cmd/remote-configuration/agent/agent.go +++ b/cmd/remote-configuration/agent/agent.go @@ -202,6 +202,19 @@ func (agent *Agent) applyRemoteConfig(config *protobufs.AgentRemoteConfig) (*pro } agent.appliedKeys[key] = true } + for collectorKey := range agent.appliedKeys { + name, namespace, err := agent.getNameAndNamespace(collectorKey) + if err != nil { + multiErr = multierr.Append(multiErr, err) + continue + } + if _, ok := config.Config.GetConfigMap()[collectorKey]; !ok { + err = agent.applier.Delete(name, namespace) + if err != nil { + multiErr = multierr.Append(multiErr, err) + } + } + } if multiErr != nil { return &protobufs.RemoteConfigStatus{ LastRemoteConfigHash: config.GetConfigHash(), diff --git a/cmd/remote-configuration/agent/agent_test.go b/cmd/remote-configuration/agent/agent_test.go index a7c475dfb7..766d0e76e1 100644 --- a/cmd/remote-configuration/agent/agent_test.go +++ b/cmd/remote-configuration/agent/agent_test.go @@ -323,6 +323,40 @@ func TestAgent_onMessage(t *testing.T) { }, }, }, + { + name: "Can delete existing collector", + fields: fields{ + configFile: "testdata/agent.yaml", + }, + args: args{ + ctx: context.Background(), + configFile: map[string]string{ + "good/testnamespace": "basic.yaml", + }, + nextConfigFile: map[string]string{}, + }, + want: want{ + contents: map[string][]string{ + "good/testnamespace": { + "kind: OpenTelemetryCollector", + "name: good", + "namespace: testnamespace", + "send_batch_size: 10000", + "processors: []", + "status:", + }, + }, + status: &protobufs.RemoteConfigStatus{ + LastRemoteConfigHash: []byte("good/testnamespace405"), + Status: protobufs.RemoteConfigStatuses_RemoteConfigStatuses_APPLIED, + }, + nextContents: map[string][]string{}, + nextStatus: &protobufs.RemoteConfigStatus{ + LastRemoteConfigHash: []byte(""), + Status: protobufs.RemoteConfigStatuses_RemoteConfigStatuses_APPLIED, + }, + }, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { diff --git a/cmd/remote-configuration/operator/client.go b/cmd/remote-configuration/operator/client.go index 738c3f545f..cbeccbd57d 100644 --- a/cmd/remote-configuration/operator/client.go +++ b/cmd/remote-configuration/operator/client.go @@ -21,6 +21,7 @@ type ConfigApplier interface { Apply(name string, namespace string, configmap *protobufs.AgentConfigFile) error GetInstance(name string, namespace string) (*v1alpha1.OpenTelemetryCollector, error) ListInstances() ([]v1alpha1.OpenTelemetryCollector, error) + Delete(name string, namespace string) error } type Client struct { @@ -92,6 +93,22 @@ func (c Client) Apply(name string, namespace string, configmap *protobufs.AgentC return c.create(ctx, name, namespace, collector) } +func (c Client) Delete(name string, namespace string) error { + ctx := context.Background() + result := v1alpha1.OpenTelemetryCollector{} + err := c.k8sClient.Get(ctx, client.ObjectKey{ + Namespace: namespace, + Name: name, + }, &result) + if errors.IsNotFound(err) { + return nil + } + if err != nil { + return err + } + return c.k8sClient.Delete(ctx, &result) +} + func (c Client) ListInstances() ([]v1alpha1.OpenTelemetryCollector, error) { ctx := context.Background() result := v1alpha1.OpenTelemetryCollectorList{} diff --git a/cmd/remote-configuration/operator/client_test.go b/cmd/remote-configuration/operator/client_test.go index 4b55bf6cb9..20e290af41 100644 --- a/cmd/remote-configuration/operator/client_test.go +++ b/cmd/remote-configuration/operator/client_test.go @@ -137,7 +137,36 @@ func Test_collectorUpdate(t *testing.T) { assert.NoError(t, err, "Should be able to list all collectors") assert.Len(t, allInstances, 1) assert.Equal(t, allInstances[0], *updatedInstance) +} +func Test_collectorDelete(t *testing.T) { + name := "test" + namespace := "testing" + fakeClient := getFakeClient(t) + c := NewClient(clientLogger, fakeClient) + colConfig, err := loadConfig("testdata/collector.yaml") + assert.NoError(t, err, "Should be no error on loading test configuration") + configmap := &protobufs.AgentConfigFile{ + Body: colConfig, + ContentType: "yaml", + } + // Apply a valid initial configuration + err = c.Apply(name, namespace, configmap) + assert.NoError(t, err, "Should apply base config") + + // Get the newly created collector + instance, err := c.GetInstance(name, namespace) + assert.NoError(t, err, "Should be able to get the newly created instance") + assert.Contains(t, instance.Spec.Config, "processors: []") + + // Delete it + err = c.Delete(name, namespace) + assert.NoError(t, err, "Should be able to delete a collector") + + // Check there's nothing left + allInstances, err := c.ListInstances() + assert.NoError(t, err, "Should be able to list all collectors") + assert.Len(t, allInstances, 0) } func loadConfig(file string) ([]byte, error) { From f6b1e95702fc3ad6ec1e50f2159af247fde54eb2 Mon Sep 17 00:00:00 2001 From: Jacob Aronoff Date: Tue, 3 Jan 2023 14:31:26 -0500 Subject: [PATCH 06/16] Add logic for specifying allowed components --- cmd/remote-configuration/agent/agent.go | 8 +- cmd/remote-configuration/agent/agent_test.go | 106 +++++++++++++++--- .../testdata/agentbasiccomponentsallowed.yaml | 25 +++++ .../agent/testdata/agentbatchnotallowed.yaml | 24 ++++ .../testdata/agentnoprocessorsallowed.yaml | 22 ++++ cmd/remote-configuration/config/cli.go | 8 +- cmd/remote-configuration/config/config.go | 25 ++++- cmd/remote-configuration/main.go | 7 +- cmd/remote-configuration/operator/client.go | 55 +++++++-- .../operator/client_test.go | 14 ++- 10 files changed, 254 insertions(+), 40 deletions(-) create mode 100644 cmd/remote-configuration/agent/testdata/agentbasiccomponentsallowed.yaml create mode 100644 cmd/remote-configuration/agent/testdata/agentbatchnotallowed.yaml create mode 100644 cmd/remote-configuration/agent/testdata/agentnoprocessorsallowed.yaml diff --git a/cmd/remote-configuration/agent/agent.go b/cmd/remote-configuration/agent/agent.go index 7f6fd9051c..86baefc609 100644 --- a/cmd/remote-configuration/agent/agent.go +++ b/cmd/remote-configuration/agent/agent.go @@ -5,12 +5,14 @@ import ( "context" "errors" "fmt" - "github.com/open-telemetry/opentelemetry-operator/cmd/remote-configuration/metrics" - "github.com/open-telemetry/opentelemetry-operator/cmd/remote-configuration/operator" - "gopkg.in/yaml.v3" "strings" "time" + "gopkg.in/yaml.v3" + + "github.com/open-telemetry/opentelemetry-operator/cmd/remote-configuration/metrics" + "github.com/open-telemetry/opentelemetry-operator/cmd/remote-configuration/operator" + "github.com/open-telemetry/opentelemetry-operator/cmd/remote-configuration/config" "github.com/oklog/ulid/v2" diff --git a/cmd/remote-configuration/agent/agent_test.go b/cmd/remote-configuration/agent/agent_test.go index 766d0e76e1..1a1d530afa 100644 --- a/cmd/remote-configuration/agent/agent_test.go +++ b/cmd/remote-configuration/agent/agent_test.go @@ -3,22 +3,25 @@ package agent import ( "context" "fmt" + "math/rand" + "os" + "sort" + "testing" + "github.com/oklog/ulid/v2" "github.com/open-telemetry/opamp-go/client" "github.com/open-telemetry/opamp-go/client/types" "github.com/open-telemetry/opamp-go/protobufs" - "github.com/open-telemetry/opentelemetry-operator/apis/v1alpha1" - "github.com/open-telemetry/opentelemetry-operator/cmd/remote-configuration/config" - "github.com/open-telemetry/opentelemetry-operator/cmd/remote-configuration/logger" - "github.com/open-telemetry/opentelemetry-operator/cmd/remote-configuration/operator" "github.com/stretchr/testify/assert" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" - "math/rand" - "os" "sigs.k8s.io/controller-runtime/pkg/client/fake" logf "sigs.k8s.io/controller-runtime/pkg/log" - "testing" + + "github.com/open-telemetry/opentelemetry-operator/apis/v1alpha1" + "github.com/open-telemetry/opentelemetry-operator/cmd/remote-configuration/config" + "github.com/open-telemetry/opentelemetry-operator/cmd/remote-configuration/logger" + "github.com/open-telemetry/opentelemetry-operator/cmd/remote-configuration/operator" ) var ( @@ -72,7 +75,7 @@ func (m *mockOpampClient) SetPackageStatuses(statuses *protobufs.PackageStatuses return nil } -func getFakeApplier(t *testing.T) *operator.Client { +func getFakeApplier(t *testing.T, conf config.Config) *operator.Client { schemeBuilder := runtime.NewSchemeBuilder(func(s *runtime.Scheme) error { s.AddKnownTypes(v1alpha1.GroupVersion, &v1alpha1.OpenTelemetryCollector{}, &v1alpha1.OpenTelemetryCollectorList{}) metav1.AddToGroupVersion(s, v1alpha1.GroupVersion) @@ -82,7 +85,7 @@ func getFakeApplier(t *testing.T) *operator.Client { err := schemeBuilder.AddToScheme(scheme) assert.NoError(t, err, "Should be able to add custom types") c := fake.NewClientBuilder().WithScheme(scheme) - return operator.NewClient(l, c.Build()) + return operator.NewClient(l, c.Build(), conf.GetComponentsAllowed()) } func TestAgent_onMessage(t *testing.T) { @@ -174,6 +177,74 @@ func TestAgent_onMessage(t *testing.T) { }, }, }, + { + name: "all components are allowed", + fields: fields{ + configFile: "testdata/agentbasiccomponentsallowed.yaml", + }, + args: args{ + ctx: context.Background(), + configFile: map[string]string{ + "good/testnamespace": "basic.yaml", + }, + }, + want: want{ + contents: map[string][]string{ + "good/testnamespace": { + "kind: OpenTelemetryCollector", + "name: good", + "namespace: testnamespace", + "send_batch_size: 10000", + "receivers: [otlp]", + "status:", + }, + }, + status: &protobufs.RemoteConfigStatus{ + LastRemoteConfigHash: []byte("good/testnamespace405"), + Status: protobufs.RemoteConfigStatuses_RemoteConfigStatuses_APPLIED, + }, + }, + }, + { + name: "batch not allowed", + fields: fields{ + configFile: "testdata/agentbatchnotallowed.yaml", + }, + args: args{ + ctx: context.Background(), + configFile: map[string]string{ + "good/testnamespace": "basic.yaml", + }, + }, + want: want{ + contents: nil, + status: &protobufs.RemoteConfigStatus{ + LastRemoteConfigHash: []byte("good/testnamespace405"), + Status: protobufs.RemoteConfigStatuses_RemoteConfigStatuses_FAILED, + ErrorMessage: "Items in config are not allowed: [processors.batch]", + }, + }, + }, + { + name: "processors not allowed", + fields: fields{ + configFile: "testdata/agentnoprocessorsallowed.yaml", + }, + args: args{ + ctx: context.Background(), + configFile: map[string]string{ + "good/testnamespace": "basic.yaml", + }, + }, + want: want{ + contents: nil, + status: &protobufs.RemoteConfigStatus{ + LastRemoteConfigHash: []byte("good/testnamespace405"), + Status: protobufs.RemoteConfigStatuses_RemoteConfigStatuses_FAILED, + ErrorMessage: "Items in config are not allowed: [processors]", + }, + }, + }, { name: "can update config and replicas", fields: fields{ @@ -360,10 +431,10 @@ func TestAgent_onMessage(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - applier := getFakeApplier(t) mockClient := &mockOpampClient{} conf, err := config.Load(tt.fields.configFile) assert.NoError(t, err, "should be able to load config") + applier := getFakeApplier(t, conf) agent := NewAgent(clientLogger, applier, conf, mockClient) err = agent.Start() defer agent.Shutdown() @@ -410,10 +481,10 @@ func TestAgent_onMessage(t *testing.T) { } func Test_CanUpdateIdentity(t *testing.T) { - applier := getFakeApplier(t) mockClient := &mockOpampClient{} conf, err := config.Load("testdata/agent.yaml") assert.NoError(t, err, "should be able to load config") + applier := getFakeApplier(t, conf) agent := NewAgent(clientLogger, applier, conf, mockClient) err = agent.Start() defer agent.Shutdown() @@ -437,8 +508,17 @@ func getMessageDataFromConfigFile(filemap map[string]string) (*types.MessageData } configs := map[string]*protobufs.AgentConfigFile{} hash := "" - for key, filename := range filemap { - yamlFile, err := os.ReadFile(fmt.Sprintf("testdata/%s", filename)) + fileNames := make([]string, len(filemap)) + i := 0 + for k := range filemap { + fileNames[i] = k + i++ + } + // We sort the filenames so we get consistent results for multiple file loads + sort.Strings(fileNames) + + for _, key := range fileNames { + yamlFile, err := os.ReadFile(fmt.Sprintf("testdata/%s", filemap[key])) if err != nil { return toReturn, err } diff --git a/cmd/remote-configuration/agent/testdata/agentbasiccomponentsallowed.yaml b/cmd/remote-configuration/agent/testdata/agentbasiccomponentsallowed.yaml new file mode 100644 index 0000000000..288d508c7b --- /dev/null +++ b/cmd/remote-configuration/agent/testdata/agentbasiccomponentsallowed.yaml @@ -0,0 +1,25 @@ +endpoint: ws://127.0.0.1:4320/v1/opamp +protocol: wss +capabilities: + - Unspecified + - ReportsStatus + - AcceptsRemoteConfig + - ReportsEffectiveConfig + # - AcceptsPackages + # - ReportsPackageStatuses + - ReportsOwnTraces + - ReportsOwnMetrics + - ReportsOwnLogs + - AcceptsOpAMPConnectionSettings + - AcceptsOtherConnectionSettings + - AcceptsRestartCommand + - ReportsHealth + - ReportsRemoteConfig +components_allowed: + receivers: + - otlp + processors: + - memory_limiter + - batch + exporters: + - logging diff --git a/cmd/remote-configuration/agent/testdata/agentbatchnotallowed.yaml b/cmd/remote-configuration/agent/testdata/agentbatchnotallowed.yaml new file mode 100644 index 0000000000..8a03415dae --- /dev/null +++ b/cmd/remote-configuration/agent/testdata/agentbatchnotallowed.yaml @@ -0,0 +1,24 @@ +endpoint: ws://127.0.0.1:4320/v1/opamp +protocol: wss +capabilities: + - Unspecified + - ReportsStatus + - AcceptsRemoteConfig + - ReportsEffectiveConfig + # - AcceptsPackages + # - ReportsPackageStatuses + - ReportsOwnTraces + - ReportsOwnMetrics + - ReportsOwnLogs + - AcceptsOpAMPConnectionSettings + - AcceptsOtherConnectionSettings + - AcceptsRestartCommand + - ReportsHealth + - ReportsRemoteConfig +components_allowed: + receivers: + - otlp + processors: + - memory_limiter + exporters: + - logging diff --git a/cmd/remote-configuration/agent/testdata/agentnoprocessorsallowed.yaml b/cmd/remote-configuration/agent/testdata/agentnoprocessorsallowed.yaml new file mode 100644 index 0000000000..2b01d21299 --- /dev/null +++ b/cmd/remote-configuration/agent/testdata/agentnoprocessorsallowed.yaml @@ -0,0 +1,22 @@ +endpoint: ws://127.0.0.1:4320/v1/opamp +protocol: wss +capabilities: + - Unspecified + - ReportsStatus + - AcceptsRemoteConfig + - ReportsEffectiveConfig + # - AcceptsPackages + # - ReportsPackageStatuses + - ReportsOwnTraces + - ReportsOwnMetrics + - ReportsOwnLogs + - AcceptsOpAMPConnectionSettings + - AcceptsOtherConnectionSettings + - AcceptsRestartCommand + - ReportsHealth + - ReportsRemoteConfig +components_allowed: + receivers: + - otlp + exporters: + - logging diff --git a/cmd/remote-configuration/config/cli.go b/cmd/remote-configuration/config/cli.go index 984a811044..2d5abc6b1b 100644 --- a/cmd/remote-configuration/config/cli.go +++ b/cmd/remote-configuration/config/cli.go @@ -3,10 +3,11 @@ package config import ( "errors" "flag" + "io/fs" + "path/filepath" + "github.com/go-logr/logr" - "github.com/open-telemetry/opentelemetry-operator/apis/v1alpha1" "github.com/spf13/pflag" - "io/fs" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/client-go/kubernetes/scheme" @@ -14,9 +15,10 @@ import ( "k8s.io/client-go/tools/clientcmd" "k8s.io/client-go/util/homedir" "k8s.io/klog/v2" - "path/filepath" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/log/zap" + + "github.com/open-telemetry/opentelemetry-operator/apis/v1alpha1" ) var ( diff --git a/cmd/remote-configuration/config/config.go b/cmd/remote-configuration/config/config.go index f324003bd6..961416a6cd 100644 --- a/cmd/remote-configuration/config/config.go +++ b/cmd/remote-configuration/config/config.go @@ -2,15 +2,17 @@ package config import ( "fmt" - "github.com/oklog/ulid/v2" - "github.com/open-telemetry/opamp-go/client" - "github.com/open-telemetry/opamp-go/protobufs" - "github.com/open-telemetry/opentelemetry-operator/cmd/remote-configuration/logger" - "gopkg.in/yaml.v2" "math/rand" "os" "runtime" "time" + + "github.com/oklog/ulid/v2" + "github.com/open-telemetry/opamp-go/client" + "github.com/open-telemetry/opamp-go/protobufs" + "gopkg.in/yaml.v2" + + "github.com/open-telemetry/opentelemetry-operator/cmd/remote-configuration/logger" ) const ( @@ -39,6 +41,19 @@ func (c *Config) CreateClient(logger *logger.Logger) client.OpAMPClient { return client.NewWebSocket(logger) } +func (c *Config) GetComponentsAllowed() map[string]map[string]bool { + m := make(map[string]map[string]bool) + for component, componentSet := range c.ComponentsAllowed { + if _, ok := m[component]; !ok { + m[component] = make(map[string]bool) + } + for _, s := range componentSet { + m[component][s] = true + } + } + return m +} + func (c *Config) GetCapabilities() protobufs.AgentCapabilities { var capabilities int32 for _, capability := range c.Capabilities { diff --git a/cmd/remote-configuration/main.go b/cmd/remote-configuration/main.go index 87da75dcb7..8078dc4e1c 100644 --- a/cmd/remote-configuration/main.go +++ b/cmd/remote-configuration/main.go @@ -1,11 +1,12 @@ package main import ( - "github.com/open-telemetry/opentelemetry-operator/cmd/remote-configuration/logger" - "github.com/open-telemetry/opentelemetry-operator/cmd/remote-configuration/operator" "os" "os/signal" + "github.com/open-telemetry/opentelemetry-operator/cmd/remote-configuration/logger" + "github.com/open-telemetry/opentelemetry-operator/cmd/remote-configuration/operator" + "github.com/open-telemetry/opentelemetry-operator/cmd/remote-configuration/agent" "github.com/open-telemetry/opentelemetry-operator/cmd/remote-configuration/config" ) @@ -29,7 +30,7 @@ func main() { cliConf.RootLogger.Error(kubeErr, "Couldn't create kubernetes client") return } - operatorClient := operator.NewClient(cliConf.RootLogger.WithName("operator-client"), kubeClient) + operatorClient := operator.NewClient(cliConf.RootLogger.WithName("operator-client"), kubeClient, cfg.GetComponentsAllowed()) opampClient := cfg.CreateClient(agentLogger) opampAgent := agent.NewAgent(agentLogger, operatorClient, cfg, opampClient) diff --git a/cmd/remote-configuration/operator/client.go b/cmd/remote-configuration/operator/client.go index cbeccbd57d..5e7a16fe24 100644 --- a/cmd/remote-configuration/operator/client.go +++ b/cmd/remote-configuration/operator/client.go @@ -2,6 +2,8 @@ package operator import ( "context" + "fmt" + "github.com/go-logr/logr" "github.com/open-telemetry/opamp-go/protobufs" "gopkg.in/yaml.v3" @@ -25,18 +27,20 @@ type ConfigApplier interface { } type Client struct { - log logr.Logger - k8sClient client.Client - close chan bool + log logr.Logger + componentsAllowed map[string]map[string]bool + k8sClient client.Client + close chan bool } var _ ConfigApplier = &Client{} -func NewClient(log logr.Logger, c client.Client) *Client { +func NewClient(log logr.Logger, c client.Client, componentsAllowed map[string]map[string]bool) *Client { return &Client{ - log: log, - k8sClient: c, - close: make(chan bool, 1), + log: log, + componentsAllowed: componentsAllowed, + k8sClient: c, + close: make(chan bool, 1), } } @@ -81,6 +85,13 @@ func (c Client) Apply(name string, namespace string, configmap *protobufs.AgentC if len(collectorSpec.Config) == 0 { return errors.NewBadRequest("Must supply valid configuration") } + reasons, validateErr := c.validate(collectorSpec) + if validateErr != nil { + return validateErr + } + if len(reasons) > 0 { + return errors.NewBadRequest(fmt.Sprintf("Items in config are not allowed: %v", reasons)) + } collector := &v1alpha1.OpenTelemetryCollector{Spec: collectorSpec} ctx := context.Background() instance, err := c.GetInstance(name, namespace) @@ -136,3 +147,33 @@ func (c Client) GetInstance(name string, namespace string) (*v1alpha1.OpenTeleme } return &result, nil } + +func (c Client) validate(spec v1alpha1.OpenTelemetryCollectorSpec) ([]string, error) { + // Do not use this feature if it's not specified + if c.componentsAllowed == nil || len(c.componentsAllowed) == 0 { + return nil, nil + } + collectorConfig := make(map[string]map[string]interface{}) + err := yaml.Unmarshal([]byte(spec.Config), &collectorConfig) + if err != nil { + return nil, err + } + var invalidComponents []string + for component, componentMap := range collectorConfig { + if component == "service" { + // We don't care about what's in the service pipelines + // Only components declared are able to be used there. + continue + } + if _, ok := c.componentsAllowed[component]; !ok { + invalidComponents = append(invalidComponents, component) + continue + } + for componentName, _ := range componentMap { + if _, ok := c.componentsAllowed[component][componentName]; !ok { + invalidComponents = append(invalidComponents, fmt.Sprintf("%s.%s", component, componentName)) + } + } + } + return invalidComponents, nil +} diff --git a/cmd/remote-configuration/operator/client_test.go b/cmd/remote-configuration/operator/client_test.go index 20e290af41..3506a370b6 100644 --- a/cmd/remote-configuration/operator/client_test.go +++ b/cmd/remote-configuration/operator/client_test.go @@ -1,16 +1,18 @@ package operator import ( + "os" + "testing" + "github.com/open-telemetry/opamp-go/protobufs" - "github.com/open-telemetry/opentelemetry-operator/apis/v1alpha1" "github.com/stretchr/testify/assert" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" - "os" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/client/fake" logf "sigs.k8s.io/controller-runtime/pkg/log" - "testing" + + "github.com/open-telemetry/opentelemetry-operator/apis/v1alpha1" ) var ( @@ -73,7 +75,7 @@ func TestClient_Apply(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { fakeClient := getFakeClient(t) - c := NewClient(clientLogger, fakeClient) + c := NewClient(clientLogger, fakeClient, nil) var colConfig []byte var err error if len(tt.args.file) > 0 { @@ -97,7 +99,7 @@ func Test_collectorUpdate(t *testing.T) { name := "test" namespace := "testing" fakeClient := getFakeClient(t) - c := NewClient(clientLogger, fakeClient) + c := NewClient(clientLogger, fakeClient, nil) colConfig, err := loadConfig("testdata/collector.yaml") assert.NoError(t, err, "Should be no error on loading test configuration") configmap := &protobufs.AgentConfigFile{ @@ -143,7 +145,7 @@ func Test_collectorDelete(t *testing.T) { name := "test" namespace := "testing" fakeClient := getFakeClient(t) - c := NewClient(clientLogger, fakeClient) + c := NewClient(clientLogger, fakeClient, nil) colConfig, err := loadConfig("testdata/collector.yaml") assert.NoError(t, err, "Should be no error on loading test configuration") configmap := &protobufs.AgentConfigFile{ From 12552c6b72b6660a98a8a68f3b4409466b8cfaf3 Mon Sep 17 00:00:00 2001 From: Jacob Aronoff Date: Tue, 3 Jan 2023 14:49:17 -0500 Subject: [PATCH 07/16] Linting, CI, header --- cmd/remote-configuration/agent/agent.go | 40 ++++++++---- cmd/remote-configuration/agent/agent_test.go | 18 +++++- cmd/remote-configuration/config/cli.go | 14 +++++ cmd/remote-configuration/config/config.go | 18 +++++- cmd/remote-configuration/header.txt | 13 ++++ cmd/remote-configuration/logger/logger.go | 14 +++++ cmd/remote-configuration/main.go | 14 +++++ cmd/remote-configuration/metrics/reporter.go | 61 ++++++++++--------- cmd/remote-configuration/operator/client.go | 16 ++++- .../operator/client_test.go | 14 +++++ 10 files changed, 175 insertions(+), 47 deletions(-) create mode 100644 cmd/remote-configuration/header.txt diff --git a/cmd/remote-configuration/agent/agent.go b/cmd/remote-configuration/agent/agent.go index 86baefc609..a177cdee18 100644 --- a/cmd/remote-configuration/agent/agent.go +++ b/cmd/remote-configuration/agent/agent.go @@ -1,3 +1,17 @@ +// Copyright The OpenTelemetry Authors +// +// 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 agent import ( @@ -126,10 +140,7 @@ func (agent *Agent) updateAgentIdentity(instanceId ulid.ULID) { instanceId.String()) agent.instanceId = instanceId - if agent.metricReporter != nil { - // TODO: reinit or update meter (possibly using a single function to update all own connection settings - // or with having a common resource factory or so) - } + // TODO: reinit or update meter (possibly using a single function to update all own connection settings } func (agent *Agent) getNameAndNamespace(key string) (string, string, error) { @@ -153,14 +164,14 @@ func (agent *Agent) getEffectiveConfig(ctx context.Context) (*protobufs.Effectiv } instanceMap := map[string]*protobufs.AgentConfigFile{} for _, instance := range instances { - marshalled, err := yaml.Marshal(instance) + marshaled, err := yaml.Marshal(instance) if err != nil { agent.logger.Errorf("couldn't marshal collector configuration", err) return nil, err } mapKey := agent.makeKeyFromNameNamespace(instance.GetName(), instance.GetNamespace()) instanceMap[mapKey] = &protobufs.AgentConfigFile{ - Body: marshalled, + Body: marshaled, ContentType: "yaml", } } @@ -185,7 +196,7 @@ func (agent *Agent) initMeter(settings *protobufs.TelemetryConnectionSettings) { } // Take the remote config, layer it over existing, done -// INVARIANT: The caller must verify that config isn't nil _and_ the configuration has changed between calls +// INVARIANT: The caller must verify that config isn't nil _and_ the configuration has changed between calls. func (agent *Agent) applyRemoteConfig(config *protobufs.AgentRemoteConfig) (*protobufs.RemoteConfigStatus, error) { var multiErr error for key, file := range config.Config.GetConfigMap() { @@ -244,8 +255,12 @@ func (agent *Agent) onMessage(ctx context.Context, msg *types.MessageData) { if msg.RemoteConfig != nil && !bytes.Equal(agent.lastHash, msg.RemoteConfig.GetConfigHash()) { var err error status, err := agent.applyRemoteConfig(msg.RemoteConfig) - setErr := agent.opampClient.SetRemoteConfigStatus(status) - if setErr != nil { + if err != nil { + agent.logger.Errorf(err.Error()) + } + err = agent.opampClient.SetRemoteConfigStatus(status) + if err != nil { + agent.logger.Errorf(err.Error()) return } err = agent.opampClient.UpdateEffectiveConfig(ctx) @@ -254,10 +269,9 @@ func (agent *Agent) onMessage(ctx context.Context, msg *types.MessageData) { } } - // TODO: figure out why metrics aren't working - //if msg.OwnMetricsConnSettings != nil { - // agent.initMeter(msg.OwnMetricsConnSettings) - //} + if msg.OwnMetricsConnSettings != nil { + agent.initMeter(msg.OwnMetricsConnSettings) + } if msg.AgentIdentification != nil { newInstanceId, err := ulid.Parse(msg.AgentIdentification.NewInstanceUid) diff --git a/cmd/remote-configuration/agent/agent_test.go b/cmd/remote-configuration/agent/agent_test.go index 1a1d530afa..6dfadd0337 100644 --- a/cmd/remote-configuration/agent/agent_test.go +++ b/cmd/remote-configuration/agent/agent_test.go @@ -1,9 +1,23 @@ +// Copyright The OpenTelemetry Authors +// +// 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 agent import ( "context" + "crypto/rand" "fmt" - "math/rand" "os" "sort" "testing" @@ -490,7 +504,7 @@ func Test_CanUpdateIdentity(t *testing.T) { defer agent.Shutdown() assert.NoError(t, err, "should be able to start agent") previousInstanceId := agent.instanceId.String() - entropy := ulid.Monotonic(rand.New(rand.NewSource(10000)), 0) + entropy := ulid.Monotonic(rand.Reader, 0) newId := ulid.MustNew(ulid.MaxTime(), entropy) agent.onMessage(context.Background(), &types.MessageData{ AgentIdentification: &protobufs.AgentIdentification{ diff --git a/cmd/remote-configuration/config/cli.go b/cmd/remote-configuration/config/cli.go index 2d5abc6b1b..fde006c87f 100644 --- a/cmd/remote-configuration/config/cli.go +++ b/cmd/remote-configuration/config/cli.go @@ -1,3 +1,17 @@ +// Copyright The OpenTelemetry Authors +// +// 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 config import ( diff --git a/cmd/remote-configuration/config/config.go b/cmd/remote-configuration/config/config.go index 961416a6cd..263bceca0b 100644 --- a/cmd/remote-configuration/config/config.go +++ b/cmd/remote-configuration/config/config.go @@ -1,8 +1,22 @@ +// Copyright The OpenTelemetry Authors +// +// 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 config import ( + "crypto/rand" "fmt" - "math/rand" "os" "runtime" "time" @@ -99,7 +113,7 @@ func keyValuePair(key string, value string) *protobufs.KeyValue { } func (c *Config) GetNewInstanceId() ulid.ULID { - entropy := ulid.Monotonic(rand.New(rand.NewSource(10000)), 0) + entropy := ulid.Monotonic(rand.Reader, 0) return ulid.MustNew(ulid.Timestamp(time.Now()), entropy) } diff --git a/cmd/remote-configuration/header.txt b/cmd/remote-configuration/header.txt new file mode 100644 index 0000000000..3881885f31 --- /dev/null +++ b/cmd/remote-configuration/header.txt @@ -0,0 +1,13 @@ +Copyright The OpenTelemetry Authors + +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. \ No newline at end of file diff --git a/cmd/remote-configuration/logger/logger.go b/cmd/remote-configuration/logger/logger.go index 6b64619cdd..e973c7f5bd 100644 --- a/cmd/remote-configuration/logger/logger.go +++ b/cmd/remote-configuration/logger/logger.go @@ -1,3 +1,17 @@ +// Copyright The OpenTelemetry Authors +// +// 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 logger import ( diff --git a/cmd/remote-configuration/main.go b/cmd/remote-configuration/main.go index 8078dc4e1c..6c7b2c799c 100644 --- a/cmd/remote-configuration/main.go +++ b/cmd/remote-configuration/main.go @@ -1,3 +1,17 @@ +// Copyright The OpenTelemetry Authors +// +// 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 main import ( diff --git a/cmd/remote-configuration/metrics/reporter.go b/cmd/remote-configuration/metrics/reporter.go index b5275f8129..bb633a1923 100644 --- a/cmd/remote-configuration/metrics/reporter.go +++ b/cmd/remote-configuration/metrics/reporter.go @@ -1,10 +1,22 @@ +// Copyright The OpenTelemetry Authors +// +// 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 metrics import ( "context" "fmt" - "math" - "math/rand" "net/url" "os" "time" @@ -62,8 +74,7 @@ func NewMetricReporter( } u, err := url.Parse(dest.DestinationEndpoint) if err != nil { - err := fmt.Errorf("invalid DestinationEndpoint: %v", err) - return nil, err + return nil, fmt.Errorf("invalid DestinationEndpoint: %w", err) } // Create OTLP/HTTP metric exporter. @@ -78,20 +89,22 @@ func NewMetricReporter( client, err := otlpmetrichttp.New(context.Background(), opts...) if err != nil { - err := fmt.Errorf("failed to initialize otlp metric http client: %v", err) - return nil, err + return nil, fmt.Errorf("failed to initialize otlp metric http client: %w", err) } // Define the Resource to be exported with all metrics. Use OpenTelemetry semantic // conventions as the OpAMP spec requires: // https://github.com/open-telemetry/opamp-spec/blob/main/specification.md#own-telemetry-reporting - resource, err := otelresource.New(context.Background(), + resource, resourceErr := otelresource.New(context.Background(), otelresource.WithAttributes( semconv.ServiceNameKey.String(agentType), semconv.ServiceVersionKey.String(agentVersion), semconv.ServiceInstanceIDKey.String(instanceId.String()), ), ) + if resourceErr != nil { + return nil, resourceErr + } provider := sdkmetric.NewMeterProvider( sdkmetric.WithResource(resource), @@ -109,8 +122,7 @@ func NewMetricReporter( reporter.process, err = process.NewProcess(int32(os.Getpid())) if err != nil { - err := fmt.Errorf("cannot query own process: %v", err) - return nil, err + return nil, fmt.Errorf("cannot query own process: %w", err) } // Create some metrics that will be reported according to OpenTelemetry semantic @@ -119,31 +131,26 @@ func NewMetricReporter( "process.cpu.time", ) if err != nil { - err := fmt.Errorf("can't create process time metric: %v", err) - return nil, err + return nil, fmt.Errorf("can't create process time metric: %w", err) } err = reporter.meter.RegisterCallback([]instrument.Asynchronous{reporter.processCpuTime}, reporter.processCpuTimeFunc) if err != nil { - err := fmt.Errorf("can't create register callback: %v", err) - return nil, err + return nil, fmt.Errorf("can't create register callback: %w", err) } reporter.processMemoryPhysical, err = reporter.meter.AsyncInt64().Gauge( "process.memory.physical_usage", ) if err != nil { - err := fmt.Errorf("can't create memory metric: %v", err) - return nil, err + return nil, fmt.Errorf("can't create memory metric: %w", err) } err = reporter.meter.RegisterCallback([]instrument.Asynchronous{reporter.processMemoryPhysical}, reporter.processMemoryPhysicalFunc) if err != nil { - err := fmt.Errorf("can't register callback: %v", err) - return nil, err + return nil, fmt.Errorf("can't register callback: %w", err) } reporter.counter, err = reporter.meter.SyncInt64().Counter("custom_metric_ticks") if err != nil { - err := fmt.Errorf("can't register counter metric: %v", err) - return nil, err + return nil, fmt.Errorf("can't register counter metric: %w", err) } reporter.meterShutdowner = func() { _ = provider.Shutdown(context.Background()) } @@ -156,24 +163,20 @@ func NewMetricReporter( func (reporter *MetricReporter) processCpuTimeFunc(c context.Context) { times, err := reporter.process.Times() if err != nil { - reporter.logger.Errorf("Cannot get process CPU times: %v", err) + reporter.logger.Errorf("Cannot get process CPU times: %w", err) } - - // Report process CPU times, but also add some randomness to make it interesting for demo. - reporter.processCpuTime.Observe(c, math.Min(times.User+rand.Float64(), 1), attribute.String("state", "user")) - reporter.processCpuTime.Observe(c, math.Min(times.System+rand.Float64(), 1), attribute.String("state", "system")) - reporter.processCpuTime.Observe(c, math.Min(times.Iowait+rand.Float64(), 1), attribute.String("state", "wait")) + reporter.processCpuTime.Observe(c, times.User, attribute.String("state", "user")) + reporter.processCpuTime.Observe(c, times.System, attribute.String("state", "system")) + reporter.processCpuTime.Observe(c, times.Iowait, attribute.String("state", "wait")) } func (reporter *MetricReporter) processMemoryPhysicalFunc(ctx context.Context) { memory, err := reporter.process.MemoryInfo() if err != nil { - reporter.logger.Errorf("Cannot get process memory information: %v", err) + reporter.logger.Errorf("Cannot get process memory information: %w", err) return } - - // Report the RSS, but also add some randomness to make it interesting for demo. - reporter.processMemoryPhysical.Observe(ctx, int64(memory.RSS)+rand.Int63n(10000000)) + reporter.processMemoryPhysical.Observe(ctx, int64(memory.RSS)) } func (reporter *MetricReporter) sendMetrics() { diff --git a/cmd/remote-configuration/operator/client.go b/cmd/remote-configuration/operator/client.go index 5e7a16fe24..0cef481cb6 100644 --- a/cmd/remote-configuration/operator/client.go +++ b/cmd/remote-configuration/operator/client.go @@ -1,3 +1,17 @@ +// Copyright The OpenTelemetry Authors +// +// 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 operator import ( @@ -169,7 +183,7 @@ func (c Client) validate(spec v1alpha1.OpenTelemetryCollectorSpec) ([]string, er invalidComponents = append(invalidComponents, component) continue } - for componentName, _ := range componentMap { + for componentName := range componentMap { if _, ok := c.componentsAllowed[component][componentName]; !ok { invalidComponents = append(invalidComponents, fmt.Sprintf("%s.%s", component, componentName)) } diff --git a/cmd/remote-configuration/operator/client_test.go b/cmd/remote-configuration/operator/client_test.go index 3506a370b6..c9cdfe821b 100644 --- a/cmd/remote-configuration/operator/client_test.go +++ b/cmd/remote-configuration/operator/client_test.go @@ -1,3 +1,17 @@ +// Copyright The OpenTelemetry Authors +// +// 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 operator import ( From 47fac4f9d7047a247ac4191d65d2c2dd84a238ff Mon Sep 17 00:00:00 2001 From: Jacob Aronoff Date: Tue, 3 Jan 2023 14:49:30 -0500 Subject: [PATCH 08/16] Makefile CI --- .github/workflows/continuous-integration.yaml | 2 +- Makefile | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/continuous-integration.yaml b/.github/workflows/continuous-integration.yaml index 2b5a9437b0..e445cd03d9 100644 --- a/.github/workflows/continuous-integration.yaml +++ b/.github/workflows/continuous-integration.yaml @@ -33,7 +33,7 @@ jobs: runs-on: ubuntu-20.04 strategy: matrix: - workdir: [".", "./cmd/otel-allocator"] + workdir: [".", "./cmd/otel-allocator", "./cmd/remote-configuration"] steps: - name: Set up Go uses: actions/setup-go@v3 diff --git a/Makefile b/Makefile index 68439b96ea..b83fb8bc8d 100644 --- a/Makefile +++ b/Makefile @@ -90,6 +90,7 @@ ci: test test: generate fmt vet ensure-generate-is-noop envtest KUBEBUILDER_ASSETS="$(shell $(ENVTEST) use $(KUBE_VERSION) -p path)" go test ${GOTEST_OPTS} ./... cd cmd/otel-allocator && KUBEBUILDER_ASSETS="$(shell $(ENVTEST) use $(KUBE_VERSION) -p path)" go test ${GOTEST_OPTS} ./... + cd cmd/remote-configuration && KUBEBUILDER_ASSETS="$(shell $(ENVTEST) use $(KUBE_VERSION) -p path)" go test ${GOTEST_OPTS} ./... # Build manager binary .PHONY: manager @@ -152,6 +153,7 @@ vet: lint: golangci-lint run cd cmd/otel-allocator && golangci-lint run + cd cmd/remote-configuration && golangci-lint run # Generate code .PHONY: generate From f153f6f4ea00d52cbf9af02ccb83ba830dee1efb Mon Sep 17 00:00:00 2001 From: Jacob Aronoff Date: Tue, 3 Jan 2023 18:12:34 -0500 Subject: [PATCH 09/16] Added comments, created an object for use by the applied keys map --- cmd/remote-configuration/agent/agent.go | 93 ++++++++++-------- cmd/remote-configuration/agent/agent_test.go | 2 +- .../agent/collector_key.go | 43 ++++++++ .../agent/collector_key_test.go | 98 +++++++++++++++++++ cmd/remote-configuration/operator/client.go | 11 ++- 5 files changed, 201 insertions(+), 46 deletions(-) create mode 100644 cmd/remote-configuration/agent/collector_key.go create mode 100644 cmd/remote-configuration/agent/collector_key_test.go diff --git a/cmd/remote-configuration/agent/agent.go b/cmd/remote-configuration/agent/agent.go index a177cdee18..961285c1a5 100644 --- a/cmd/remote-configuration/agent/agent.go +++ b/cmd/remote-configuration/agent/agent.go @@ -17,9 +17,6 @@ package agent import ( "bytes" "context" - "errors" - "fmt" - "strings" "time" "gopkg.in/yaml.v3" @@ -40,8 +37,7 @@ import ( type Agent struct { logger types.Logger - // A set of the applied object keys (name/namespace) - appliedKeys map[string]bool + appliedKeys map[collectorKey]bool startTime uint64 lastHash []byte @@ -60,13 +56,13 @@ func NewAgent(logger types.Logger, applier operator.ConfigApplier, config config config: config, applier: applier, logger: logger, - appliedKeys: map[string]bool{}, + appliedKeys: map[collectorKey]bool{}, instanceId: config.GetNewInstanceId(), agentDescription: config.GetDescription(), opampClient: opampClient, } - agent.logger.Debugf("Agent starting, id=%v, type=%s, version=%s.", + agent.logger.Debugf("Agent created, id=%v, type=%s, version=%s.", agent.instanceId.String(), config.GetAgentType(), config.GetAgentVersion()) return agent @@ -80,22 +76,27 @@ func (agent *Agent) getHealth() *protobufs.AgentHealth { } } +// onConnect is called when an agent is successfully connected to a server. func (agent *Agent) onConnect() { agent.logger.Debugf("Connected to the server.") } +// onConnectFailed is called when an agent was unable to connect to a server. func (agent *Agent) onConnectFailed(err error) { agent.logger.Errorf("Failed to connect to the server: %v", err) } +// onError is called when an agent receives an error response from the server. func (agent *Agent) onError(err *protobufs.ServerErrorResponse) { agent.logger.Errorf("Server returned an error response: %v", err.ErrorMessage) } +// saveRemoteConfigStatus receives a status from the server when the server sets a remote configuration. func (agent *Agent) saveRemoteConfigStatus(_ context.Context, status *protobufs.RemoteConfigStatus) { agent.remoteConfigStatus = status } +// Start sets up the callbacks for the OpAMP client and begins the client's connection to the server. func (agent *Agent) Start() error { agent.startTime = uint64(time.Now().UnixNano()) settings := types.StartSettings{ @@ -134,28 +135,17 @@ func (agent *Agent) Start() error { return nil } +// updateAgentIdentity receives a new instanced Id from the remote server and updates the agent's instanceID field. +// The meter will be reinitialized by the onMessage function. func (agent *Agent) updateAgentIdentity(instanceId ulid.ULID) { agent.logger.Debugf("Agent identify is being changed from id=%v to id=%v", agent.instanceId.String(), instanceId.String()) agent.instanceId = instanceId - - // TODO: reinit or update meter (possibly using a single function to update all own connection settings -} - -func (agent *Agent) getNameAndNamespace(key string) (string, string, error) { - s := strings.Split(key, "/") - // We expect map keys to be of the form name/namespace - if len(s) != 2 { - return "", "", errors.New("invalid key") - } - return s[0], s[1], nil -} - -func (agent *Agent) makeKeyFromNameNamespace(name string, namespace string) string { - return fmt.Sprintf("%s/%s", name, namespace) } +// getEffectiveConfig is called when a remote server needs to learn of the current effective configuration of each +// collector the agent is managing. func (agent *Agent) getEffectiveConfig(ctx context.Context) (*protobufs.EffectiveConfig, error) { instances, err := agent.applier.ListInstances() if err != nil { @@ -169,8 +159,8 @@ func (agent *Agent) getEffectiveConfig(ctx context.Context) (*protobufs.Effectiv agent.logger.Errorf("couldn't marshal collector configuration", err) return nil, err } - mapKey := agent.makeKeyFromNameNamespace(instance.GetName(), instance.GetNamespace()) - instanceMap[mapKey] = &protobufs.AgentConfigFile{ + mapKey := newCollectorKey(instance.GetName(), instance.GetNamespace()) + instanceMap[mapKey.String()] = &protobufs.AgentConfigFile{ Body: marshaled, ContentType: "yaml", } @@ -182,6 +172,9 @@ func (agent *Agent) getEffectiveConfig(ctx context.Context) (*protobufs.Effectiv }, nil } +// initMeter initializes a metric reporter instance for the agent to report runtime metrics to the +// configured destination. The settings received will be used to initialize a reporter, shutting down any previously +// running metrics reporting instances. func (agent *Agent) initMeter(settings *protobufs.TelemetryConnectionSettings) { reporter, err := metrics.NewMetricReporter(agent.logger, settings, agent.config.GetAgentType(), agent.config.GetAgentVersion(), agent.instanceId) if err != nil { @@ -195,60 +188,71 @@ func (agent *Agent) initMeter(settings *protobufs.TelemetryConnectionSettings) { agent.metricReporter = reporter } -// Take the remote config, layer it over existing, done +// applyRemoteConfig receives a remote configuration from a remote server of the following form: +// +// map[name/namespace] -> collector CRD spec +// +// For every key in the received remote configuration, the agent attempts to apply it to the connected +// Kubernetes cluster. If an agent fails to apply a collector CRD, it will continue to the next entry. The agent will +// store the received configuration hash regardless of application status as per the OpAMP spec. +// // INVARIANT: The caller must verify that config isn't nil _and_ the configuration has changed between calls. func (agent *Agent) applyRemoteConfig(config *protobufs.AgentRemoteConfig) (*protobufs.RemoteConfigStatus, error) { var multiErr error + // Apply changes from the received config map for key, file := range config.Config.GetConfigMap() { if len(key) == 0 || len(file.Body) == 0 { continue } - name, namespace, err := agent.getNameAndNamespace(key) + colKey, err := collectorKeyFromKey(key) if err != nil { multiErr = multierr.Append(multiErr, err) continue } - err = agent.applier.Apply(name, namespace, file) + err = agent.applier.Apply(colKey.name, colKey.namespace, file) if err != nil { multiErr = multierr.Append(multiErr, err) continue } - agent.appliedKeys[key] = true + agent.appliedKeys[colKey] = true } + // Check if anything was deleted for collectorKey := range agent.appliedKeys { - name, namespace, err := agent.getNameAndNamespace(collectorKey) - if err != nil { - multiErr = multierr.Append(multiErr, err) - continue - } - if _, ok := config.Config.GetConfigMap()[collectorKey]; !ok { - err = agent.applier.Delete(name, namespace) + if _, ok := config.Config.GetConfigMap()[collectorKey.String()]; !ok { + err := agent.applier.Delete(collectorKey.name, collectorKey.namespace) if err != nil { multiErr = multierr.Append(multiErr, err) } } } + agent.lastHash = config.GetConfigHash() if multiErr != nil { return &protobufs.RemoteConfigStatus{ - LastRemoteConfigHash: config.GetConfigHash(), + LastRemoteConfigHash: agent.lastHash, Status: protobufs.RemoteConfigStatuses_RemoteConfigStatuses_FAILED, ErrorMessage: multiErr.Error(), }, multiErr } - agent.lastHash = config.ConfigHash return &protobufs.RemoteConfigStatus{ - LastRemoteConfigHash: config.ConfigHash, + LastRemoteConfigHash: agent.lastHash, Status: protobufs.RemoteConfigStatuses_RemoteConfigStatuses_APPLIED, }, nil } +// Shutdown will stop the OpAMP client gracefully. func (agent *Agent) Shutdown() { agent.logger.Debugf("Agent shutting down...") if agent.opampClient != nil { - _ = agent.opampClient.Stop(context.Background()) + err := agent.opampClient.Stop(context.Background()) + if err != nil { + agent.logger.Errorf(err.Error()) + } } } +// onMessage is called when the client receives a new message from the connected OpAMP server. The agent is responsible +// for checking if it should apply a new remote configuration. The agent will also initialize metrics based on the +// settings received from the server. The agent is also able to update its identifier if it needs to. func (agent *Agent) onMessage(ctx context.Context, msg *types.MessageData) { // If we received remote configuration, and it's not the same as the previously applied one @@ -269,15 +273,18 @@ func (agent *Agent) onMessage(ctx context.Context, msg *types.MessageData) { } } - if msg.OwnMetricsConnSettings != nil { - agent.initMeter(msg.OwnMetricsConnSettings) - } - + // The instance id is updated prior to the meter initialization so that the new meter will report using the updated + // instanceId. if msg.AgentIdentification != nil { newInstanceId, err := ulid.Parse(msg.AgentIdentification.NewInstanceUid) if err != nil { agent.logger.Errorf(err.Error()) + return } agent.updateAgentIdentity(newInstanceId) } + + if msg.OwnMetricsConnSettings != nil { + agent.initMeter(msg.OwnMetricsConnSettings) + } } diff --git a/cmd/remote-configuration/agent/agent_test.go b/cmd/remote-configuration/agent/agent_test.go index 6dfadd0337..8a3aeb4420 100644 --- a/cmd/remote-configuration/agent/agent_test.go +++ b/cmd/remote-configuration/agent/agent_test.go @@ -409,7 +409,7 @@ func TestAgent_onMessage(t *testing.T) { }, }, { - name: "Can delete existing collector", + name: "can delete existing collector", fields: fields{ configFile: "testdata/agent.yaml", }, diff --git a/cmd/remote-configuration/agent/collector_key.go b/cmd/remote-configuration/agent/collector_key.go new file mode 100644 index 0000000000..f1353d3472 --- /dev/null +++ b/cmd/remote-configuration/agent/collector_key.go @@ -0,0 +1,43 @@ +// Copyright The OpenTelemetry Authors +// +// 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 agent + +import ( + "errors" + "fmt" + "strings" +) + +type collectorKey struct { + name string + namespace string +} + +func newCollectorKey(name string, namespace string) collectorKey { + return collectorKey{name: name, namespace: namespace} +} + +func collectorKeyFromKey(key string) (collectorKey, error) { + s := strings.Split(key, "/") + // We expect map keys to be of the form name/namespace + if len(s) != 2 { + return collectorKey{}, errors.New("invalid key") + } + return newCollectorKey(s[0], s[1]), nil +} + +func (k collectorKey) String() string { + return fmt.Sprintf("%s/%s", k.name, k.namespace) +} diff --git a/cmd/remote-configuration/agent/collector_key_test.go b/cmd/remote-configuration/agent/collector_key_test.go new file mode 100644 index 0000000000..b0b2546485 --- /dev/null +++ b/cmd/remote-configuration/agent/collector_key_test.go @@ -0,0 +1,98 @@ +// Copyright The OpenTelemetry Authors +// +// 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 agent + +import ( + "fmt" + "testing" + + "github.com/stretchr/testify/assert" +) + +func Test_collectorKeyFromKey(t *testing.T) { + type args struct { + key string + } + tests := []struct { + name string + args args + want collectorKey + wantErr assert.ErrorAssertionFunc + }{ + { + name: "base case", + args: args{ + key: "good/namespace", + }, + want: collectorKey{ + name: "good", + namespace: "namespace", + }, + wantErr: assert.NoError, + }, + { + name: "unable to get key", + args: args{ + key: "badnamespace", + }, + want: collectorKey{}, + wantErr: assert.Error, + }, + { + name: "too many slashes", + args: args{ + key: "too/many/slashes", + }, + want: collectorKey{}, + wantErr: assert.Error, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := collectorKeyFromKey(tt.args.key) + if !tt.wantErr(t, err, fmt.Sprintf("collectorKeyFromKey(%v)", tt.args.key)) { + return + } + assert.Equalf(t, tt.want, got, "collectorKeyFromKey(%v)", tt.args.key) + }) + } +} + +func Test_collectorKey_String(t *testing.T) { + type fields struct { + name string + namespace string + } + tests := []struct { + name string + fields fields + want string + }{ + { + name: "can make a key", + fields: fields{ + name: "good", + namespace: "namespace", + }, + want: "good/namespace", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + k := newCollectorKey(tt.fields.name, tt.fields.namespace) + assert.Equalf(t, tt.want, k.String(), "String()") + }) + } +} diff --git a/cmd/remote-configuration/operator/client.go b/cmd/remote-configuration/operator/client.go index 0cef481cb6..89ef87e69e 100644 --- a/cmd/remote-configuration/operator/client.go +++ b/cmd/remote-configuration/operator/client.go @@ -34,9 +34,16 @@ const ( ) type ConfigApplier interface { + // Apply receives a name and namespace to apply an OpenTelemetryCollector CRD that is contained in the configmap. Apply(name string, namespace string, configmap *protobufs.AgentConfigFile) error + + // GetInstance retrieves an OpenTelemetryCollector CRD given a name and namespace. GetInstance(name string, namespace string) (*v1alpha1.OpenTelemetryCollector, error) + + // ListInstances retrieves all OpenTelemetryCollector CRDs created by the remote-configuration agent. ListInstances() ([]v1alpha1.OpenTelemetryCollector, error) + + // Delete attempts to delete an OpenTelemetryCollector object given a name and namespace. Delete(name string, namespace string) error } @@ -175,8 +182,8 @@ func (c Client) validate(spec v1alpha1.OpenTelemetryCollectorSpec) ([]string, er var invalidComponents []string for component, componentMap := range collectorConfig { if component == "service" { - // We don't care about what's in the service pipelines - // Only components declared are able to be used there. + // We don't care about what's in the service pipelines. + // Only components declared in the configuration can be used in the service pipeline. continue } if _, ok := c.componentsAllowed[component]; !ok { From 1d28d6fd422066feb8cda369ac56b372e37488c5 Mon Sep 17 00:00:00 2001 From: Jacob Aronoff Date: Wed, 4 Jan 2023 10:37:16 -0500 Subject: [PATCH 10/16] Fix makefile, update to use require --- Makefile | 3 +- cmd/remote-configuration/agent/agent_test.go | 19 ++++++------ .../operator/client_test.go | 29 ++++++++++--------- 3 files changed, 26 insertions(+), 25 deletions(-) diff --git a/Makefile b/Makefile index 6e5b657669..ffab235855 100644 --- a/Makefile +++ b/Makefile @@ -179,9 +179,8 @@ e2e-log-operator: kubectl get deploy -A .PHONY: prepare-e2e -prepare-e2e: kuttl set-image-controller container container-target-allocator start-kind cert-manager install-metrics-server install-openshift-routes load-image-all deploy +prepare-e2e: kuttl set-image-controller container container-target-allocator container-remote-configuration start-kind cert-manager install-metrics-server install-openshift-routes load-image-all deploy TARGETALLOCATOR_IMG=$(TARGETALLOCATOR_IMG) ./hack/modify-test-images.sh - REMOTECONFIGURATION_IMG=$(REMOTECONFIGURATION_IMG) ./hack/modify-test-images.sh .PHONY: scorecard-tests scorecard-tests: operator-sdk diff --git a/cmd/remote-configuration/agent/agent_test.go b/cmd/remote-configuration/agent/agent_test.go index 8a3aeb4420..c295d7b4a5 100644 --- a/cmd/remote-configuration/agent/agent_test.go +++ b/cmd/remote-configuration/agent/agent_test.go @@ -18,6 +18,7 @@ import ( "context" "crypto/rand" "fmt" + "github.com/stretchr/testify/require" "os" "sort" "testing" @@ -97,7 +98,7 @@ func getFakeApplier(t *testing.T, conf config.Config) *operator.Client { }) scheme := runtime.NewScheme() err := schemeBuilder.AddToScheme(scheme) - assert.NoError(t, err, "Should be able to add custom types") + require.NoError(t, err, "Should be able to add custom types") c := fake.NewClientBuilder().WithScheme(scheme) return operator.NewClient(l, c.Build(), conf.GetComponentsAllowed()) } @@ -447,17 +448,17 @@ func TestAgent_onMessage(t *testing.T) { t.Run(tt.name, func(t *testing.T) { mockClient := &mockOpampClient{} conf, err := config.Load(tt.fields.configFile) - assert.NoError(t, err, "should be able to load config") + require.NoError(t, err, "should be able to load config") applier := getFakeApplier(t, conf) agent := NewAgent(clientLogger, applier, conf, mockClient) err = agent.Start() defer agent.Shutdown() - assert.NoError(t, err, "should be able to start agent") + require.NoError(t, err, "should be able to start agent") data, err := getMessageDataFromConfigFile(tt.args.configFile) - assert.NoError(t, err, "should be able to load data") + require.NoError(t, err, "should be able to load data") agent.onMessage(tt.args.ctx, data) effectiveConfig, err := agent.getEffectiveConfig(tt.args.ctx) - assert.NoError(t, err, "should be able to get effective config") + require.NoError(t, err, "should be able to get effective config") if tt.args.configFile != nil { // We should only expect this to happen if we supply configuration assert.Equal(t, effectiveConfig, mockClient.lastEffectiveConfig, "client's config should be updated") @@ -476,10 +477,10 @@ func TestAgent_onMessage(t *testing.T) { return } nextData, err := getMessageDataFromConfigFile(tt.args.nextConfigFile) - assert.NoError(t, err, "should be able to load updated data") + require.NoError(t, err, "should be able to load updated data") agent.onMessage(tt.args.ctx, nextData) nextEffectiveConfig, err := agent.getEffectiveConfig(tt.args.ctx) - assert.NoError(t, err, "should be able to get updated effective config") + require.NoError(t, err, "should be able to get updated effective config") assert.Equal(t, nextEffectiveConfig, mockClient.lastEffectiveConfig, "client's config should be updated") assert.NotNilf(t, nextEffectiveConfig.ConfigMap.GetConfigMap(), "configmap should have updated data") for colNameNamespace, expectedContents := range tt.want.nextContents { @@ -497,12 +498,12 @@ func TestAgent_onMessage(t *testing.T) { func Test_CanUpdateIdentity(t *testing.T) { mockClient := &mockOpampClient{} conf, err := config.Load("testdata/agent.yaml") - assert.NoError(t, err, "should be able to load config") + require.NoError(t, err, "should be able to load config") applier := getFakeApplier(t, conf) agent := NewAgent(clientLogger, applier, conf, mockClient) err = agent.Start() defer agent.Shutdown() - assert.NoError(t, err, "should be able to start agent") + require.NoError(t, err, "should be able to start agent") previousInstanceId := agent.instanceId.String() entropy := ulid.Monotonic(rand.Reader, 0) newId := ulid.MustNew(ulid.MaxTime(), entropy) diff --git a/cmd/remote-configuration/operator/client_test.go b/cmd/remote-configuration/operator/client_test.go index c9cdfe821b..1b688967ec 100644 --- a/cmd/remote-configuration/operator/client_test.go +++ b/cmd/remote-configuration/operator/client_test.go @@ -15,6 +15,7 @@ package operator import ( + "github.com/stretchr/testify/require" "os" "testing" @@ -41,7 +42,7 @@ func getFakeClient(t *testing.T) client.WithWatch { }) scheme := runtime.NewScheme() err := schemeBuilder.AddToScheme(scheme) - assert.NoError(t, err, "Should be able to add custom types") + require.NoError(t, err, "Should be able to add custom types") c := fake.NewClientBuilder().WithScheme(scheme) return c.Build() } @@ -94,7 +95,7 @@ func TestClient_Apply(t *testing.T) { var err error if len(tt.args.file) > 0 { colConfig, err = loadConfig(tt.args.file) - assert.NoError(t, err, "Should be no error on loading test configuration") + require.NoError(t, err, "Should be no error on loading test configuration") } else { colConfig = []byte(tt.args.config) } @@ -115,18 +116,18 @@ func Test_collectorUpdate(t *testing.T) { fakeClient := getFakeClient(t) c := NewClient(clientLogger, fakeClient, nil) colConfig, err := loadConfig("testdata/collector.yaml") - assert.NoError(t, err, "Should be no error on loading test configuration") + require.NoError(t, err, "Should be no error on loading test configuration") configmap := &protobufs.AgentConfigFile{ Body: colConfig, ContentType: "yaml", } // Apply a valid initial configuration err = c.Apply(name, namespace, configmap) - assert.NoError(t, err, "Should apply base config") + require.NoError(t, err, "Should apply base config") // Get the newly created collector instance, err := c.GetInstance(name, namespace) - assert.NoError(t, err, "Should be able to get the newly created instance") + require.NoError(t, err, "Should be able to get the newly created instance") assert.Contains(t, instance.Spec.Config, "processors: []") // Try updating with an invalid one @@ -136,21 +137,21 @@ func Test_collectorUpdate(t *testing.T) { // Update successfully with a valid configuration newColConfig, err := loadConfig("testdata/updated-collector.yaml") - assert.NoError(t, err, "Should be no error on loading test configuration") + require.NoError(t, err, "Should be no error on loading test configuration") newConfigMap := &protobufs.AgentConfigFile{ Body: newColConfig, ContentType: "yaml", } err = c.Apply(name, namespace, newConfigMap) - assert.NoError(t, err, "Should be able to update collector") + require.NoError(t, err, "Should be able to update collector") // Get the updated collector updatedInstance, err := c.GetInstance(name, namespace) - assert.NoError(t, err, "Should be able to get the updated instance") + require.NoError(t, err, "Should be able to get the updated instance") assert.Contains(t, updatedInstance.Spec.Config, "processors: [memory_limiter, batch]") allInstances, err := c.ListInstances() - assert.NoError(t, err, "Should be able to list all collectors") + require.NoError(t, err, "Should be able to list all collectors") assert.Len(t, allInstances, 1) assert.Equal(t, allInstances[0], *updatedInstance) } @@ -161,27 +162,27 @@ func Test_collectorDelete(t *testing.T) { fakeClient := getFakeClient(t) c := NewClient(clientLogger, fakeClient, nil) colConfig, err := loadConfig("testdata/collector.yaml") - assert.NoError(t, err, "Should be no error on loading test configuration") + require.NoError(t, err, "Should be no error on loading test configuration") configmap := &protobufs.AgentConfigFile{ Body: colConfig, ContentType: "yaml", } // Apply a valid initial configuration err = c.Apply(name, namespace, configmap) - assert.NoError(t, err, "Should apply base config") + require.NoError(t, err, "Should apply base config") // Get the newly created collector instance, err := c.GetInstance(name, namespace) - assert.NoError(t, err, "Should be able to get the newly created instance") + require.NoError(t, err, "Should be able to get the newly created instance") assert.Contains(t, instance.Spec.Config, "processors: []") // Delete it err = c.Delete(name, namespace) - assert.NoError(t, err, "Should be able to delete a collector") + require.NoError(t, err, "Should be able to delete a collector") // Check there's nothing left allInstances, err := c.ListInstances() - assert.NoError(t, err, "Should be able to list all collectors") + require.NoError(t, err, "Should be able to list all collectors") assert.Len(t, allInstances, 0) } From d5622cc60061c9dee97dff8ac949a21f73ec782e Mon Sep 17 00:00:00 2001 From: Jacob Aronoff Date: Wed, 4 Jan 2023 10:44:49 -0500 Subject: [PATCH 11/16] IMports --- cmd/remote-configuration/agent/agent_test.go | 3 ++- cmd/remote-configuration/operator/client_test.go | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/cmd/remote-configuration/agent/agent_test.go b/cmd/remote-configuration/agent/agent_test.go index c295d7b4a5..b8d06dc60c 100644 --- a/cmd/remote-configuration/agent/agent_test.go +++ b/cmd/remote-configuration/agent/agent_test.go @@ -18,11 +18,12 @@ import ( "context" "crypto/rand" "fmt" - "github.com/stretchr/testify/require" "os" "sort" "testing" + "github.com/stretchr/testify/require" + "github.com/oklog/ulid/v2" "github.com/open-telemetry/opamp-go/client" "github.com/open-telemetry/opamp-go/client/types" diff --git a/cmd/remote-configuration/operator/client_test.go b/cmd/remote-configuration/operator/client_test.go index 1b688967ec..9d4284b90c 100644 --- a/cmd/remote-configuration/operator/client_test.go +++ b/cmd/remote-configuration/operator/client_test.go @@ -15,10 +15,11 @@ package operator import ( - "github.com/stretchr/testify/require" "os" "testing" + "github.com/stretchr/testify/require" + "github.com/open-telemetry/opamp-go/protobufs" "github.com/stretchr/testify/assert" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" From 30aa8a2b85c777927fcdc5f9e4592372e2062a45 Mon Sep 17 00:00:00 2001 From: Jacob Aronoff Date: Fri, 6 Jan 2023 12:18:58 -0500 Subject: [PATCH 12/16] updated from comments --- cmd/remote-configuration/Dockerfile | 2 +- cmd/remote-configuration/agent/agent.go | 6 +- cmd/remote-configuration/go.mod | 2 +- cmd/remote-configuration/go.sum | 4 +- cmd/remote-configuration/main.go | 4 +- cmd/remote-configuration/metrics/reporter.go | 65 +++++--------------- cmd/remote-configuration/operator/client.go | 12 ++-- 7 files changed, 32 insertions(+), 63 deletions(-) diff --git a/cmd/remote-configuration/Dockerfile b/cmd/remote-configuration/Dockerfile index dbc121f7b1..63193e5146 100644 --- a/cmd/remote-configuration/Dockerfile +++ b/cmd/remote-configuration/Dockerfile @@ -14,7 +14,7 @@ COPY . . RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o main . ######## Start a new stage from scratch ####### -FROM alpine:latest +FROM scratch RUN apk --no-cache add ca-certificates diff --git a/cmd/remote-configuration/agent/agent.go b/cmd/remote-configuration/agent/agent.go index 961285c1a5..d687c2b3af 100644 --- a/cmd/remote-configuration/agent/agent.go +++ b/cmd/remote-configuration/agent/agent.go @@ -68,6 +68,7 @@ func NewAgent(logger types.Logger, applier operator.ConfigApplier, config config return agent } +// TODO: Something should run on a schedule to set the health of the OpAMP client. func (agent *Agent) getHealth() *protobufs.AgentHealth { return &protobufs.AgentHealth{ Healthy: true, @@ -138,7 +139,7 @@ func (agent *Agent) Start() error { // updateAgentIdentity receives a new instanced Id from the remote server and updates the agent's instanceID field. // The meter will be reinitialized by the onMessage function. func (agent *Agent) updateAgentIdentity(instanceId ulid.ULID) { - agent.logger.Debugf("Agent identify is being changed from id=%v to id=%v", + agent.logger.Debugf("Agent identity is being changed from id=%v to id=%v", agent.instanceId.String(), instanceId.String()) agent.instanceId = instanceId @@ -248,6 +249,9 @@ func (agent *Agent) Shutdown() { agent.logger.Errorf(err.Error()) } } + if agent.metricReporter != nil { + agent.metricReporter.Shutdown() + } } // onMessage is called when the client receives a new message from the connected OpAMP server. The agent is responsible diff --git a/cmd/remote-configuration/go.mod b/cmd/remote-configuration/go.mod index 9ebba0e1f9..d583c88364 100644 --- a/cmd/remote-configuration/go.mod +++ b/cmd/remote-configuration/go.mod @@ -11,7 +11,7 @@ require ( github.com/spf13/pflag v1.0.5 github.com/stretchr/testify v1.8.1 go.opentelemetry.io/otel v1.11.2 - go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v0.34.0 + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.34.0 go.opentelemetry.io/otel/metric v0.34.0 go.opentelemetry.io/otel/sdk v1.11.2 go.opentelemetry.io/otel/sdk/metric v0.34.0 diff --git a/cmd/remote-configuration/go.sum b/cmd/remote-configuration/go.sum index bdd771b446..fdcc339d77 100644 --- a/cmd/remote-configuration/go.sum +++ b/cmd/remote-configuration/go.sum @@ -327,8 +327,8 @@ go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.11.2 h1:htgM8vZIF8oPSC go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.11.2/go.mod h1:rqbht/LlhVBgn5+k3M5QK96K5Xb0DvXpMJ5SFQpY6uw= go.opentelemetry.io/otel/exporters/otlp/otlpmetric v0.34.0 h1:kpskzLZ60cJ48SJ4uxWa6waBL+4kSV6nVK8rP+QM8Wg= go.opentelemetry.io/otel/exporters/otlp/otlpmetric v0.34.0/go.mod h1:4+x3i62TEegDHuzNva0bMcAN8oUi5w4liGb1d/VgPYo= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v0.34.0 h1:t4Ajxj8JGjxkqoBtbkCOY2cDUl9RwiNE9LPQavooi9U= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v0.34.0/go.mod h1:WO7omosl4P7JoanH9NgInxDxEn2F2M5YinIh8EyeT8w= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.34.0 h1:e7kFb4pJLbhJgAwUdoVTHzB9pGujs5O8/7gFyZL88fg= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.34.0/go.mod h1:3x00m9exjIbhK+zTO4MsCSlfbVmgvLP0wjDgDKa/8bw= go.opentelemetry.io/otel/metric v0.34.0 h1:MCPoQxcg/26EuuJwpYN1mZTeCYAUGx8ABxfW07YkjP8= go.opentelemetry.io/otel/metric v0.34.0/go.mod h1:ZFuI4yQGNCupurTXCwkeD/zHBt+C2bR7bw5JqUm/AP8= go.opentelemetry.io/otel/sdk v1.11.2 h1:GF4JoaEx7iihdMFu30sOyRx52HDHOkl9xQ8SMqNXUiU= diff --git a/cmd/remote-configuration/main.go b/cmd/remote-configuration/main.go index 6c7b2c799c..4885b8233b 100644 --- a/cmd/remote-configuration/main.go +++ b/cmd/remote-configuration/main.go @@ -42,7 +42,7 @@ func main() { kubeClient, kubeErr := cliConf.GetKubernetesClient() if kubeErr != nil { cliConf.RootLogger.Error(kubeErr, "Couldn't create kubernetes client") - return + os.Exit(1) } operatorClient := operator.NewClient(cliConf.RootLogger.WithName("operator-client"), kubeClient, cfg.GetComponentsAllowed()) @@ -51,7 +51,7 @@ func main() { if err := opampAgent.Start(); err != nil { cliConf.RootLogger.Error(err, "Cannot start OpAMP client") - return + os.Exit(1) } interrupt := make(chan os.Signal, 1) diff --git a/cmd/remote-configuration/metrics/reporter.go b/cmd/remote-configuration/metrics/reporter.go index bb633a1923..e07d259d50 100644 --- a/cmd/remote-configuration/metrics/reporter.go +++ b/cmd/remote-configuration/metrics/reporter.go @@ -17,20 +17,17 @@ package metrics import ( "context" "fmt" - "net/url" "os" "time" "github.com/oklog/ulid/v2" "github.com/shirou/gopsutil/process" "go.opentelemetry.io/otel/attribute" - "go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp" + "go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc" "go.opentelemetry.io/otel/metric" - "go.opentelemetry.io/otel/metric/global" "go.opentelemetry.io/otel/metric/instrument" "go.opentelemetry.io/otel/metric/instrument/asyncfloat64" "go.opentelemetry.io/otel/metric/instrument/asyncint64" - "go.opentelemetry.io/otel/metric/instrument/syncint64" sdkmetric "go.opentelemetry.io/otel/sdk/metric" otelresource "go.opentelemetry.io/otel/sdk/resource" semconv "go.opentelemetry.io/otel/semconv/v1.4.0" @@ -53,10 +50,12 @@ type MetricReporter struct { // Some example metrics to report. processMemoryPhysical asyncint64.Gauge - counter syncint64.Counter processCpuTime asyncfloat64.Counter } +// NewMetricReporter creates an OTLP gRPC client to the destination address supplied by the server. +// TODO: do more validation on the endpoint, allow for http. +// TODO: set global provider and add more metrics to be reported. func NewMetricReporter( logger types.Logger, dest *protobufs.TelemetryConnectionSettings, @@ -65,31 +64,25 @@ func NewMetricReporter( instanceId ulid.ULID, ) (*MetricReporter, error) { - // Check the destination credentials to make sure they look like a valid OTLP/HTTP - // destination. - if dest.DestinationEndpoint == "" { err := fmt.Errorf("metric destination must specify DestinationEndpoint") return nil, err } - u, err := url.Parse(dest.DestinationEndpoint) - if err != nil { - return nil, fmt.Errorf("invalid DestinationEndpoint: %w", err) - } - // Create OTLP/HTTP metric exporter. - opts := []otlpmetrichttp.Option{ - otlpmetrichttp.WithEndpoint(u.Host), - otlpmetrichttp.WithURLPath(u.Path), + // Create OTLP/grpc metric exporter. + opts := []otlpmetricgrpc.Option{ + otlpmetricgrpc.WithEndpoint(dest.DestinationEndpoint), } - if u.Scheme == "http" { - opts = append(opts, otlpmetrichttp.WithInsecure()) + headers := map[string]string{} + for _, header := range dest.Headers.GetHeaders() { + headers[header.GetKey()] = header.GetValue() } + opts = append(opts, otlpmetricgrpc.WithHeaders(headers)) - client, err := otlpmetrichttp.New(context.Background(), opts...) + client, err := otlpmetricgrpc.New(context.Background(), opts...) if err != nil { - return nil, fmt.Errorf("failed to initialize otlp metric http client: %w", err) + return nil, fmt.Errorf("failed to initialize otlp metric grpc client: %w", err) } // Define the Resource to be exported with all metrics. Use OpenTelemetry semantic @@ -108,9 +101,7 @@ func NewMetricReporter( provider := sdkmetric.NewMeterProvider( sdkmetric.WithResource(resource), - sdkmetric.WithReader(sdkmetric.NewPeriodicReader(client))) - - global.SetMeterProvider(provider) + sdkmetric.WithReader(sdkmetric.NewPeriodicReader(client, sdkmetric.WithInterval(5*time.Second)))) reporter := &MetricReporter{ logger: logger, @@ -118,7 +109,7 @@ func NewMetricReporter( reporter.done = make(chan struct{}) - reporter.meter = global.Meter("opamp") + reporter.meter = provider.Meter("opamp") reporter.process, err = process.NewProcess(int32(os.Getpid())) if err != nil { @@ -148,15 +139,8 @@ func NewMetricReporter( return nil, fmt.Errorf("can't register callback: %w", err) } - reporter.counter, err = reporter.meter.SyncInt64().Counter("custom_metric_ticks") - if err != nil { - return nil, fmt.Errorf("can't register counter metric: %w", err) - } - reporter.meterShutdowner = func() { _ = provider.Shutdown(context.Background()) } - go reporter.sendMetrics() - return reporter, nil } @@ -179,25 +163,6 @@ func (reporter *MetricReporter) processMemoryPhysicalFunc(ctx context.Context) { reporter.processMemoryPhysical.Observe(ctx, int64(memory.RSS)) } -func (reporter *MetricReporter) sendMetrics() { - - // Collect metrics every 5 seconds. - t := time.NewTicker(time.Second * 5) - ticks := int64(0) - - for { - select { - case <-reporter.done: - return - - case <-t.C: - ctx := context.Background() - reporter.counter.Add(ctx, ticks) - ticks++ - } - } -} - func (reporter *MetricReporter) Shutdown() { if reporter.done != nil { close(reporter.done) diff --git a/cmd/remote-configuration/operator/client.go b/cmd/remote-configuration/operator/client.go index 89ef87e69e..0ef9bc8343 100644 --- a/cmd/remote-configuration/operator/client.go +++ b/cmd/remote-configuration/operator/client.go @@ -132,10 +132,10 @@ func (c Client) Delete(name string, namespace string) error { Namespace: namespace, Name: name, }, &result) - if errors.IsNotFound(err) { - return nil - } if err != nil { + if errors.IsNotFound(err) { + return nil + } return err } return c.k8sClient.Delete(ctx, &result) @@ -160,10 +160,10 @@ func (c Client) GetInstance(name string, namespace string) (*v1alpha1.OpenTeleme Namespace: namespace, Name: name, }, &result) - if errors.IsNotFound(err) { - return nil, nil - } if err != nil { + if errors.IsNotFound(err) { + return nil, nil + } return nil, err } return &result, nil From d67f2a7311d48bcb014d9384ff0e5eb740f0a552 Mon Sep 17 00:00:00 2001 From: Jacob Aronoff Date: Fri, 6 Jan 2023 16:36:01 -0500 Subject: [PATCH 13/16] Improved logging, working dockerfile --- cmd/remote-configuration/Dockerfile | 9 ++++++--- cmd/remote-configuration/config/cli.go | 11 ++++++++--- cmd/remote-configuration/main.go | 21 +++++++++++---------- 3 files changed, 25 insertions(+), 16 deletions(-) diff --git a/cmd/remote-configuration/Dockerfile b/cmd/remote-configuration/Dockerfile index 63193e5146..f65910cead 100644 --- a/cmd/remote-configuration/Dockerfile +++ b/cmd/remote-configuration/Dockerfile @@ -1,8 +1,10 @@ # Build the remote-configuration binary -FROM golang:1.19 as builder +FROM golang:1.19-alpine as builder WORKDIR /app +RUN apk --no-cache add ca-certificates + # Copy go mod and sum files COPY go.mod go.sum ./ @@ -16,10 +18,11 @@ RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o main . ######## Start a new stage from scratch ####### FROM scratch -RUN apk --no-cache add ca-certificates - WORKDIR /root/ +# Copy the certs from the builder +COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ca-certificates.crt + # Copy the pre-built binary file from the previous stage COPY --from=builder /app/main . diff --git a/cmd/remote-configuration/config/cli.go b/cmd/remote-configuration/config/cli.go index fde006c87f..06a782a0c0 100644 --- a/cmd/remote-configuration/config/cli.go +++ b/cmd/remote-configuration/config/cli.go @@ -55,18 +55,23 @@ type CLIConfig struct { RootLogger logr.Logger } -func ParseCLI() (CLIConfig, error) { +func GetLogger() logr.Logger { opts := zap.Options{} opts.BindFlags(flag.CommandLine) + + return zap.New(zap.UseFlagOptions(&opts)) +} + +func ParseCLI(logger logr.Logger) (CLIConfig, error) { cLIConf := CLIConfig{ + RootLogger: logger, ListenAddr: pflag.String("listen-addr", ":8080", "The address where this service serves."), ConfigFilePath: pflag.String("config-file", defaultConfigFilePath, "The path to the config file."), } kubeconfigPath := pflag.String("kubeconfig-path", filepath.Join(homedir.HomeDir(), ".kube", "config"), "absolute path to the KubeconfigPath file") pflag.Parse() - cLIConf.RootLogger = zap.New(zap.UseFlagOptions(&opts)) - klog.SetLogger(cLIConf.RootLogger) + klog.SetLogger(logger) clusterConfig, err := clientcmd.BuildConfigFromFlags("", *kubeconfigPath) cLIConf.KubeConfigFilePath = *kubeconfigPath diff --git a/cmd/remote-configuration/main.go b/cmd/remote-configuration/main.go index 4885b8233b..0c82a7828d 100644 --- a/cmd/remote-configuration/main.go +++ b/cmd/remote-configuration/main.go @@ -18,39 +18,40 @@ import ( "os" "os/signal" - "github.com/open-telemetry/opentelemetry-operator/cmd/remote-configuration/logger" - "github.com/open-telemetry/opentelemetry-operator/cmd/remote-configuration/operator" - "github.com/open-telemetry/opentelemetry-operator/cmd/remote-configuration/agent" "github.com/open-telemetry/opentelemetry-operator/cmd/remote-configuration/config" + "github.com/open-telemetry/opentelemetry-operator/cmd/remote-configuration/logger" + "github.com/open-telemetry/opentelemetry-operator/cmd/remote-configuration/operator" ) func main() { - cliConf, err := config.ParseCLI() + l := config.GetLogger() + cliConf, err := config.ParseCLI(l.WithName("cli-config")) if err != nil { + l.Error(err, "unable to load ") os.Exit(1) } cfg, configLoadErr := config.Load(*cliConf.ConfigFilePath) if configLoadErr != nil { - cliConf.RootLogger.Error(configLoadErr, "Unable to load configuration") + l.Error(configLoadErr, "Unable to load configuration") return } - cliConf.RootLogger.Info("Starting the Remote Configuration service") - agentLogf := cliConf.RootLogger.WithName("agent") + l.Info("Starting the Remote Configuration service") + agentLogf := l.WithName("agent") agentLogger := logger.NewLogger(&agentLogf) kubeClient, kubeErr := cliConf.GetKubernetesClient() if kubeErr != nil { - cliConf.RootLogger.Error(kubeErr, "Couldn't create kubernetes client") + l.Error(kubeErr, "Couldn't create kubernetes client") os.Exit(1) } - operatorClient := operator.NewClient(cliConf.RootLogger.WithName("operator-client"), kubeClient, cfg.GetComponentsAllowed()) + operatorClient := operator.NewClient(l.WithName("operator-client"), kubeClient, cfg.GetComponentsAllowed()) opampClient := cfg.CreateClient(agentLogger) opampAgent := agent.NewAgent(agentLogger, operatorClient, cfg, opampClient) if err := opampAgent.Start(); err != nil { - cliConf.RootLogger.Error(err, "Cannot start OpAMP client") + l.Error(err, "Cannot start OpAMP client") os.Exit(1) } From d3f43ac660f499ac472a2bc9a1a56d91f893bd49 Mon Sep 17 00:00:00 2001 From: Jacob Aronoff Date: Fri, 6 Jan 2023 16:39:48 -0500 Subject: [PATCH 14/16] Rename the whole thing --- .github/workflows/continuous-integration.yaml | 2 +- Makefile | 24 +++++++++---------- .../Dockerfile | 2 +- .../agent/agent.go | 6 ++--- .../agent/agent_test.go | 6 ++--- .../agent/collector_key.go | 0 .../agent/collector_key_test.go | 0 .../agent/testdata/agent.yaml | 0 .../testdata/agentbasiccomponentsallowed.yaml | 0 .../agent/testdata/agentbatchnotallowed.yaml | 0 .../testdata/agentnoprocessorsallowed.yaml | 0 .../agent/testdata/basic.yaml | 0 .../agent/testdata/invalid.yaml | 0 .../agent/testdata/updated.yaml | 0 .../config/cli.go | 0 .../config/config.go | 4 ++-- .../go.mod | 2 +- .../go.sum | 0 .../header.txt | 0 .../logger/logger.go | 0 .../main.go | 8 +++---- .../metrics/reporter.go | 0 .../operator/client.go | 4 ++-- .../operator/client_test.go | 0 .../operator/testdata/collector.yaml | 0 .../operator/testdata/invalid-collector.yaml | 0 .../operator/testdata/updated-collector.yaml | 0 27 files changed, 29 insertions(+), 29 deletions(-) rename cmd/{remote-configuration => operator-opamp-bridge}/Dockerfile (93%) rename cmd/{remote-configuration => operator-opamp-bridge}/agent/agent.go (97%) rename cmd/{remote-configuration => operator-opamp-bridge}/agent/agent_test.go (98%) rename cmd/{remote-configuration => operator-opamp-bridge}/agent/collector_key.go (100%) rename cmd/{remote-configuration => operator-opamp-bridge}/agent/collector_key_test.go (100%) rename cmd/{remote-configuration => operator-opamp-bridge}/agent/testdata/agent.yaml (100%) rename cmd/{remote-configuration => operator-opamp-bridge}/agent/testdata/agentbasiccomponentsallowed.yaml (100%) rename cmd/{remote-configuration => operator-opamp-bridge}/agent/testdata/agentbatchnotallowed.yaml (100%) rename cmd/{remote-configuration => operator-opamp-bridge}/agent/testdata/agentnoprocessorsallowed.yaml (100%) rename cmd/{remote-configuration => operator-opamp-bridge}/agent/testdata/basic.yaml (100%) rename cmd/{remote-configuration => operator-opamp-bridge}/agent/testdata/invalid.yaml (100%) rename cmd/{remote-configuration => operator-opamp-bridge}/agent/testdata/updated.yaml (100%) rename cmd/{remote-configuration => operator-opamp-bridge}/config/cli.go (100%) rename cmd/{remote-configuration => operator-opamp-bridge}/config/config.go (95%) rename cmd/{remote-configuration => operator-opamp-bridge}/go.mod (98%) rename cmd/{remote-configuration => operator-opamp-bridge}/go.sum (100%) rename cmd/{remote-configuration => operator-opamp-bridge}/header.txt (100%) rename cmd/{remote-configuration => operator-opamp-bridge}/logger/logger.go (100%) rename cmd/{remote-configuration => operator-opamp-bridge}/main.go (83%) rename cmd/{remote-configuration => operator-opamp-bridge}/metrics/reporter.go (100%) rename cmd/{remote-configuration => operator-opamp-bridge}/operator/client.go (98%) rename cmd/{remote-configuration => operator-opamp-bridge}/operator/client_test.go (100%) rename cmd/{remote-configuration => operator-opamp-bridge}/operator/testdata/collector.yaml (100%) rename cmd/{remote-configuration => operator-opamp-bridge}/operator/testdata/invalid-collector.yaml (100%) rename cmd/{remote-configuration => operator-opamp-bridge}/operator/testdata/updated-collector.yaml (100%) diff --git a/.github/workflows/continuous-integration.yaml b/.github/workflows/continuous-integration.yaml index ba9a1e21c0..1ecdd99c68 100644 --- a/.github/workflows/continuous-integration.yaml +++ b/.github/workflows/continuous-integration.yaml @@ -33,7 +33,7 @@ jobs: runs-on: ubuntu-20.04 strategy: matrix: - workdir: [".", "./cmd/otel-allocator", "./cmd/remote-configuration"] + workdir: [".", "./cmd/otel-allocator", "./cmd/operator-opamp-bridge"] steps: - name: Set up Go uses: actions/setup-go@v3 diff --git a/Makefile b/Makefile index ffab235855..6c5392e438 100644 --- a/Makefile +++ b/Makefile @@ -21,8 +21,8 @@ BUNDLE_IMG ?= ${IMG_PREFIX}/${IMG_REPO}-bundle:${VERSION} TARGETALLOCATOR_IMG_REPO ?= target-allocator TARGETALLOCATOR_IMG ?= ${IMG_PREFIX}/${TARGETALLOCATOR_IMG_REPO}:$(addprefix v,${VERSION}) -REMOTECONFIGURATION_IMG_REPO ?= remote-configuration -REMOTECONFIGURATION_IMG ?= ${IMG_PREFIX}/${REMOTECONFIGURATION_IMG_REPO}:$(addprefix v,${VERSION}) +OPERATOROPAMPBRIDGE_IMG_REPO ?= operator-opamp-bridge +OPERATOROPAMPBRIDGE_IMG ?= ${IMG_PREFIX}/${OPERATOROPAMPBRIDGE_IMG_REPO}:$(addprefix v,${VERSION}) # Options for 'bundle-build' ifneq ($(origin CHANNELS), undefined) @@ -92,7 +92,7 @@ ci: test test: generate fmt vet ensure-generate-is-noop envtest KUBEBUILDER_ASSETS="$(shell $(ENVTEST) use $(KUBE_VERSION) -p path)" go test ${GOTEST_OPTS} ./... cd cmd/otel-allocator && KUBEBUILDER_ASSETS="$(shell $(ENVTEST) use $(KUBE_VERSION) -p path)" go test ${GOTEST_OPTS} ./... - cd cmd/remote-configuration && KUBEBUILDER_ASSETS="$(shell $(ENVTEST) use $(KUBE_VERSION) -p path)" go test ${GOTEST_OPTS} ./... + cd cmd/operator-opamp-bridge && KUBEBUILDER_ASSETS="$(shell $(ENVTEST) use $(KUBE_VERSION) -p path)" go test ${GOTEST_OPTS} ./... # Build manager binary .PHONY: manager @@ -156,7 +156,7 @@ vet: lint: golangci-lint run cd cmd/otel-allocator && golangci-lint run - cd cmd/remote-configuration && golangci-lint run + cd cmd/operator-opamp-bridge && golangci-lint run # Generate code .PHONY: generate @@ -179,7 +179,7 @@ e2e-log-operator: kubectl get deploy -A .PHONY: prepare-e2e -prepare-e2e: kuttl set-image-controller container container-target-allocator container-remote-configuration start-kind cert-manager install-metrics-server install-openshift-routes load-image-all deploy +prepare-e2e: kuttl set-image-controller container container-target-allocator container-operator-opamp-bridge start-kind cert-manager install-metrics-server install-openshift-routes load-image-all deploy TARGETALLOCATOR_IMG=$(TARGETALLOCATOR_IMG) ./hack/modify-test-images.sh .PHONY: scorecard-tests @@ -206,9 +206,9 @@ container-target-allocator-push: container-target-allocator: docker buildx build --load --platform linux/${ARCH} -t ${TARGETALLOCATOR_IMG} cmd/otel-allocator -.PHONY: container-remote-configuration -container-remote-configuration: - docker buildx build --platform linux/${ARCH} -t ${REMOTECONFIGURATION_IMG} cmd/remote-configuration +.PHONY: container-operator-opamp-bridge +container-operator-opamp-bridge: + docker buildx build --platform linux/${ARCH} -t ${OPERATOROPAMPBRIDGE_IMG} cmd/operator-opamp-bridge .PHONY: start-kind start-kind: @@ -225,7 +225,7 @@ install-openshift-routes: ./hack/install-openshift-routes.sh .PHONY: load-image-all -load-image-all: load-image-operator load-image-target-allocator load-image-remote-configuration +load-image-all: load-image-operator load-image-target-allocator load-image-operator-opamp-bridge .PHONY: load-image-operator load-image-operator: container @@ -245,9 +245,9 @@ else endif -.PHONY: load-image-remote-configuration -load-image-remote-configuration: - kind load docker-image ${REMOTECONFIGURATION_IMG} +.PHONY: load-image-operator-opamp-bridge +load-image-operator-opamp-bridge: + kind load docker-image ${OPERATOROPAMPBRIDGE_IMG} .PHONY: cert-manager cert-manager: cmctl diff --git a/cmd/remote-configuration/Dockerfile b/cmd/operator-opamp-bridge/Dockerfile similarity index 93% rename from cmd/remote-configuration/Dockerfile rename to cmd/operator-opamp-bridge/Dockerfile index f65910cead..ce62eca286 100644 --- a/cmd/remote-configuration/Dockerfile +++ b/cmd/operator-opamp-bridge/Dockerfile @@ -1,4 +1,4 @@ -# Build the remote-configuration binary +# Build the operator-opamp-bridge binary FROM golang:1.19-alpine as builder WORKDIR /app diff --git a/cmd/remote-configuration/agent/agent.go b/cmd/operator-opamp-bridge/agent/agent.go similarity index 97% rename from cmd/remote-configuration/agent/agent.go rename to cmd/operator-opamp-bridge/agent/agent.go index d687c2b3af..3bc2072525 100644 --- a/cmd/remote-configuration/agent/agent.go +++ b/cmd/operator-opamp-bridge/agent/agent.go @@ -21,10 +21,10 @@ import ( "gopkg.in/yaml.v3" - "github.com/open-telemetry/opentelemetry-operator/cmd/remote-configuration/metrics" - "github.com/open-telemetry/opentelemetry-operator/cmd/remote-configuration/operator" + "github.com/open-telemetry/opentelemetry-operator/cmd/operator-opamp-bridge/metrics" + "github.com/open-telemetry/opentelemetry-operator/cmd/operator-opamp-bridge/operator" - "github.com/open-telemetry/opentelemetry-operator/cmd/remote-configuration/config" + "github.com/open-telemetry/opentelemetry-operator/cmd/operator-opamp-bridge/config" "github.com/oklog/ulid/v2" "go.uber.org/multierr" diff --git a/cmd/remote-configuration/agent/agent_test.go b/cmd/operator-opamp-bridge/agent/agent_test.go similarity index 98% rename from cmd/remote-configuration/agent/agent_test.go rename to cmd/operator-opamp-bridge/agent/agent_test.go index b8d06dc60c..707e5315e1 100644 --- a/cmd/remote-configuration/agent/agent_test.go +++ b/cmd/operator-opamp-bridge/agent/agent_test.go @@ -35,9 +35,9 @@ import ( logf "sigs.k8s.io/controller-runtime/pkg/log" "github.com/open-telemetry/opentelemetry-operator/apis/v1alpha1" - "github.com/open-telemetry/opentelemetry-operator/cmd/remote-configuration/config" - "github.com/open-telemetry/opentelemetry-operator/cmd/remote-configuration/logger" - "github.com/open-telemetry/opentelemetry-operator/cmd/remote-configuration/operator" + "github.com/open-telemetry/opentelemetry-operator/cmd/operator-opamp-bridge/config" + "github.com/open-telemetry/opentelemetry-operator/cmd/operator-opamp-bridge/logger" + "github.com/open-telemetry/opentelemetry-operator/cmd/operator-opamp-bridge/operator" ) var ( diff --git a/cmd/remote-configuration/agent/collector_key.go b/cmd/operator-opamp-bridge/agent/collector_key.go similarity index 100% rename from cmd/remote-configuration/agent/collector_key.go rename to cmd/operator-opamp-bridge/agent/collector_key.go diff --git a/cmd/remote-configuration/agent/collector_key_test.go b/cmd/operator-opamp-bridge/agent/collector_key_test.go similarity index 100% rename from cmd/remote-configuration/agent/collector_key_test.go rename to cmd/operator-opamp-bridge/agent/collector_key_test.go diff --git a/cmd/remote-configuration/agent/testdata/agent.yaml b/cmd/operator-opamp-bridge/agent/testdata/agent.yaml similarity index 100% rename from cmd/remote-configuration/agent/testdata/agent.yaml rename to cmd/operator-opamp-bridge/agent/testdata/agent.yaml diff --git a/cmd/remote-configuration/agent/testdata/agentbasiccomponentsallowed.yaml b/cmd/operator-opamp-bridge/agent/testdata/agentbasiccomponentsallowed.yaml similarity index 100% rename from cmd/remote-configuration/agent/testdata/agentbasiccomponentsallowed.yaml rename to cmd/operator-opamp-bridge/agent/testdata/agentbasiccomponentsallowed.yaml diff --git a/cmd/remote-configuration/agent/testdata/agentbatchnotallowed.yaml b/cmd/operator-opamp-bridge/agent/testdata/agentbatchnotallowed.yaml similarity index 100% rename from cmd/remote-configuration/agent/testdata/agentbatchnotallowed.yaml rename to cmd/operator-opamp-bridge/agent/testdata/agentbatchnotallowed.yaml diff --git a/cmd/remote-configuration/agent/testdata/agentnoprocessorsallowed.yaml b/cmd/operator-opamp-bridge/agent/testdata/agentnoprocessorsallowed.yaml similarity index 100% rename from cmd/remote-configuration/agent/testdata/agentnoprocessorsallowed.yaml rename to cmd/operator-opamp-bridge/agent/testdata/agentnoprocessorsallowed.yaml diff --git a/cmd/remote-configuration/agent/testdata/basic.yaml b/cmd/operator-opamp-bridge/agent/testdata/basic.yaml similarity index 100% rename from cmd/remote-configuration/agent/testdata/basic.yaml rename to cmd/operator-opamp-bridge/agent/testdata/basic.yaml diff --git a/cmd/remote-configuration/agent/testdata/invalid.yaml b/cmd/operator-opamp-bridge/agent/testdata/invalid.yaml similarity index 100% rename from cmd/remote-configuration/agent/testdata/invalid.yaml rename to cmd/operator-opamp-bridge/agent/testdata/invalid.yaml diff --git a/cmd/remote-configuration/agent/testdata/updated.yaml b/cmd/operator-opamp-bridge/agent/testdata/updated.yaml similarity index 100% rename from cmd/remote-configuration/agent/testdata/updated.yaml rename to cmd/operator-opamp-bridge/agent/testdata/updated.yaml diff --git a/cmd/remote-configuration/config/cli.go b/cmd/operator-opamp-bridge/config/cli.go similarity index 100% rename from cmd/remote-configuration/config/cli.go rename to cmd/operator-opamp-bridge/config/cli.go diff --git a/cmd/remote-configuration/config/config.go b/cmd/operator-opamp-bridge/config/config.go similarity index 95% rename from cmd/remote-configuration/config/config.go rename to cmd/operator-opamp-bridge/config/config.go index 263bceca0b..fe7fa3df1f 100644 --- a/cmd/remote-configuration/config/config.go +++ b/cmd/operator-opamp-bridge/config/config.go @@ -26,11 +26,11 @@ import ( "github.com/open-telemetry/opamp-go/protobufs" "gopkg.in/yaml.v2" - "github.com/open-telemetry/opentelemetry-operator/cmd/remote-configuration/logger" + "github.com/open-telemetry/opentelemetry-operator/cmd/operator-opamp-bridge/logger" ) const ( - agentType = "io.opentelemetry.remote-configuration" + agentType = "io.opentelemetry.operator-opamp-bridge" defaultConfigFilePath = "/conf/remoteconfiguration.yaml" ) diff --git a/cmd/remote-configuration/go.mod b/cmd/operator-opamp-bridge/go.mod similarity index 98% rename from cmd/remote-configuration/go.mod rename to cmd/operator-opamp-bridge/go.mod index d583c88364..ad5a31954b 100644 --- a/cmd/remote-configuration/go.mod +++ b/cmd/operator-opamp-bridge/go.mod @@ -1,4 +1,4 @@ -module github.com/open-telemetry/opentelemetry-operator/cmd/remote-configuration +module github.com/open-telemetry/opentelemetry-operator/cmd/operator-opamp-bridge go 1.19 diff --git a/cmd/remote-configuration/go.sum b/cmd/operator-opamp-bridge/go.sum similarity index 100% rename from cmd/remote-configuration/go.sum rename to cmd/operator-opamp-bridge/go.sum diff --git a/cmd/remote-configuration/header.txt b/cmd/operator-opamp-bridge/header.txt similarity index 100% rename from cmd/remote-configuration/header.txt rename to cmd/operator-opamp-bridge/header.txt diff --git a/cmd/remote-configuration/logger/logger.go b/cmd/operator-opamp-bridge/logger/logger.go similarity index 100% rename from cmd/remote-configuration/logger/logger.go rename to cmd/operator-opamp-bridge/logger/logger.go diff --git a/cmd/remote-configuration/main.go b/cmd/operator-opamp-bridge/main.go similarity index 83% rename from cmd/remote-configuration/main.go rename to cmd/operator-opamp-bridge/main.go index 0c82a7828d..abbd4d8246 100644 --- a/cmd/remote-configuration/main.go +++ b/cmd/operator-opamp-bridge/main.go @@ -18,10 +18,10 @@ import ( "os" "os/signal" - "github.com/open-telemetry/opentelemetry-operator/cmd/remote-configuration/agent" - "github.com/open-telemetry/opentelemetry-operator/cmd/remote-configuration/config" - "github.com/open-telemetry/opentelemetry-operator/cmd/remote-configuration/logger" - "github.com/open-telemetry/opentelemetry-operator/cmd/remote-configuration/operator" + "github.com/open-telemetry/opentelemetry-operator/cmd/operator-opamp-bridge/agent" + "github.com/open-telemetry/opentelemetry-operator/cmd/operator-opamp-bridge/config" + "github.com/open-telemetry/opentelemetry-operator/cmd/operator-opamp-bridge/logger" + "github.com/open-telemetry/opentelemetry-operator/cmd/operator-opamp-bridge/operator" ) func main() { diff --git a/cmd/remote-configuration/metrics/reporter.go b/cmd/operator-opamp-bridge/metrics/reporter.go similarity index 100% rename from cmd/remote-configuration/metrics/reporter.go rename to cmd/operator-opamp-bridge/metrics/reporter.go diff --git a/cmd/remote-configuration/operator/client.go b/cmd/operator-opamp-bridge/operator/client.go similarity index 98% rename from cmd/remote-configuration/operator/client.go rename to cmd/operator-opamp-bridge/operator/client.go index 0ef9bc8343..b83b476fb3 100644 --- a/cmd/remote-configuration/operator/client.go +++ b/cmd/operator-opamp-bridge/operator/client.go @@ -30,7 +30,7 @@ import ( const ( CollectorResource = "OpenTelemetryCollector" ResourceIdentifierKey = "created-by" - ResourceIdentifierValue = "remote-configuration" + ResourceIdentifierValue = "operator-opamp-bridge" ) type ConfigApplier interface { @@ -40,7 +40,7 @@ type ConfigApplier interface { // GetInstance retrieves an OpenTelemetryCollector CRD given a name and namespace. GetInstance(name string, namespace string) (*v1alpha1.OpenTelemetryCollector, error) - // ListInstances retrieves all OpenTelemetryCollector CRDs created by the remote-configuration agent. + // ListInstances retrieves all OpenTelemetryCollector CRDs created by the operator-opamp-bridge agent. ListInstances() ([]v1alpha1.OpenTelemetryCollector, error) // Delete attempts to delete an OpenTelemetryCollector object given a name and namespace. diff --git a/cmd/remote-configuration/operator/client_test.go b/cmd/operator-opamp-bridge/operator/client_test.go similarity index 100% rename from cmd/remote-configuration/operator/client_test.go rename to cmd/operator-opamp-bridge/operator/client_test.go diff --git a/cmd/remote-configuration/operator/testdata/collector.yaml b/cmd/operator-opamp-bridge/operator/testdata/collector.yaml similarity index 100% rename from cmd/remote-configuration/operator/testdata/collector.yaml rename to cmd/operator-opamp-bridge/operator/testdata/collector.yaml diff --git a/cmd/remote-configuration/operator/testdata/invalid-collector.yaml b/cmd/operator-opamp-bridge/operator/testdata/invalid-collector.yaml similarity index 100% rename from cmd/remote-configuration/operator/testdata/invalid-collector.yaml rename to cmd/operator-opamp-bridge/operator/testdata/invalid-collector.yaml diff --git a/cmd/remote-configuration/operator/testdata/updated-collector.yaml b/cmd/operator-opamp-bridge/operator/testdata/updated-collector.yaml similarity index 100% rename from cmd/remote-configuration/operator/testdata/updated-collector.yaml rename to cmd/operator-opamp-bridge/operator/testdata/updated-collector.yaml From 1f9d9b712aa6db7e1ce282daaa5e3629c4a90b06 Mon Sep 17 00:00:00 2001 From: Jacob Aronoff Date: Fri, 6 Jan 2023 16:40:51 -0500 Subject: [PATCH 15/16] Change service name --- .chloggen/1318-remote-config-service.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.chloggen/1318-remote-config-service.yaml b/.chloggen/1318-remote-config-service.yaml index 2a7a3dca35..13fb153bad 100755 --- a/.chloggen/1318-remote-config-service.yaml +++ b/.chloggen/1318-remote-config-service.yaml @@ -2,10 +2,10 @@ change_type: new_component # The name of the component, or a single word describing the area of concern, (e.g. operator, target allocator, github action) -component: Remote Configuration +component: Operator OpAMP Bridge # A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`). -note: Introducing the Operator Remote Configuration service, which allows a user to manage OpenTelemetry Collector CRDs via OpAMP +note: Introducing the Operator OpAMP Bridge service, which allows a user to manage OpenTelemetry Collector CRDs via OpAMP # One or more tracking issues related to the change issues: [1318] From 1eaa51b55ffc84d241923619144d0c260b3d3703 Mon Sep 17 00:00:00 2001 From: Jacob Aronoff Date: Tue, 10 Jan 2023 17:55:11 -0500 Subject: [PATCH 16/16] Update from feedback --- cmd/operator-opamp-bridge/agent/agent.go | 27 +++++++++--------- .../agent/testdata/agent.yaml | 2 -- .../testdata/agentbasiccomponentsallowed.yaml | 2 -- .../agent/testdata/agentbatchnotallowed.yaml | 2 -- .../testdata/agentnoprocessorsallowed.yaml | 2 -- cmd/operator-opamp-bridge/config/config.go | 5 ++++ cmd/operator-opamp-bridge/go.mod | 2 +- cmd/operator-opamp-bridge/go.sum | 4 +-- cmd/operator-opamp-bridge/metrics/reporter.go | 28 +++++++++++-------- 9 files changed, 39 insertions(+), 35 deletions(-) diff --git a/cmd/operator-opamp-bridge/agent/agent.go b/cmd/operator-opamp-bridge/agent/agent.go index 3bc2072525..fb8067d22e 100644 --- a/cmd/operator-opamp-bridge/agent/agent.go +++ b/cmd/operator-opamp-bridge/agent/agent.go @@ -45,21 +45,23 @@ type Agent struct { agentDescription *protobufs.AgentDescription remoteConfigStatus *protobufs.RemoteConfigStatus - opampClient client.OpAMPClient - metricReporter *metrics.MetricReporter - config config.Config - applier operator.ConfigApplier + opampClient client.OpAMPClient + metricReporter *metrics.MetricReporter + config config.Config + applier operator.ConfigApplier + remoteConfigEnabled bool } func NewAgent(logger types.Logger, applier operator.ConfigApplier, config config.Config, opampClient client.OpAMPClient) *Agent { agent := &Agent{ - config: config, - applier: applier, - logger: logger, - appliedKeys: map[collectorKey]bool{}, - instanceId: config.GetNewInstanceId(), - agentDescription: config.GetDescription(), - opampClient: opampClient, + config: config, + applier: applier, + logger: logger, + appliedKeys: map[collectorKey]bool{}, + instanceId: config.GetNewInstanceId(), + agentDescription: config.GetDescription(), + remoteConfigEnabled: config.RemoteConfigEnabled(), + opampClient: opampClient, } agent.logger.Debugf("Agent created, id=%v, type=%s, version=%s.", @@ -258,9 +260,8 @@ func (agent *Agent) Shutdown() { // for checking if it should apply a new remote configuration. The agent will also initialize metrics based on the // settings received from the server. The agent is also able to update its identifier if it needs to. func (agent *Agent) onMessage(ctx context.Context, msg *types.MessageData) { - // If we received remote configuration, and it's not the same as the previously applied one - if msg.RemoteConfig != nil && !bytes.Equal(agent.lastHash, msg.RemoteConfig.GetConfigHash()) { + if agent.remoteConfigEnabled && msg.RemoteConfig != nil && !bytes.Equal(agent.lastHash, msg.RemoteConfig.GetConfigHash()) { var err error status, err := agent.applyRemoteConfig(msg.RemoteConfig) if err != nil { diff --git a/cmd/operator-opamp-bridge/agent/testdata/agent.yaml b/cmd/operator-opamp-bridge/agent/testdata/agent.yaml index c1e126aceb..b03015cefd 100644 --- a/cmd/operator-opamp-bridge/agent/testdata/agent.yaml +++ b/cmd/operator-opamp-bridge/agent/testdata/agent.yaml @@ -1,8 +1,6 @@ endpoint: ws://127.0.0.1:4320/v1/opamp protocol: wss capabilities: - - Unspecified - - ReportsStatus - AcceptsRemoteConfig - ReportsEffectiveConfig # - AcceptsPackages diff --git a/cmd/operator-opamp-bridge/agent/testdata/agentbasiccomponentsallowed.yaml b/cmd/operator-opamp-bridge/agent/testdata/agentbasiccomponentsallowed.yaml index 288d508c7b..b98d517b1c 100644 --- a/cmd/operator-opamp-bridge/agent/testdata/agentbasiccomponentsallowed.yaml +++ b/cmd/operator-opamp-bridge/agent/testdata/agentbasiccomponentsallowed.yaml @@ -1,8 +1,6 @@ endpoint: ws://127.0.0.1:4320/v1/opamp protocol: wss capabilities: - - Unspecified - - ReportsStatus - AcceptsRemoteConfig - ReportsEffectiveConfig # - AcceptsPackages diff --git a/cmd/operator-opamp-bridge/agent/testdata/agentbatchnotallowed.yaml b/cmd/operator-opamp-bridge/agent/testdata/agentbatchnotallowed.yaml index 8a03415dae..2369aa80b2 100644 --- a/cmd/operator-opamp-bridge/agent/testdata/agentbatchnotallowed.yaml +++ b/cmd/operator-opamp-bridge/agent/testdata/agentbatchnotallowed.yaml @@ -1,8 +1,6 @@ endpoint: ws://127.0.0.1:4320/v1/opamp protocol: wss capabilities: - - Unspecified - - ReportsStatus - AcceptsRemoteConfig - ReportsEffectiveConfig # - AcceptsPackages diff --git a/cmd/operator-opamp-bridge/agent/testdata/agentnoprocessorsallowed.yaml b/cmd/operator-opamp-bridge/agent/testdata/agentnoprocessorsallowed.yaml index 2b01d21299..625f6b11e4 100644 --- a/cmd/operator-opamp-bridge/agent/testdata/agentnoprocessorsallowed.yaml +++ b/cmd/operator-opamp-bridge/agent/testdata/agentnoprocessorsallowed.yaml @@ -1,8 +1,6 @@ endpoint: ws://127.0.0.1:4320/v1/opamp protocol: wss capabilities: - - Unspecified - - ReportsStatus - AcceptsRemoteConfig - ReportsEffectiveConfig # - AcceptsPackages diff --git a/cmd/operator-opamp-bridge/config/config.go b/cmd/operator-opamp-bridge/config/config.go index fe7fa3df1f..706ff09e00 100644 --- a/cmd/operator-opamp-bridge/config/config.go +++ b/cmd/operator-opamp-bridge/config/config.go @@ -117,6 +117,11 @@ func (c *Config) GetNewInstanceId() ulid.ULID { return ulid.MustNew(ulid.Timestamp(time.Now()), entropy) } +func (c *Config) RemoteConfigEnabled() bool { + capabilities := c.GetCapabilities() + return capabilities&protobufs.AgentCapabilities_AgentCapabilities_AcceptsRemoteConfig != 0 +} + func Load(file string) (Config, error) { var cfg Config if err := unmarshal(&cfg, file); err != nil { diff --git a/cmd/operator-opamp-bridge/go.mod b/cmd/operator-opamp-bridge/go.mod index ad5a31954b..0b4927c834 100644 --- a/cmd/operator-opamp-bridge/go.mod +++ b/cmd/operator-opamp-bridge/go.mod @@ -11,7 +11,7 @@ require ( github.com/spf13/pflag v1.0.5 github.com/stretchr/testify v1.8.1 go.opentelemetry.io/otel v1.11.2 - go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.34.0 + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v0.34.0 go.opentelemetry.io/otel/metric v0.34.0 go.opentelemetry.io/otel/sdk v1.11.2 go.opentelemetry.io/otel/sdk/metric v0.34.0 diff --git a/cmd/operator-opamp-bridge/go.sum b/cmd/operator-opamp-bridge/go.sum index fdcc339d77..bdd771b446 100644 --- a/cmd/operator-opamp-bridge/go.sum +++ b/cmd/operator-opamp-bridge/go.sum @@ -327,8 +327,8 @@ go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.11.2 h1:htgM8vZIF8oPSC go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.11.2/go.mod h1:rqbht/LlhVBgn5+k3M5QK96K5Xb0DvXpMJ5SFQpY6uw= go.opentelemetry.io/otel/exporters/otlp/otlpmetric v0.34.0 h1:kpskzLZ60cJ48SJ4uxWa6waBL+4kSV6nVK8rP+QM8Wg= go.opentelemetry.io/otel/exporters/otlp/otlpmetric v0.34.0/go.mod h1:4+x3i62TEegDHuzNva0bMcAN8oUi5w4liGb1d/VgPYo= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.34.0 h1:e7kFb4pJLbhJgAwUdoVTHzB9pGujs5O8/7gFyZL88fg= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.34.0/go.mod h1:3x00m9exjIbhK+zTO4MsCSlfbVmgvLP0wjDgDKa/8bw= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v0.34.0 h1:t4Ajxj8JGjxkqoBtbkCOY2cDUl9RwiNE9LPQavooi9U= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v0.34.0/go.mod h1:WO7omosl4P7JoanH9NgInxDxEn2F2M5YinIh8EyeT8w= go.opentelemetry.io/otel/metric v0.34.0 h1:MCPoQxcg/26EuuJwpYN1mZTeCYAUGx8ABxfW07YkjP8= go.opentelemetry.io/otel/metric v0.34.0/go.mod h1:ZFuI4yQGNCupurTXCwkeD/zHBt+C2bR7bw5JqUm/AP8= go.opentelemetry.io/otel/sdk v1.11.2 h1:GF4JoaEx7iihdMFu30sOyRx52HDHOkl9xQ8SMqNXUiU= diff --git a/cmd/operator-opamp-bridge/metrics/reporter.go b/cmd/operator-opamp-bridge/metrics/reporter.go index e07d259d50..08dd8a5ef1 100644 --- a/cmd/operator-opamp-bridge/metrics/reporter.go +++ b/cmd/operator-opamp-bridge/metrics/reporter.go @@ -17,13 +17,14 @@ package metrics import ( "context" "fmt" + "net/url" "os" "time" "github.com/oklog/ulid/v2" "github.com/shirou/gopsutil/process" "go.opentelemetry.io/otel/attribute" - "go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc" + "go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp" "go.opentelemetry.io/otel/metric" "go.opentelemetry.io/otel/metric/instrument" "go.opentelemetry.io/otel/metric/instrument/asyncfloat64" @@ -53,8 +54,8 @@ type MetricReporter struct { processCpuTime asyncfloat64.Counter } -// NewMetricReporter creates an OTLP gRPC client to the destination address supplied by the server. -// TODO: do more validation on the endpoint, allow for http. +// NewMetricReporter creates an OTLP/HTTP client to the destination address supplied by the server. +// TODO: do more validation on the endpoint, allow for gRPC. // TODO: set global provider and add more metrics to be reported. func NewMetricReporter( logger types.Logger, @@ -65,24 +66,29 @@ func NewMetricReporter( ) (*MetricReporter, error) { if dest.DestinationEndpoint == "" { - err := fmt.Errorf("metric destination must specify DestinationEndpoint") - return nil, err + return nil, fmt.Errorf("metric destination must specify DestinationEndpoint") } - // Create OTLP/grpc metric exporter. - opts := []otlpmetricgrpc.Option{ - otlpmetricgrpc.WithEndpoint(dest.DestinationEndpoint), + u, err := url.Parse(dest.DestinationEndpoint) + if err != nil { + return nil, fmt.Errorf("invalid DestinationEndpoint: %w", err) + } + + // Create OTLP/HTTP metric exporter. + opts := []otlpmetrichttp.Option{ + otlpmetrichttp.WithEndpoint(u.Host), + otlpmetrichttp.WithURLPath(u.Path), } headers := map[string]string{} for _, header := range dest.Headers.GetHeaders() { headers[header.GetKey()] = header.GetValue() } - opts = append(opts, otlpmetricgrpc.WithHeaders(headers)) + opts = append(opts, otlpmetrichttp.WithHeaders(headers)) - client, err := otlpmetricgrpc.New(context.Background(), opts...) + client, err := otlpmetrichttp.New(context.Background(), opts...) if err != nil { - return nil, fmt.Errorf("failed to initialize otlp metric grpc client: %w", err) + return nil, fmt.Errorf("failed to initialize otlp metric http client: %w", err) } // Define the Resource to be exported with all metrics. Use OpenTelemetry semantic