constellation/coordinator/cloudprovider/gcp/metadata_test.go
2022-06-02 13:08:25 +02:00

435 lines
12 KiB
Go

package gcp
import (
"context"
"errors"
"testing"
"github.com/edgelesssys/constellation/coordinator/cloudprovider/cloudtypes"
"github.com/edgelesssys/constellation/coordinator/core"
"github.com/edgelesssys/constellation/coordinator/role"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestList(t *testing.T) {
err := errors.New("some err")
uid := "1234"
instancesGenerator := func() *[]cloudtypes.Instance {
return &[]cloudtypes.Instance{
{
Name: "someInstance",
ProviderID: "gce://someProject/someZone/someInstance",
PrivateIPs: []string{"192.0.2.0"},
},
}
}
testCases := map[string]struct {
client stubGCPClient
instancesGenerator func() *[]cloudtypes.Instance
instancesMutator func(*[]cloudtypes.Instance)
wantErr bool
wantInstances []cloudtypes.Instance
}{
"retrieve works": {
client: stubGCPClient{
projectID: "someProjectID",
zone: "someZone",
retrieveInstanceMetadaValues: map[string]string{
"constellation-uid": uid,
},
},
instancesGenerator: instancesGenerator,
wantInstances: []cloudtypes.Instance{
{
Name: "someInstance",
ProviderID: "gce://someProject/someZone/someInstance",
PrivateIPs: []string{"192.0.2.0"},
},
},
},
"retrieve error is detected": {
client: stubGCPClient{
projectID: "someProjectID",
zone: "someZone",
retrieveInstanceMetadaValues: map[string]string{
"constellation-uid": uid,
},
retrieveInstancesErr: err,
},
instancesGenerator: instancesGenerator,
wantErr: true,
},
"project metadata retrieval error is detected": {
client: stubGCPClient{
retrieveProjectIDErr: err,
},
instancesGenerator: instancesGenerator,
wantErr: true,
},
"zone retrieval error is detected": {
client: stubGCPClient{
retrieveZoneErr: err,
},
instancesGenerator: instancesGenerator,
wantErr: true,
},
}
for name, tc := range testCases {
t.Run(name, func(t *testing.T) {
assert := assert.New(t)
require := require.New(t)
tc.client.retrieveInstancesValues = *tc.instancesGenerator()
if tc.instancesMutator != nil {
tc.instancesMutator(&tc.client.retrieveInstancesValues)
}
metadata := New(&tc.client)
instances, err := metadata.List(context.Background())
if tc.wantErr {
assert.Error(err)
return
}
require.NoError(err)
assert.ElementsMatch(tc.wantInstances, instances)
})
}
}
func TestSelf(t *testing.T) {
err := errors.New("some err")
uid := "1234"
testCases := map[string]struct {
client stubGCPClient
wantErr bool
wantInstance cloudtypes.Instance
}{
"retrieve works": {
client: stubGCPClient{
projectID: "someProjectID",
zone: "someZone",
retrieveInstanceValue: cloudtypes.Instance{
Name: "someInstance",
ProviderID: "gce://someProject/someZone/someInstance",
PrivateIPs: []string{"192.0.2.0"},
},
},
wantInstance: cloudtypes.Instance{
Name: "someInstance",
ProviderID: "gce://someProject/someZone/someInstance",
PrivateIPs: []string{"192.0.2.0"},
},
},
"retrieve error is detected": {
client: stubGCPClient{
projectID: "someProjectID",
zone: "someZone",
retrieveInstanceMetadaValues: map[string]string{
"constellation-uid": uid,
},
retrieveInstanceErr: err,
},
wantErr: true,
},
"project id retrieval error is detected": {
client: stubGCPClient{
retrieveProjectIDErr: err,
},
wantErr: true,
},
"zone retrieval error is detected": {
client: stubGCPClient{
retrieveZoneErr: err,
},
wantErr: true,
},
"instance name retrieval error is detected": {
client: stubGCPClient{
retrieveInstanceNameErr: err,
},
wantErr: true,
},
}
for name, tc := range testCases {
t.Run(name, func(t *testing.T) {
assert := assert.New(t)
require := require.New(t)
cloud := New(&tc.client)
instance, err := cloud.Self(context.Background())
if tc.wantErr {
assert.Error(err)
return
}
require.NoError(err)
assert.Equal(tc.wantInstance, instance)
})
}
}
func TestGetInstance(t *testing.T) {
err := errors.New("some err")
testCases := map[string]struct {
providerID string
client stubGCPClient
wantErr bool
wantInstance cloudtypes.Instance
}{
"retrieve works": {
providerID: "gce://someProject/someZone/someInstance",
client: stubGCPClient{
retrieveInstanceValue: cloudtypes.Instance{
Name: "someInstance",
ProviderID: "gce://someProject/someZone/someInstance",
PrivateIPs: []string{"192.0.2.0"},
},
},
wantInstance: cloudtypes.Instance{
Name: "someInstance",
ProviderID: "gce://someProject/someZone/someInstance",
PrivateIPs: []string{"192.0.2.0"},
},
},
"retrieve error is detected": {
providerID: "gce://someProject/someZone/someInstance",
client: stubGCPClient{
retrieveInstanceErr: err,
},
wantErr: true,
},
"malformed providerID with too many fields is detected": {
providerID: "gce://someProject/someZone/someInstance/tooMany/fields",
wantErr: true,
},
"malformed providerID with too few fields is detected": {
providerID: "gce://someProject",
wantErr: true,
},
}
for name, tc := range testCases {
t.Run(name, func(t *testing.T) {
assert := assert.New(t)
require := require.New(t)
cloud := New(&tc.client)
instance, err := cloud.GetInstance(context.Background(), tc.providerID)
if tc.wantErr {
assert.Error(err)
return
}
require.NoError(err)
assert.Equal(tc.wantInstance, instance)
})
}
}
func TestSignalRole(t *testing.T) {
err := errors.New("some err")
testCases := map[string]struct {
client stubGCPClient
wantErr bool
wantRole role.Role
}{
"signaling role works": {
client: stubGCPClient{
projectID: "someProjectID",
zone: "someZone",
instanceName: "someName",
},
wantRole: role.Coordinator,
},
"project metadata retrieval error is detected": {
client: stubGCPClient{
retrieveProjectIDErr: err,
},
wantErr: true,
},
"instance zone retrieval error is detected": {
client: stubGCPClient{
retrieveZoneErr: err,
},
wantErr: true,
},
"instance name retrieval error is detected": {
client: stubGCPClient{
retrieveInstanceNameErr: err,
},
wantErr: true,
},
}
for name, tc := range testCases {
t.Run(name, func(t *testing.T) {
assert := assert.New(t)
require := require.New(t)
cloud := New(&tc.client)
err := cloud.SignalRole(context.Background(), tc.wantRole)
if tc.wantErr {
assert.Error(err)
return
}
require.NoError(err)
assert.ElementsMatch([]string{"someProjectID"}, tc.client.instanceMetadataProjects)
assert.ElementsMatch([]string{"someZone"}, tc.client.instanceMetadataZones)
assert.ElementsMatch([]string{"someName"}, tc.client.instanceMetadataInstanceNames)
assert.ElementsMatch([]string{core.RoleMetadataKey}, tc.client.instanceMetadataKeys)
assert.ElementsMatch([]string{tc.wantRole.String()}, tc.client.instanceMetadataValues)
})
}
}
func TestSetVPNIP(t *testing.T) {
err := errors.New("some err")
testCases := map[string]struct {
client stubGCPClient
wantErr bool
wantVPNIP string
}{
"signaling role works": {
client: stubGCPClient{
projectID: "someProjectID",
zone: "someZone",
instanceName: "someName",
},
wantVPNIP: "192.0.2.0",
},
"project metadata retrieval error is detected": {
client: stubGCPClient{
retrieveProjectIDErr: err,
},
wantErr: true,
},
"instance zone retrieval error is detected": {
client: stubGCPClient{
retrieveZoneErr: err,
},
wantErr: true,
},
"instance name retrieval error is detected": {
client: stubGCPClient{
retrieveInstanceNameErr: err,
},
wantErr: true,
},
}
for name, tc := range testCases {
t.Run(name, func(t *testing.T) {
assert := assert.New(t)
require := require.New(t)
cloud := New(&tc.client)
err := cloud.SetVPNIP(context.Background(), tc.wantVPNIP)
if tc.wantErr {
assert.Error(err)
return
}
require.NoError(err)
assert.ElementsMatch([]string{"someProjectID"}, tc.client.instanceMetadataProjects)
assert.ElementsMatch([]string{"someZone"}, tc.client.instanceMetadataZones)
assert.ElementsMatch([]string{"someName"}, tc.client.instanceMetadataInstanceNames)
assert.ElementsMatch([]string{core.VPNIPMetadataKey}, tc.client.instanceMetadataKeys)
assert.ElementsMatch([]string{tc.wantVPNIP}, tc.client.instanceMetadataValues)
})
}
}
func TestTrivialMetadataFunctions(t *testing.T) {
assert := assert.New(t)
metadata := Metadata{}
assert.True(metadata.Supported())
}
type stubGCPClient struct {
retrieveInstanceValue cloudtypes.Instance
retrieveInstanceErr error
retrieveInstancesValues []cloudtypes.Instance
retrieveInstancesErr error
retrieveInstanceMetadaValues map[string]string
retrieveInstanceMetadataErr error
retrieveSubentworkAliasErr error
projectID string
zone string
instanceName string
retrieveProjectIDErr error
retrieveZoneErr error
retrieveInstanceNameErr error
setInstanceMetadataErr error
unsetInstanceMetadataErr error
instanceMetadataProjects []string
instanceMetadataZones []string
instanceMetadataInstanceNames []string
instanceMetadataKeys []string
instanceMetadataValues []string
unsetMetadataProjects []string
unsetMetadataZones []string
unsetMetadataInstanceNames []string
unsetMetadataKeys []string
}
func (s *stubGCPClient) RetrieveInstances(ctx context.Context, project, zone string) ([]cloudtypes.Instance, error) {
return s.retrieveInstancesValues, s.retrieveInstancesErr
}
func (s *stubGCPClient) RetrieveInstance(ctx context.Context, project, zone string, instanceName string) (cloudtypes.Instance, error) {
return s.retrieveInstanceValue, s.retrieveInstanceErr
}
func (s *stubGCPClient) RetrieveInstanceMetadata(attr string) (string, error) {
return s.retrieveInstanceMetadaValues[attr], s.retrieveInstanceMetadataErr
}
func (s *stubGCPClient) RetrieveProjectID() (string, error) {
return s.projectID, s.retrieveProjectIDErr
}
func (s *stubGCPClient) RetrieveZone() (string, error) {
return s.zone, s.retrieveZoneErr
}
func (s *stubGCPClient) RetrieveInstanceName() (string, error) {
return s.instanceName, s.retrieveInstanceNameErr
}
func (s *stubGCPClient) SetInstanceMetadata(ctx context.Context, project, zone, instanceName, key, value string) error {
s.instanceMetadataProjects = append(s.instanceMetadataProjects, project)
s.instanceMetadataZones = append(s.instanceMetadataZones, zone)
s.instanceMetadataInstanceNames = append(s.instanceMetadataInstanceNames, instanceName)
s.instanceMetadataKeys = append(s.instanceMetadataKeys, key)
s.instanceMetadataValues = append(s.instanceMetadataValues, value)
return s.setInstanceMetadataErr
}
func (s *stubGCPClient) UnsetInstanceMetadata(ctx context.Context, project, zone, instanceName, key string) error {
s.unsetMetadataProjects = append(s.unsetMetadataProjects, project)
s.unsetMetadataZones = append(s.unsetMetadataZones, zone)
s.unsetMetadataInstanceNames = append(s.unsetMetadataInstanceNames, instanceName)
s.unsetMetadataKeys = append(s.unsetMetadataKeys, key)
return s.unsetInstanceMetadataErr
}
func (s *stubGCPClient) RetrieveSubnetworkAliasCIDR(ctx context.Context, project, zone, instanceName string) (string, error) {
return "", s.retrieveSubentworkAliasErr
}