consul/agent/hcp/deps.go
Melissa Kam 3b9bb8d6f9
[CC-7044] Start HCP manager as part of link creation (#20312)
* Check for ACL write permissions on write

Link eventually will be creating a token, so require acl:write.

* Convert Run to Start, only allow to start once

* Always initialize HCP components at startup

* Support for updating config and client

* Pass HCP manager to controller

* Start HCP manager in link resource

Start as part of link creation rather than always starting. Update
the HCP manager with values from the link before starting as well.

* Fix metrics sink leaked goroutine

* Remove the hardcoded disabled hostname prefix

The HCP metrics sink will always be enabled, so the length of sinks will
always be greater than zero. This also means that we will also always
default to prefixing metrics with the hostname, which is what our
documentation states is the expected behavior anyway.

* Add changelog

* Check and set running status in one method

* Check for primary datacenter, add back test

* Clarify merge reasoning, fix timing issue in test

* Add comment about controller placement

* Expand on breaking change, fix typo in changelog
2024-01-29 16:31:44 -06:00

84 lines
2.2 KiB
Go

// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: BUSL-1.1
package hcp
import (
"context"
"fmt"
"github.com/armon/go-metrics"
"github.com/hashicorp/go-hclog"
"github.com/hashicorp/consul/agent/hcp/client"
"github.com/hashicorp/consul/agent/hcp/config"
"github.com/hashicorp/consul/agent/hcp/scada"
"github.com/hashicorp/consul/agent/hcp/telemetry"
)
// Deps contains the interfaces that the rest of Consul core depends on for HCP integration.
type Deps struct {
Config config.CloudConfig
Provider scada.Provider
Sink metrics.ShutdownSink
TelemetryProvider *hcpProviderImpl
DataDir string
}
func NewDeps(cfg config.CloudConfig, logger hclog.Logger, dataDir string) (Deps, error) {
ctx := context.Background()
ctx = hclog.WithContext(ctx, logger)
provider, err := scada.New(logger.Named("scada"))
if err != nil {
return Deps{}, fmt.Errorf("failed to init scada: %w", err)
}
metricsProvider := NewHCPProvider(ctx)
if err != nil {
logger.Error("failed to init HCP metrics provider", "error", err)
return Deps{}, fmt.Errorf("failed to init HCP metrics provider: %w", err)
}
metricsClient := client.NewMetricsClient(ctx, metricsProvider)
sink, err := sink(ctx, metricsClient, metricsProvider)
if err != nil {
// Do not prevent server start if sink init fails, only log error.
logger.Error("failed to init sink", "error", err)
}
return Deps{
Config: cfg,
Provider: provider,
Sink: sink,
TelemetryProvider: metricsProvider,
DataDir: dataDir,
}, nil
}
// sink initializes an OTELSink which forwards Consul metrics to HCP.
// This step should not block server initialization, errors are returned, only to be logged.
func sink(
ctx context.Context,
metricsClient telemetry.MetricsClient,
cfgProvider *hcpProviderImpl,
) (metrics.ShutdownSink, error) {
logger := hclog.FromContext(ctx)
reader := telemetry.NewOTELReader(metricsClient, cfgProvider)
sinkOpts := &telemetry.OTELSinkOpts{
Reader: reader,
ConfigProvider: cfgProvider,
}
sink, err := telemetry.NewOTELSink(ctx, sinkOpts)
if err != nil {
return nil, fmt.Errorf("failed to create OTELSink: %w", err)
}
logger.Debug("initialized HCP metrics sink")
return sink, nil
}