From 144b1c74e6294decfcfa460fb635ccbc4349913d Mon Sep 17 00:00:00 2001 From: "Daniel J. Holmes (jaitaiwan)" Date: Fri, 1 Aug 2025 17:32:58 +1000 Subject: [PATCH] feat: add named errors to cloud config Changes errors created by cloud config to be standardized so that any other packages relying on the cloud config can check if the error is of the same "type". Signed-off-by: Daniel J. Holmes (jaitaiwan) --- pkg/config/config.go | 23 +++++++++++++++++------ pkg/config/config_test.go | 5 +++++ 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/pkg/config/config.go b/pkg/config/config.go index 7558bc2..e9159e8 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -18,6 +18,7 @@ limitations under the License. package config import ( + "errors" "fmt" "io" "os" @@ -71,31 +72,41 @@ type ClustersConfig struct { Clusters []*proxmoxpool.ProxmoxCluster `yaml:"clusters,omitempty"` } +// Errors for Reading Cloud Config +var ( + ErrMissingPVERegion = errors.New("missing PVE region in cloud config") + ErrMissingPVEAPIURL = errors.New("missing PVE API URL in cloud config") + ErrAuthCredentialsMissing = errors.New("user or token credentials are required") + ErrInvalidAuthCredentials = errors.New("must specify one of user or token credentials, not both") + ErrInvalidCloudConfig = errors.New("invalid cloud config") + ErrInvalidNetworkMode = fmt.Errorf("invalid network mode, valid modes are %v", ValidNetworkModes) +) + // ReadCloudConfig reads cloud config from a reader. func ReadCloudConfig(config io.Reader) (ClustersConfig, error) { cfg := ClustersConfig{} if config != nil { if err := yaml.NewDecoder(config).Decode(&cfg); err != nil { - return ClustersConfig{}, err + return ClustersConfig{}, errors.Join(ErrInvalidCloudConfig, err) } } for idx, c := range cfg.Clusters { if c.Username != "" && c.Password != "" { if c.TokenID != "" || c.TokenSecret != "" { - return ClustersConfig{}, fmt.Errorf("cluster #%d: token_id and token_secret are not allowed when username and password are set", idx+1) + return ClustersConfig{}, fmt.Errorf("cluster #%d: %w", idx+1, ErrInvalidAuthCredentials) } } else if c.TokenID == "" || c.TokenSecret == "" { - return ClustersConfig{}, fmt.Errorf("cluster #%d: either username and password or token_id and token_secret are required", idx+1) + return ClustersConfig{}, fmt.Errorf("cluster #%d: %w", idx+1, ErrAuthCredentialsMissing) } if c.Region == "" { - return ClustersConfig{}, fmt.Errorf("cluster #%d: region is required", idx+1) + return ClustersConfig{}, fmt.Errorf("cluster #%d: %w", idx+1, ErrMissingPVERegion) } if c.URL == "" || !strings.HasPrefix(c.URL, "http") { - return ClustersConfig{}, fmt.Errorf("cluster #%d: url is required", idx+1) + return ClustersConfig{}, fmt.Errorf("cluster #%d: %w", idx+1, ErrMissingPVEAPIURL) } } @@ -109,7 +120,7 @@ func ReadCloudConfig(config io.Reader) (ClustersConfig, error) { // Validate network mode is valid if !slices.Contains(ValidNetworkModes, cfg.Features.Network.Mode) { - return ClustersConfig{}, fmt.Errorf("invalid network mode: %s, valid modes are %v", cfg.Features.Network.Mode, ValidNetworkModes) + return ClustersConfig{}, ErrInvalidNetworkMode } return cfg, nil diff --git a/pkg/config/config_test.go b/pkg/config/config_test.go index a60934f..ca6732d 100644 --- a/pkg/config/config_test.go +++ b/pkg/config/config_test.go @@ -44,6 +44,7 @@ clusters: `)) assert.NotNil(t, err) + assert.ErrorIs(t, err, providerconfig.ErrInvalidCloudConfig) assert.NotNil(t, cfg) // Non full config @@ -54,6 +55,7 @@ clusters: `)) assert.NotNil(t, err) + assert.ErrorIs(t, err, providerconfig.ErrAuthCredentialsMissing) assert.NotNil(t, cfg) // Valid config with one cluster @@ -142,6 +144,7 @@ clusters: password: "secret" `)) assert.NotNil(t, err) + assert.ErrorIs(t, err, providerconfig.ErrMissingPVERegion) // Errors when empty url _, err = providerconfig.ReadCloudConfig(strings.NewReader(` @@ -155,6 +158,7 @@ clusters: password: "secret" `)) assert.NotNil(t, err) + assert.ErrorIs(t, err, providerconfig.ErrMissingPVEAPIURL) // Errors when invalid url protocol _, err = providerconfig.ReadCloudConfig(strings.NewReader(` @@ -168,6 +172,7 @@ clusters: password: "secret" `)) assert.NotNil(t, err) + assert.ErrorIs(t, err, providerconfig.ErrMissingPVEAPIURL) } func TestNetworkConfig(t *testing.T) {