Skip to content

Commit

Permalink
egoscale v3 refactor
Browse files Browse the repository at this point in the history
Signed-off-by: Pierre-Emmanuel Jacquier <[email protected]>
  • Loading branch information
pierre-emmanuelJ committed Nov 8, 2024
1 parent b4fcd32 commit 6c204cc
Show file tree
Hide file tree
Showing 320 changed files with 76,633 additions and 125 deletions.
58 changes: 31 additions & 27 deletions exoscale/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,24 +8,24 @@ import (
"path/filepath"
"sync"

egoscale "github.com/exoscale/egoscale/v2"
v3 "github.com/exoscale/egoscale/v3"
"github.com/exoscale/egoscale/v3/credentials"

"gopkg.in/fsnotify.v1"
)

const defaultComputeEnvironment = "api"

type exoscaleClient interface {
CreateNetworkLoadBalancer(context.Context, string, *egoscale.NetworkLoadBalancer) (*egoscale.NetworkLoadBalancer, error)
CreateNetworkLoadBalancerService(context.Context, string, *egoscale.NetworkLoadBalancer, *egoscale.NetworkLoadBalancerService) (*egoscale.NetworkLoadBalancerService, error)
DeleteNetworkLoadBalancer(context.Context, string, *egoscale.NetworkLoadBalancer) error
DeleteNetworkLoadBalancerService(context.Context, string, *egoscale.NetworkLoadBalancer, *egoscale.NetworkLoadBalancerService) error
GetInstance(context.Context, string, string) (*egoscale.Instance, error)
GetInstanceType(context.Context, string, string) (*egoscale.InstanceType, error)
GetNetworkLoadBalancer(context.Context, string, string) (*egoscale.NetworkLoadBalancer, error)
ListInstances(context.Context, string, ...egoscale.ListInstancesOpt) ([]*egoscale.Instance, error)
UpdateNetworkLoadBalancer(context.Context, string, *egoscale.NetworkLoadBalancer) error
UpdateNetworkLoadBalancerService(context.Context, string, *egoscale.NetworkLoadBalancer, *egoscale.NetworkLoadBalancerService) error
CreateLoadBalancer(ctx context.Context, req v3.CreateLoadBalancerRequest) (*v3.Operation, error)
AddServiceToLoadBalancer(ctx context.Context, id v3.UUID, req v3.AddServiceToLoadBalancerRequest) (*v3.Operation, error)
DeleteLoadBalancer(ctx context.Context, id v3.UUID) (*v3.Operation, error)
DeleteLoadBalancerService(ctx context.Context, id v3.UUID, serviceID v3.UUID) (*v3.Operation, error)
GetInstance(ctx context.Context, id v3.UUID) (*v3.Instance, error)
GetInstanceType(ctx context.Context, id v3.UUID) (*v3.InstanceType, error)
GetLoadBalancer(ctx context.Context, id v3.UUID) (*v3.LoadBalancer, error)
ListInstances(ctx context.Context, opts ...v3.ListInstancesOpt) (*v3.ListInstancesResponse, error)
UpdateLoadBalancer(ctx context.Context, id v3.UUID, req v3.UpdateLoadBalancerRequest) (*v3.Operation, error)
UpdateLoadBalancerService(ctx context.Context, id v3.UUID, serviceID v3.UUID, req v3.UpdateLoadBalancerServiceRequest) (*v3.Operation, error)
Wait(ctx context.Context, op *v3.Operation, states ...v3.OperationState) (*v3.Operation, error)
}

type exoscaleAPICredentials struct {
Expand All @@ -37,39 +37,41 @@ type exoscaleAPICredentials struct {
type refreshableExoscaleClient struct {
exo exoscaleClient
apiCredentials exoscaleAPICredentials
apiEnvironment string
apiEndpoint string

*sync.RWMutex
}

func newRefreshableExoscaleClient(ctx context.Context, config *globalConfig) (*refreshableExoscaleClient, error) {
c := &refreshableExoscaleClient{
RWMutex: &sync.RWMutex{},
apiEnvironment: defaultComputeEnvironment,
RWMutex: &sync.RWMutex{},
}

if config.ApiEnvironment != "" {
c.apiEnvironment = config.ApiEnvironment
if config.APIEndpoint != "" {
c.apiEndpoint = config.APIEndpoint
}

if config.ApiKey != "" && config.ApiSecret != "" { //nolint:gocritic
if config.APIKey != "" && config.APISecret != "" { //nolint:gocritic
infof("using Exoscale actual API credentials (key + secret)")

c.apiCredentials = exoscaleAPICredentials{
APIKey: config.ApiKey,
APISecret: config.ApiSecret,
APIKey: config.APIKey,
APISecret: config.APISecret,
}

exo, err := egoscale.NewClient(c.apiCredentials.APIKey, c.apiCredentials.APISecret)
//TODO add chain credentials with env...etc
creds := credentials.NewStaticCredentials(c.apiCredentials.APIKey, c.apiCredentials.APISecret)

exo, err := v3.NewClient(creds)
if err != nil {
return nil, err
}
c.exo = exo
} else if config.ApiCredentialsFile != "" {
infof("reading (watching) Exoscale API credentials from file %q", config.ApiCredentialsFile)
} else if config.APICredentialsFile != "" {
infof("reading (watching) Exoscale API credentials from file %q", config.APICredentialsFile)

c.refreshCredentialsFromFile(config.ApiCredentialsFile)
go c.watchCredentialsFile(ctx, config.ApiCredentialsFile)
c.refreshCredentialsFromFile(config.APICredentialsFile)
go c.watchCredentialsFile(ctx, config.APICredentialsFile)
} else {
return nil, errors.New("incomplete or missing Exoscale API credentials")
}
Expand Down Expand Up @@ -131,7 +133,9 @@ func (c *refreshableExoscaleClient) refreshCredentialsFromFile(path string) {
return
}

client, err := egoscale.NewClient(apiCredentials.APIKey, apiCredentials.APISecret)
//TODO add chain credentials with env...etc
creds := credentials.NewStaticCredentials(c.apiCredentials.APIKey, c.apiCredentials.APISecret)
client, err := v3.NewClient(creds)
if err != nil {
infof("failed to initialize Exoscale client: %v", err)
return
Expand Down
1 change: 0 additions & 1 deletion exoscale/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ func (ts *exoscaleCCMTestSuite) Test_newRefreshableExoscaleClient_credentials()
APIKey: testAPIKey,
APISecret: testAPISecret,
},
apiEnvironment: defaultComputeEnvironment,
}

actual, err := newRefreshableExoscaleClient(context.Background(), &testConfig_typical.Global)
Expand Down
10 changes: 5 additions & 5 deletions exoscale/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,26 +7,26 @@ import (
"net/http"
"strings"

egoscale "github.com/exoscale/egoscale/v2"
v3 "github.com/exoscale/egoscale/v3"
)

const metadataEndpoint = "http://metadata.exoscale.com/1.0/meta-data/"

func (p *cloudProvider) computeInstanceByProviderID(ctx context.Context, providerID string) (*egoscale.Instance, error) {
func (p *cloudProvider) computeInstanceByProviderID(ctx context.Context, providerID string) (*v3.Instance, error) {
id, err := formatProviderID(providerID)
if err != nil {
return nil, err
}

return p.client.GetInstance(ctx, p.zone, id)
return p.client.GetInstance(ctx, id)
}

func formatProviderID(providerID string) (string, error) {
func formatProviderID(providerID string) (v3.UUID, error) {
if providerID == "" {
return "", errors.New("provider ID cannot be empty")
}

return strings.TrimPrefix(providerID, providerPrefix), nil
return v3.UUID(strings.TrimPrefix(providerID, providerPrefix)), nil
}

func queryInstanceMetadata(key string) (string, error) {
Expand Down
23 changes: 9 additions & 14 deletions exoscale/exoscale_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@ type cloudConfig struct {

type globalConfig struct {
Zone string
ApiKey string `yaml:"apiKey"`
ApiSecret string `yaml:"apiSecret"`
ApiCredentialsFile string `yaml:"apiCredentialsFile"`
ApiEnvironment string `yaml:"apiEnvironment"`
APIKey string `yaml:"apiKey"`
APISecret string `yaml:"apiSecret"`
APICredentialsFile string `yaml:"apiCredentialsFile"`
APIEndpoint string `yaml:"apiEndpoint"`
}

func readExoscaleConfig(config io.Reader) (cloudConfig, error) {
Expand All @@ -37,21 +37,16 @@ func readExoscaleConfig(config io.Reader) (cloudConfig, error) {
cfg.Global.Zone = value
}
if value, exists := os.LookupEnv("EXOSCALE_API_KEY"); exists {
cfg.Global.ApiKey = value
cfg.Global.APIKey = value
}
if value, exists := os.LookupEnv("EXOSCALE_API_SECRET"); exists {
cfg.Global.ApiSecret = value
cfg.Global.APISecret = value
}
if value, exists := os.LookupEnv("EXOSCALE_API_CREDENTIALS_FILE"); exists {
cfg.Global.ApiCredentialsFile = value
cfg.Global.APICredentialsFile = value
}
if value, exists := os.LookupEnv("EXOSCALE_API_ENVIRONMENT"); exists {
cfg.Global.ApiEnvironment = value
}

// Defaults
if cfg.Global.ApiEnvironment == "" {
cfg.Global.ApiEnvironment = defaultComputeEnvironment
if value, exists := os.LookupEnv("EXOSCALE_API_ENPOINT"); exists {
cfg.Global.APIEndpoint = value
}

return cfg, nil
Expand Down
39 changes: 19 additions & 20 deletions exoscale/exoscale_config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ var (
testConfig_typical = cloudConfig{
Global: globalConfig{
Zone: testZone,
ApiKey: testAPIKey,
ApiSecret: testAPISecret,
APIKey: testAPIKey,
APISecret: testAPISecret,
},
Instances: instancesConfig{
Overrides: []instancesOverrideConfig{{
Expand Down Expand Up @@ -67,10 +67,9 @@ func (ts *exoscaleCCMTestSuite) Test_readExoscaleConfig_empty() {
cfg, err := readExoscaleConfig(strings.NewReader(testConfigYAML_empty))
ts.Require().NoError(err)
ts.Require().Equal("", cfg.Global.Zone)
ts.Require().Equal("", cfg.Global.ApiKey)
ts.Require().Equal("", cfg.Global.ApiSecret)
ts.Require().Equal("", cfg.Global.ApiCredentialsFile)
ts.Require().Equal(defaultComputeEnvironment, cfg.Global.ApiEnvironment)
ts.Require().Equal("", cfg.Global.APIKey)
ts.Require().Equal("", cfg.Global.APISecret)
ts.Require().Equal("", cfg.Global.APICredentialsFile)
ts.Require().Equal(false, cfg.Instances.Disabled)
ts.Require().Equal(false, cfg.LoadBalancer.Disabled)
}
Expand All @@ -83,9 +82,9 @@ func (ts *exoscaleCCMTestSuite) Test_readExoscaleConfig_env_credsFile() {

cfg, err := readExoscaleConfig(strings.NewReader(testConfigYAML_empty))
ts.Require().NoError(err)
ts.Require().Equal("", cfg.Global.ApiKey)
ts.Require().Equal("", cfg.Global.ApiSecret)
ts.Require().Equal(testAPICredentialsFile, cfg.Global.ApiCredentialsFile)
ts.Require().Equal("", cfg.Global.APIKey)
ts.Require().Equal("", cfg.Global.APISecret)
ts.Require().Equal(testAPICredentialsFile, cfg.Global.APICredentialsFile)
}

func (ts *exoscaleCCMTestSuite) Test_readExoscaleConfig_env_typical() {
Expand All @@ -103,10 +102,10 @@ func (ts *exoscaleCCMTestSuite) Test_readExoscaleConfig_env_typical() {
cfg, err := readExoscaleConfig(strings.NewReader(testConfigYAML_empty))
ts.Require().NoError(err)
ts.Require().Equal(testZone, cfg.Global.Zone)
ts.Require().Equal(testAPIKey, cfg.Global.ApiKey)
ts.Require().Equal(testAPISecret, cfg.Global.ApiSecret)
ts.Require().Equal("", cfg.Global.ApiCredentialsFile)
ts.Require().Equal(testAPIEnvironment, cfg.Global.ApiEnvironment)
ts.Require().Equal(testAPIKey, cfg.Global.APIKey)
ts.Require().Equal(testAPISecret, cfg.Global.APISecret)
ts.Require().Equal("", cfg.Global.APICredentialsFile)
ts.Require().Equal(testAPIEnvironment, cfg.Global.APIEndpoint)
}

func (ts *exoscaleCCMTestSuite) Test_readExoscaleConfig_disabled() {
Expand All @@ -121,9 +120,9 @@ func (ts *exoscaleCCMTestSuite) Test_readExoscaleConfig_credsFile() {

cfg, err := readExoscaleConfig(strings.NewReader(testConfigYAML_credsFile))
ts.Require().NoError(err)
ts.Require().Equal("", cfg.Global.ApiKey)
ts.Require().Equal("", cfg.Global.ApiSecret)
ts.Require().Equal(testAPICredentialsFile, cfg.Global.ApiCredentialsFile)
ts.Require().Equal("", cfg.Global.APIKey)
ts.Require().Equal("", cfg.Global.APISecret)
ts.Require().Equal(testAPICredentialsFile, cfg.Global.APICredentialsFile)
}

func (ts *exoscaleCCMTestSuite) Test_readExoscaleConfig_typical() {
Expand All @@ -135,10 +134,10 @@ func (ts *exoscaleCCMTestSuite) Test_readExoscaleConfig_typical() {
cfg, err := readExoscaleConfig(strings.NewReader(testConfigYAML_typical))
ts.Require().NoError(err)
ts.Require().Equal(testZone, cfg.Global.Zone)
ts.Require().Equal(testAPIKey, cfg.Global.ApiKey)
ts.Require().Equal(testAPISecret, cfg.Global.ApiSecret)
ts.Require().Equal("", cfg.Global.ApiCredentialsFile)
ts.Require().Equal(testAPIEnvironment, cfg.Global.ApiEnvironment)
ts.Require().Equal(testAPIKey, cfg.Global.APIKey)
ts.Require().Equal(testAPISecret, cfg.Global.APISecret)
ts.Require().Equal("", cfg.Global.APICredentialsFile)
ts.Require().Equal(testAPIEnvironment, cfg.Global.APIEndpoint)
ts.Require().Equal(false, cfg.Instances.Disabled)
ts.Require().Equal(false, cfg.LoadBalancer.Disabled)
}
Loading

0 comments on commit 6c204cc

Please sign in to comment.