v2: remove HCP Link integration (#21883)

Also prevent de-registered retired v2 types from being restored from a
snapshot, such as these hcp resources. Without doing this, anyone with
any of these types in their state store will retain them forever with no
avenue to remove them.
This commit is contained in:
R.B. Boyer 2024-11-07 11:47:55 -06:00 committed by GitHub
parent 32515c77f2
commit a2e69236a2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
40 changed files with 443 additions and 3449 deletions

3
.changelog/21883.txt Normal file
View File

@ -0,0 +1,3 @@
```release-note:feature
v2: remove HCP Link integration
```

View File

@ -53,7 +53,6 @@ import (
"github.com/hashicorp/consul/agent/consul/xdscapacity"
"github.com/hashicorp/consul/agent/grpc-external/services/peerstream"
"github.com/hashicorp/consul/agent/hcp"
"github.com/hashicorp/consul/agent/hcp/bootstrap"
hcpclient "github.com/hashicorp/consul/agent/hcp/client"
logdrop "github.com/hashicorp/consul/agent/log-drop"
"github.com/hashicorp/consul/agent/metadata"
@ -65,7 +64,6 @@ import (
"github.com/hashicorp/consul/agent/token"
"github.com/hashicorp/consul/internal/controller"
"github.com/hashicorp/consul/internal/gossip/librtt"
hcpctl "github.com/hashicorp/consul/internal/hcp"
"github.com/hashicorp/consul/internal/multicluster"
"github.com/hashicorp/consul/internal/resource"
"github.com/hashicorp/consul/internal/resource/demo"
@ -838,25 +836,6 @@ func NewServer(config *Config, flat Deps, externalGRPCServer *grpc.Server,
// to enable RPC forwarding.
s.grpcLeaderForwarder = flat.LeaderForwarder
if s.config.Cloud.IsConfigured() {
// Start watching HCP Link resource. This needs to be created after
// the GRPC services are set up in order for the resource service client to
// function. This uses the insecure grpc channel so that it doesn't need to
// present a valid ACL token.
go hcp.RunHCPLinkWatcher(
&lib.StopChannelContext{StopCh: shutdownCh},
logger.Named("hcp-link-watcher"),
pbresource.NewResourceServiceClient(s.insecureSafeGRPCChan),
hcp.HCPManagerLifecycleFn(
s.hcpManager,
hcpclient.NewClient,
bootstrap.LoadManagementToken,
flat.HCP.Config,
flat.HCP.DataDir,
),
)
}
s.controllerManager = controller.NewManager(
// Usage of the insecure + unsafe grpc chan is required for the controller
// manager. It must be unauthorized so that controllers do not need to
@ -928,15 +907,7 @@ func NewServer(config *Config, flat Deps, externalGRPCServer *grpc.Server,
return s, nil
}
func (s *Server) registerControllers(deps Deps) error {
if s.config.Cloud.IsConfigured() {
hcpctl.RegisterControllers(
s.controllerManager, hcpctl.ControllerDependencies{
CloudConfig: deps.HCP.Config,
},
)
}
func (s *Server) registerControllers(_ Deps) error {
shim := NewExportedServicesShim(s)
multicluster.RegisterCompatControllers(s.controllerManager, multicluster.DefaultCompatControllerDependencies(shim))

View File

@ -7,8 +7,6 @@ flowchart TD
demo/v1/recordlabel
demo/v2/album
demo/v2/artist
hcp/v2/link
hcp/v2/telemetrystate
internal/v1/tombstone
multicluster/v2/computedexportedservices --> multicluster/v2/exportedservices
multicluster/v2/computedexportedservices --> multicluster/v2/namespaceexportedservices
@ -16,4 +14,4 @@ flowchart TD
multicluster/v2/exportedservices
multicluster/v2/namespaceexportedservices
multicluster/v2/partitionexportedservices
```
```

View File

@ -4,7 +4,6 @@
package consul
import (
"github.com/hashicorp/consul/internal/hcp"
"github.com/hashicorp/consul/internal/multicluster"
"github.com/hashicorp/consul/internal/resource"
"github.com/hashicorp/consul/internal/resource/demo"
@ -22,7 +21,6 @@ func NewTypeRegistry() resource.Registry {
demo.RegisterTypes(registry)
multicluster.RegisterTypes(registry)
hcp.RegisterTypes(registry)
return registry
}

View File

@ -1,68 +0,0 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: BUSL-1.1
package hcp
import (
"context"
"time"
"github.com/hashicorp/go-hclog"
hcpctl "github.com/hashicorp/consul/internal/hcp"
"github.com/hashicorp/consul/lib/retry"
pbhcp "github.com/hashicorp/consul/proto-public/pbhcp/v2"
"github.com/hashicorp/consul/proto-public/pbresource"
)
type LinkEventHandler = func(context.Context, hclog.Logger, *pbresource.WatchEvent)
func handleLinkEvents(ctx context.Context, logger hclog.Logger, watchClient pbresource.ResourceService_WatchListClient, linkEventHandler LinkEventHandler) {
for {
select {
case <-ctx.Done():
logger.Debug("context canceled, exiting")
return
default:
watchEvent, err := watchClient.Recv()
if err != nil {
logger.Error("error receiving link watch event", "error", err)
return
}
linkEventHandler(ctx, logger, watchEvent)
}
}
}
func RunHCPLinkWatcher(
ctx context.Context, logger hclog.Logger, client pbresource.ResourceServiceClient, linkEventHandler LinkEventHandler,
) {
errorBackoff := &retry.Waiter{
MinFailures: 10,
MinWait: 0,
MaxWait: 1 * time.Minute,
}
for {
select {
case <-ctx.Done():
logger.Debug("context canceled, exiting")
return
default:
watchClient, err := client.WatchList(
ctx, &pbresource.WatchListRequest{
Type: pbhcp.LinkType,
NamePrefix: hcpctl.LinkName,
},
)
if err != nil {
logger.Error("failed to create watch on Link", "error", err)
errorBackoff.Wait(ctx)
continue
}
errorBackoff.Reset()
handleLinkEvents(ctx, logger, watchClient, linkEventHandler)
}
}
}

View File

@ -1,101 +0,0 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: BUSL-1.1
package hcp
import (
"context"
"errors"
"testing"
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"
"google.golang.org/grpc"
"github.com/hashicorp/go-hclog"
mockpbresource "github.com/hashicorp/consul/grpcmocks/proto-public/pbresource"
hcpctl "github.com/hashicorp/consul/internal/hcp"
pbhcp "github.com/hashicorp/consul/proto-public/pbhcp/v2"
"github.com/hashicorp/consul/proto-public/pbresource"
)
// This tests that when we get a watch event from the Recv call, we get that same event on the
// output channel, then we
func TestLinkWatcher_Ok(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
t.Cleanup(cancel)
testWatchEvent := &pbresource.WatchEvent{}
mockWatchListClient := mockpbresource.NewResourceService_WatchListClient(t)
mockWatchListClient.EXPECT().Recv().Return(testWatchEvent, nil)
eventCh := make(chan *pbresource.WatchEvent)
mockLinkHandler := func(_ context.Context, _ hclog.Logger, event *pbresource.WatchEvent) {
eventCh <- event
}
client := mockpbresource.NewResourceServiceClient(t)
client.EXPECT().WatchList(mock.Anything, &pbresource.WatchListRequest{
Type: pbhcp.LinkType,
NamePrefix: hcpctl.LinkName,
}).Return(mockWatchListClient, nil)
go RunHCPLinkWatcher(ctx, hclog.Default(), client, mockLinkHandler)
// Assert that the link handler is called with the testWatchEvent
receivedWatchEvent := <-eventCh
require.Equal(t, testWatchEvent, receivedWatchEvent)
}
func TestLinkWatcher_RecvError(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
// Our mock WatchListClient will simulate 5 errors, then will cancel the context.
// We expect RunHCPLinkWatcher to attempt to create the WatchListClient 6 times (initial attempt plus 5 retries)
// before exiting due to context cancellation.
mockWatchListClient := mockpbresource.NewResourceService_WatchListClient(t)
numFailures := 5
failures := 0
mockWatchListClient.EXPECT().Recv().RunAndReturn(func() (*pbresource.WatchEvent, error) {
if failures < numFailures {
failures++
return nil, errors.New("unexpectedError")
}
defer cancel()
return &pbresource.WatchEvent{}, nil
})
client := mockpbresource.NewResourceServiceClient(t)
client.EXPECT().WatchList(mock.Anything, &pbresource.WatchListRequest{
Type: pbhcp.LinkType,
NamePrefix: hcpctl.LinkName,
}).Return(mockWatchListClient, nil).Times(numFailures + 1)
RunHCPLinkWatcher(ctx, hclog.Default(), client, func(_ context.Context, _ hclog.Logger, _ *pbresource.WatchEvent) {})
}
func TestLinkWatcher_WatchListError(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
// Our mock WatchList will simulate 5 errors, then will cancel the context.
// We expect RunHCPLinkWatcher to attempt to create the WatchListClient 6 times (initial attempt plus 5 retries)
// before exiting due to context cancellation.
numFailures := 5
failures := 0
client := mockpbresource.NewResourceServiceClient(t)
client.EXPECT().WatchList(mock.Anything, &pbresource.WatchListRequest{
Type: pbhcp.LinkType,
NamePrefix: hcpctl.LinkName,
}).RunAndReturn(func(_ context.Context, _ *pbresource.WatchListRequest, _ ...grpc.CallOption) (pbresource.ResourceService_WatchListClient, error) {
if failures < numFailures {
failures++
return nil, errors.New("unexpectedError")
}
defer cancel()
return mockpbresource.NewResourceService_WatchListClient(t), nil
}).Times(numFailures + 1)
RunHCPLinkWatcher(ctx, hclog.Default(), client, func(_ context.Context, _ hclog.Logger, _ *pbresource.WatchEvent) {})
}

View File

@ -1,107 +0,0 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: BUSL-1.1
package hcp
import (
"context"
"os"
"path/filepath"
"github.com/hashicorp/go-hclog"
"github.com/hashicorp/consul/agent/hcp/bootstrap/constants"
hcpclient "github.com/hashicorp/consul/agent/hcp/client"
"github.com/hashicorp/consul/agent/hcp/config"
hcpctl "github.com/hashicorp/consul/internal/hcp"
pbhcp "github.com/hashicorp/consul/proto-public/pbhcp/v2"
"github.com/hashicorp/consul/proto-public/pbresource"
)
// HCPManagerLifecycleFn returns a LinkEventHandler function which will appropriately
// Start and Stop the HCP Manager based on the Link event received. If a link is upserted,
// the HCP Manager is started, and if a link is deleted, the HCP manager is stopped.
func HCPManagerLifecycleFn(
m Manager,
hcpClientFn func(cfg config.CloudConfig) (hcpclient.Client, error),
loadMgmtTokenFn func(
ctx context.Context, logger hclog.Logger, hcpClient hcpclient.Client, dataDir string,
) (string, error),
cloudConfig config.CloudConfig,
dataDir string,
) LinkEventHandler {
return func(ctx context.Context, logger hclog.Logger, watchEvent *pbresource.WatchEvent) {
// This indicates that a Link was deleted
if watchEvent.GetDelete() != nil {
logger.Debug("HCP Link deleted, stopping HCP manager")
if dataDir != "" {
hcpConfigDir := filepath.Join(dataDir, constants.SubDir)
logger.Debug("deleting hcp-config dir", "dir", hcpConfigDir)
err := os.RemoveAll(hcpConfigDir)
if err != nil {
logger.Error("failed to delete hcp-config dir", "dir", hcpConfigDir, "err", err)
}
}
err := m.Stop()
if err != nil {
logger.Error("error stopping HCP manager", "error", err)
}
return
}
// This indicates that a Link was either created or updated
if watchEvent.GetUpsert() != nil {
logger.Debug("HCP Link upserted, starting manager if not already started")
res := watchEvent.GetUpsert().GetResource()
var link pbhcp.Link
if err := res.GetData().UnmarshalTo(&link); err != nil {
logger.Error("error unmarshalling link data", "error", err)
return
}
if validated, reason := hcpctl.IsValidated(res); !validated {
logger.Debug("HCP Link not validated, not starting manager", "reason", reason)
return
}
// Update the HCP manager configuration with the link values
// Merge the link data with the existing cloud config so that we only overwrite the
// fields that are provided by the link. This ensures that:
// 1. The HCP configuration (i.e., how to connect to HCP) is preserved
// 2. The Consul agent's node ID and node name are preserved
newCfg := config.CloudConfig{
ResourceID: link.ResourceId,
ClientID: link.ClientId,
ClientSecret: link.ClientSecret,
}
mergedCfg := config.Merge(cloudConfig, newCfg)
hcpClient, err := hcpClientFn(mergedCfg)
if err != nil {
logger.Error("error creating HCP client", "error", err)
return
}
// Load the management token if access is set to read-write. Read-only clusters
// will not have a management token provided by HCP.
var token string
if link.GetAccessLevel() == pbhcp.AccessLevel_ACCESS_LEVEL_GLOBAL_READ_WRITE {
token, err = loadMgmtTokenFn(ctx, logger, hcpClient, dataDir)
if err != nil {
logger.Error("error loading management token", "error", err)
return
}
}
mergedCfg.ManagementToken = token
m.UpdateConfig(hcpClient, mergedCfg)
err = m.Start(ctx)
if err != nil {
logger.Error("error starting HCP manager", "error", err)
}
}
}
}

View File

@ -1,236 +0,0 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: BUSL-1.1
package hcp
import (
"context"
"errors"
"io"
"os"
"path/filepath"
"testing"
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"
"google.golang.org/protobuf/types/known/anypb"
"github.com/hashicorp/go-hclog"
"github.com/hashicorp/consul/agent/hcp/bootstrap/constants"
hcpclient "github.com/hashicorp/consul/agent/hcp/client"
"github.com/hashicorp/consul/agent/hcp/config"
hcpctl "github.com/hashicorp/consul/internal/hcp"
pbhcp "github.com/hashicorp/consul/proto-public/pbhcp/v2"
"github.com/hashicorp/consul/proto-public/pbresource"
"github.com/hashicorp/consul/sdk/testutil"
)
func TestHCPManagerLifecycleFn(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
t.Cleanup(cancel)
logger := hclog.New(&hclog.LoggerOptions{Output: io.Discard})
mockHCPClient := hcpclient.NewMockClient(t)
mockHcpClientFn := func(_ config.CloudConfig) (hcpclient.Client, error) {
return mockHCPClient, nil
}
mockLoadMgmtTokenFn := func(ctx context.Context, logger hclog.Logger, hcpClient hcpclient.Client, dataDir string) (string, error) {
return "test-mgmt-token", nil
}
dataDir := testutil.TempDir(t, "test-link-controller")
err := os.Mkdir(filepath.Join(dataDir, constants.SubDir), os.ModeDir)
require.NoError(t, err)
existingCfg := config.CloudConfig{
AuthURL: "test.com",
}
type testCase struct {
mutateLink func(*pbhcp.Link)
mutateUpsertEvent func(*pbresource.WatchEvent_Upsert)
applyMocksAndAssertions func(*testing.T, *MockManager, *pbhcp.Link)
hcpClientFn func(config.CloudConfig) (hcpclient.Client, error)
loadMgmtTokenFn func(context.Context, hclog.Logger, hcpclient.Client, string) (string, error)
}
testCases := map[string]testCase{
// HCP manager should be started when link is created and stopped when link is deleted
"Ok": {
applyMocksAndAssertions: func(t *testing.T, mgr *MockManager, link *pbhcp.Link) {
mgr.EXPECT().Start(mock.Anything).Return(nil).Once()
expectedCfg := config.CloudConfig{
ResourceID: link.ResourceId,
ClientID: link.ClientId,
ClientSecret: link.ClientSecret,
AuthURL: "test.com",
ManagementToken: "test-mgmt-token",
}
mgr.EXPECT().UpdateConfig(mockHCPClient, expectedCfg).Once()
mgr.EXPECT().Stop().Return(nil).Once()
},
},
// HCP manager should not be updated with management token
"ReadOnly": {
mutateLink: func(link *pbhcp.Link) {
link.AccessLevel = pbhcp.AccessLevel_ACCESS_LEVEL_GLOBAL_READ_ONLY
},
applyMocksAndAssertions: func(t *testing.T, mgr *MockManager, link *pbhcp.Link) {
mgr.EXPECT().Start(mock.Anything).Return(nil).Once()
expectedCfg := config.CloudConfig{
ResourceID: link.ResourceId,
ClientID: link.ClientId,
ClientSecret: link.ClientSecret,
AuthURL: "test.com",
ManagementToken: "",
}
mgr.EXPECT().UpdateConfig(mockHCPClient, expectedCfg).Once()
mgr.EXPECT().Stop().Return(nil).Once()
},
},
// HCP manager should not be started or updated if link is not validated
"ValidationError": {
mutateUpsertEvent: func(upsert *pbresource.WatchEvent_Upsert) {
upsert.Resource.Status = map[string]*pbresource.Status{
hcpctl.StatusKey: {
Conditions: []*pbresource.Condition{hcpctl.ConditionValidatedFailed},
},
}
},
applyMocksAndAssertions: func(t *testing.T, mgr *MockManager, link *pbhcp.Link) {
mgr.AssertNotCalled(t, "Start", mock.Anything)
mgr.AssertNotCalled(t, "UpdateConfig", mock.Anything, mock.Anything)
mgr.EXPECT().Stop().Return(nil).Once()
},
},
"Error_InvalidLink": {
mutateUpsertEvent: func(upsert *pbresource.WatchEvent_Upsert) {
upsert.Resource = nil
},
applyMocksAndAssertions: func(t *testing.T, mgr *MockManager, link *pbhcp.Link) {
mgr.AssertNotCalled(t, "Start", mock.Anything)
mgr.AssertNotCalled(t, "UpdateConfig", mock.Anything, mock.Anything)
mgr.EXPECT().Stop().Return(nil).Once()
},
},
"Error_HCPManagerStop": {
applyMocksAndAssertions: func(t *testing.T, mgr *MockManager, link *pbhcp.Link) {
mgr.EXPECT().Start(mock.Anything).Return(nil).Once()
mgr.EXPECT().UpdateConfig(mock.Anything, mock.Anything).Return().Once()
mgr.EXPECT().Stop().Return(errors.New("could not stop HCP manager")).Once()
},
},
"Error_CreatingHCPClient": {
applyMocksAndAssertions: func(t *testing.T, mgr *MockManager, link *pbhcp.Link) {
mgr.AssertNotCalled(t, "Start", mock.Anything)
mgr.AssertNotCalled(t, "UpdateConfig", mock.Anything, mock.Anything)
mgr.EXPECT().Stop().Return(nil).Once()
},
hcpClientFn: func(_ config.CloudConfig) (hcpclient.Client, error) {
return nil, errors.New("could not create HCP client")
},
},
// This should result in the HCP manager not being started
"Error_LoadMgmtToken": {
applyMocksAndAssertions: func(t *testing.T, mgr *MockManager, link *pbhcp.Link) {
mgr.AssertNotCalled(t, "Start", mock.Anything)
mgr.AssertNotCalled(t, "UpdateConfig", mock.Anything, mock.Anything)
mgr.EXPECT().Stop().Return(nil).Once()
},
loadMgmtTokenFn: func(ctx context.Context, logger hclog.Logger, hcpClient hcpclient.Client, dataDir string) (string, error) {
return "", errors.New("could not load management token")
},
},
"Error_HCPManagerStart": {
applyMocksAndAssertions: func(t *testing.T, mgr *MockManager, link *pbhcp.Link) {
mgr.EXPECT().Start(mock.Anything).Return(errors.New("could not start HCP manager")).Once()
mgr.EXPECT().UpdateConfig(mock.Anything, mock.Anything).Return().Once()
mgr.EXPECT().Stop().Return(nil).Once()
},
},
}
for name, test := range testCases {
t.Run(name, func(t2 *testing.T) {
mgr := NewMockManager(t2)
// Set up a link
link := pbhcp.Link{
ResourceId: "abc",
ClientId: "def",
ClientSecret: "ghi",
AccessLevel: pbhcp.AccessLevel_ACCESS_LEVEL_GLOBAL_READ_WRITE,
}
if test.mutateLink != nil {
test.mutateLink(&link)
}
linkResource, err := anypb.New(&link)
require.NoError(t2, err)
if test.applyMocksAndAssertions != nil {
test.applyMocksAndAssertions(t2, mgr, &link)
}
testHcpClientFn := mockHcpClientFn
if test.hcpClientFn != nil {
testHcpClientFn = test.hcpClientFn
}
testLoadMgmtToken := mockLoadMgmtTokenFn
if test.loadMgmtTokenFn != nil {
testLoadMgmtToken = test.loadMgmtTokenFn
}
updateManagerLifecycle := HCPManagerLifecycleFn(
mgr, testHcpClientFn,
testLoadMgmtToken, existingCfg, dataDir,
)
upsertEvent := &pbresource.WatchEvent_Upsert{
Resource: &pbresource.Resource{
Id: &pbresource.ID{
Name: "global",
Type: pbhcp.LinkType,
},
Status: map[string]*pbresource.Status{
hcpctl.StatusKey: {
Conditions: []*pbresource.Condition{hcpctl.ConditionValidatedSuccess},
},
},
Data: linkResource,
},
}
if test.mutateUpsertEvent != nil {
test.mutateUpsertEvent(upsertEvent)
}
// Handle upsert event
updateManagerLifecycle(ctx, logger, &pbresource.WatchEvent{
Event: &pbresource.WatchEvent_Upsert_{
Upsert: upsertEvent,
},
})
// Handle delete event. This should stop HCP manager
updateManagerLifecycle(ctx, logger, &pbresource.WatchEvent{
Event: &pbresource.WatchEvent_Delete_{
Delete: &pbresource.WatchEvent_Delete{},
},
})
// Ensure hcp-config directory is removed
file := filepath.Join(dataDir, constants.SubDir)
if _, err := os.Stat(file); err == nil || !os.IsNotExist(err) {
require.Fail(t2, "should have removed hcp-config directory")
}
})
}
}

View File

@ -12,75 +12,15 @@ import (
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"
"golang.org/x/net/context"
"google.golang.org/protobuf/types/known/anypb"
"github.com/hashicorp/go-hclog"
hcpclient "github.com/hashicorp/consul/agent/hcp/client"
"github.com/hashicorp/consul/agent/hcp/config"
"github.com/hashicorp/consul/agent/hcp/scada"
hcpctl "github.com/hashicorp/consul/internal/hcp"
pbhcp "github.com/hashicorp/consul/proto-public/pbhcp/v2"
"github.com/hashicorp/consul/proto-public/pbresource"
"github.com/hashicorp/consul/sdk/testutil"
)
func TestManager_MonitorHCPLink(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
t.Cleanup(cancel)
logger := hclog.New(&hclog.LoggerOptions{Output: io.Discard})
mgr := NewManager(
ManagerConfig{
Logger: hclog.New(&hclog.LoggerOptions{Output: io.Discard}),
},
)
mockHCPClient := hcpclient.NewMockClient(t)
mockHcpClientFn := func(_ config.CloudConfig) (hcpclient.Client, error) {
return mockHCPClient, nil
}
loadMgmtTokenFn := func(ctx context.Context, logger hclog.Logger, hcpClient hcpclient.Client, dataDir string) (string, error) {
return "test-mgmt-token", nil
}
require.False(t, mgr.isRunning())
updateManagerLifecycle := HCPManagerLifecycleFn(
mgr, mockHcpClientFn,
loadMgmtTokenFn, config.CloudConfig{}, "",
)
// Set up a link
link := pbhcp.Link{
ResourceId: "abc",
ClientId: "def",
ClientSecret: "ghi",
AccessLevel: pbhcp.AccessLevel_ACCESS_LEVEL_GLOBAL_READ_WRITE,
}
linkResource, err := anypb.New(&link)
require.NoError(t, err)
updateManagerLifecycle(ctx, logger, &pbresource.WatchEvent{
Event: &pbresource.WatchEvent_Upsert_{
Upsert: &pbresource.WatchEvent_Upsert{
Resource: &pbresource.Resource{
Id: &pbresource.ID{
Name: "global",
Type: pbhcp.LinkType,
},
Status: map[string]*pbresource.Status{
hcpctl.StatusKey: {
Conditions: []*pbresource.Condition{hcpctl.ConditionValidatedSuccess},
},
},
Data: linkResource,
},
},
},
})
// Validate that the HCP manager is started
require.True(t, mgr.isRunning())
}
func TestManager_Start(t *testing.T) {
client := hcpclient.NewMockClient(t)
statusF := func(ctx context.Context) (hcpclient.ServerStatus, error) {

View File

@ -1,34 +0,0 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: BUSL-1.1
package hcp
import (
"github.com/hashicorp/consul/internal/controller"
"github.com/hashicorp/consul/internal/hcp/internal/controllers"
"github.com/hashicorp/consul/internal/hcp/internal/controllers/link"
"github.com/hashicorp/consul/internal/hcp/internal/types"
"github.com/hashicorp/consul/internal/resource"
)
// RegisterTypes adds all resource types within the "hcp" API group
// to the given type registry
func RegisterTypes(r resource.Registry) {
types.Register(r)
}
type ControllerDependencies = controllers.Dependencies
var IsValidated = link.IsValidated
var LinkName = types.LinkName
// RegisterControllers registers controllers for the catalog types with
// the given controller Manager.
func RegisterControllers(mgr *controller.Manager, deps ControllerDependencies) {
controllers.Register(mgr, deps)
}
// Needed for testing
var StatusKey = link.StatusKey
var ConditionValidatedSuccess = link.ConditionValidatedSuccess
var ConditionValidatedFailed = link.ConditionValidatedFailed

View File

@ -1,234 +0,0 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: BUSL-1.1
package link
import (
"context"
"crypto/tls"
"strings"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
"google.golang.org/protobuf/types/known/anypb"
gnmmod "github.com/hashicorp/hcp-sdk-go/clients/cloud-global-network-manager-service/preview/2022-02-15/models"
hcpclient "github.com/hashicorp/consul/agent/hcp/client"
"github.com/hashicorp/consul/agent/hcp/config"
"github.com/hashicorp/consul/internal/controller"
"github.com/hashicorp/consul/internal/hcp/internal/types"
"github.com/hashicorp/consul/internal/storage"
pbhcp "github.com/hashicorp/consul/proto-public/pbhcp/v2"
"github.com/hashicorp/consul/proto-public/pbresource"
)
// HCPClientFn is a function that can be used to create an HCP client from a Link object.
// This function type should be passed to a LinkController in order to tell it how to make a client from
// a Link. For normal use, DefaultHCPClientFn should be used, but tests can substitute in a function that creates a
// mock client.
type HCPClientFn func(config.CloudConfig) (hcpclient.Client, error)
var DefaultHCPClientFn HCPClientFn = func(cfg config.CloudConfig) (hcpclient.Client, error) {
hcpClient, err := hcpclient.NewClient(cfg)
if err != nil {
return nil, err
}
return hcpClient, nil
}
func LinkController(
hcpClientFn HCPClientFn,
cfg config.CloudConfig,
) *controller.Controller {
return controller.NewController("link", pbhcp.LinkType).
WithInitializer(
&linkInitializer{
cloudConfig: cfg,
},
).
WithReconciler(
&linkReconciler{
hcpClientFn: hcpClientFn,
cloudConfig: cfg,
},
)
}
type linkReconciler struct {
hcpClientFn HCPClientFn
cloudConfig config.CloudConfig
}
func hcpAccessLevelToConsul(level *gnmmod.HashicorpCloudGlobalNetworkManager20220215ClusterConsulAccessLevel) pbhcp.AccessLevel {
if level == nil {
return pbhcp.AccessLevel_ACCESS_LEVEL_UNSPECIFIED
}
switch *level {
case gnmmod.HashicorpCloudGlobalNetworkManager20220215ClusterConsulAccessLevelCONSULACCESSLEVELUNSPECIFIED:
return pbhcp.AccessLevel_ACCESS_LEVEL_UNSPECIFIED
case gnmmod.HashicorpCloudGlobalNetworkManager20220215ClusterConsulAccessLevelCONSULACCESSLEVELGLOBALREADWRITE:
return pbhcp.AccessLevel_ACCESS_LEVEL_GLOBAL_READ_WRITE
case gnmmod.HashicorpCloudGlobalNetworkManager20220215ClusterConsulAccessLevelCONSULACCESSLEVELGLOBALREADONLY:
return pbhcp.AccessLevel_ACCESS_LEVEL_GLOBAL_READ_ONLY
default:
return pbhcp.AccessLevel_ACCESS_LEVEL_UNSPECIFIED
}
}
func (r *linkReconciler) Reconcile(ctx context.Context, rt controller.Runtime, req controller.Request) error {
// The runtime is passed by value so replacing it here for the remainder of this
// reconciliation request processing will not affect future invocations.
rt.Logger = rt.Logger.With("resource-id", req.ID, "controller", StatusKey)
rt.Logger.Trace("reconciling link")
rsp, err := rt.Client.Read(ctx, &pbresource.ReadRequest{Id: req.ID})
switch {
case status.Code(err) == codes.NotFound:
rt.Logger.Trace("link has been deleted")
return nil
case err != nil:
rt.Logger.Error("the resource service has returned an unexpected error", "error", err)
return err
}
res := rsp.Resource
var link pbhcp.Link
if err := res.Data.UnmarshalTo(&link); err != nil {
rt.Logger.Error("error unmarshalling link data", "error", err)
return err
}
newStatus := &pbresource.Status{
ObservedGeneration: res.Generation,
Conditions: []*pbresource.Condition{},
}
defer writeStatusIfNotEqual(ctx, rt, res, newStatus)
newStatus.Conditions = append(newStatus.Conditions, ConditionValidatedSuccess)
// Merge the link data with the existing cloud config so that we only overwrite the
// fields that are provided by the link. This ensures that:
// 1. The HCP configuration (i.e., how to connect to HCP) is preserved
// 2. The Consul agent's node ID and node name are preserved
newCfg := CloudConfigFromLink(&link)
cfg := config.Merge(r.cloudConfig, newCfg)
hcpClient, err := r.hcpClientFn(cfg)
if err != nil {
rt.Logger.Error("error creating HCP client", "error", err)
return err
}
// Sync cluster data from HCP
cluster, err := hcpClient.GetCluster(ctx)
if err != nil {
rt.Logger.Error("error querying HCP for cluster", "error", err)
condition := linkingFailedCondition(err)
newStatus.Conditions = append(newStatus.Conditions, condition)
return err
}
accessLevel := hcpAccessLevelToConsul(cluster.AccessLevel)
if link.HcpClusterUrl != cluster.HCPPortalURL ||
link.AccessLevel != accessLevel {
link.HcpClusterUrl = cluster.HCPPortalURL
link.AccessLevel = accessLevel
updatedData, err := anypb.New(&link)
if err != nil {
rt.Logger.Error("error marshalling link data", "error", err)
return err
}
_, err = rt.Client.Write(
ctx, &pbresource.WriteRequest{Resource: &pbresource.Resource{
Id: &pbresource.ID{
Name: types.LinkName,
Type: pbhcp.LinkType,
},
Metadata: res.Metadata,
Data: updatedData,
}},
)
if err != nil {
rt.Logger.Error("error updating link", "error", err)
return err
}
}
newStatus.Conditions = append(newStatus.Conditions, ConditionLinked(link.ResourceId))
return writeStatusIfNotEqual(ctx, rt, res, newStatus)
}
type linkInitializer struct {
cloudConfig config.CloudConfig
}
func (i *linkInitializer) Initialize(ctx context.Context, rt controller.Runtime) error {
if !i.cloudConfig.IsConfigured() {
return nil
}
// Construct a link resource to reflect the configuration
data, err := anypb.New(
&pbhcp.Link{
ResourceId: i.cloudConfig.ResourceID,
ClientId: i.cloudConfig.ClientID,
ClientSecret: i.cloudConfig.ClientSecret,
},
)
if err != nil {
return err
}
// Create the link resource for a configuration-based link
_, err = rt.Client.Write(
ctx,
&pbresource.WriteRequest{
Resource: &pbresource.Resource{
Id: &pbresource.ID{
Name: types.LinkName,
Type: pbhcp.LinkType,
},
Metadata: map[string]string{
types.MetadataSourceKey: types.MetadataSourceConfig,
},
Data: data,
},
},
)
if err != nil {
if strings.Contains(err.Error(), storage.ErrWrongUid.Error()) ||
strings.Contains(err.Error(), "leader unknown") {
// If the error is likely ignorable and could eventually resolve itself,
// log it as TRACE rather than ERROR.
rt.Logger.Trace("error initializing controller", "error", err)
} else {
rt.Logger.Error("error initializing controller", "error", err)
}
return err
}
return nil
}
func CloudConfigFromLink(link *pbhcp.Link) config.CloudConfig {
var cfg config.CloudConfig
if link == nil {
return cfg
}
cfg = config.CloudConfig{
ResourceID: link.GetResourceId(),
ClientID: link.GetClientId(),
ClientSecret: link.GetClientSecret(),
}
if link.GetHcpConfig() != nil {
cfg.AuthURL = link.GetHcpConfig().GetAuthUrl()
cfg.ScadaAddress = link.GetHcpConfig().GetScadaAddress()
cfg.Hostname = link.GetHcpConfig().GetApiAddress()
cfg.TLSConfig = &tls.Config{InsecureSkipVerify: link.GetHcpConfig().GetTlsInsecureSkipVerify()}
}
return cfg
}

View File

@ -1,248 +0,0 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: BUSL-1.1
package link
import (
"context"
"fmt"
"testing"
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"
"github.com/stretchr/testify/suite"
gnmmod "github.com/hashicorp/hcp-sdk-go/clients/cloud-global-network-manager-service/preview/2022-02-15/models"
svctest "github.com/hashicorp/consul/agent/grpc-external/services/resource/testing"
hcpclient "github.com/hashicorp/consul/agent/hcp/client"
"github.com/hashicorp/consul/agent/hcp/config"
"github.com/hashicorp/consul/internal/controller"
"github.com/hashicorp/consul/internal/hcp/internal/types"
rtest "github.com/hashicorp/consul/internal/resource/resourcetest"
pbhcp "github.com/hashicorp/consul/proto-public/pbhcp/v2"
"github.com/hashicorp/consul/proto-public/pbresource"
"github.com/hashicorp/consul/sdk/testutil"
)
type controllerSuite struct {
suite.Suite
ctx context.Context
client *rtest.Client
rt controller.Runtime
tenancies []*pbresource.Tenancy
}
func mockHcpClientFn(t *testing.T) (*hcpclient.MockClient, HCPClientFn) {
mockClient := hcpclient.NewMockClient(t)
mockClientFunc := func(config config.CloudConfig) (hcpclient.Client, error) {
return mockClient, nil
}
return mockClient, mockClientFunc
}
func (suite *controllerSuite) SetupTest() {
suite.ctx = testutil.TestContext(suite.T())
suite.tenancies = rtest.TestTenancies()
client := svctest.NewResourceServiceBuilder().
WithRegisterFns(types.Register).
WithTenancies(suite.tenancies...).
Run(suite.T())
suite.rt = controller.Runtime{
Client: client,
Logger: testutil.Logger(suite.T()),
}
suite.client = rtest.NewClient(client)
}
func TestLinkController(t *testing.T) {
suite.Run(t, new(controllerSuite))
}
func (suite *controllerSuite) deleteResourceFunc(id *pbresource.ID) func() {
return func() {
suite.client.MustDelete(suite.T(), id)
suite.client.WaitForDeletion(suite.T(), id)
}
}
func (suite *controllerSuite) TestController_Ok() {
// Run the controller manager
mgr := controller.NewManager(suite.client, suite.rt.Logger)
mockClient, mockClientFn := mockHcpClientFn(suite.T())
readWrite := gnmmod.HashicorpCloudGlobalNetworkManager20220215ClusterConsulAccessLevelCONSULACCESSLEVELGLOBALREADWRITE
mockClient.EXPECT().GetCluster(mock.Anything).Return(&hcpclient.Cluster{
HCPPortalURL: "http://test.com",
AccessLevel: &readWrite,
}, nil)
mgr.Register(LinkController(
mockClientFn,
config.CloudConfig{},
))
mgr.SetRaftLeader(true)
go mgr.Run(suite.ctx)
linkData := &pbhcp.Link{
ClientId: "abc",
ClientSecret: "abc",
ResourceId: types.GenerateTestResourceID(suite.T()),
}
link := rtest.Resource(pbhcp.LinkType, "global").
WithData(suite.T(), linkData).
Write(suite.T(), suite.client)
suite.T().Cleanup(suite.deleteResourceFunc(link.Id))
suite.client.WaitForStatusCondition(suite.T(), link.Id, StatusKey, ConditionLinked(linkData.ResourceId))
var updatedLink pbhcp.Link
updatedLinkResource := suite.client.WaitForNewVersion(suite.T(), link.Id, link.Version)
require.NoError(suite.T(), updatedLinkResource.Data.UnmarshalTo(&updatedLink))
require.Equal(suite.T(), "http://test.com", updatedLink.HcpClusterUrl)
require.Equal(suite.T(), pbhcp.AccessLevel_ACCESS_LEVEL_GLOBAL_READ_WRITE, updatedLink.AccessLevel)
}
func (suite *controllerSuite) TestController_Initialize() {
// Run the controller manager with a configured link
mgr := controller.NewManager(suite.client, suite.rt.Logger)
mockClient, mockClientFn := mockHcpClientFn(suite.T())
readOnly := gnmmod.HashicorpCloudGlobalNetworkManager20220215ClusterConsulAccessLevelCONSULACCESSLEVELGLOBALREADONLY
mockClient.EXPECT().GetCluster(mock.Anything).Return(&hcpclient.Cluster{
HCPPortalURL: "http://test.com",
AccessLevel: &readOnly,
}, nil)
cloudCfg := config.CloudConfig{
ClientID: "client-id-abc",
ClientSecret: "client-secret-abc",
ResourceID: types.GenerateTestResourceID(suite.T()),
}
mgr.Register(LinkController(
mockClientFn,
cloudCfg,
))
mgr.SetRaftLeader(true)
go mgr.Run(suite.ctx)
// Wait for link to be created by initializer
id := &pbresource.ID{
Type: pbhcp.LinkType,
Name: types.LinkName,
}
suite.T().Cleanup(suite.deleteResourceFunc(id))
r := suite.client.WaitForResourceExists(suite.T(), id)
// Check that created link has expected values
var link pbhcp.Link
err := r.Data.UnmarshalTo(&link)
require.NoError(suite.T(), err)
require.Equal(suite.T(), cloudCfg.ResourceID, link.ResourceId)
require.Equal(suite.T(), cloudCfg.ClientID, link.ClientId)
require.Equal(suite.T(), cloudCfg.ClientSecret, link.ClientSecret)
require.Equal(suite.T(), types.MetadataSourceConfig, r.Metadata[types.MetadataSourceKey])
// Wait for link to be connected successfully
suite.client.WaitForStatusCondition(suite.T(), id, StatusKey, ConditionLinked(link.ResourceId))
}
func (suite *controllerSuite) TestController_GetClusterError() {
type testCase struct {
expectErr error
expectCondition *pbresource.Condition
}
tt := map[string]testCase{
"unexpected": {
expectErr: fmt.Errorf("error"),
expectCondition: ConditionFailed,
},
"unauthorized": {
expectErr: hcpclient.ErrUnauthorized,
expectCondition: ConditionUnauthorized,
},
"forbidden": {
expectErr: hcpclient.ErrForbidden,
expectCondition: ConditionForbidden,
},
}
for name, tc := range tt {
suite.T().Run(name, func(t *testing.T) {
// Run the controller manager
mgr := controller.NewManager(suite.client, suite.rt.Logger)
mockClient, mockClientFunc := mockHcpClientFn(t)
mockClient.EXPECT().GetCluster(mock.Anything).Return(nil, tc.expectErr)
mgr.Register(LinkController(
mockClientFunc,
config.CloudConfig{},
))
mgr.SetRaftLeader(true)
ctx, cancel := context.WithCancel(suite.ctx)
t.Cleanup(cancel)
go mgr.Run(ctx)
linkData := &pbhcp.Link{
ClientId: "abc",
ClientSecret: "abc",
ResourceId: types.GenerateTestResourceID(t),
}
link := rtest.Resource(pbhcp.LinkType, "global").
WithData(t, linkData).
Write(t, suite.client)
t.Cleanup(suite.deleteResourceFunc(link.Id))
suite.client.WaitForStatusCondition(t, link.Id, StatusKey, tc.expectCondition)
})
}
}
func Test_hcpAccessModeToConsul(t *testing.T) {
type testCase struct {
hcpAccessLevel *gnmmod.HashicorpCloudGlobalNetworkManager20220215ClusterConsulAccessLevel
consulAccessLevel pbhcp.AccessLevel
}
tt := map[string]testCase{
"unspecified": {
hcpAccessLevel: func() *gnmmod.HashicorpCloudGlobalNetworkManager20220215ClusterConsulAccessLevel {
t := gnmmod.HashicorpCloudGlobalNetworkManager20220215ClusterConsulAccessLevelCONSULACCESSLEVELUNSPECIFIED
return &t
}(),
consulAccessLevel: pbhcp.AccessLevel_ACCESS_LEVEL_UNSPECIFIED,
},
"invalid": {
hcpAccessLevel: nil,
consulAccessLevel: pbhcp.AccessLevel_ACCESS_LEVEL_UNSPECIFIED,
},
"read_only": {
hcpAccessLevel: func() *gnmmod.HashicorpCloudGlobalNetworkManager20220215ClusterConsulAccessLevel {
t := gnmmod.HashicorpCloudGlobalNetworkManager20220215ClusterConsulAccessLevelCONSULACCESSLEVELGLOBALREADONLY
return &t
}(),
consulAccessLevel: pbhcp.AccessLevel_ACCESS_LEVEL_GLOBAL_READ_ONLY,
},
"read_write": {
hcpAccessLevel: func() *gnmmod.HashicorpCloudGlobalNetworkManager20220215ClusterConsulAccessLevel {
t := gnmmod.HashicorpCloudGlobalNetworkManager20220215ClusterConsulAccessLevelCONSULACCESSLEVELGLOBALREADWRITE
return &t
}(),
consulAccessLevel: pbhcp.AccessLevel_ACCESS_LEVEL_GLOBAL_READ_WRITE,
},
}
for name, tc := range tt {
t.Run(name, func(t *testing.T) {
accessLevel := hcpAccessLevelToConsul(tc.hcpAccessLevel)
require.Equal(t, tc.consulAccessLevel, accessLevel)
})
}
}

View File

@ -1,142 +0,0 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: BUSL-1.1
package link
import (
"context"
"errors"
"fmt"
"github.com/hashicorp/consul/agent/hcp/client"
"github.com/hashicorp/consul/internal/controller"
"github.com/hashicorp/consul/internal/resource"
pbhcp "github.com/hashicorp/consul/proto-public/pbhcp/v2"
"github.com/hashicorp/consul/proto-public/pbresource"
)
const (
StatusKey = "consul.io/hcp/link"
// Statuses
StatusLinked = "linked"
StatusValidated = "validated"
LinkedSuccessReason = "SUCCESS"
LinkedFailedReason = "FAILED"
LinkedDisabledReasonV2ResourcesUnsupportedReason = "DISABLED_V2_RESOURCES_UNSUPPORTED"
LinkedUnauthorizedReason = "UNAUTHORIZED"
LinkedForbiddenReason = "FORBIDDEN"
ValidatedSuccessReason = "SUCCESS"
ValidatedFailedV2ResourcesReason = "V2_RESOURCES_UNSUPPORTED"
LinkedMessageFormat = "Successfully linked to cluster '%s'"
FailedMessage = "Failed to link to HCP due to unexpected error"
DisabledResourceAPIsEnabledMessage = "Link is disabled because resource-apis are enabled"
UnauthorizedMessage = "Access denied, check client_id and client_secret"
ForbiddenMessage = "Access denied, check the resource_id"
ValidatedSuccessMessage = "Successfully validated link"
ValidatedFailedV2ResourcesMessage = "Link is disabled because resource-apis are enabled"
)
var (
ConditionDisabled = &pbresource.Condition{
Type: StatusLinked,
State: pbresource.Condition_STATE_FALSE,
Reason: LinkedDisabledReasonV2ResourcesUnsupportedReason,
Message: DisabledResourceAPIsEnabledMessage,
}
ConditionFailed = &pbresource.Condition{
Type: StatusLinked,
State: pbresource.Condition_STATE_FALSE,
Reason: LinkedFailedReason,
Message: FailedMessage,
}
ConditionUnauthorized = &pbresource.Condition{
Type: StatusLinked,
State: pbresource.Condition_STATE_FALSE,
Reason: LinkedUnauthorizedReason,
Message: UnauthorizedMessage,
}
ConditionForbidden = &pbresource.Condition{
Type: StatusLinked,
State: pbresource.Condition_STATE_FALSE,
Reason: LinkedForbiddenReason,
Message: ForbiddenMessage,
}
ConditionValidatedSuccess = &pbresource.Condition{
Type: StatusValidated,
State: pbresource.Condition_STATE_TRUE,
Reason: ValidatedSuccessReason,
Message: ValidatedSuccessMessage,
}
ConditionValidatedFailed = &pbresource.Condition{
Type: StatusValidated,
State: pbresource.Condition_STATE_FALSE,
Reason: ValidatedFailedV2ResourcesReason,
Message: ValidatedFailedV2ResourcesMessage,
}
)
func ConditionLinked(resourceId string) *pbresource.Condition {
return &pbresource.Condition{
Type: StatusLinked,
State: pbresource.Condition_STATE_TRUE,
Reason: LinkedSuccessReason,
Message: fmt.Sprintf(LinkedMessageFormat, resourceId),
}
}
func writeStatusIfNotEqual(ctx context.Context, rt controller.Runtime, res *pbresource.Resource, status *pbresource.Status) error {
if resource.EqualStatus(res.Status[StatusKey], status, false) {
return nil
}
_, err := rt.Client.WriteStatus(
ctx, &pbresource.WriteStatusRequest{
Id: res.Id,
Key: StatusKey,
Status: status,
},
)
if err != nil {
rt.Logger.Error("error writing link status", "error", err)
}
return err
}
func linkingFailedCondition(err error) *pbresource.Condition {
switch {
case errors.Is(err, client.ErrUnauthorized):
return ConditionUnauthorized
case errors.Is(err, client.ErrForbidden):
return ConditionForbidden
default:
return ConditionFailed
}
}
func IsLinked(res *pbresource.Resource) (linked bool, reason string) {
return isConditionTrue(res, StatusLinked)
}
func IsValidated(res *pbresource.Resource) (linked bool, reason string) {
return isConditionTrue(res, StatusValidated)
}
func isConditionTrue(res *pbresource.Resource, statusType string) (bool, string) {
if !resource.EqualType(res.GetId().GetType(), pbhcp.LinkType) {
return false, "resource is not hcp.Link type"
}
linkStatus, ok := res.GetStatus()[StatusKey]
if !ok {
return false, "link status not set"
}
for _, cond := range linkStatus.GetConditions() {
if cond.Type == statusType && cond.GetState() == pbresource.Condition_STATE_TRUE {
return true, ""
}
}
return false, fmt.Sprintf("link status does not include positive %s condition", statusType)
}

View File

@ -1,26 +0,0 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: BUSL-1.1
package controllers
import (
"github.com/hashicorp/consul/agent/hcp/config"
"github.com/hashicorp/consul/internal/controller"
"github.com/hashicorp/consul/internal/hcp/internal/controllers/link"
"github.com/hashicorp/consul/internal/hcp/internal/controllers/telemetrystate"
)
type Dependencies struct {
CloudConfig config.CloudConfig
}
func Register(mgr *controller.Manager, deps Dependencies) {
mgr.Register(
link.LinkController(
link.DefaultHCPClientFn,
deps.CloudConfig,
),
)
mgr.Register(telemetrystate.TelemetryStateController(link.DefaultHCPClientFn))
}

View File

@ -1,203 +0,0 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: BUSL-1.1
package telemetrystate
import (
"context"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
"google.golang.org/protobuf/proto"
"google.golang.org/protobuf/types/known/anypb"
"github.com/hashicorp/consul/internal/controller"
"github.com/hashicorp/consul/internal/controller/dependency"
"github.com/hashicorp/consul/internal/hcp/internal/controllers/link"
"github.com/hashicorp/consul/internal/hcp/internal/types"
"github.com/hashicorp/consul/internal/resource"
pbhcp "github.com/hashicorp/consul/proto-public/pbhcp/v2"
"github.com/hashicorp/consul/proto-public/pbresource"
)
var (
globalID = &pbresource.ID{
Name: "global",
Type: pbhcp.TelemetryStateType,
Tenancy: &pbresource.Tenancy{},
}
)
const MetaKeyDebugSkipDeletion = StatusKey + "/debug/skip-deletion"
func TelemetryStateController(hcpClientFn link.HCPClientFn) *controller.Controller {
return controller.NewController(StatusKey, pbhcp.TelemetryStateType).
WithWatch(pbhcp.LinkType, dependency.ReplaceType(pbhcp.TelemetryStateType)).
WithReconciler(&telemetryStateReconciler{
hcpClientFn: hcpClientFn,
})
}
type telemetryStateReconciler struct {
hcpClientFn link.HCPClientFn
}
func (r *telemetryStateReconciler) Reconcile(ctx context.Context, rt controller.Runtime, req controller.Request) error {
// The runtime is passed by value so replacing it here for the remainder of this
// reconciliation request processing will not affect future invocations.
rt.Logger = rt.Logger.With("resource-id", req.ID, "controller", StatusKey)
rt.Logger.Trace("reconciling telemetry-state")
// First get the link resource in order to build a hcp client. If the link resource
// doesn't exist then the telemetry-state should not exist either.
res, err := getLinkResource(ctx, rt)
if err != nil {
rt.Logger.Error("failed to lookup Link resource", "error", err)
return err
}
if res == nil {
return ensureTelemetryStateDeleted(ctx, rt)
}
// Check that the link resource indicates the cluster is linked
// If the cluster is not linked, the telemetry-state resource should not exist
if linked, reason := link.IsLinked(res.GetResource()); !linked {
rt.Logger.Trace("cluster is not linked", "reason", reason)
return ensureTelemetryStateDeleted(ctx, rt)
}
hcpClient, err := r.hcpClientFn(link.CloudConfigFromLink(res.GetData()))
if err != nil {
rt.Logger.Error("error creating HCP Client", "error", err)
return err
}
// Get the telemetry configuration and observability scoped credentials from hcp
tCfg, err := hcpClient.FetchTelemetryConfig(ctx)
if err != nil {
rt.Logger.Error("error requesting telemetry config", "error", err)
return err
}
clientID, clientSecret, err := hcpClient.GetObservabilitySecret(ctx)
if err != nil {
rt.Logger.Error("error requesting telemetry credentials", "error", err)
return nil
}
// TODO allow hcp client config override from hcp TelemetryConfig
hcpCfg := res.GetData().GetHcpConfig()
// TODO implement proxy options from hcp
proxyCfg := &pbhcp.ProxyConfig{}
state := &pbhcp.TelemetryState{
ResourceId: res.GetData().ResourceId,
ClientId: clientID,
ClientSecret: clientSecret,
HcpConfig: hcpCfg,
Proxy: proxyCfg,
Metrics: &pbhcp.MetricsConfig{
Labels: tCfg.MetricsConfig.Labels,
Disabled: tCfg.MetricsConfig.Disabled,
},
}
if tCfg.MetricsConfig.Endpoint != nil {
state.Metrics.Endpoint = tCfg.MetricsConfig.Endpoint.String()
}
if tCfg.MetricsConfig.Filters != nil {
state.Metrics.IncludeList = []string{tCfg.MetricsConfig.Filters.String()}
}
if err := writeTelemetryStateIfUpdated(ctx, rt, state); err != nil {
rt.Logger.Error("error updating telemetry-state", "error", err)
return err
}
return nil
}
func ensureTelemetryStateDeleted(ctx context.Context, rt controller.Runtime) error {
resp, err := rt.Client.Read(ctx, &pbresource.ReadRequest{Id: &pbresource.ID{Name: "global", Type: pbhcp.TelemetryStateType}})
switch {
case status.Code(err) == codes.NotFound:
return nil
case err != nil:
rt.Logger.Error("the resource service has returned an unexpected error", "error", err)
return err
}
rt.Logger.Trace("deleting telemetry-state")
if _, ok := resp.GetResource().Metadata[MetaKeyDebugSkipDeletion]; ok {
rt.Logger.Debug("skip-deletion metadata key found, skipping deletion of telemetry-state resource")
return nil
}
if _, err := rt.Client.Delete(ctx, &pbresource.DeleteRequest{Id: resp.GetResource().GetId()}); err != nil {
rt.Logger.Error("error deleting telemetry-state resource", "error", err)
return err
}
return nil
}
func writeTelemetryStateIfUpdated(ctx context.Context, rt controller.Runtime, state *pbhcp.TelemetryState) error {
currentState, err := getTelemetryStateResource(ctx, rt)
if err != nil {
return err
}
if currentState != nil && proto.Equal(currentState.GetData(), state) {
return nil
}
stateData, err := anypb.New(state)
if err != nil {
return err
}
_, err = rt.Client.Write(ctx, &pbresource.WriteRequest{Resource: &pbresource.Resource{
Id: &pbresource.ID{
Name: "global",
Type: pbhcp.TelemetryStateType,
},
Data: stateData,
}})
return err
}
func getGlobalResource(ctx context.Context, rt controller.Runtime, t *pbresource.Type) (*pbresource.Resource, error) {
resp, err := rt.Client.Read(ctx, &pbresource.ReadRequest{Id: &pbresource.ID{Name: "global", Type: t}})
switch {
case status.Code(err) == codes.NotFound:
return nil, nil
case err != nil:
return nil, err
}
return resp.GetResource(), nil
}
// getLinkResource returns the cluster scoped pbhcp.Link resource. If the resource is not found a nil
// pointer and no error will be returned.
func getLinkResource(ctx context.Context, rt controller.Runtime) (*types.DecodedLink, error) {
res, err := getGlobalResource(ctx, rt, pbhcp.LinkType)
if err != nil {
return nil, err
}
if res == nil {
return nil, nil
}
return resource.Decode[*pbhcp.Link](res)
}
func getTelemetryStateResource(ctx context.Context, rt controller.Runtime) (*types.DecodedTelemetryState, error) {
res, err := getGlobalResource(ctx, rt, pbhcp.TelemetryStateType)
if err != nil {
return nil, err
}
if res == nil {
return nil, nil
}
return resource.Decode[*pbhcp.TelemetryState](res)
}

View File

@ -1,174 +0,0 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: BUSL-1.1
package telemetrystate
import (
"context"
"net/url"
"regexp"
"testing"
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"
"github.com/stretchr/testify/suite"
svctest "github.com/hashicorp/consul/agent/grpc-external/services/resource/testing"
hcpclient "github.com/hashicorp/consul/agent/hcp/client"
"github.com/hashicorp/consul/agent/hcp/config"
"github.com/hashicorp/consul/internal/controller"
"github.com/hashicorp/consul/internal/hcp/internal/controllers/link"
"github.com/hashicorp/consul/internal/hcp/internal/types"
"github.com/hashicorp/consul/internal/resource"
rtest "github.com/hashicorp/consul/internal/resource/resourcetest"
pbhcp "github.com/hashicorp/consul/proto-public/pbhcp/v2"
"github.com/hashicorp/consul/proto-public/pbresource"
"github.com/hashicorp/consul/sdk/testutil"
)
type controllerSuite struct {
suite.Suite
ctx context.Context
client *rtest.Client
rt controller.Runtime
ctl *controller.TestController
tenancies []*pbresource.Tenancy
hcpMock *hcpclient.MockClient
}
func mockHcpClientFn(t *testing.T) (*hcpclient.MockClient, link.HCPClientFn) {
mockClient := hcpclient.NewMockClient(t)
mockClientFunc := func(link config.CloudConfig) (hcpclient.Client, error) {
return mockClient, nil
}
return mockClient, mockClientFunc
}
func (suite *controllerSuite) SetupTest() {
suite.ctx = testutil.TestContext(suite.T())
suite.tenancies = rtest.TestTenancies()
client := svctest.NewResourceServiceBuilder().
WithRegisterFns(types.Register).
WithTenancies(suite.tenancies...).
Run(suite.T())
hcpMock, hcpClientFn := mockHcpClientFn(suite.T())
suite.hcpMock = hcpMock
suite.ctl = controller.NewTestController(TelemetryStateController(hcpClientFn), client).
WithLogger(testutil.Logger(suite.T()))
suite.rt = suite.ctl.Runtime()
suite.client = rtest.NewClient(client)
}
func TestTelemetryStateController(t *testing.T) {
suite.Run(t, new(controllerSuite))
}
func (suite *controllerSuite) deleteResourceFunc(id *pbresource.ID) func() {
return func() {
suite.client.MustDelete(suite.T(), id)
}
}
func (suite *controllerSuite) TestController_Ok() {
// Run the controller manager
mgr := controller.NewManager(suite.client, suite.rt.Logger)
mockClient, mockClientFn := mockHcpClientFn(suite.T())
mockClient.EXPECT().FetchTelemetryConfig(mock.Anything).Return(&hcpclient.TelemetryConfig{
MetricsConfig: &hcpclient.MetricsConfig{
Endpoint: &url.URL{
Scheme: "http",
Host: "localhost",
Path: "/test",
},
Labels: map[string]string{"foo": "bar"},
Filters: regexp.MustCompile(".*"),
},
RefreshConfig: &hcpclient.RefreshConfig{},
}, nil)
mockClient.EXPECT().GetObservabilitySecret(mock.Anything).Return("xxx", "yyy", nil)
mgr.Register(TelemetryStateController(mockClientFn))
mgr.SetRaftLeader(true)
go mgr.Run(suite.ctx)
link := suite.writeLinkResource()
tsRes := suite.client.WaitForResourceExists(suite.T(), &pbresource.ID{Name: "global", Type: pbhcp.TelemetryStateType})
decodedState, err := resource.Decode[*pbhcp.TelemetryState](tsRes)
require.NoError(suite.T(), err)
require.Equal(suite.T(), link.GetData().GetResourceId(), decodedState.GetData().ResourceId)
require.Equal(suite.T(), "xxx", decodedState.GetData().ClientId)
require.Equal(suite.T(), "http://localhost/test", decodedState.GetData().Metrics.Endpoint)
suite.client.MustDelete(suite.T(), link.Id)
suite.client.WaitForDeletion(suite.T(), tsRes.Id)
}
func (suite *controllerSuite) TestReconcile_AvoidReconciliationWriteLoop() {
suite.hcpMock.EXPECT().FetchTelemetryConfig(mock.Anything).Return(&hcpclient.TelemetryConfig{
MetricsConfig: &hcpclient.MetricsConfig{
Endpoint: &url.URL{
Scheme: "http",
Host: "localhost",
Path: "/test",
},
Labels: map[string]string{"foo": "bar"},
Filters: regexp.MustCompile(".*"),
},
RefreshConfig: &hcpclient.RefreshConfig{},
}, nil)
link := suite.writeLinkResource()
suite.hcpMock.EXPECT().GetObservabilitySecret(mock.Anything).Return("xxx", "yyy", nil)
suite.NoError(suite.ctl.Reconcile(context.Background(), controller.Request{ID: link.Id}))
tsRes := suite.client.WaitForResourceExists(suite.T(), &pbresource.ID{Name: "global", Type: pbhcp.TelemetryStateType})
suite.NoError(suite.ctl.Reconcile(context.Background(), controller.Request{ID: tsRes.Id}))
suite.client.RequireVersionUnchanged(suite.T(), tsRes.Id, tsRes.Version)
}
func (suite *controllerSuite) TestController_LinkingDisabled() {
// Run the controller manager
mgr := controller.NewManager(suite.client, suite.rt.Logger)
_, mockClientFn := mockHcpClientFn(suite.T())
mgr.Register(TelemetryStateController(mockClientFn))
mgr.SetRaftLeader(true)
go mgr.Run(suite.ctx)
linkData := &pbhcp.Link{
ClientId: "abc",
ClientSecret: "abc",
ResourceId: types.GenerateTestResourceID(suite.T()),
}
rtest.Resource(pbhcp.LinkType, "global").
WithData(suite.T(), linkData).
WithStatus(link.StatusKey, &pbresource.Status{Conditions: []*pbresource.Condition{link.ConditionDisabled}}).
Write(suite.T(), suite.client)
suite.client.WaitForDeletion(suite.T(), &pbresource.ID{Name: "global", Type: pbhcp.TelemetryStateType})
}
func (suite *controllerSuite) writeLinkResource() *types.DecodedLink {
suite.T().Helper()
linkData := &pbhcp.Link{
ClientId: "abc",
ClientSecret: "abc",
ResourceId: types.GenerateTestResourceID(suite.T()),
}
res := rtest.Resource(pbhcp.LinkType, "global").
WithData(suite.T(), linkData).
WithStatus(link.StatusKey, &pbresource.Status{Conditions: []*pbresource.Condition{link.ConditionLinked(linkData.ResourceId)}}).
Write(suite.T(), suite.client)
suite.T().Cleanup(suite.deleteResourceFunc(res.Id))
link, err := resource.Decode[*pbhcp.Link](res)
require.NoError(suite.T(), err)
return link
}

View File

@ -1,8 +0,0 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: BUSL-1.1
package telemetrystate
const (
StatusKey = "consul.io/hcp/telemetry-state"
)

View File

@ -1,117 +0,0 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: BUSL-1.1
package types
import (
"errors"
"github.com/hashicorp/go-multierror"
hcpresource "github.com/hashicorp/hcp-sdk-go/resource"
"github.com/hashicorp/consul/acl"
"github.com/hashicorp/consul/internal/resource"
pbhcp "github.com/hashicorp/consul/proto-public/pbhcp/v2"
"github.com/hashicorp/consul/proto-public/pbresource"
)
type DecodedLink = resource.DecodedResource[*pbhcp.Link]
const (
LinkName = "global"
MetadataSourceKey = "source"
MetadataSourceConfig = "config"
)
var (
errLinkConfigurationName = errors.New("only a single Link resource is allowed and it must be named global")
errInvalidHCPResourceID = errors.New("could not parse, invalid format")
)
func RegisterLink(r resource.Registry) {
r.Register(resource.Registration{
Type: pbhcp.LinkType,
Proto: &pbhcp.Link{},
Scope: resource.ScopeCluster,
Validate: ValidateLink,
ACLs: &resource.ACLHooks{
Read: aclReadHookLink,
Write: aclWriteHookLink,
List: aclListHookLink,
},
})
}
func aclReadHookLink(authorizer acl.Authorizer, authzContext *acl.AuthorizerContext, _ *pbresource.ID, _ *pbresource.Resource) error {
err := authorizer.ToAllowAuthorizer().OperatorReadAllowed(authzContext)
if err != nil {
return err
}
return nil
}
func aclWriteHookLink(authorizer acl.Authorizer, authzContext *acl.AuthorizerContext, _ *pbresource.Resource) error {
err := authorizer.ToAllowAuthorizer().OperatorWriteAllowed(authzContext)
if err != nil {
return err
}
err = authorizer.ToAllowAuthorizer().ACLWriteAllowed(authzContext)
if err != nil {
return err
}
return nil
}
func aclListHookLink(authorizer acl.Authorizer, authzContext *acl.AuthorizerContext) error {
err := authorizer.ToAllowAuthorizer().OperatorReadAllowed(authzContext)
if err != nil {
return err
}
return nil
}
var ValidateLink = resource.DecodeAndValidate(validateLink)
func validateLink(res *DecodedLink) error {
var err error
if res.Id.Name != LinkName {
err = multierror.Append(err, resource.ErrInvalidField{
Name: "name",
Wrapped: errLinkConfigurationName,
})
}
if res.Data.ClientId == "" {
err = multierror.Append(err, resource.ErrInvalidField{
Name: "client_id",
Wrapped: resource.ErrMissing,
})
}
if res.Data.ClientSecret == "" {
err = multierror.Append(err, resource.ErrInvalidField{
Name: "client_secret",
Wrapped: resource.ErrMissing,
})
}
if res.Data.ResourceId == "" {
err = multierror.Append(err, resource.ErrInvalidField{
Name: "resource_id",
Wrapped: resource.ErrMissing,
})
} else {
_, parseErr := hcpresource.FromString(res.Data.ResourceId)
if parseErr != nil {
err = multierror.Append(err, resource.ErrInvalidField{
Name: "resource_id",
Wrapped: errInvalidHCPResourceID,
})
}
}
return err
}

View File

@ -1,205 +0,0 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: BUSL-1.1
package types
import (
"testing"
"github.com/stretchr/testify/require"
"google.golang.org/protobuf/reflect/protoreflect"
"google.golang.org/protobuf/types/known/anypb"
"github.com/hashicorp/consul/internal/resource"
rtest "github.com/hashicorp/consul/internal/resource/resourcetest"
pbhcp "github.com/hashicorp/consul/proto-public/pbhcp/v2"
"github.com/hashicorp/consul/proto-public/pbresource"
)
func createCloudLinkResource(t *testing.T, data protoreflect.ProtoMessage) *pbresource.Resource {
res := &pbresource.Resource{
Id: &pbresource.ID{
Type: pbhcp.LinkType,
Name: "global",
},
}
var err error
res.Data, err = anypb.New(data)
require.NoError(t, err)
return res
}
func TestValidateLink_Ok(t *testing.T) {
data := &pbhcp.Link{
ClientId: "abc",
ClientSecret: "abc",
ResourceId: GenerateTestResourceID(t),
}
res := createCloudLinkResource(t, data)
err := ValidateLink(res)
require.NoError(t, err)
}
func TestValidateLink_ParseError(t *testing.T) {
// Any type other than the Link type would work
// to cause the error we are expecting
data := &pbresource.Type{Group: "a", GroupVersion: "b", Kind: "c"}
res := createCloudLinkResource(t, data)
err := ValidateLink(res)
require.Error(t, err)
require.ErrorAs(t, err, &resource.ErrDataParse{})
}
func TestValidateLink_InvalidName(t *testing.T) {
data := &pbhcp.Link{
ClientId: "abc",
ClientSecret: "abc",
ResourceId: GenerateTestResourceID(t),
}
res := createCloudLinkResource(t, data)
res.Id.Name = "default"
err := ValidateLink(res)
expected := resource.ErrInvalidField{
Name: "name",
Wrapped: errLinkConfigurationName,
}
var actual resource.ErrInvalidField
require.ErrorAs(t, err, &actual)
require.Equal(t, expected, actual)
}
func TestValidateLink_MissingClientId(t *testing.T) {
data := &pbhcp.Link{
ClientId: "",
ClientSecret: "abc",
ResourceId: GenerateTestResourceID(t),
}
res := createCloudLinkResource(t, data)
err := ValidateLink(res)
expected := resource.ErrInvalidField{
Name: "client_id",
Wrapped: resource.ErrMissing,
}
var actual resource.ErrInvalidField
require.ErrorAs(t, err, &actual)
require.Equal(t, expected, actual)
}
func TestValidateLink_MissingClientSecret(t *testing.T) {
data := &pbhcp.Link{
ClientId: "abc",
ClientSecret: "",
ResourceId: GenerateTestResourceID(t),
}
res := createCloudLinkResource(t, data)
err := ValidateLink(res)
expected := resource.ErrInvalidField{
Name: "client_secret",
Wrapped: resource.ErrMissing,
}
var actual resource.ErrInvalidField
require.ErrorAs(t, err, &actual)
require.Equal(t, expected, actual)
}
func TestValidateLink_MissingResourceId(t *testing.T) {
data := &pbhcp.Link{
ClientId: "abc",
ClientSecret: "abc",
ResourceId: "",
}
res := createCloudLinkResource(t, data)
err := ValidateLink(res)
expected := resource.ErrInvalidField{
Name: "resource_id",
Wrapped: resource.ErrMissing,
}
var actual resource.ErrInvalidField
require.ErrorAs(t, err, &actual)
require.Equal(t, expected, actual)
}
func TestValidateLink_InvalidResourceId(t *testing.T) {
data := &pbhcp.Link{
ClientId: "abc",
ClientSecret: "abc",
ResourceId: "abc",
}
res := createCloudLinkResource(t, data)
err := ValidateLink(res)
expected := resource.ErrInvalidField{
Name: "resource_id",
Wrapped: errInvalidHCPResourceID,
}
var actual resource.ErrInvalidField
require.ErrorAs(t, err, &actual)
require.Equal(t, expected, actual)
}
// Currently, we have no specific ACLs configured so the default `operator` permissions are required
func TestLinkACLs(t *testing.T) {
registry := resource.NewRegistry()
RegisterLink(registry)
data := &pbhcp.Link{
ClientId: "abc",
ClientSecret: "abc",
ResourceId: GenerateTestResourceID(t),
}
link := createCloudLinkResource(t, data)
cases := map[string]rtest.ACLTestCase{
"no rules": {
Rules: ``,
Res: link,
ReadOK: rtest.DENY,
WriteOK: rtest.DENY,
ListOK: rtest.DENY,
},
"link test read and list": {
Rules: `{"operator": "read"}`,
Res: link,
ReadOK: rtest.ALLOW,
WriteOK: rtest.DENY,
ListOK: rtest.ALLOW,
},
"link test write": {
Rules: `{"operator": "write", "acl": "write"}`,
Res: link,
ReadOK: rtest.ALLOW,
WriteOK: rtest.ALLOW,
ListOK: rtest.ALLOW,
},
}
for name, tc := range cases {
t.Run(name, func(t *testing.T) {
rtest.RunACLTestCase(t, tc, registry)
})
}
}

View File

@ -1,85 +0,0 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: BUSL-1.1
package types
import (
"errors"
"github.com/hashicorp/go-multierror"
"github.com/hashicorp/consul/internal/resource"
pbhcp "github.com/hashicorp/consul/proto-public/pbhcp/v2"
)
type DecodedTelemetryState = resource.DecodedResource[*pbhcp.TelemetryState]
var (
telemetryStateConfigurationNameError = errors.New("only a single Telemetry resource is allowed and it must be named global")
)
func RegisterTelemetryState(r resource.Registry) {
r.Register(resource.Registration{
Type: pbhcp.TelemetryStateType,
Proto: &pbhcp.TelemetryState{},
Scope: resource.ScopeCluster,
Validate: ValidateTelemetryState,
})
}
var ValidateTelemetryState = resource.DecodeAndValidate(validateTelemetryState)
func validateTelemetryState(res *DecodedTelemetryState) error {
var err error
if res.GetId().GetName() != "global" {
err = multierror.Append(err, resource.ErrInvalidField{
Name: "name",
Wrapped: telemetryStateConfigurationNameError,
})
}
if res.GetData().GetClientId() == "" {
err = multierror.Append(err, resource.ErrInvalidField{
Name: "client_id",
Wrapped: resource.ErrMissing,
})
}
if res.GetData().GetClientSecret() == "" {
err = multierror.Append(err, resource.ErrInvalidField{
Name: "client_secret",
Wrapped: resource.ErrMissing,
})
}
if res.GetData().GetResourceId() == "" {
err = multierror.Append(err, resource.ErrInvalidField{
Name: "resource_id",
Wrapped: resource.ErrMissing,
})
}
if res.GetData().GetMetrics().GetEndpoint() == "" {
err = multierror.Append(err, resource.ErrInvalidField{
Name: "metrics.endpoint",
Wrapped: resource.ErrMissing,
})
}
if res.GetData().GetMetrics().GetIncludeList() == nil {
err = multierror.Append(err, resource.ErrInvalidField{
Name: "metrics.include_list",
Wrapped: resource.ErrMissing,
})
}
if res.GetData().GetMetrics().GetLabels() == nil {
err = multierror.Append(err, resource.ErrInvalidField{
Name: "metrics.labels",
Wrapped: resource.ErrMissing,
})
}
return err
}

View File

@ -1,23 +0,0 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: BUSL-1.1
package types
import (
"fmt"
"testing"
"github.com/hashicorp/go-uuid"
"github.com/stretchr/testify/require"
)
func GenerateTestResourceID(t *testing.T) string {
orgID, err := uuid.GenerateUUID()
require.NoError(t, err)
projectID, err := uuid.GenerateUUID()
require.NoError(t, err)
template := "organization/%s/project/%s/hashicorp.consul.global-network-manager.cluster/test-cluster"
return fmt.Sprintf(template, orgID, projectID)
}

View File

@ -1,11 +0,0 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: BUSL-1.1
package types
import "github.com/hashicorp/consul/internal/resource"
func Register(r resource.Registry) {
RegisterLink(r)
RegisterTelemetryState(r)
}

View File

@ -14,10 +14,10 @@ import (
"github.com/hashicorp/go-hclog"
"github.com/hashicorp/consul/internal/resource"
"github.com/hashicorp/consul/internal/storage"
"github.com/hashicorp/consul/internal/storage/inmem"
"github.com/hashicorp/consul/proto-public/pbresource"
pbstorage "github.com/hashicorp/consul/proto/private/pbstorage"
)
@ -53,7 +53,7 @@ func NewBackend(h Handle, l hclog.Logger) (*Backend, error) {
if err != nil {
return nil, err
}
b := &Backend{handle: h, store: s}
b := &Backend{handle: h, store: s, logger: l}
b.forwardingServer = newForwardingServer(b)
b.forwardingClient = newForwardingClient(h, l)
return b, nil
@ -80,6 +80,7 @@ type Handle interface {
type Backend struct {
handle Handle
store *inmem.Store
logger hclog.Logger
forwardingServer *forwardingServer
forwardingClient *forwardingClient
@ -225,6 +226,24 @@ func (b *Backend) ListByOwner(_ context.Context, id *pbresource.ID) ([]*pbresour
return b.store.ListByOwner(id)
}
// isRetiredType ensures that types that have been formally retired (deprecated
// and deleted) do not sneak back in during a snapshot restore.
func isRetiredType(typ *pbresource.Type) bool {
switch typ.GetGroupVersion() {
case "v2":
switch typ.GetGroup() {
case "hcp":
return true
}
case "v2beta1":
switch typ.GetGroup() {
case "auth", "catalog", "mesh", "multicluster", "tenancy":
return true
}
}
return false
}
// Apply is called by the FSM with the bytes of a Raft log entry, with Consul's
// envelope (i.e. type prefix and msgpack wrapper) stripped off.
func (b *Backend) Apply(buf []byte, idx uint64) any {
@ -239,8 +258,18 @@ func (b *Backend) Apply(buf []byte, idx uint64) any {
oldVsn := res.Version
res.Version = strconv.Itoa(int(idx))
if err := b.store.WriteCAS(res, oldVsn); err != nil {
return err
if isRetiredType(res.GetId().GetType()) {
// When a type is retired, the caller should think that the write
// was applied, but we should simply skip loading it. This means
// that retired types will not linger in the database indefinitely.
b.logger.Warn("ignoring operation for retired type",
"operation", "apply",
"type", resource.ToGVK(res.GetId().GetType()),
)
} else {
if err := b.store.WriteCAS(res, oldVsn); err != nil {
return err
}
}
return &pbstorage.LogResponse{
@ -250,8 +279,19 @@ func (b *Backend) Apply(buf []byte, idx uint64) any {
}
case pbstorage.LogType_LOG_TYPE_DELETE:
req := req.GetDelete()
if err := b.store.DeleteCAS(req.Id, req.Version); err != nil {
return err
if isRetiredType(req.GetId().GetType()) {
// When a type is retired, the caller should think that the write
// was applied, but we should simply skip loading it. This means
// that retired types will not linger in the database indefinitely.
b.logger.Warn("ignoring operation for retired type",
"operation", "delete",
"type", resource.ToGVK(req.GetId().GetType()),
)
} else {
if err := b.store.DeleteCAS(req.Id, req.Version); err != nil {
return err
}
}
return &pbstorage.LogResponse{
Response: &pbstorage.LogResponse_Delete{},

View File

@ -0,0 +1,392 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: BUSL-1.1
package raft
import (
"testing"
"github.com/stretchr/testify/require"
"github.com/hashicorp/consul/internal/resource"
"github.com/hashicorp/consul/proto-public/pbresource"
)
func TestIsRetiredType(t *testing.T) {
var retired []*pbresource.Type
{
const (
GroupName = "hcp"
Version = "v2"
LinkKind = "Link"
TelemetryStateKind = "TelemetryState"
)
retired = append(retired, &pbresource.Type{
Group: GroupName,
GroupVersion: Version,
Kind: LinkKind,
})
retired = append(retired, &pbresource.Type{
Group: GroupName,
GroupVersion: Version,
Kind: TelemetryStateKind,
})
}
{
const (
GroupName = "tenancy"
Version = "v2beta1"
NamespaceKind = "Namespace"
PartitionKind = "Partition"
)
retired = append(retired, &pbresource.Type{
Group: GroupName,
GroupVersion: Version,
Kind: NamespaceKind,
})
retired = append(retired, &pbresource.Type{
Group: GroupName,
GroupVersion: Version,
Kind: PartitionKind,
})
}
{
const (
GroupName = "multicluster"
Version = "v2beta1"
SamenessGroupKind = "SamenessGroup"
)
retired = append(retired, &pbresource.Type{
Group: GroupName,
GroupVersion: Version,
Kind: SamenessGroupKind,
})
}
{
const (
GroupName = "mesh"
Version = "v2beta1"
APIGatewayKind = "APIGateway"
ComputedExplicitDestinationsKind = "ComputedExplicitDestinations"
ComputedGatewayRoutesKind = "ComputedGatewayRoutes"
ComputedImplicitDestinationsKind = "ComputedImplicitDestinations"
ComputedProxyConfigurationKind = "ComputedProxyConfiguration"
ComputedRoutesKind = "ComputedRoutes"
DestinationPolicyKind = "DestinationPolicy"
DestinationsKind = "Destinations"
DestinationsConfigurationKind = "DestinationsConfiguration"
GRPCRouteKind = "GRPCRoute"
HTTPRouteKind = "HTTPRoute"
MeshConfigurationKind = "MeshConfiguration"
MeshGatewayKind = "MeshGateway"
ProxyConfigurationKind = "ProxyConfiguration"
ProxyStateTemplateKind = "ProxyStateTemplate"
TCPRouteKind = "TCPRoute"
)
retired = append(retired, &pbresource.Type{
Group: GroupName,
GroupVersion: Version,
Kind: APIGatewayKind,
})
retired = append(retired, &pbresource.Type{
Group: GroupName,
GroupVersion: Version,
Kind: ComputedExplicitDestinationsKind,
})
retired = append(retired, &pbresource.Type{
Group: GroupName,
GroupVersion: Version,
Kind: ComputedGatewayRoutesKind,
})
retired = append(retired, &pbresource.Type{
Group: GroupName,
GroupVersion: Version,
Kind: ComputedImplicitDestinationsKind,
})
retired = append(retired, &pbresource.Type{
Group: GroupName,
GroupVersion: Version,
Kind: ComputedProxyConfigurationKind,
})
retired = append(retired, &pbresource.Type{
Group: GroupName,
GroupVersion: Version,
Kind: ComputedRoutesKind,
})
retired = append(retired, &pbresource.Type{
Group: GroupName,
GroupVersion: Version,
Kind: DestinationPolicyKind,
})
retired = append(retired, &pbresource.Type{
Group: GroupName,
GroupVersion: Version,
Kind: DestinationsKind,
})
retired = append(retired, &pbresource.Type{
Group: GroupName,
GroupVersion: Version,
Kind: DestinationsConfigurationKind,
})
retired = append(retired, &pbresource.Type{
Group: GroupName,
GroupVersion: Version,
Kind: GRPCRouteKind,
})
retired = append(retired, &pbresource.Type{
Group: GroupName,
GroupVersion: Version,
Kind: HTTPRouteKind,
})
retired = append(retired, &pbresource.Type{
Group: GroupName,
GroupVersion: Version,
Kind: MeshConfigurationKind,
})
retired = append(retired, &pbresource.Type{
Group: GroupName,
GroupVersion: Version,
Kind: MeshGatewayKind,
})
retired = append(retired, &pbresource.Type{
Group: GroupName,
GroupVersion: Version,
Kind: ProxyConfigurationKind,
})
retired = append(retired, &pbresource.Type{
Group: GroupName,
GroupVersion: Version,
Kind: ProxyStateTemplateKind,
})
retired = append(retired, &pbresource.Type{
Group: GroupName,
GroupVersion: Version,
Kind: TCPRouteKind,
})
}
{
const (
GroupName = "auth"
Version = "v2beta1"
ComputedTrafficPermissionsKind = "ComputedTrafficPermissions"
NamespaceTrafficPermissionsKind = "NamespaceTrafficPermissions"
PartitionTrafficPermissionsKind = "PartitionTrafficPermissions"
TrafficPermissionsKind = "TrafficPermissions"
WorkloadIdentityKind = "WorkloadIdentity"
)
retired = append(retired, &pbresource.Type{
Group: GroupName,
GroupVersion: Version,
Kind: ComputedTrafficPermissionsKind,
})
retired = append(retired, &pbresource.Type{
Group: GroupName,
GroupVersion: Version,
Kind: NamespaceTrafficPermissionsKind,
})
retired = append(retired, &pbresource.Type{
Group: GroupName,
GroupVersion: Version,
Kind: PartitionTrafficPermissionsKind,
})
retired = append(retired, &pbresource.Type{
Group: GroupName,
GroupVersion: Version,
Kind: TrafficPermissionsKind,
})
retired = append(retired, &pbresource.Type{
Group: GroupName,
GroupVersion: Version,
Kind: WorkloadIdentityKind,
})
}
{
const (
GroupName = "catalog"
Version = "v2beta1"
ComputedFailoverPolicyKind = "ComputedFailoverPolicy"
FailoverPolicyKind = "FailoverPolicy"
HealthChecksKind = "HealthChecks"
HealthStatusKind = "HealthStatus"
NodeKind = "Node"
NodeHealthStatusKind = "NodeHealthStatus"
ServiceKind = "Service"
ServiceEndpointsKind = "ServiceEndpoints"
VirtualIPsKind = "VirtualIPs"
WorkloadKind = "Workload"
)
retired = append(retired, &pbresource.Type{
Group: GroupName,
GroupVersion: Version,
Kind: ComputedFailoverPolicyKind,
})
retired = append(retired, &pbresource.Type{
Group: GroupName,
GroupVersion: Version,
Kind: FailoverPolicyKind,
})
retired = append(retired, &pbresource.Type{
Group: GroupName,
GroupVersion: Version,
Kind: HealthChecksKind,
})
retired = append(retired, &pbresource.Type{
Group: GroupName,
GroupVersion: Version,
Kind: HealthStatusKind,
})
retired = append(retired, &pbresource.Type{
Group: GroupName,
GroupVersion: Version,
Kind: NodeKind,
})
retired = append(retired, &pbresource.Type{
Group: GroupName,
GroupVersion: Version,
Kind: NodeHealthStatusKind,
})
retired = append(retired, &pbresource.Type{
Group: GroupName,
GroupVersion: Version,
Kind: ServiceKind,
})
retired = append(retired, &pbresource.Type{
Group: GroupName,
GroupVersion: Version,
Kind: ServiceEndpointsKind,
})
retired = append(retired, &pbresource.Type{
Group: GroupName,
GroupVersion: Version,
Kind: VirtualIPsKind,
})
retired = append(retired, &pbresource.Type{
Group: GroupName,
GroupVersion: Version,
Kind: WorkloadKind,
})
}
/*
*/
var retained []*pbresource.Type
{
const (
GroupName = "demo"
Version = "v2"
AlbumKind = "Album"
ArtistKind = "Artist"
FestivalKind = "Festival"
)
retained = append(retained, &pbresource.Type{
Group: GroupName,
GroupVersion: Version,
Kind: AlbumKind,
})
retained = append(retained, &pbresource.Type{
Group: GroupName,
GroupVersion: Version,
Kind: ArtistKind,
})
retained = append(retained, &pbresource.Type{
Group: GroupName,
GroupVersion: Version,
Kind: FestivalKind,
})
}
{
const (
GroupName = "demo"
Version = "v1"
AlbumKind = "Album"
ArtistKind = "Artist"
ConceptKind = "Concept"
ExecutiveKind = "Executive"
RecordLabelKind = "RecordLabel"
)
retained = append(retained, &pbresource.Type{
Group: GroupName,
GroupVersion: Version,
Kind: AlbumKind,
})
retained = append(retained, &pbresource.Type{
Group: GroupName,
GroupVersion: Version,
Kind: ArtistKind,
})
retained = append(retained, &pbresource.Type{
Group: GroupName,
GroupVersion: Version,
Kind: ConceptKind,
})
retained = append(retained, &pbresource.Type{
Group: GroupName,
GroupVersion: Version,
Kind: ExecutiveKind,
})
retained = append(retained, &pbresource.Type{
Group: GroupName,
GroupVersion: Version,
Kind: RecordLabelKind,
})
}
{
const (
GroupName = "multicluster"
Version = "v2"
ComputedExportedServicesKind = "ComputedExportedServices"
ExportedServicesKind = "ExportedServices"
NamespaceExportedServicesKind = "NamespaceExportedServices"
PartitionExportedServicesKind = "PartitionExportedServices"
)
retained = append(retained, &pbresource.Type{
Group: GroupName,
GroupVersion: Version,
Kind: ComputedExportedServicesKind,
})
retained = append(retained, &pbresource.Type{
Group: GroupName,
GroupVersion: Version,
Kind: ExportedServicesKind,
})
retained = append(retained, &pbresource.Type{
Group: GroupName,
GroupVersion: Version,
Kind: NamespaceExportedServicesKind,
})
retained = append(retained, &pbresource.Type{
Group: GroupName,
GroupVersion: Version,
Kind: PartitionExportedServicesKind,
})
}
for _, typ := range retired {
t.Run("gone - "+resource.ToGVK(typ), func(t *testing.T) {
require.True(t, isRetiredType(typ))
})
}
for _, typ := range retained {
t.Run("allowed - "+resource.ToGVK(typ), func(t *testing.T) {
require.False(t, isRetiredType(typ))
})
}
}

View File

@ -1,18 +0,0 @@
// Code generated by protoc-gen-go-binary. DO NOT EDIT.
// source: pbhcp/v2/hcp_config.proto
package hcpv2
import (
"google.golang.org/protobuf/proto"
)
// MarshalBinary implements encoding.BinaryMarshaler
func (msg *HCPConfig) MarshalBinary() ([]byte, error) {
return proto.Marshal(msg)
}
// UnmarshalBinary implements encoding.BinaryUnmarshaler
func (msg *HCPConfig) UnmarshalBinary(b []byte) error {
return proto.Unmarshal(b, msg)
}

View File

@ -1,199 +0,0 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.33.0
// protoc (unknown)
// source: pbhcp/v2/hcp_config.proto
package hcpv2
import (
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
sync "sync"
)
const (
// Verify that this generated code is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
// Verify that runtime/protoimpl is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
)
// HCPConfig is used to configure the HCP SDK for communicating with
// the HashiCorp Cloud Platform. All configuration is optional with default
// values provided by the SDK.
type HCPConfig struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
// AuthUrl is the URL which will be used to authenticate.
AuthUrl string `protobuf:"bytes,1,opt,name=auth_url,json=authUrl,proto3" json:"auth_url,omitempty"`
// ApiAddress is the address (<hostname>[:port]) of the HCP api.
ApiAddress string `protobuf:"bytes,2,opt,name=api_address,json=apiAddress,proto3" json:"api_address,omitempty"`
// ScadaAddress is the address (<hostname>[:port]) of the HCP SCADA endpoint.
ScadaAddress string `protobuf:"bytes,3,opt,name=scada_address,json=scadaAddress,proto3" json:"scada_address,omitempty"`
// TlsInsecureSkipVerify if true will ignore server name verification when making HTTPS requests
TlsInsecureSkipVerify bool `protobuf:"varint,4,opt,name=tls_insecure_skip_verify,json=tlsInsecureSkipVerify,proto3" json:"tls_insecure_skip_verify,omitempty"`
}
func (x *HCPConfig) Reset() {
*x = HCPConfig{}
if protoimpl.UnsafeEnabled {
mi := &file_pbhcp_v2_hcp_config_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *HCPConfig) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*HCPConfig) ProtoMessage() {}
func (x *HCPConfig) ProtoReflect() protoreflect.Message {
mi := &file_pbhcp_v2_hcp_config_proto_msgTypes[0]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use HCPConfig.ProtoReflect.Descriptor instead.
func (*HCPConfig) Descriptor() ([]byte, []int) {
return file_pbhcp_v2_hcp_config_proto_rawDescGZIP(), []int{0}
}
func (x *HCPConfig) GetAuthUrl() string {
if x != nil {
return x.AuthUrl
}
return ""
}
func (x *HCPConfig) GetApiAddress() string {
if x != nil {
return x.ApiAddress
}
return ""
}
func (x *HCPConfig) GetScadaAddress() string {
if x != nil {
return x.ScadaAddress
}
return ""
}
func (x *HCPConfig) GetTlsInsecureSkipVerify() bool {
if x != nil {
return x.TlsInsecureSkipVerify
}
return false
}
var File_pbhcp_v2_hcp_config_proto protoreflect.FileDescriptor
var file_pbhcp_v2_hcp_config_proto_rawDesc = []byte{
0x0a, 0x19, 0x70, 0x62, 0x68, 0x63, 0x70, 0x2f, 0x76, 0x32, 0x2f, 0x68, 0x63, 0x70, 0x5f, 0x63,
0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x17, 0x68, 0x61, 0x73,
0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x68, 0x63,
0x70, 0x2e, 0x76, 0x32, 0x22, 0xa5, 0x01, 0x0a, 0x09, 0x48, 0x43, 0x50, 0x43, 0x6f, 0x6e, 0x66,
0x69, 0x67, 0x12, 0x19, 0x0a, 0x08, 0x61, 0x75, 0x74, 0x68, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x01,
0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x75, 0x74, 0x68, 0x55, 0x72, 0x6c, 0x12, 0x1f, 0x0a,
0x0b, 0x61, 0x70, 0x69, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x02, 0x20, 0x01,
0x28, 0x09, 0x52, 0x0a, 0x61, 0x70, 0x69, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x23,
0x0a, 0x0d, 0x73, 0x63, 0x61, 0x64, 0x61, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18,
0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x73, 0x63, 0x61, 0x64, 0x61, 0x41, 0x64, 0x64, 0x72,
0x65, 0x73, 0x73, 0x12, 0x37, 0x0a, 0x18, 0x74, 0x6c, 0x73, 0x5f, 0x69, 0x6e, 0x73, 0x65, 0x63,
0x75, 0x72, 0x65, 0x5f, 0x73, 0x6b, 0x69, 0x70, 0x5f, 0x76, 0x65, 0x72, 0x69, 0x66, 0x79, 0x18,
0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x15, 0x74, 0x6c, 0x73, 0x49, 0x6e, 0x73, 0x65, 0x63, 0x75,
0x72, 0x65, 0x53, 0x6b, 0x69, 0x70, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x42, 0xe5, 0x01, 0x0a,
0x1b, 0x63, 0x6f, 0x6d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63,
0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x68, 0x63, 0x70, 0x2e, 0x76, 0x32, 0x42, 0x0e, 0x48, 0x63,
0x70, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x37,
0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x73, 0x68, 0x69,
0x63, 0x6f, 0x72, 0x70, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2f, 0x70, 0x72, 0x6f, 0x74,
0x6f, 0x2d, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x2f, 0x70, 0x62, 0x68, 0x63, 0x70, 0x2f, 0x76,
0x32, 0x3b, 0x68, 0x63, 0x70, 0x76, 0x32, 0xa2, 0x02, 0x03, 0x48, 0x43, 0x48, 0xaa, 0x02, 0x17,
0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c,
0x2e, 0x48, 0x63, 0x70, 0x2e, 0x56, 0x32, 0xca, 0x02, 0x17, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63,
0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x48, 0x63, 0x70, 0x5c, 0x56,
0x32, 0xe2, 0x02, 0x23, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f,
0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x48, 0x63, 0x70, 0x5c, 0x56, 0x32, 0x5c, 0x47, 0x50, 0x42, 0x4d,
0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x1a, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63,
0x6f, 0x72, 0x70, 0x3a, 0x3a, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x3a, 0x3a, 0x48, 0x63, 0x70,
0x3a, 0x3a, 0x56, 0x32, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
file_pbhcp_v2_hcp_config_proto_rawDescOnce sync.Once
file_pbhcp_v2_hcp_config_proto_rawDescData = file_pbhcp_v2_hcp_config_proto_rawDesc
)
func file_pbhcp_v2_hcp_config_proto_rawDescGZIP() []byte {
file_pbhcp_v2_hcp_config_proto_rawDescOnce.Do(func() {
file_pbhcp_v2_hcp_config_proto_rawDescData = protoimpl.X.CompressGZIP(file_pbhcp_v2_hcp_config_proto_rawDescData)
})
return file_pbhcp_v2_hcp_config_proto_rawDescData
}
var file_pbhcp_v2_hcp_config_proto_msgTypes = make([]protoimpl.MessageInfo, 1)
var file_pbhcp_v2_hcp_config_proto_goTypes = []interface{}{
(*HCPConfig)(nil), // 0: hashicorp.consul.hcp.v2.HCPConfig
}
var file_pbhcp_v2_hcp_config_proto_depIdxs = []int32{
0, // [0:0] is the sub-list for method output_type
0, // [0:0] is the sub-list for method input_type
0, // [0:0] is the sub-list for extension type_name
0, // [0:0] is the sub-list for extension extendee
0, // [0:0] is the sub-list for field type_name
}
func init() { file_pbhcp_v2_hcp_config_proto_init() }
func file_pbhcp_v2_hcp_config_proto_init() {
if File_pbhcp_v2_hcp_config_proto != nil {
return
}
if !protoimpl.UnsafeEnabled {
file_pbhcp_v2_hcp_config_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*HCPConfig); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_pbhcp_v2_hcp_config_proto_rawDesc,
NumEnums: 0,
NumMessages: 1,
NumExtensions: 0,
NumServices: 0,
},
GoTypes: file_pbhcp_v2_hcp_config_proto_goTypes,
DependencyIndexes: file_pbhcp_v2_hcp_config_proto_depIdxs,
MessageInfos: file_pbhcp_v2_hcp_config_proto_msgTypes,
}.Build()
File_pbhcp_v2_hcp_config_proto = out.File
file_pbhcp_v2_hcp_config_proto_rawDesc = nil
file_pbhcp_v2_hcp_config_proto_goTypes = nil
file_pbhcp_v2_hcp_config_proto_depIdxs = nil
}

View File

@ -1,23 +0,0 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0
syntax = "proto3";
package hashicorp.consul.hcp.v2;
// HCPConfig is used to configure the HCP SDK for communicating with
// the HashiCorp Cloud Platform. All configuration is optional with default
// values provided by the SDK.
message HCPConfig {
// AuthUrl is the URL which will be used to authenticate.
string auth_url = 1;
// ApiAddress is the address (<hostname>[:port]) of the HCP api.
string api_address = 2;
// ScadaAddress is the address (<hostname>[:port]) of the HCP SCADA endpoint.
string scada_address = 3;
// TlsInsecureSkipVerify if true will ignore server name verification when making HTTPS requests
bool tls_insecure_skip_verify = 4;
}

View File

@ -1,27 +0,0 @@
// Code generated by protoc-gen-deepcopy. DO NOT EDIT.
package hcpv2
import (
proto "google.golang.org/protobuf/proto"
)
// DeepCopyInto supports using HCPConfig within kubernetes types, where deepcopy-gen is used.
func (in *HCPConfig) DeepCopyInto(out *HCPConfig) {
proto.Reset(out)
proto.Merge(out, proto.Clone(in))
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HCPConfig. Required by controller-gen.
func (in *HCPConfig) DeepCopy() *HCPConfig {
if in == nil {
return nil
}
out := new(HCPConfig)
in.DeepCopyInto(out)
return out
}
// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new HCPConfig. Required by controller-gen.
func (in *HCPConfig) DeepCopyInterface() interface{} {
return in.DeepCopy()
}

View File

@ -1,22 +0,0 @@
// Code generated by protoc-json-shim. DO NOT EDIT.
package hcpv2
import (
protojson "google.golang.org/protobuf/encoding/protojson"
)
// MarshalJSON is a custom marshaler for HCPConfig
func (this *HCPConfig) MarshalJSON() ([]byte, error) {
str, err := HcpConfigMarshaler.Marshal(this)
return []byte(str), err
}
// UnmarshalJSON is a custom unmarshaler for HCPConfig
func (this *HCPConfig) UnmarshalJSON(b []byte) error {
return HcpConfigUnmarshaler.Unmarshal(b, this)
}
var (
HcpConfigMarshaler = &protojson.MarshalOptions{}
HcpConfigUnmarshaler = &protojson.UnmarshalOptions{DiscardUnknown: false}
)

View File

@ -1,18 +0,0 @@
// Code generated by protoc-gen-go-binary. DO NOT EDIT.
// source: pbhcp/v2/link.proto
package hcpv2
import (
"google.golang.org/protobuf/proto"
)
// MarshalBinary implements encoding.BinaryMarshaler
func (msg *Link) MarshalBinary() ([]byte, error) {
return proto.Marshal(msg)
}
// UnmarshalBinary implements encoding.BinaryUnmarshaler
func (msg *Link) UnmarshalBinary(b []byte) error {
return proto.Unmarshal(b, msg)
}

View File

@ -1,283 +0,0 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.33.0
// protoc (unknown)
// source: pbhcp/v2/link.proto
package hcpv2
import (
_ "github.com/hashicorp/consul/proto-public/pbresource"
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
sync "sync"
)
const (
// Verify that this generated code is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
// Verify that runtime/protoimpl is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
)
type AccessLevel int32
const (
AccessLevel_ACCESS_LEVEL_UNSPECIFIED AccessLevel = 0
AccessLevel_ACCESS_LEVEL_GLOBAL_READ_WRITE AccessLevel = 1
AccessLevel_ACCESS_LEVEL_GLOBAL_READ_ONLY AccessLevel = 2
)
// Enum value maps for AccessLevel.
var (
AccessLevel_name = map[int32]string{
0: "ACCESS_LEVEL_UNSPECIFIED",
1: "ACCESS_LEVEL_GLOBAL_READ_WRITE",
2: "ACCESS_LEVEL_GLOBAL_READ_ONLY",
}
AccessLevel_value = map[string]int32{
"ACCESS_LEVEL_UNSPECIFIED": 0,
"ACCESS_LEVEL_GLOBAL_READ_WRITE": 1,
"ACCESS_LEVEL_GLOBAL_READ_ONLY": 2,
}
)
func (x AccessLevel) Enum() *AccessLevel {
p := new(AccessLevel)
*p = x
return p
}
func (x AccessLevel) String() string {
return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
}
func (AccessLevel) Descriptor() protoreflect.EnumDescriptor {
return file_pbhcp_v2_link_proto_enumTypes[0].Descriptor()
}
func (AccessLevel) Type() protoreflect.EnumType {
return &file_pbhcp_v2_link_proto_enumTypes[0]
}
func (x AccessLevel) Number() protoreflect.EnumNumber {
return protoreflect.EnumNumber(x)
}
// Deprecated: Use AccessLevel.Descriptor instead.
func (AccessLevel) EnumDescriptor() ([]byte, []int) {
return file_pbhcp_v2_link_proto_rawDescGZIP(), []int{0}
}
type Link struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
ResourceId string `protobuf:"bytes,1,opt,name=resource_id,json=resourceId,proto3" json:"resource_id,omitempty"`
ClientId string `protobuf:"bytes,2,opt,name=client_id,json=clientId,proto3" json:"client_id,omitempty"`
ClientSecret string `protobuf:"bytes,3,opt,name=client_secret,json=clientSecret,proto3" json:"client_secret,omitempty"`
HcpClusterUrl string `protobuf:"bytes,4,opt,name=hcp_cluster_url,json=hcpClusterUrl,proto3" json:"hcp_cluster_url,omitempty"`
AccessLevel AccessLevel `protobuf:"varint,5,opt,name=access_level,json=accessLevel,proto3,enum=hashicorp.consul.hcp.v2.AccessLevel" json:"access_level,omitempty"`
HcpConfig *HCPConfig `protobuf:"bytes,6,opt,name=hcp_config,json=hcpConfig,proto3" json:"hcp_config,omitempty"`
}
func (x *Link) Reset() {
*x = Link{}
if protoimpl.UnsafeEnabled {
mi := &file_pbhcp_v2_link_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *Link) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*Link) ProtoMessage() {}
func (x *Link) ProtoReflect() protoreflect.Message {
mi := &file_pbhcp_v2_link_proto_msgTypes[0]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use Link.ProtoReflect.Descriptor instead.
func (*Link) Descriptor() ([]byte, []int) {
return file_pbhcp_v2_link_proto_rawDescGZIP(), []int{0}
}
func (x *Link) GetResourceId() string {
if x != nil {
return x.ResourceId
}
return ""
}
func (x *Link) GetClientId() string {
if x != nil {
return x.ClientId
}
return ""
}
func (x *Link) GetClientSecret() string {
if x != nil {
return x.ClientSecret
}
return ""
}
func (x *Link) GetHcpClusterUrl() string {
if x != nil {
return x.HcpClusterUrl
}
return ""
}
func (x *Link) GetAccessLevel() AccessLevel {
if x != nil {
return x.AccessLevel
}
return AccessLevel_ACCESS_LEVEL_UNSPECIFIED
}
func (x *Link) GetHcpConfig() *HCPConfig {
if x != nil {
return x.HcpConfig
}
return nil
}
var File_pbhcp_v2_link_proto protoreflect.FileDescriptor
var file_pbhcp_v2_link_proto_rawDesc = []byte{
0x0a, 0x13, 0x70, 0x62, 0x68, 0x63, 0x70, 0x2f, 0x76, 0x32, 0x2f, 0x6c, 0x69, 0x6e, 0x6b, 0x2e,
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x17, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70,
0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x68, 0x63, 0x70, 0x2e, 0x76, 0x32, 0x1a, 0x19,
0x70, 0x62, 0x68, 0x63, 0x70, 0x2f, 0x76, 0x32, 0x2f, 0x68, 0x63, 0x70, 0x5f, 0x63, 0x6f, 0x6e,
0x66, 0x69, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1c, 0x70, 0x62, 0x72, 0x65, 0x73,
0x6f, 0x75, 0x72, 0x63, 0x65, 0x2f, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e,
0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xa5, 0x02, 0x0a, 0x04, 0x4c, 0x69, 0x6e, 0x6b,
0x12, 0x1f, 0x0a, 0x0b, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18,
0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49,
0x64, 0x12, 0x1b, 0x0a, 0x09, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02,
0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x23,
0x0a, 0x0d, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x18,
0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x53, 0x65, 0x63,
0x72, 0x65, 0x74, 0x12, 0x26, 0x0a, 0x0f, 0x68, 0x63, 0x70, 0x5f, 0x63, 0x6c, 0x75, 0x73, 0x74,
0x65, 0x72, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x68, 0x63,
0x70, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x55, 0x72, 0x6c, 0x12, 0x47, 0x0a, 0x0c, 0x61,
0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x18, 0x05, 0x20, 0x01, 0x28,
0x0e, 0x32, 0x24, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f,
0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x68, 0x63, 0x70, 0x2e, 0x76, 0x32, 0x2e, 0x41, 0x63, 0x63, 0x65,
0x73, 0x73, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x52, 0x0b, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4c,
0x65, 0x76, 0x65, 0x6c, 0x12, 0x41, 0x0a, 0x0a, 0x68, 0x63, 0x70, 0x5f, 0x63, 0x6f, 0x6e, 0x66,
0x69, 0x67, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69,
0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x68, 0x63, 0x70, 0x2e,
0x76, 0x32, 0x2e, 0x48, 0x43, 0x50, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x09, 0x68, 0x63,
0x70, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x3a, 0x06, 0xa2, 0x93, 0x04, 0x02, 0x08, 0x01, 0x2a,
0x72, 0x0a, 0x0b, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x1c,
0x0a, 0x18, 0x41, 0x43, 0x43, 0x45, 0x53, 0x53, 0x5f, 0x4c, 0x45, 0x56, 0x45, 0x4c, 0x5f, 0x55,
0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x22, 0x0a, 0x1e,
0x41, 0x43, 0x43, 0x45, 0x53, 0x53, 0x5f, 0x4c, 0x45, 0x56, 0x45, 0x4c, 0x5f, 0x47, 0x4c, 0x4f,
0x42, 0x41, 0x4c, 0x5f, 0x52, 0x45, 0x41, 0x44, 0x5f, 0x57, 0x52, 0x49, 0x54, 0x45, 0x10, 0x01,
0x12, 0x21, 0x0a, 0x1d, 0x41, 0x43, 0x43, 0x45, 0x53, 0x53, 0x5f, 0x4c, 0x45, 0x56, 0x45, 0x4c,
0x5f, 0x47, 0x4c, 0x4f, 0x42, 0x41, 0x4c, 0x5f, 0x52, 0x45, 0x41, 0x44, 0x5f, 0x4f, 0x4e, 0x4c,
0x59, 0x10, 0x02, 0x42, 0xe0, 0x01, 0x0a, 0x1b, 0x63, 0x6f, 0x6d, 0x2e, 0x68, 0x61, 0x73, 0x68,
0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x68, 0x63, 0x70,
0x2e, 0x76, 0x32, 0x42, 0x09, 0x4c, 0x69, 0x6e, 0x6b, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01,
0x5a, 0x37, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x73,
0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2f, 0x70, 0x72,
0x6f, 0x74, 0x6f, 0x2d, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x2f, 0x70, 0x62, 0x68, 0x63, 0x70,
0x2f, 0x76, 0x32, 0x3b, 0x68, 0x63, 0x70, 0x76, 0x32, 0xa2, 0x02, 0x03, 0x48, 0x43, 0x48, 0xaa,
0x02, 0x17, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x43, 0x6f, 0x6e, 0x73,
0x75, 0x6c, 0x2e, 0x48, 0x63, 0x70, 0x2e, 0x56, 0x32, 0xca, 0x02, 0x17, 0x48, 0x61, 0x73, 0x68,
0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x48, 0x63, 0x70,
0x5c, 0x56, 0x32, 0xe2, 0x02, 0x23, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c,
0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x48, 0x63, 0x70, 0x5c, 0x56, 0x32, 0x5c, 0x47, 0x50,
0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x1a, 0x48, 0x61, 0x73, 0x68,
0x69, 0x63, 0x6f, 0x72, 0x70, 0x3a, 0x3a, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x3a, 0x3a, 0x48,
0x63, 0x70, 0x3a, 0x3a, 0x56, 0x32, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
file_pbhcp_v2_link_proto_rawDescOnce sync.Once
file_pbhcp_v2_link_proto_rawDescData = file_pbhcp_v2_link_proto_rawDesc
)
func file_pbhcp_v2_link_proto_rawDescGZIP() []byte {
file_pbhcp_v2_link_proto_rawDescOnce.Do(func() {
file_pbhcp_v2_link_proto_rawDescData = protoimpl.X.CompressGZIP(file_pbhcp_v2_link_proto_rawDescData)
})
return file_pbhcp_v2_link_proto_rawDescData
}
var file_pbhcp_v2_link_proto_enumTypes = make([]protoimpl.EnumInfo, 1)
var file_pbhcp_v2_link_proto_msgTypes = make([]protoimpl.MessageInfo, 1)
var file_pbhcp_v2_link_proto_goTypes = []interface{}{
(AccessLevel)(0), // 0: hashicorp.consul.hcp.v2.AccessLevel
(*Link)(nil), // 1: hashicorp.consul.hcp.v2.Link
(*HCPConfig)(nil), // 2: hashicorp.consul.hcp.v2.HCPConfig
}
var file_pbhcp_v2_link_proto_depIdxs = []int32{
0, // 0: hashicorp.consul.hcp.v2.Link.access_level:type_name -> hashicorp.consul.hcp.v2.AccessLevel
2, // 1: hashicorp.consul.hcp.v2.Link.hcp_config:type_name -> hashicorp.consul.hcp.v2.HCPConfig
2, // [2:2] is the sub-list for method output_type
2, // [2:2] is the sub-list for method input_type
2, // [2:2] is the sub-list for extension type_name
2, // [2:2] is the sub-list for extension extendee
0, // [0:2] is the sub-list for field type_name
}
func init() { file_pbhcp_v2_link_proto_init() }
func file_pbhcp_v2_link_proto_init() {
if File_pbhcp_v2_link_proto != nil {
return
}
file_pbhcp_v2_hcp_config_proto_init()
if !protoimpl.UnsafeEnabled {
file_pbhcp_v2_link_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Link); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_pbhcp_v2_link_proto_rawDesc,
NumEnums: 1,
NumMessages: 1,
NumExtensions: 0,
NumServices: 0,
},
GoTypes: file_pbhcp_v2_link_proto_goTypes,
DependencyIndexes: file_pbhcp_v2_link_proto_depIdxs,
EnumInfos: file_pbhcp_v2_link_proto_enumTypes,
MessageInfos: file_pbhcp_v2_link_proto_msgTypes,
}.Build()
File_pbhcp_v2_link_proto = out.File
file_pbhcp_v2_link_proto_rawDesc = nil
file_pbhcp_v2_link_proto_goTypes = nil
file_pbhcp_v2_link_proto_depIdxs = nil
}

View File

@ -1,26 +0,0 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0
syntax = "proto3";
package hashicorp.consul.hcp.v2;
import "pbhcp/v2/hcp_config.proto";
import "pbresource/annotations.proto";
enum AccessLevel {
ACCESS_LEVEL_UNSPECIFIED = 0;
ACCESS_LEVEL_GLOBAL_READ_WRITE = 1;
ACCESS_LEVEL_GLOBAL_READ_ONLY = 2;
}
message Link {
option (hashicorp.consul.resource.spec) = {scope: SCOPE_CLUSTER};
string resource_id = 1;
string client_id = 2;
string client_secret = 3;
string hcp_cluster_url = 4;
AccessLevel access_level = 5;
HCPConfig hcp_config = 6;
}

View File

@ -1,27 +0,0 @@
// Code generated by protoc-gen-deepcopy. DO NOT EDIT.
package hcpv2
import (
proto "google.golang.org/protobuf/proto"
)
// DeepCopyInto supports using Link within kubernetes types, where deepcopy-gen is used.
func (in *Link) DeepCopyInto(out *Link) {
proto.Reset(out)
proto.Merge(out, proto.Clone(in))
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Link. Required by controller-gen.
func (in *Link) DeepCopy() *Link {
if in == nil {
return nil
}
out := new(Link)
in.DeepCopyInto(out)
return out
}
// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new Link. Required by controller-gen.
func (in *Link) DeepCopyInterface() interface{} {
return in.DeepCopy()
}

View File

@ -1,22 +0,0 @@
// Code generated by protoc-json-shim. DO NOT EDIT.
package hcpv2
import (
protojson "google.golang.org/protobuf/encoding/protojson"
)
// MarshalJSON is a custom marshaler for Link
func (this *Link) MarshalJSON() ([]byte, error) {
str, err := LinkMarshaler.Marshal(this)
return []byte(str), err
}
// UnmarshalJSON is a custom unmarshaler for Link
func (this *Link) UnmarshalJSON(b []byte) error {
return LinkUnmarshaler.Unmarshal(b, this)
}
var (
LinkMarshaler = &protojson.MarshalOptions{}
LinkUnmarshaler = &protojson.UnmarshalOptions{DiscardUnknown: false}
)

View File

@ -1,29 +0,0 @@
// Code generated by protoc-gen-resource-types. DO NOT EDIT.
package hcpv2
import (
"github.com/hashicorp/consul/proto-public/pbresource"
)
const (
GroupName = "hcp"
Version = "v2"
LinkKind = "Link"
TelemetryStateKind = "TelemetryState"
)
var (
LinkType = &pbresource.Type{
Group: GroupName,
GroupVersion: Version,
Kind: LinkKind,
}
TelemetryStateType = &pbresource.Type{
Group: GroupName,
GroupVersion: Version,
Kind: TelemetryStateKind,
}
)

View File

@ -1,38 +0,0 @@
// Code generated by protoc-gen-go-binary. DO NOT EDIT.
// source: pbhcp/v2/telemetry_state.proto
package hcpv2
import (
"google.golang.org/protobuf/proto"
)
// MarshalBinary implements encoding.BinaryMarshaler
func (msg *TelemetryState) MarshalBinary() ([]byte, error) {
return proto.Marshal(msg)
}
// UnmarshalBinary implements encoding.BinaryUnmarshaler
func (msg *TelemetryState) UnmarshalBinary(b []byte) error {
return proto.Unmarshal(b, msg)
}
// MarshalBinary implements encoding.BinaryMarshaler
func (msg *MetricsConfig) MarshalBinary() ([]byte, error) {
return proto.Marshal(msg)
}
// UnmarshalBinary implements encoding.BinaryUnmarshaler
func (msg *MetricsConfig) UnmarshalBinary(b []byte) error {
return proto.Unmarshal(b, msg)
}
// MarshalBinary implements encoding.BinaryMarshaler
func (msg *ProxyConfig) MarshalBinary() ([]byte, error) {
return proto.Marshal(msg)
}
// UnmarshalBinary implements encoding.BinaryUnmarshaler
func (msg *ProxyConfig) UnmarshalBinary(b []byte) error {
return proto.Unmarshal(b, msg)
}

View File

@ -1,426 +0,0 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.33.0
// protoc (unknown)
// source: pbhcp/v2/telemetry_state.proto
package hcpv2
import (
_ "github.com/hashicorp/consul/proto-public/pbresource"
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
sync "sync"
)
const (
// Verify that this generated code is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
// Verify that runtime/protoimpl is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
)
// TelemetryState describes configuration required to forward telemetry to the HashiCorp Cloud Platform.
// This resource is managed internally and is only written if the cluster is linked to HCP. Any
// manual changes to the resource will be reconciled and overwritten with the internally computed
// state.
type TelemetryState struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
// ResourceId is the identifier for the cluster linked with HCP.
ResourceId string `protobuf:"bytes,1,opt,name=resource_id,json=resourceId,proto3" json:"resource_id,omitempty"`
// ClientId is the oauth client identifier for cluster.
// This client has capabilities limited to writing telemetry data for this cluster.
ClientId string `protobuf:"bytes,2,opt,name=client_id,json=clientId,proto3" json:"client_id,omitempty"`
// ClientSecret is the oauth secret used to authenticate requests to send telemetry data to HCP.
ClientSecret string `protobuf:"bytes,3,opt,name=client_secret,json=clientSecret,proto3" json:"client_secret,omitempty"`
HcpConfig *HCPConfig `protobuf:"bytes,4,opt,name=hcp_config,json=hcpConfig,proto3" json:"hcp_config,omitempty"`
Proxy *ProxyConfig `protobuf:"bytes,5,opt,name=proxy,proto3" json:"proxy,omitempty"`
Metrics *MetricsConfig `protobuf:"bytes,6,opt,name=metrics,proto3" json:"metrics,omitempty"`
}
func (x *TelemetryState) Reset() {
*x = TelemetryState{}
if protoimpl.UnsafeEnabled {
mi := &file_pbhcp_v2_telemetry_state_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *TelemetryState) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*TelemetryState) ProtoMessage() {}
func (x *TelemetryState) ProtoReflect() protoreflect.Message {
mi := &file_pbhcp_v2_telemetry_state_proto_msgTypes[0]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use TelemetryState.ProtoReflect.Descriptor instead.
func (*TelemetryState) Descriptor() ([]byte, []int) {
return file_pbhcp_v2_telemetry_state_proto_rawDescGZIP(), []int{0}
}
func (x *TelemetryState) GetResourceId() string {
if x != nil {
return x.ResourceId
}
return ""
}
func (x *TelemetryState) GetClientId() string {
if x != nil {
return x.ClientId
}
return ""
}
func (x *TelemetryState) GetClientSecret() string {
if x != nil {
return x.ClientSecret
}
return ""
}
func (x *TelemetryState) GetHcpConfig() *HCPConfig {
if x != nil {
return x.HcpConfig
}
return nil
}
func (x *TelemetryState) GetProxy() *ProxyConfig {
if x != nil {
return x.Proxy
}
return nil
}
func (x *TelemetryState) GetMetrics() *MetricsConfig {
if x != nil {
return x.Metrics
}
return nil
}
// MetricsConfig configures metric specific collection details
type MetricsConfig struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
// Endpoint is the HTTPS address and path to forward metrics to
Endpoint string `protobuf:"bytes,1,opt,name=endpoint,proto3" json:"endpoint,omitempty"`
// IncludeList contains patterns to match against metric names. Only matched metrics are forwarded.
IncludeList []string `protobuf:"bytes,2,rep,name=include_list,json=includeList,proto3" json:"include_list,omitempty"`
// Labels contains key value pairs that are associated with all metrics collected and fowarded.
Labels map[string]string `protobuf:"bytes,3,rep,name=labels,proto3" json:"labels,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
// Disabled toggles metric forwarding. If true, metric forwarding will stop until disabled is set to false.
Disabled bool `protobuf:"varint,4,opt,name=disabled,proto3" json:"disabled,omitempty"`
}
func (x *MetricsConfig) Reset() {
*x = MetricsConfig{}
if protoimpl.UnsafeEnabled {
mi := &file_pbhcp_v2_telemetry_state_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *MetricsConfig) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*MetricsConfig) ProtoMessage() {}
func (x *MetricsConfig) ProtoReflect() protoreflect.Message {
mi := &file_pbhcp_v2_telemetry_state_proto_msgTypes[1]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use MetricsConfig.ProtoReflect.Descriptor instead.
func (*MetricsConfig) Descriptor() ([]byte, []int) {
return file_pbhcp_v2_telemetry_state_proto_rawDescGZIP(), []int{1}
}
func (x *MetricsConfig) GetEndpoint() string {
if x != nil {
return x.Endpoint
}
return ""
}
func (x *MetricsConfig) GetIncludeList() []string {
if x != nil {
return x.IncludeList
}
return nil
}
func (x *MetricsConfig) GetLabels() map[string]string {
if x != nil {
return x.Labels
}
return nil
}
func (x *MetricsConfig) GetDisabled() bool {
if x != nil {
return x.Disabled
}
return false
}
// ProxyConfig describes configuration for forwarding requests through an http proxy
type ProxyConfig struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
// HttpProxy configures the http proxy to use for HTTP (non-TLS) requests.
HttpProxy string `protobuf:"bytes,1,opt,name=http_proxy,json=httpProxy,proto3" json:"http_proxy,omitempty"`
// HttpsProxy configures the http proxy to use for HTTPS (TLS) requests.
HttpsProxy string `protobuf:"bytes,2,opt,name=https_proxy,json=httpsProxy,proto3" json:"https_proxy,omitempty"`
// NoProxy can be configured to include domains which should NOT be forwarded through the configured http proxy
NoProxy []string `protobuf:"bytes,3,rep,name=no_proxy,json=noProxy,proto3" json:"no_proxy,omitempty"`
}
func (x *ProxyConfig) Reset() {
*x = ProxyConfig{}
if protoimpl.UnsafeEnabled {
mi := &file_pbhcp_v2_telemetry_state_proto_msgTypes[2]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *ProxyConfig) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*ProxyConfig) ProtoMessage() {}
func (x *ProxyConfig) ProtoReflect() protoreflect.Message {
mi := &file_pbhcp_v2_telemetry_state_proto_msgTypes[2]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use ProxyConfig.ProtoReflect.Descriptor instead.
func (*ProxyConfig) Descriptor() ([]byte, []int) {
return file_pbhcp_v2_telemetry_state_proto_rawDescGZIP(), []int{2}
}
func (x *ProxyConfig) GetHttpProxy() string {
if x != nil {
return x.HttpProxy
}
return ""
}
func (x *ProxyConfig) GetHttpsProxy() string {
if x != nil {
return x.HttpsProxy
}
return ""
}
func (x *ProxyConfig) GetNoProxy() []string {
if x != nil {
return x.NoProxy
}
return nil
}
var File_pbhcp_v2_telemetry_state_proto protoreflect.FileDescriptor
var file_pbhcp_v2_telemetry_state_proto_rawDesc = []byte{
0x0a, 0x1e, 0x70, 0x62, 0x68, 0x63, 0x70, 0x2f, 0x76, 0x32, 0x2f, 0x74, 0x65, 0x6c, 0x65, 0x6d,
0x65, 0x74, 0x72, 0x79, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
0x12, 0x17, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73,
0x75, 0x6c, 0x2e, 0x68, 0x63, 0x70, 0x2e, 0x76, 0x32, 0x1a, 0x19, 0x70, 0x62, 0x68, 0x63, 0x70,
0x2f, 0x76, 0x32, 0x2f, 0x68, 0x63, 0x70, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x70,
0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1c, 0x70, 0x62, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65,
0x2f, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f,
0x74, 0x6f, 0x22, 0xbc, 0x02, 0x0a, 0x0e, 0x54, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79,
0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63,
0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x72, 0x65, 0x73, 0x6f,
0x75, 0x72, 0x63, 0x65, 0x49, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74,
0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x63, 0x6c, 0x69, 0x65, 0x6e,
0x74, 0x49, 0x64, 0x12, 0x23, 0x0a, 0x0d, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x65,
0x63, 0x72, 0x65, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x63, 0x6c, 0x69, 0x65,
0x6e, 0x74, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x12, 0x41, 0x0a, 0x0a, 0x68, 0x63, 0x70, 0x5f,
0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x68,
0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e,
0x68, 0x63, 0x70, 0x2e, 0x76, 0x32, 0x2e, 0x48, 0x43, 0x50, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67,
0x52, 0x09, 0x68, 0x63, 0x70, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x3a, 0x0a, 0x05, 0x70,
0x72, 0x6f, 0x78, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x68, 0x61, 0x73,
0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x68, 0x63,
0x70, 0x2e, 0x76, 0x32, 0x2e, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67,
0x52, 0x05, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x12, 0x40, 0x0a, 0x07, 0x6d, 0x65, 0x74, 0x72, 0x69,
0x63, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69,
0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x68, 0x63, 0x70, 0x2e,
0x76, 0x32, 0x2e, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67,
0x52, 0x07, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x3a, 0x06, 0xa2, 0x93, 0x04, 0x02, 0x08,
0x01, 0x22, 0xf1, 0x01, 0x0a, 0x0d, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x43, 0x6f, 0x6e,
0x66, 0x69, 0x67, 0x12, 0x1a, 0x0a, 0x08, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18,
0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12,
0x21, 0x0a, 0x0c, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x18,
0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0b, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x4c, 0x69,
0x73, 0x74, 0x12, 0x4a, 0x0a, 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x18, 0x03, 0x20, 0x03,
0x28, 0x0b, 0x32, 0x32, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63,
0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x68, 0x63, 0x70, 0x2e, 0x76, 0x32, 0x2e, 0x4d, 0x65, 0x74,
0x72, 0x69, 0x63, 0x73, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x4c, 0x61, 0x62, 0x65, 0x6c,
0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x12, 0x1a,
0x0a, 0x08, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08,
0x52, 0x08, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x1a, 0x39, 0x0a, 0x0b, 0x4c, 0x61,
0x62, 0x65, 0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79,
0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76,
0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75,
0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x68, 0x0a, 0x0b, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x43, 0x6f,
0x6e, 0x66, 0x69, 0x67, 0x12, 0x1d, 0x0a, 0x0a, 0x68, 0x74, 0x74, 0x70, 0x5f, 0x70, 0x72, 0x6f,
0x78, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x68, 0x74, 0x74, 0x70, 0x50, 0x72,
0x6f, 0x78, 0x79, 0x12, 0x1f, 0x0a, 0x0b, 0x68, 0x74, 0x74, 0x70, 0x73, 0x5f, 0x70, 0x72, 0x6f,
0x78, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x68, 0x74, 0x74, 0x70, 0x73, 0x50,
0x72, 0x6f, 0x78, 0x79, 0x12, 0x19, 0x0a, 0x08, 0x6e, 0x6f, 0x5f, 0x70, 0x72, 0x6f, 0x78, 0x79,
0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x6e, 0x6f, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x42,
0xea, 0x01, 0x0a, 0x1b, 0x63, 0x6f, 0x6d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72,
0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x68, 0x63, 0x70, 0x2e, 0x76, 0x32, 0x42,
0x13, 0x54, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x53, 0x74, 0x61, 0x74, 0x65, 0x50,
0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x37, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63,
0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x63, 0x6f, 0x6e,
0x73, 0x75, 0x6c, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2d, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63,
0x2f, 0x70, 0x62, 0x68, 0x63, 0x70, 0x2f, 0x76, 0x32, 0x3b, 0x68, 0x63, 0x70, 0x76, 0x32, 0xa2,
0x02, 0x03, 0x48, 0x43, 0x48, 0xaa, 0x02, 0x17, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72,
0x70, 0x2e, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x48, 0x63, 0x70, 0x2e, 0x56, 0x32, 0xca,
0x02, 0x17, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73,
0x75, 0x6c, 0x5c, 0x48, 0x63, 0x70, 0x5c, 0x56, 0x32, 0xe2, 0x02, 0x23, 0x48, 0x61, 0x73, 0x68,
0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x48, 0x63, 0x70,
0x5c, 0x56, 0x32, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea,
0x02, 0x1a, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x3a, 0x3a, 0x43, 0x6f, 0x6e,
0x73, 0x75, 0x6c, 0x3a, 0x3a, 0x48, 0x63, 0x70, 0x3a, 0x3a, 0x56, 0x32, 0x62, 0x06, 0x70, 0x72,
0x6f, 0x74, 0x6f, 0x33,
}
var (
file_pbhcp_v2_telemetry_state_proto_rawDescOnce sync.Once
file_pbhcp_v2_telemetry_state_proto_rawDescData = file_pbhcp_v2_telemetry_state_proto_rawDesc
)
func file_pbhcp_v2_telemetry_state_proto_rawDescGZIP() []byte {
file_pbhcp_v2_telemetry_state_proto_rawDescOnce.Do(func() {
file_pbhcp_v2_telemetry_state_proto_rawDescData = protoimpl.X.CompressGZIP(file_pbhcp_v2_telemetry_state_proto_rawDescData)
})
return file_pbhcp_v2_telemetry_state_proto_rawDescData
}
var file_pbhcp_v2_telemetry_state_proto_msgTypes = make([]protoimpl.MessageInfo, 4)
var file_pbhcp_v2_telemetry_state_proto_goTypes = []interface{}{
(*TelemetryState)(nil), // 0: hashicorp.consul.hcp.v2.TelemetryState
(*MetricsConfig)(nil), // 1: hashicorp.consul.hcp.v2.MetricsConfig
(*ProxyConfig)(nil), // 2: hashicorp.consul.hcp.v2.ProxyConfig
nil, // 3: hashicorp.consul.hcp.v2.MetricsConfig.LabelsEntry
(*HCPConfig)(nil), // 4: hashicorp.consul.hcp.v2.HCPConfig
}
var file_pbhcp_v2_telemetry_state_proto_depIdxs = []int32{
4, // 0: hashicorp.consul.hcp.v2.TelemetryState.hcp_config:type_name -> hashicorp.consul.hcp.v2.HCPConfig
2, // 1: hashicorp.consul.hcp.v2.TelemetryState.proxy:type_name -> hashicorp.consul.hcp.v2.ProxyConfig
1, // 2: hashicorp.consul.hcp.v2.TelemetryState.metrics:type_name -> hashicorp.consul.hcp.v2.MetricsConfig
3, // 3: hashicorp.consul.hcp.v2.MetricsConfig.labels:type_name -> hashicorp.consul.hcp.v2.MetricsConfig.LabelsEntry
4, // [4:4] is the sub-list for method output_type
4, // [4:4] is the sub-list for method input_type
4, // [4:4] is the sub-list for extension type_name
4, // [4:4] is the sub-list for extension extendee
0, // [0:4] is the sub-list for field type_name
}
func init() { file_pbhcp_v2_telemetry_state_proto_init() }
func file_pbhcp_v2_telemetry_state_proto_init() {
if File_pbhcp_v2_telemetry_state_proto != nil {
return
}
file_pbhcp_v2_hcp_config_proto_init()
if !protoimpl.UnsafeEnabled {
file_pbhcp_v2_telemetry_state_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*TelemetryState); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_pbhcp_v2_telemetry_state_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*MetricsConfig); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_pbhcp_v2_telemetry_state_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*ProxyConfig); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_pbhcp_v2_telemetry_state_proto_rawDesc,
NumEnums: 0,
NumMessages: 4,
NumExtensions: 0,
NumServices: 0,
},
GoTypes: file_pbhcp_v2_telemetry_state_proto_goTypes,
DependencyIndexes: file_pbhcp_v2_telemetry_state_proto_depIdxs,
MessageInfos: file_pbhcp_v2_telemetry_state_proto_msgTypes,
}.Build()
File_pbhcp_v2_telemetry_state_proto = out.File
file_pbhcp_v2_telemetry_state_proto_rawDesc = nil
file_pbhcp_v2_telemetry_state_proto_goTypes = nil
file_pbhcp_v2_telemetry_state_proto_depIdxs = nil
}

View File

@ -1,55 +0,0 @@
syntax = "proto3";
package hashicorp.consul.hcp.v2;
import "pbhcp/v2/hcp_config.proto";
import "pbresource/annotations.proto";
// TelemetryState describes configuration required to forward telemetry to the HashiCorp Cloud Platform.
// This resource is managed internally and is only written if the cluster is linked to HCP. Any
// manual changes to the resource will be reconciled and overwritten with the internally computed
// state.
message TelemetryState {
option (hashicorp.consul.resource.spec) = {scope: SCOPE_CLUSTER};
// ResourceId is the identifier for the cluster linked with HCP.
string resource_id = 1;
// ClientId is the oauth client identifier for cluster.
// This client has capabilities limited to writing telemetry data for this cluster.
string client_id = 2;
// ClientSecret is the oauth secret used to authenticate requests to send telemetry data to HCP.
string client_secret = 3;
HCPConfig hcp_config = 4;
ProxyConfig proxy = 5;
MetricsConfig metrics = 6;
}
// MetricsConfig configures metric specific collection details
message MetricsConfig {
// Endpoint is the HTTPS address and path to forward metrics to
string endpoint = 1;
// IncludeList contains patterns to match against metric names. Only matched metrics are forwarded.
repeated string include_list = 2;
// Labels contains key value pairs that are associated with all metrics collected and fowarded.
map<string, string> labels = 3;
// Disabled toggles metric forwarding. If true, metric forwarding will stop until disabled is set to false.
bool disabled = 4;
}
// ProxyConfig describes configuration for forwarding requests through an http proxy
message ProxyConfig {
// HttpProxy configures the http proxy to use for HTTP (non-TLS) requests.
string http_proxy = 1;
// HttpsProxy configures the http proxy to use for HTTPS (TLS) requests.
string https_proxy = 2;
// NoProxy can be configured to include domains which should NOT be forwarded through the configured http proxy
repeated string no_proxy = 3;
}

View File

@ -1,69 +0,0 @@
// Code generated by protoc-gen-deepcopy. DO NOT EDIT.
package hcpv2
import (
proto "google.golang.org/protobuf/proto"
)
// DeepCopyInto supports using TelemetryState within kubernetes types, where deepcopy-gen is used.
func (in *TelemetryState) DeepCopyInto(out *TelemetryState) {
proto.Reset(out)
proto.Merge(out, proto.Clone(in))
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TelemetryState. Required by controller-gen.
func (in *TelemetryState) DeepCopy() *TelemetryState {
if in == nil {
return nil
}
out := new(TelemetryState)
in.DeepCopyInto(out)
return out
}
// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new TelemetryState. Required by controller-gen.
func (in *TelemetryState) DeepCopyInterface() interface{} {
return in.DeepCopy()
}
// DeepCopyInto supports using MetricsConfig within kubernetes types, where deepcopy-gen is used.
func (in *MetricsConfig) DeepCopyInto(out *MetricsConfig) {
proto.Reset(out)
proto.Merge(out, proto.Clone(in))
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MetricsConfig. Required by controller-gen.
func (in *MetricsConfig) DeepCopy() *MetricsConfig {
if in == nil {
return nil
}
out := new(MetricsConfig)
in.DeepCopyInto(out)
return out
}
// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new MetricsConfig. Required by controller-gen.
func (in *MetricsConfig) DeepCopyInterface() interface{} {
return in.DeepCopy()
}
// DeepCopyInto supports using ProxyConfig within kubernetes types, where deepcopy-gen is used.
func (in *ProxyConfig) DeepCopyInto(out *ProxyConfig) {
proto.Reset(out)
proto.Merge(out, proto.Clone(in))
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ProxyConfig. Required by controller-gen.
func (in *ProxyConfig) DeepCopy() *ProxyConfig {
if in == nil {
return nil
}
out := new(ProxyConfig)
in.DeepCopyInto(out)
return out
}
// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new ProxyConfig. Required by controller-gen.
func (in *ProxyConfig) DeepCopyInterface() interface{} {
return in.DeepCopy()
}

View File

@ -1,44 +0,0 @@
// Code generated by protoc-json-shim. DO NOT EDIT.
package hcpv2
import (
protojson "google.golang.org/protobuf/encoding/protojson"
)
// MarshalJSON is a custom marshaler for TelemetryState
func (this *TelemetryState) MarshalJSON() ([]byte, error) {
str, err := TelemetryStateMarshaler.Marshal(this)
return []byte(str), err
}
// UnmarshalJSON is a custom unmarshaler for TelemetryState
func (this *TelemetryState) UnmarshalJSON(b []byte) error {
return TelemetryStateUnmarshaler.Unmarshal(b, this)
}
// MarshalJSON is a custom marshaler for MetricsConfig
func (this *MetricsConfig) MarshalJSON() ([]byte, error) {
str, err := TelemetryStateMarshaler.Marshal(this)
return []byte(str), err
}
// UnmarshalJSON is a custom unmarshaler for MetricsConfig
func (this *MetricsConfig) UnmarshalJSON(b []byte) error {
return TelemetryStateUnmarshaler.Unmarshal(b, this)
}
// MarshalJSON is a custom marshaler for ProxyConfig
func (this *ProxyConfig) MarshalJSON() ([]byte, error) {
str, err := TelemetryStateMarshaler.Marshal(this)
return []byte(str), err
}
// UnmarshalJSON is a custom unmarshaler for ProxyConfig
func (this *ProxyConfig) UnmarshalJSON(b []byte) error {
return TelemetryStateUnmarshaler.Unmarshal(b, this)
}
var (
TelemetryStateMarshaler = &protojson.MarshalOptions{}
TelemetryStateUnmarshaler = &protojson.UnmarshalOptions{DiscardUnknown: false}
)