2022-09-05 03:06:08 -04:00
/ *
Copyright ( c ) Edgeless Systems GmbH
SPDX - License - Identifier : AGPL - 3.0 - only
* /
2022-03-22 11:03:15 -04:00
package config
import (
2022-08-02 06:24:55 -04:00
"reflect"
2022-03-22 11:03:15 -04:00
"testing"
2022-11-15 09:40:49 -05:00
"github.com/edgelesssys/constellation/v2/internal/attestation/measurements"
2022-09-21 07:47:57 -04:00
"github.com/edgelesssys/constellation/v2/internal/cloud/cloudprovider"
"github.com/edgelesssys/constellation/v2/internal/config/instancetypes"
"github.com/edgelesssys/constellation/v2/internal/constants"
"github.com/edgelesssys/constellation/v2/internal/file"
2022-09-07 05:53:44 -04:00
"github.com/go-playground/locales/en"
ut "github.com/go-playground/universal-translator"
"github.com/go-playground/validator/v10"
2022-03-22 11:03:15 -04:00
"github.com/spf13/afero"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
2022-06-30 09:24:36 -04:00
"go.uber.org/goleak"
2022-11-15 09:40:49 -05:00
"go.uber.org/multierr"
2022-03-22 11:03:15 -04:00
)
2022-06-30 09:24:36 -04:00
func TestMain ( m * testing . M ) {
2022-11-14 03:02:56 -05:00
goleak . VerifyTestMain ( m )
2022-06-30 09:24:36 -04:00
}
2022-03-22 11:03:15 -04:00
func TestDefaultConfig ( t * testing . T ) {
assert := assert . New ( t )
def := Default ( )
assert . NotNil ( def )
}
func TestFromFile ( t * testing . T ) {
testCases := map [ string ] struct {
2022-05-16 12:54:25 -04:00
config * Config
configName string
wantResult * Config
wantErr bool
2022-03-22 11:03:15 -04:00
} {
2022-05-16 12:54:25 -04:00
"default config from default file" : {
config : Default ( ) ,
configName : constants . ConfigFilename ,
wantResult : Default ( ) ,
} ,
"default config from different path" : {
config : Default ( ) ,
configName : "other-config.yaml" ,
wantResult : Default ( ) ,
2022-03-22 11:03:15 -04:00
} ,
2022-05-16 12:54:25 -04:00
"default config when path empty" : {
config : nil ,
configName : "" ,
2022-08-08 05:04:17 -04:00
wantErr : true ,
2022-03-22 11:03:15 -04:00
} ,
2022-05-16 12:54:25 -04:00
"err when path not exist" : {
config : nil ,
configName : "wrong-name.yaml" ,
wantErr : true ,
} ,
"custom config from default file" : {
config : & Config {
2022-11-22 09:53:39 -05:00
Version : Version2 ,
2022-05-16 12:54:25 -04:00
} ,
configName : constants . ConfigFilename ,
wantResult : & Config {
2022-11-22 09:53:39 -05:00
Version : Version2 ,
2022-05-16 12:54:25 -04:00
} ,
} ,
"modify default config" : {
config : func ( ) * Config {
conf := Default ( )
conf . Provider . GCP . Region = "eu-north1"
conf . Provider . GCP . Zone = "eu-north1-a"
return conf
} ( ) ,
configName : constants . ConfigFilename ,
wantResult : func ( ) * Config {
conf := Default ( )
conf . Provider . GCP . Region = "eu-north1"
conf . Provider . GCP . Zone = "eu-north1-a"
return conf
} ( ) ,
2022-03-22 11:03:15 -04:00
} ,
}
for name , tc := range testCases {
t . Run ( name , func ( t * testing . T ) {
assert := assert . New ( t )
require := require . New ( t )
fileHandler := file . NewHandler ( afero . NewMemMapFs ( ) )
2022-05-16 12:54:25 -04:00
if tc . config != nil {
require . NoError ( fileHandler . WriteYAML ( tc . configName , tc . config , file . OptNone ) )
}
2022-03-22 11:03:15 -04:00
result , err := FromFile ( fileHandler , tc . configName )
if tc . wantErr {
assert . Error ( err )
} else {
require . NoError ( err )
2022-05-16 12:54:25 -04:00
assert . Equal ( tc . wantResult , result )
2022-03-22 11:03:15 -04:00
}
} )
}
}
2022-05-18 05:39:14 -04:00
2022-11-15 09:40:49 -05:00
func TestNewWithDefaultOptions ( t * testing . T ) {
testCases := map [ string ] struct {
confToWrite * Config
envToSet map [ string ] string
wantErr bool
wantClientSecretValue string
} {
"set env works" : {
confToWrite : func ( ) * Config { // valid config with all, but clientSecretValue
c := Default ( )
c . RemoveProviderExcept ( cloudprovider . Azure )
2022-11-22 12:47:08 -05:00
c . Image = "v0.0.0"
2022-11-15 09:40:49 -05:00
c . Provider . Azure . SubscriptionID = "f4278079-288c-4766-a98c-ab9d5dba01a5"
c . Provider . Azure . TenantID = "d4ff9d63-6d6d-4042-8f6a-21e804add5aa"
c . Provider . Azure . Location = "westus"
c . Provider . Azure . ResourceGroup = "test"
c . Provider . Azure . UserAssignedIdentity = "/subscriptions/8b8bd01f-efd9-4113-9bd1-c82137c32da7/resourcegroups/constellation-identity/providers/Microsoft.ManagedIdentity/userAssignedIdentities/constellation-identity"
c . Provider . Azure . AppClientID = "3ea4bdc1-1cc1-4237-ae78-0831eff3491e"
return c
} ( ) ,
envToSet : map [ string ] string {
constants . EnvVarAzureClientSecretValue : "some-secret" ,
} ,
wantClientSecretValue : "some-secret" ,
} ,
"set env overwrites" : {
confToWrite : func ( ) * Config {
c := Default ( )
c . RemoveProviderExcept ( cloudprovider . Azure )
2022-11-22 12:47:08 -05:00
c . Image = "v0.0.0"
2022-11-15 09:40:49 -05:00
c . Provider . Azure . SubscriptionID = "f4278079-288c-4766-a98c-ab9d5dba01a5"
c . Provider . Azure . TenantID = "d4ff9d63-6d6d-4042-8f6a-21e804add5aa"
c . Provider . Azure . Location = "westus"
c . Provider . Azure . ResourceGroup = "test"
c . Provider . Azure . ClientSecretValue = "other-value" // < Note secret set in config, as well.
c . Provider . Azure . UserAssignedIdentity = "/subscriptions/8b8bd01f-efd9-4113-9bd1-c82137c32da7/resourcegroups/constellation-identity/providers/Microsoft.ManagedIdentity/userAssignedIdentities/constellation-identity"
c . Provider . Azure . AppClientID = "3ea4bdc1-1cc1-4237-ae78-0831eff3491e"
return c
} ( ) ,
envToSet : map [ string ] string {
constants . EnvVarAzureClientSecretValue : "some-secret" ,
} ,
wantClientSecretValue : "some-secret" ,
} ,
}
for name , tc := range testCases {
t . Run ( name , func ( t * testing . T ) {
assert := assert . New ( t )
require := require . New ( t )
// Setup
fileHandler := file . NewHandler ( afero . NewMemMapFs ( ) )
err := fileHandler . WriteYAML ( constants . ConfigFilename , tc . confToWrite )
require . NoError ( err )
for envKey , envValue := range tc . envToSet {
t . Setenv ( envKey , envValue )
}
// Test
c , err := New ( fileHandler , constants . ConfigFilename )
if tc . wantErr {
assert . Error ( err )
return
}
assert . NoError ( err )
assert . Equal ( c . Provider . Azure . ClientSecretValue , tc . wantClientSecretValue )
} )
}
}
2022-05-23 09:01:39 -04:00
func TestValidate ( t * testing . T ) {
2022-11-22 12:47:08 -05:00
const defaultErrCount = 17 // expect this number of error messages by default because user-specific values are not set and multiple providers are defined by default
2022-11-15 09:40:49 -05:00
const azErrCount = 8
const gcpErrCount = 5
2022-09-11 10:09:05 -04:00
2022-05-23 09:01:39 -04:00
testCases := map [ string ] struct {
cnf * Config
2022-11-15 09:40:49 -05:00
wantErr bool
wantErrCount int
2022-05-23 09:01:39 -04:00
} {
2022-11-15 09:40:49 -05:00
"default config is not valid" : {
2022-05-23 09:01:39 -04:00
cnf : Default ( ) ,
2022-11-15 09:40:49 -05:00
wantErr : true ,
wantErrCount : defaultErrCount ,
2022-05-23 09:01:39 -04:00
} ,
2022-11-15 09:40:49 -05:00
"v0 is one error" : {
2022-05-23 09:01:39 -04:00
cnf : func ( ) * Config {
cnf := Default ( )
cnf . Version = "v0"
return cnf
} ( ) ,
2022-11-15 09:40:49 -05:00
wantErr : true ,
wantErrCount : defaultErrCount + 1 ,
2022-05-23 09:01:39 -04:00
} ,
2022-11-15 09:40:49 -05:00
"v0 and negative state disk are two errors" : {
2022-05-23 09:01:39 -04:00
cnf : func ( ) * Config {
cnf := Default ( )
cnf . Version = "v0"
cnf . StateDiskSizeGB = - 1
return cnf
} ( ) ,
2022-11-15 09:40:49 -05:00
wantErr : true ,
wantErrCount : defaultErrCount + 2 ,
} ,
"default Azure config is not valid" : {
cnf : func ( ) * Config {
cnf := Default ( )
az := cnf . Provider . Azure
cnf . Provider = ProviderConfig { }
cnf . Provider . Azure = az
return cnf
} ( ) ,
wantErr : true ,
wantErrCount : azErrCount ,
} ,
"Azure config with all required fields is valid" : {
cnf : func ( ) * Config {
cnf := Default ( )
2022-11-22 12:47:08 -05:00
cnf . Image = "v0.0.0"
2022-11-15 09:40:49 -05:00
az := cnf . Provider . Azure
az . SubscriptionID = "01234567-0123-0123-0123-0123456789ab"
az . TenantID = "01234567-0123-0123-0123-0123456789ab"
az . Location = "test-location"
az . UserAssignedIdentity = "test-identity"
az . ResourceGroup = "test-resource-group"
az . AppClientID = "01234567-0123-0123-0123-0123456789ab"
az . ClientSecretValue = "test-client-secret"
cnf . Provider = ProviderConfig { }
cnf . Provider . Azure = az
return cnf
} ( ) ,
} ,
"default GCP config is not valid" : {
cnf : func ( ) * Config {
cnf := Default ( )
gcp := cnf . Provider . GCP
cnf . Provider = ProviderConfig { }
cnf . Provider . GCP = gcp
return cnf
} ( ) ,
wantErr : true ,
wantErrCount : gcpErrCount ,
} ,
"GCP config with all required fields is valid" : {
cnf : func ( ) * Config {
cnf := Default ( )
2022-11-22 12:47:08 -05:00
cnf . Image = "v0.0.0"
2022-11-15 09:40:49 -05:00
gcp := cnf . Provider . GCP
gcp . Region = "test-region"
gcp . Project = "test-project"
gcp . Zone = "test-zone"
gcp . ServiceAccountKeyPath = "test-key-path"
cnf . Provider = ProviderConfig { }
cnf . Provider . GCP = gcp
return cnf
} ( ) ,
2022-05-23 09:01:39 -04:00
} ,
}
for name , tc := range testCases {
t . Run ( name , func ( t * testing . T ) {
assert := assert . New ( t )
2022-11-15 09:40:49 -05:00
err := tc . cnf . Validate ( )
if tc . wantErr {
assert . Error ( err )
assert . Len ( multierr . Errors ( err ) , tc . wantErrCount )
return
}
assert . NoError ( err )
2022-05-23 09:01:39 -04:00
} )
}
}
func TestHasProvider ( t * testing . T ) {
assert := assert . New ( t )
assert . False ( ( & Config { } ) . HasProvider ( cloudprovider . Unknown ) )
assert . False ( ( & Config { } ) . HasProvider ( cloudprovider . Azure ) )
assert . False ( ( & Config { } ) . HasProvider ( cloudprovider . GCP ) )
assert . False ( ( & Config { } ) . HasProvider ( cloudprovider . QEMU ) )
assert . False ( Default ( ) . HasProvider ( cloudprovider . Unknown ) )
assert . True ( Default ( ) . HasProvider ( cloudprovider . Azure ) )
assert . True ( Default ( ) . HasProvider ( cloudprovider . GCP ) )
cnfWithAzure := Config { Provider : ProviderConfig { Azure : & AzureConfig { } } }
assert . False ( cnfWithAzure . HasProvider ( cloudprovider . Unknown ) )
assert . True ( cnfWithAzure . HasProvider ( cloudprovider . Azure ) )
assert . False ( cnfWithAzure . HasProvider ( cloudprovider . GCP ) )
}
2022-05-18 05:39:14 -04:00
func TestConfigRemoveProviderExcept ( t * testing . T ) {
testCases := map [ string ] struct {
removeExcept cloudprovider . Provider
2022-10-21 06:24:18 -04:00
wantAWS * AWSConfig
2022-05-18 05:39:14 -04:00
wantAzure * AzureConfig
wantGCP * GCPConfig
wantQEMU * QEMUConfig
} {
2022-10-21 06:24:18 -04:00
"except aws" : {
removeExcept : cloudprovider . AWS ,
wantAWS : Default ( ) . Provider . AWS ,
} ,
2022-05-18 05:39:14 -04:00
"except azure" : {
removeExcept : cloudprovider . Azure ,
wantAzure : Default ( ) . Provider . Azure ,
} ,
"except gcp" : {
removeExcept : cloudprovider . GCP ,
wantGCP : Default ( ) . Provider . GCP ,
} ,
"except qemu" : {
removeExcept : cloudprovider . QEMU ,
wantQEMU : Default ( ) . Provider . QEMU ,
} ,
"unknown provider" : {
removeExcept : cloudprovider . Unknown ,
2022-10-21 06:24:18 -04:00
wantAWS : Default ( ) . Provider . AWS ,
2022-05-18 05:39:14 -04:00
wantAzure : Default ( ) . Provider . Azure ,
wantGCP : Default ( ) . Provider . GCP ,
wantQEMU : Default ( ) . Provider . QEMU ,
} ,
}
for name , tc := range testCases {
t . Run ( name , func ( t * testing . T ) {
assert := assert . New ( t )
conf := Default ( )
conf . RemoveProviderExcept ( tc . removeExcept )
2022-10-21 06:24:18 -04:00
assert . Equal ( tc . wantAWS , conf . Provider . AWS )
2022-05-18 05:39:14 -04:00
assert . Equal ( tc . wantAzure , conf . Provider . Azure )
assert . Equal ( tc . wantGCP , conf . Provider . GCP )
assert . Equal ( tc . wantQEMU , conf . Provider . QEMU )
} )
}
}
2022-05-18 12:10:57 -04:00
func TestConfigGeneratedDocsFresh ( t * testing . T ) {
assert := assert . New ( t )
2022-08-02 06:24:55 -04:00
updateMsg := "remember to re-generate config docs! 🔨"
assert . Len ( ConfigDoc . Fields , reflect . ValueOf ( Config { } ) . NumField ( ) , updateMsg )
2022-08-29 10:49:44 -04:00
assert . Len ( UpgradeConfigDoc . Fields , reflect . ValueOf ( UpgradeConfig { } ) . NumField ( ) , updateMsg )
2022-08-02 06:24:55 -04:00
assert . Len ( ProviderConfigDoc . Fields , reflect . ValueOf ( ProviderConfig { } ) . NumField ( ) , updateMsg )
2022-11-22 12:47:08 -05:00
assert . Len ( AWSConfigDoc . Fields , reflect . ValueOf ( AWSConfig { } ) . NumField ( ) , updateMsg )
2022-08-02 06:24:55 -04:00
assert . Len ( AzureConfigDoc . Fields , reflect . ValueOf ( AzureConfig { } ) . NumField ( ) , updateMsg )
assert . Len ( GCPConfigDoc . Fields , reflect . ValueOf ( GCPConfig { } ) . NumField ( ) , updateMsg )
assert . Len ( QEMUConfigDoc . Fields , reflect . ValueOf ( QEMUConfig { } ) . NumField ( ) , updateMsg )
2022-05-18 12:10:57 -04:00
}
2022-08-01 03:37:05 -04:00
func TestConfig_UpdateMeasurements ( t * testing . T ) {
assert := assert . New ( t )
2022-11-15 09:40:49 -05:00
newMeasurements := measurements . M {
1 : measurements . PCRWithAllBytes ( 0x00 ) ,
2 : measurements . PCRWithAllBytes ( 0x01 ) ,
3 : measurements . PCRWithAllBytes ( 0x02 ) ,
2022-08-01 03:37:05 -04:00
}
2022-10-21 06:24:18 -04:00
{ // AWS
conf := Default ( )
conf . RemoveProviderExcept ( cloudprovider . AWS )
for k := range conf . Provider . AWS . Measurements {
delete ( conf . Provider . AWS . Measurements , k )
}
conf . UpdateMeasurements ( newMeasurements )
assert . Equal ( newMeasurements , conf . Provider . AWS . Measurements )
}
2022-08-01 03:37:05 -04:00
{ // Azure
conf := Default ( )
conf . RemoveProviderExcept ( cloudprovider . Azure )
for k := range conf . Provider . Azure . Measurements {
delete ( conf . Provider . Azure . Measurements , k )
}
conf . UpdateMeasurements ( newMeasurements )
assert . Equal ( newMeasurements , conf . Provider . Azure . Measurements )
}
{ // GCP
conf := Default ( )
conf . RemoveProviderExcept ( cloudprovider . GCP )
for k := range conf . Provider . GCP . Measurements {
delete ( conf . Provider . GCP . Measurements , k )
}
conf . UpdateMeasurements ( newMeasurements )
assert . Equal ( newMeasurements , conf . Provider . GCP . Measurements )
}
{ // QEMU
conf := Default ( )
conf . RemoveProviderExcept ( cloudprovider . QEMU )
for k := range conf . Provider . QEMU . Measurements {
delete ( conf . Provider . QEMU . Measurements , k )
}
conf . UpdateMeasurements ( newMeasurements )
assert . Equal ( newMeasurements , conf . Provider . QEMU . Measurements )
}
}
2022-08-16 09:53:54 -04:00
2022-11-22 12:47:08 -05:00
func TestConfig_IsReleaseImage ( t * testing . T ) {
2022-08-16 09:53:54 -04:00
testCases := map [ string ] struct {
conf * Config
want bool
} {
2022-11-22 12:47:08 -05:00
"release image v0.0.0" : {
2022-08-16 09:53:54 -04:00
conf : func ( ) * Config {
conf := Default ( )
2022-11-22 12:47:08 -05:00
conf . Image = "v0.0.0"
2022-08-16 09:53:54 -04:00
return conf
} ( ) ,
want : true ,
} ,
2022-11-22 12:47:08 -05:00
"branch image" : {
2022-08-16 09:53:54 -04:00
conf : func ( ) * Config {
conf := Default ( )
2022-11-22 12:47:08 -05:00
conf . Image = "feat-x-vX.Y.Z-pre.0.yyyymmddhhmmss-abcdefabcdef"
2022-08-16 09:53:54 -04:00
return conf
} ( ) ,
want : false ,
} ,
2022-11-22 12:47:08 -05:00
"debug image" : {
2022-08-16 09:53:54 -04:00
conf : func ( ) * Config {
conf := Default ( )
2022-11-22 12:47:08 -05:00
conf . Image = "debug-vX.Y.Z-pre.0.yyyymmddhhmmss-abcdefabcdef"
2022-08-16 09:53:54 -04:00
return conf
} ( ) ,
2022-11-22 12:47:08 -05:00
want : false ,
2022-08-16 09:53:54 -04:00
} ,
"empty config" : {
conf : & Config { } ,
want : false ,
} ,
}
for name , tc := range testCases {
t . Run ( name , func ( t * testing . T ) {
assert := assert . New ( t )
2022-11-22 12:47:08 -05:00
assert . Equal ( tc . want , tc . conf . IsReleaseImage ( ) )
2022-08-16 09:53:54 -04:00
} )
}
}
2022-08-31 11:35:33 -04:00
func TestValidInstanceTypeForProvider ( t * testing . T ) {
testCases := map [ string ] struct {
provider cloudprovider . Provider
instanceTypes [ ] string
nonCVMsAllowed bool
expectedResult bool
} {
"empty all" : {
provider : cloudprovider . Unknown ,
instanceTypes : [ ] string { } ,
expectedResult : false ,
} ,
2022-10-21 06:24:18 -04:00
"empty aws" : {
provider : cloudprovider . AWS ,
instanceTypes : [ ] string { } ,
expectedResult : false ,
} ,
2022-08-31 11:35:33 -04:00
"empty azure only CVMs" : {
provider : cloudprovider . Azure ,
instanceTypes : [ ] string { } ,
expectedResult : false ,
} ,
"empty azure with non-CVMs" : {
provider : cloudprovider . Azure ,
instanceTypes : [ ] string { } ,
nonCVMsAllowed : true ,
expectedResult : false ,
} ,
"empty gcp" : {
provider : cloudprovider . GCP ,
instanceTypes : [ ] string { } ,
expectedResult : false ,
} ,
"azure only CVMs" : {
provider : cloudprovider . Azure ,
instanceTypes : instancetypes . AzureCVMInstanceTypes ,
expectedResult : true ,
} ,
"azure CVMs but CVMs disabled" : {
provider : cloudprovider . Azure ,
instanceTypes : instancetypes . AzureCVMInstanceTypes ,
nonCVMsAllowed : true ,
expectedResult : false ,
} ,
"azure trusted launch VMs with CVMs enabled" : {
provider : cloudprovider . Azure ,
instanceTypes : instancetypes . AzureTrustedLaunchInstanceTypes ,
expectedResult : false ,
} ,
2022-10-21 06:24:18 -04:00
"azure trusted launch VMs with CVMs disabled" : {
2022-08-31 11:35:33 -04:00
provider : cloudprovider . Azure ,
instanceTypes : instancetypes . AzureTrustedLaunchInstanceTypes ,
nonCVMsAllowed : true ,
expectedResult : true ,
} ,
"gcp" : {
provider : cloudprovider . GCP ,
instanceTypes : instancetypes . GCPInstanceTypes ,
expectedResult : true ,
} ,
"put gcp when azure is set" : {
provider : cloudprovider . Azure ,
instanceTypes : instancetypes . GCPInstanceTypes ,
expectedResult : false ,
} ,
"put gcp when azure is set with CVMs disabled" : {
provider : cloudprovider . Azure ,
instanceTypes : instancetypes . GCPInstanceTypes ,
nonCVMsAllowed : true ,
expectedResult : false ,
} ,
"put azure when gcp is set" : {
provider : cloudprovider . GCP ,
instanceTypes : instancetypes . AzureCVMInstanceTypes ,
expectedResult : false ,
} ,
"put azure when gcp is set with CVMs disabled" : {
provider : cloudprovider . GCP ,
instanceTypes : instancetypes . AzureTrustedLaunchInstanceTypes ,
nonCVMsAllowed : true ,
expectedResult : false ,
} ,
2022-10-21 06:24:18 -04:00
// Testing every possible instance type for AWS is not feasible, so we just test a few based on known supported / unsupported families
// Also serves as a test for checkIfInstanceInValidAWSFamilys
"aws two valid instances" : {
provider : cloudprovider . AWS ,
instanceTypes : [ ] string { "c5.xlarge" , "c5a.2xlarge" , "c5a.16xlarge" , "u-12tb1.112xlarge" } ,
expectedResult : true ,
} ,
"aws one valid instance one with too little vCPUs" : {
provider : cloudprovider . AWS ,
instanceTypes : [ ] string { "c5.medium" } ,
expectedResult : false ,
} ,
"aws graviton sub-family unsupported" : {
provider : cloudprovider . AWS ,
instanceTypes : [ ] string { "m6g.xlarge" , "r6g.2xlarge" , "x2gd.xlarge" , "g5g.8xlarge" } ,
expectedResult : false ,
} ,
"aws combined two valid instances as one string" : {
provider : cloudprovider . AWS ,
instanceTypes : [ ] string { "c5.xlarge, c5a.2xlarge" } ,
expectedResult : false ,
} ,
2022-08-31 11:35:33 -04:00
}
for name , tc := range testCases {
t . Run ( name , func ( t * testing . T ) {
assert := assert . New ( t )
for _ , instanceType := range tc . instanceTypes {
assert . Equal ( tc . expectedResult , validInstanceTypeForProvider ( instanceType , tc . nonCVMsAllowed , tc . provider ) , instanceType )
}
} )
}
}
2022-09-05 10:53:37 -04:00
func TestIsDebugCluster ( t * testing . T ) {
testCases := map [ string ] struct {
config * Config
prepareConfig func ( * Config )
expectedResult bool
} {
"empty config" : {
config : & Config { } ,
expectedResult : false ,
} ,
"default config" : {
config : Default ( ) ,
expectedResult : false ,
} ,
"enabled" : {
config : Default ( ) ,
prepareConfig : func ( conf * Config ) {
* conf . DebugCluster = true
} ,
expectedResult : true ,
} ,
}
for name , tc := range testCases {
t . Run ( name , func ( t * testing . T ) {
assert := assert . New ( t )
if tc . prepareConfig != nil {
tc . prepareConfig ( tc . config )
}
assert . Equal ( tc . expectedResult , tc . config . IsDebugCluster ( ) )
} )
}
}
2022-09-07 05:53:44 -04:00
func TestValidateProvider ( t * testing . T ) {
testCases := map [ string ] struct {
provider ProviderConfig
wantErr bool
expectedErrorTag string
} {
"empty, should trigger no provider error" : {
provider : ProviderConfig { } ,
wantErr : true ,
expectedErrorTag : "no_provider" ,
} ,
"azure only, should be okay" : {
provider : ProviderConfig {
Azure : & AzureConfig { } ,
} ,
wantErr : false ,
} ,
"gcp only, should be okay" : {
provider : ProviderConfig {
GCP : & GCPConfig { } ,
} ,
wantErr : false ,
} ,
"qemu only, should be okay" : {
provider : ProviderConfig {
QEMU : & QEMUConfig { } ,
} ,
wantErr : false ,
} ,
"azure and gcp, should trigger multiple provider error" : {
provider : ProviderConfig {
Azure : & AzureConfig { } ,
GCP : & GCPConfig { } ,
} ,
wantErr : true ,
expectedErrorTag : "more_than_one_provider" ,
} ,
}
for name , tc := range testCases {
t . Run ( name , func ( t * testing . T ) {
assert := assert . New ( t )
require := require . New ( t )
v := validator . New ( )
trans := ut . New ( en . New ( ) ) . GetFallback ( )
conf := Default ( )
conf . Provider = tc . provider
v . RegisterStructValidation ( validateProvider , ProviderConfig { } )
err := v . StructPartial ( tc . provider )
// Register provider validation error types.
// Make sure the tags and expected strings below are in sync with the actual implementation.
require . NoError ( v . RegisterTranslation ( "no_provider" , trans , registerNoProviderError , translateNoProviderError ) )
require . NoError ( v . RegisterTranslation ( "more_than_one_provider" , trans , registerMoreThanOneProviderError , conf . translateMoreThanOneProviderError ) )
// Continue if no error is expected.
if ! tc . wantErr {
assert . NoError ( err )
return
}
// Validate if the error was identified correctly.
require . NotNil ( err )
assert . Error ( err )
assert . Contains ( err . Error ( ) , tc . expectedErrorTag )
// Check if error translation works correctly.
validationErr := err . ( validator . ValidationErrors )
translatedErr := validationErr . Translate ( trans )
// The translator does not seem to export a list of available translations or for a specific field.
// So we need to hardcode expected strings. Needs to be in sync with implementation.
switch tc . expectedErrorTag {
case "no_provider" :
assert . Contains ( translatedErr [ "ProviderConfig.Provider" ] , "No provider has been defined" )
case "more_than_one_provider" :
assert . Contains ( translatedErr [ "ProviderConfig.Provider" ] , "Only one provider can be defined" )
}
} )
}
}