|
|
|
@ -26,13 +26,10 @@ import (
|
|
|
|
|
"github.com/hashicorp/consul/sdk/testutil"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
func TestMonitorHCPLink_Ok(t *testing.T) {
|
|
|
|
|
func TestMonitorHCPLink(t *testing.T) {
|
|
|
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
|
|
|
t.Cleanup(cancel)
|
|
|
|
|
|
|
|
|
|
linkWatchCh := make(chan *pbresource.WatchEvent)
|
|
|
|
|
mgr := NewMockManager(t)
|
|
|
|
|
|
|
|
|
|
mockHCPClient := hcpclient.NewMockClient(t)
|
|
|
|
|
mockHcpClientFn := func(_ config.CloudConfig) (hcpclient.Client, error) {
|
|
|
|
|
return mockHCPClient, nil
|
|
|
|
@ -43,213 +40,110 @@ func TestMonitorHCPLink_Ok(t *testing.T) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
dataDir := testutil.TempDir(t, "test-link-controller")
|
|
|
|
|
os.Mkdir(filepath.Join(dataDir, constants.SubDir), os.ModeDir)
|
|
|
|
|
err := os.Mkdir(filepath.Join(dataDir, constants.SubDir), os.ModeDir)
|
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
existingCfg := config.CloudConfig{
|
|
|
|
|
AuthURL: "test.com",
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var wg sync.WaitGroup
|
|
|
|
|
type testCase struct {
|
|
|
|
|
mutateLink func(*pbhcp.Link)
|
|
|
|
|
mutateUpsertEvent func(*pbresource.WatchEvent_Upsert)
|
|
|
|
|
applyMocksAndAssertions func(*testing.T, *MockManager, *pbhcp.Link)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
wg.Add(1)
|
|
|
|
|
go func() {
|
|
|
|
|
defer wg.Done()
|
|
|
|
|
MonitorHCPLink(
|
|
|
|
|
ctx, hclog.New(&hclog.LoggerOptions{Output: io.Discard}), mgr, linkWatchCh, mockHcpClientFn,
|
|
|
|
|
loadMgmtTokenFn, existingCfg, dataDir,
|
|
|
|
|
)
|
|
|
|
|
}()
|
|
|
|
|
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()
|
|
|
|
|
|
|
|
|
|
// Set up a link
|
|
|
|
|
link := pbhcp.Link{
|
|
|
|
|
ResourceId: "abc",
|
|
|
|
|
ClientId: "def",
|
|
|
|
|
ClientSecret: "ghi",
|
|
|
|
|
AccessLevel: pbhcp.AccessLevel_ACCESS_LEVEL_GLOBAL_READ_WRITE,
|
|
|
|
|
}
|
|
|
|
|
expectedCfg := config.CloudConfig{
|
|
|
|
|
ResourceID: link.ResourceId,
|
|
|
|
|
ClientID: link.ClientId,
|
|
|
|
|
ClientSecret: link.ClientSecret,
|
|
|
|
|
AuthURL: "test.com",
|
|
|
|
|
ManagementToken: "test-mgmt-token",
|
|
|
|
|
}
|
|
|
|
|
linkResource, err := anypb.New(&link)
|
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
expectedCfg := config.CloudConfig{
|
|
|
|
|
ResourceID: link.ResourceId,
|
|
|
|
|
ClientID: link.ClientId,
|
|
|
|
|
ClientSecret: link.ClientSecret,
|
|
|
|
|
AuthURL: "test.com",
|
|
|
|
|
ManagementToken: "test-mgmt-token",
|
|
|
|
|
}
|
|
|
|
|
mgr.EXPECT().UpdateConfig(mockHCPClient, expectedCfg)
|
|
|
|
|
|
|
|
|
|
// Create link, expect HCP manager to be updated and started
|
|
|
|
|
mgr.EXPECT().Start(mock.Anything).Return(nil).Once()
|
|
|
|
|
mgr.EXPECT().UpdateConfig(mockHCPClient, expectedCfg)
|
|
|
|
|
linkWatchCh <- &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,
|
|
|
|
|
},
|
|
|
|
|
mgr.EXPECT().Stop().Return(nil).Once()
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Delete link, expect HCP manager to be stopped
|
|
|
|
|
mgr.EXPECT().Stop().Return(nil).Once()
|
|
|
|
|
linkWatchCh <- &pbresource.WatchEvent{
|
|
|
|
|
Event: &pbresource.WatchEvent_Delete_{
|
|
|
|
|
Delete: &pbresource.WatchEvent_Delete{},
|
|
|
|
|
// 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)
|
|
|
|
|
|
|
|
|
|
mgr.EXPECT().Stop().Return(nil).Once()
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Wait for MonitorHCPLink to return before assertions run
|
|
|
|
|
close(linkWatchCh)
|
|
|
|
|
wg.Wait()
|
|
|
|
|
|
|
|
|
|
// Ensure hcp-config directory is removed
|
|
|
|
|
file := filepath.Join(dataDir, constants.SubDir)
|
|
|
|
|
if _, err := os.Stat(file); err == nil || !os.IsNotExist(err) {
|
|
|
|
|
require.Fail(t, "should have removed hcp-config directory")
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestMonitorHCPLink_ValidationError(t *testing.T) {
|
|
|
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
|
|
|
t.Cleanup(cancel)
|
|
|
|
|
|
|
|
|
|
linkWatchCh := make(chan *pbresource.WatchEvent)
|
|
|
|
|
mgr := NewMockManager(t)
|
|
|
|
|
|
|
|
|
|
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
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
dataDir := testutil.TempDir(t, "test-link-controller")
|
|
|
|
|
os.Mkdir(filepath.Join(dataDir, constants.SubDir), os.ModeDir)
|
|
|
|
|
|
|
|
|
|
var wg sync.WaitGroup
|
|
|
|
|
|
|
|
|
|
wg.Add(1)
|
|
|
|
|
go func() {
|
|
|
|
|
defer wg.Done()
|
|
|
|
|
MonitorHCPLink(
|
|
|
|
|
ctx, hclog.New(&hclog.LoggerOptions{Output: io.Discard}), mgr, linkWatchCh, mockHcpClientFn,
|
|
|
|
|
loadMgmtTokenFn, config.CloudConfig{}, dataDir,
|
|
|
|
|
)
|
|
|
|
|
}()
|
|
|
|
|
|
|
|
|
|
// 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)
|
|
|
|
|
|
|
|
|
|
// Create link, expect HCP manager to be updated and started
|
|
|
|
|
linkWatchCh <- &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.ConditionValidatedFailed},
|
|
|
|
|
},
|
|
|
|
|
// 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},
|
|
|
|
|
},
|
|
|
|
|
Data: linkResource,
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
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()
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Delete link, expect HCP manager to be stopped
|
|
|
|
|
mgr.EXPECT().Stop().Return(nil).Once()
|
|
|
|
|
linkWatchCh <- &pbresource.WatchEvent{
|
|
|
|
|
Event: &pbresource.WatchEvent_Delete_{
|
|
|
|
|
Delete: &pbresource.WatchEvent_Delete{},
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Wait for MonitorHCPLink to return before assertions run
|
|
|
|
|
close(linkWatchCh)
|
|
|
|
|
wg.Wait()
|
|
|
|
|
|
|
|
|
|
// Ensure hcp-config directory is removed
|
|
|
|
|
file := filepath.Join(dataDir, constants.SubDir)
|
|
|
|
|
if _, err := os.Stat(file); err == nil || !os.IsNotExist(err) {
|
|
|
|
|
require.Fail(t, "should have removed hcp-config directory")
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestMonitorHCPLink_Ok_ReadOnly(t *testing.T) {
|
|
|
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
|
|
|
t.Cleanup(cancel)
|
|
|
|
|
for name, test := range testCases {
|
|
|
|
|
t.Run(name, func(t2 *testing.T) {
|
|
|
|
|
mgr := NewMockManager(t2)
|
|
|
|
|
|
|
|
|
|
linkWatchCh := make(chan *pbresource.WatchEvent)
|
|
|
|
|
mgr := NewMockManager(t)
|
|
|
|
|
// Set up a link
|
|
|
|
|
link := pbhcp.Link{
|
|
|
|
|
ResourceId: "abc",
|
|
|
|
|
ClientId: "def",
|
|
|
|
|
ClientSecret: "ghi",
|
|
|
|
|
AccessLevel: pbhcp.AccessLevel_ACCESS_LEVEL_GLOBAL_READ_WRITE,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
mockHCPClient := hcpclient.NewMockClient(t)
|
|
|
|
|
mockHcpClientFn := func(_ config.CloudConfig) (hcpclient.Client, error) {
|
|
|
|
|
return mockHCPClient, nil
|
|
|
|
|
}
|
|
|
|
|
if test.mutateLink != nil {
|
|
|
|
|
test.mutateLink(&link)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
loadMgmtTokenFn := func(ctx context.Context, logger hclog.Logger, hcpClient hcpclient.Client, dataDir string) (string, error) {
|
|
|
|
|
return "test-mgmt-token", nil
|
|
|
|
|
}
|
|
|
|
|
existingManagerCfg := config.CloudConfig{
|
|
|
|
|
AuthURL: "test.com",
|
|
|
|
|
}
|
|
|
|
|
linkResource, err := anypb.New(&link)
|
|
|
|
|
require.NoError(t2, err)
|
|
|
|
|
|
|
|
|
|
var wg sync.WaitGroup
|
|
|
|
|
if test.applyMocksAndAssertions != nil {
|
|
|
|
|
test.applyMocksAndAssertions(t2, mgr, &link)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
wg.Add(1)
|
|
|
|
|
go func() {
|
|
|
|
|
defer wg.Done()
|
|
|
|
|
MonitorHCPLink(
|
|
|
|
|
ctx, hclog.New(&hclog.LoggerOptions{Output: io.Discard}), mgr, linkWatchCh, mockHcpClientFn,
|
|
|
|
|
loadMgmtTokenFn, existingManagerCfg, "",
|
|
|
|
|
)
|
|
|
|
|
}()
|
|
|
|
|
linkWatchCh := make(chan *pbresource.WatchEvent)
|
|
|
|
|
|
|
|
|
|
// Set up a link with READ_ONLY AccessLevel
|
|
|
|
|
// In this case, we don't expect the HCP manager to be updated with any management token
|
|
|
|
|
link := pbhcp.Link{
|
|
|
|
|
ResourceId: "abc",
|
|
|
|
|
ClientId: "def",
|
|
|
|
|
ClientSecret: "ghi",
|
|
|
|
|
AccessLevel: pbhcp.AccessLevel_ACCESS_LEVEL_GLOBAL_READ_ONLY,
|
|
|
|
|
}
|
|
|
|
|
expectedCfg := config.CloudConfig{
|
|
|
|
|
ResourceID: link.ResourceId,
|
|
|
|
|
ClientID: link.ClientId,
|
|
|
|
|
ClientSecret: link.ClientSecret,
|
|
|
|
|
AuthURL: "test.com",
|
|
|
|
|
ManagementToken: "",
|
|
|
|
|
}
|
|
|
|
|
linkResource, err := anypb.New(&link)
|
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
// Start MonitorHCPLink
|
|
|
|
|
var wg sync.WaitGroup
|
|
|
|
|
wg.Add(1)
|
|
|
|
|
go func() {
|
|
|
|
|
defer wg.Done()
|
|
|
|
|
MonitorHCPLink(
|
|
|
|
|
ctx, hclog.New(&hclog.LoggerOptions{Output: io.Discard}), mgr, linkWatchCh, mockHcpClientFn,
|
|
|
|
|
loadMgmtTokenFn, existingCfg, dataDir,
|
|
|
|
|
)
|
|
|
|
|
}()
|
|
|
|
|
|
|
|
|
|
// Create link, expect HCP manager to be updated and started
|
|
|
|
|
mgr.EXPECT().Start(mock.Anything).Return(nil).Once()
|
|
|
|
|
mgr.EXPECT().UpdateConfig(mockHCPClient, expectedCfg)
|
|
|
|
|
linkWatchCh <- &pbresource.WatchEvent{
|
|
|
|
|
Event: &pbresource.WatchEvent_Upsert_{
|
|
|
|
|
Upsert: &pbresource.WatchEvent_Upsert{
|
|
|
|
|
upsertEvent := &pbresource.WatchEvent_Upsert{
|
|
|
|
|
Resource: &pbresource.Resource{
|
|
|
|
|
Id: &pbresource.ID{
|
|
|
|
|
Name: "global",
|
|
|
|
@ -262,11 +156,33 @@ func TestMonitorHCPLink_Ok_ReadOnly(t *testing.T) {
|
|
|
|
|
},
|
|
|
|
|
Data: linkResource,
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if test.mutateUpsertEvent != nil {
|
|
|
|
|
test.mutateUpsertEvent(upsertEvent)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
linkWatchCh <- &pbresource.WatchEvent{
|
|
|
|
|
Event: &pbresource.WatchEvent_Upsert_{
|
|
|
|
|
Upsert: upsertEvent,
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Delete link, expect HCP manager to be stopped
|
|
|
|
|
linkWatchCh <- &pbresource.WatchEvent{
|
|
|
|
|
Event: &pbresource.WatchEvent_Delete_{
|
|
|
|
|
Delete: &pbresource.WatchEvent_Delete{},
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Wait for MonitorHCPLink to return before assertions run
|
|
|
|
|
close(linkWatchCh)
|
|
|
|
|
wg.Wait()
|
|
|
|
|
// Wait for MonitorHCPLink to return before assertions run
|
|
|
|
|
close(linkWatchCh)
|
|
|
|
|
wg.Wait()
|
|
|
|
|
|
|
|
|
|
// 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")
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|