feat(api): return remote storage states for worker
This commit is contained in:
1 parent
11272b6c2a
commit
c0cf5c4e1b
13 files changed
+787
-108
No files matched your search
@@ -27,6 +27,7 @@ import (
|
||||
"github.com/hashicorp/boundary/internal/types/scope"
|
||||
"github.com/hashicorp/boundary/internal/util"
|
||||
pb "github.com/hashicorp/boundary/sdk/pbs/controller/api/resources/workers"
|
||||
"github.com/hashicorp/boundary/sdk/pbs/plugin"
|
||||
"github.com/hashicorp/go-secure-stdlib/strutil"
|
||||
"github.com/hashicorp/nodeenrollment/types"
|
||||
"github.com/mr-tron/base58"
|
||||
@@ -924,10 +925,67 @@ func (s Service) toProto(ctx context.Context, in *server.Worker, opt ...handlers
|
||||
return nil, errors.Wrap(ctx, err, op, errors.WithMsg("error preparing canonical tags proto"))
|
||||
}
|
||||
}
|
||||
|
||||
if outputFields.Has(globals.RemoteStorageStateField) && len(in.RemoteStorageStates) > 0 {
|
||||
var err error
|
||||
out.RemoteStorageState, err = remoteStorageStatesToMapProto(in.RemoteStorageStates)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(ctx, err, op, errors.WithMsg("error preparing remote storage state proto"))
|
||||
}
|
||||
}
|
||||
return &out, nil
|
||||
}
|
||||
|
||||
func remoteStorageStatesToMapProto(in map[string]*plugin.StorageBucketCredentialState) (map[string]*pb.RemoteStorageState, error) {
|
||||
ret := make(map[string]*pb.RemoteStorageState)
|
||||
for storageBucketId, sbcState := range in {
|
||||
status := server.RemoteStorageStateAvailable
|
||||
writeState := server.PermissionStateUnknown.String()
|
||||
readState := server.PermissionStateUnknown.String()
|
||||
deleteState := server.PermissionStateUnknown.String()
|
||||
if sbcState.GetState() != nil {
|
||||
if sbcState.GetState().GetWrite() != nil {
|
||||
writePermissionState, err := server.ParsePermissionState(sbcState.GetState().GetWrite().GetState())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
writeState = writePermissionState
|
||||
if writeState == server.PermissionStateError.String() {
|
||||
status = server.RemoteStorageStateError
|
||||
}
|
||||
}
|
||||
if sbcState.GetState().GetRead() != nil {
|
||||
readPermissionState, err := server.ParsePermissionState(sbcState.GetState().GetRead().GetState())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
readState = readPermissionState
|
||||
if readState == server.PermissionStateError.String() {
|
||||
status = server.RemoteStorageStateError
|
||||
}
|
||||
}
|
||||
if sbcState.GetState().GetDelete() != nil {
|
||||
deletePermissionState, err := server.ParsePermissionState(sbcState.GetState().GetDelete().GetState())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
deleteState = deletePermissionState
|
||||
if deleteState == server.PermissionStateError.String() {
|
||||
status = server.RemoteStorageStateError
|
||||
}
|
||||
}
|
||||
}
|
||||
ret[storageBucketId] = &pb.RemoteStorageState{
|
||||
Status: status.String(),
|
||||
Permissions: &pb.RemoteStoragePermissions{
|
||||
Write: writeState,
|
||||
Read: readState,
|
||||
Delete: deleteState,
|
||||
},
|
||||
}
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func tagsToMapProto(in map[string][]string) (map[string]*structpb.ListValue, error) {
|
||||
b := make(map[string][]any)
|
||||
for k, v := range in {
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
"sort"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/google/go-cmp/cmp/cmpopts"
|
||||
@@ -26,6 +27,7 @@ import (
|
||||
"github.com/hashicorp/boundary/internal/types/scope"
|
||||
"github.com/hashicorp/boundary/sdk/pbs/controller/api/resources/scopes"
|
||||
pb "github.com/hashicorp/boundary/sdk/pbs/controller/api/resources/workers"
|
||||
"github.com/hashicorp/boundary/sdk/pbs/plugin"
|
||||
"github.com/hashicorp/go-secure-stdlib/strutil"
|
||||
"github.com/hashicorp/nodeenrollment"
|
||||
"github.com/hashicorp/nodeenrollment/rotation"
|
||||
@@ -1597,6 +1599,7 @@ func TestCreateWorkerLed(t *testing.T) {
|
||||
tc.res.Item.Scope = got.GetItem().Scope
|
||||
tc.res.Item.AuthorizedActions = got.GetItem().GetAuthorizedActions()
|
||||
tc.res.Item.LocalStorageState = got.GetItem().GetLocalStorageState()
|
||||
tc.res.Item.DirectlyConnectedDownstreamWorkers = got.GetItem().GetDirectlyConnectedDownstreamWorkers()
|
||||
}
|
||||
}
|
||||
assert.Equal(tc.res, got)
|
||||
@@ -1945,6 +1948,7 @@ func TestCreateControllerLed(t *testing.T) {
|
||||
tc.res.Item.AuthorizedActions = got.GetItem().GetAuthorizedActions()
|
||||
tc.res.Item.ControllerGeneratedActivationToken = got.GetItem().GetControllerGeneratedActivationToken()
|
||||
tc.res.Item.LocalStorageState = got.GetItem().GetLocalStorageState()
|
||||
tc.res.Item.DirectlyConnectedDownstreamWorkers = got.GetItem().GetDirectlyConnectedDownstreamWorkers()
|
||||
}
|
||||
}
|
||||
assert.Equal(tc.res, got)
|
||||
@@ -2619,3 +2623,211 @@ func TestReinitializeCertificateAuthority(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_RemoteStorageStatesToMapProto(t *testing.T) {
|
||||
t.Parallel()
|
||||
testTime := timestamppb.New(time.Now().UTC().Round(time.Second))
|
||||
tests := []struct {
|
||||
name string
|
||||
input map[string]*plugin.StorageBucketCredentialState
|
||||
expectedErrMsg string
|
||||
expectedOutput map[string]*pb.RemoteStorageState
|
||||
}{
|
||||
{
|
||||
name: "nil",
|
||||
expectedOutput: map[string]*pb.RemoteStorageState{},
|
||||
},
|
||||
{
|
||||
name: "empty",
|
||||
expectedOutput: map[string]*pb.RemoteStorageState{},
|
||||
},
|
||||
{
|
||||
name: "available",
|
||||
input: map[string]*plugin.StorageBucketCredentialState{
|
||||
"sb_1234567890": {
|
||||
State: &plugin.Permissions{
|
||||
Write: &plugin.Permission{
|
||||
State: plugin.StateType_STATE_TYPE_OK,
|
||||
CheckedAt: testTime,
|
||||
},
|
||||
Read: &plugin.Permission{
|
||||
State: plugin.StateType_STATE_TYPE_OK,
|
||||
CheckedAt: testTime,
|
||||
},
|
||||
Delete: &plugin.Permission{
|
||||
State: plugin.StateType_STATE_TYPE_OK,
|
||||
CheckedAt: testTime,
|
||||
},
|
||||
},
|
||||
Version: 1,
|
||||
},
|
||||
},
|
||||
expectedOutput: map[string]*pb.RemoteStorageState{
|
||||
"sb_1234567890": {
|
||||
Status: "available",
|
||||
Permissions: &pb.RemoteStoragePermissions{
|
||||
Write: "ok",
|
||||
Read: "ok",
|
||||
Delete: "ok",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "write error",
|
||||
input: map[string]*plugin.StorageBucketCredentialState{
|
||||
"sb_1234567890": {
|
||||
State: &plugin.Permissions{
|
||||
Write: &plugin.Permission{
|
||||
State: plugin.StateType_STATE_TYPE_ERROR,
|
||||
ErrorDetails: "invalid credentials",
|
||||
CheckedAt: testTime,
|
||||
},
|
||||
Read: &plugin.Permission{
|
||||
State: plugin.StateType_STATE_TYPE_OK,
|
||||
CheckedAt: testTime,
|
||||
},
|
||||
Delete: &plugin.Permission{
|
||||
State: plugin.StateType_STATE_TYPE_OK,
|
||||
CheckedAt: testTime,
|
||||
},
|
||||
},
|
||||
Version: 1,
|
||||
},
|
||||
},
|
||||
expectedOutput: map[string]*pb.RemoteStorageState{
|
||||
"sb_1234567890": {
|
||||
Status: "error",
|
||||
Permissions: &pb.RemoteStoragePermissions{
|
||||
Write: "error",
|
||||
Read: "ok",
|
||||
Delete: "ok",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "read error",
|
||||
input: map[string]*plugin.StorageBucketCredentialState{
|
||||
"sb_1234567890": {
|
||||
State: &plugin.Permissions{
|
||||
Write: &plugin.Permission{
|
||||
State: plugin.StateType_STATE_TYPE_OK,
|
||||
CheckedAt: testTime,
|
||||
},
|
||||
Read: &plugin.Permission{
|
||||
State: plugin.StateType_STATE_TYPE_ERROR,
|
||||
ErrorDetails: "invalid credentials",
|
||||
CheckedAt: testTime,
|
||||
},
|
||||
Delete: &plugin.Permission{
|
||||
State: plugin.StateType_STATE_TYPE_OK,
|
||||
CheckedAt: testTime,
|
||||
},
|
||||
},
|
||||
Version: 1,
|
||||
},
|
||||
},
|
||||
expectedOutput: map[string]*pb.RemoteStorageState{
|
||||
"sb_1234567890": {
|
||||
Status: "error",
|
||||
Permissions: &pb.RemoteStoragePermissions{
|
||||
Write: "ok",
|
||||
Read: "error",
|
||||
Delete: "ok",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "delete error",
|
||||
input: map[string]*plugin.StorageBucketCredentialState{
|
||||
"sb_1234567890": {
|
||||
State: &plugin.Permissions{
|
||||
Write: &plugin.Permission{
|
||||
State: plugin.StateType_STATE_TYPE_OK,
|
||||
CheckedAt: testTime,
|
||||
},
|
||||
Read: &plugin.Permission{
|
||||
State: plugin.StateType_STATE_TYPE_OK,
|
||||
CheckedAt: testTime,
|
||||
},
|
||||
Delete: &plugin.Permission{
|
||||
State: plugin.StateType_STATE_TYPE_ERROR,
|
||||
ErrorDetails: "invalid credentials",
|
||||
CheckedAt: testTime,
|
||||
},
|
||||
},
|
||||
Version: 1,
|
||||
},
|
||||
},
|
||||
expectedOutput: map[string]*pb.RemoteStorageState{
|
||||
"sb_1234567890": {
|
||||
Status: "error",
|
||||
Permissions: &pb.RemoteStoragePermissions{
|
||||
Write: "ok",
|
||||
Read: "ok",
|
||||
Delete: "error",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "error",
|
||||
input: map[string]*plugin.StorageBucketCredentialState{
|
||||
"sb_1234567890": {
|
||||
State: &plugin.Permissions{
|
||||
Write: &plugin.Permission{
|
||||
State: plugin.StateType_STATE_TYPE_ERROR,
|
||||
ErrorDetails: "invalid credentials",
|
||||
CheckedAt: testTime,
|
||||
},
|
||||
Read: &plugin.Permission{
|
||||
State: plugin.StateType_STATE_TYPE_ERROR,
|
||||
ErrorDetails: "invalid credentials",
|
||||
CheckedAt: testTime,
|
||||
},
|
||||
Delete: &plugin.Permission{
|
||||
State: plugin.StateType_STATE_TYPE_ERROR,
|
||||
ErrorDetails: "invalid credentials",
|
||||
CheckedAt: testTime,
|
||||
},
|
||||
},
|
||||
Version: 1,
|
||||
},
|
||||
},
|
||||
expectedOutput: map[string]*pb.RemoteStorageState{
|
||||
"sb_1234567890": {
|
||||
Status: "error",
|
||||
Permissions: &pb.RemoteStoragePermissions{
|
||||
Write: "error",
|
||||
Read: "error",
|
||||
Delete: "error",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tc := range tests {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
require, assert := require.New(t), assert.New(t)
|
||||
actualOutput, err := remoteStorageStatesToMapProto(tc.input)
|
||||
if tc.expectedErrMsg != "" {
|
||||
require.Error(err)
|
||||
assert.ErrorContains(err, tc.expectedErrMsg)
|
||||
assert.Nil(actualOutput)
|
||||
return
|
||||
}
|
||||
require.NoError(err)
|
||||
require.Len(actualOutput, len(tc.expectedOutput))
|
||||
for storageBucketId, expectedState := range tc.expectedOutput {
|
||||
actualState, ok := actualOutput[storageBucketId]
|
||||
require.True(ok)
|
||||
assert.Equal(expectedState.GetStatus(), actualState.GetStatus())
|
||||
assert.Equal(expectedState.GetPermissions().GetWrite(), actualState.GetPermissions().GetWrite())
|
||||
assert.Equal(expectedState.GetPermissions().GetRead(), actualState.GetPermissions().GetRead())
|
||||
assert.Equal(expectedState.GetPermissions().GetDelete(), actualState.GetPermissions().GetDelete())
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user