Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion deploy/csi-plugin/controllerplugin.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ spec:
- name: CSI_ENDPOINT
value: unix://csi/csi.sock
- name: CLOUD_CONFIG
value: /etc/config/cloud.conf
value: /etc/config/cloud.yaml
- name: CLUSTER_NAME
value: kubernetes
- name: STACKIT_SERVICE_ACCOUNT_KEY_PATH
Expand Down
2 changes: 1 addition & 1 deletion deploy/csi-plugin/nodeplugin.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ spec:
- name: CSI_ENDPOINT
value: unix://csi/csi.sock
- name: CLOUD_CONFIG
value: /etc/config/cloud.conf
value: /etc/config/cloud.yaml
imagePullPolicy: "IfNotPresent"
ports:
- containerPort: 9808
Expand Down
4 changes: 1 addition & 3 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,11 @@ require (
github.com/stackitcloud/stackit-sdk-go/services/iaas v1.3.0
github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.6.2
go.uber.org/mock v0.6.0
go.yaml.in/yaml/v2 v2.4.3
golang.org/x/sync v0.19.0
golang.org/x/sys v0.39.0
google.golang.org/grpc v1.77.0
google.golang.org/protobuf v1.36.11
gopkg.in/gcfg.v1 v1.2.3
gopkg.in/yaml.v3 v3.0.1
k8s.io/api v0.34.3
k8s.io/apimachinery v0.34.3
Expand Down Expand Up @@ -114,7 +114,6 @@ require (
go.opentelemetry.io/proto/otlp v1.5.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
go.uber.org/zap v1.27.0 // indirect
go.yaml.in/yaml/v2 v2.4.3 // indirect
go.yaml.in/yaml/v3 v3.0.4 // indirect
golang.org/x/crypto v0.43.0 // indirect
golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b // indirect
Expand All @@ -130,7 +129,6 @@ require (
gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect
gopkg.in/warnings.v0 v0.1.2 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
k8s.io/apiserver v0.34.2 // indirect
k8s.io/component-helpers v0.34.2 // indirect
Expand Down
4 changes: 0 additions & 4 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -345,14 +345,10 @@ gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntN
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/evanphx/json-patch.v4 v4.12.0 h1:n6jtcsulIzXPJaxegRbvFNNrZDjbij7ny3gmSPG+6V4=
gopkg.in/evanphx/json-patch.v4 v4.12.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M=
gopkg.in/gcfg.v1 v1.2.3 h1:m8OOJ4ccYHnx2f4gQwpno8nAX5OGOh7RLaaz0pj3Ogs=
gopkg.in/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o=
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc=
gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc=
gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME=
gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
Expand Down
51 changes: 20 additions & 31 deletions pkg/ccm/stackit.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,20 +41,9 @@ type CloudControllerManager struct {
instances *Instances
}

// Config is used to read and store information from the cloud configuration file
type Config struct {
ProjectID string `yaml:"projectId"`
NetworkID string `yaml:"networkId"`
ExtraLabels map[string]string `yaml:"extraLabels"`
Region string `yaml:"region"`
LoadBalancerAPI struct {
URL string `yaml:"url"`
} `yaml:"loadBalancerApi"`
}

func init() {
cloudprovider.RegisterCloudProvider(ProviderName, func(config io.Reader) (cloudprovider.Interface, error) {
cfg, err := ReadConfig(config)
cfg, err := stackit.GetConfig(config)
if err != nil {
klog.Warningf("failed to read config: %v", err)
return nil, err
Expand All @@ -72,31 +61,31 @@ func init() {
})
}

func ReadConfig(configReader io.Reader) (Config, error) {
func ReadConfig(configReader io.Reader) (stackit.Config, error) {
if configReader == nil {
return Config{}, errors.New("cloud config is missing")
return stackit.Config{}, errors.New("cloud config is missing")
}
configBytes, err := io.ReadAll(configReader)
if err != nil {
return Config{}, err
return stackit.Config{}, err
}
config := Config{}
config := stackit.Config{}
err = yaml.Unmarshal(configBytes, &config)
if err != nil {
return Config{}, err
return stackit.Config{}, err
}
if config.ProjectID == "" {
return Config{}, errors.New("projectId must be set")
if config.Global.ProjectID == "" {
return stackit.Config{}, errors.New("projectId must be set")
}
if config.NetworkID == "" {
return Config{}, errors.New("networkId must be set")
if config.Global.NetworkID == "" {
return stackit.Config{}, errors.New("networkId must be set")
}
if config.Region == "" {
return Config{}, errors.New("region must be set")
if config.Global.Region == "" {
return stackit.Config{}, errors.New("region must be set")
}

if config.LoadBalancerAPI.URL == "" {
config.LoadBalancerAPI.URL = "https://load-balancer.api.eu01.stackit.cloud"
if config.LoadBalancer.API == "" {
config.LoadBalancer.API = "https://load-balancer.api.eu01.stackit.cloud"
}

return config, nil
Expand Down Expand Up @@ -130,25 +119,25 @@ func BuildObservability() (*MetricsRemoteWrite, error) {
}

// NewCloudControllerManager creates a new instance of the stackit struct from a config struct
func NewCloudControllerManager(cfg *Config, obs *MetricsRemoteWrite) (*CloudControllerManager, error) {
func NewCloudControllerManager(cfg *stackit.Config, obs *MetricsRemoteWrite) (*CloudControllerManager, error) {
lbOpts := []sdkconfig.ConfigurationOption{
sdkconfig.WithEndpoint(cfg.LoadBalancerAPI.URL),
sdkconfig.WithEndpoint(cfg.LoadBalancer.API),
sdkconfig.WithHTTPClient(metrics.NewInstrumentedHTTPClient()),
}

// The token is only provided by the 'gardener-extension-provider-stackit' in case of emergency access.
// In those cases, the [cfg.LoadBalancerAPI.URL] will also be different (direct API URL instead of the API Gateway)
lbEmergencyAPIToken := os.Getenv(stackitLoadBalancerEmergencyAPIToken)
if lbEmergencyAPIToken != "" {
klog.Warningf("using emergency token for loadbalancer api on host: %s", cfg.LoadBalancerAPI.URL)
klog.Warningf("using emergency token for loadbalancer api on host: %s", cfg.LoadBalancer.API)
lbOpts = append(lbOpts, sdkconfig.WithToken(lbEmergencyAPIToken))
}

innerClient, err := loadbalancer.NewAPIClient(lbOpts...)
if err != nil {
return nil, err
}
client, err := stackit.NewLoadbalancerClient(innerClient, cfg.Region)
client, err := stackit.NewLoadbalancerClient(innerClient, cfg.Global.Region)
if err != nil {
return nil, err
}
Expand All @@ -161,12 +150,12 @@ func NewCloudControllerManager(cfg *Config, obs *MetricsRemoteWrite) (*CloudCont
if err != nil {
return nil, fmt.Errorf("failed to create Node client: %v", err)
}
instances, err := NewInstance(nodeClient, cfg.ProjectID, cfg.Region)
instances, err := NewInstance(nodeClient, cfg.Global.ProjectID, cfg.Global.Region)
if err != nil {
return nil, err
}

lb, err := NewLoadBalancer(client, cfg.ProjectID, cfg.NetworkID, cfg.ExtraLabels, obs)
lb, err := NewLoadBalancer(client, cfg.Global.ProjectID, cfg.Global.NetworkID, cfg.Global.ExtraLabels, obs)
if err != nil {
return nil, err
}
Expand Down
52 changes: 37 additions & 15 deletions pkg/stackit/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"context"
"errors"
"fmt"
"io"
"net/http"
"os"
"strings"
Expand All @@ -28,7 +29,7 @@ import (
oapiError "github.com/stackitcloud/stackit-sdk-go/core/oapierror"
"github.com/stackitcloud/stackit-sdk-go/services/iaas"
"github.com/stackitcloud/stackit-sdk-go/services/loadbalancer"
"gopkg.in/gcfg.v1"
"go.yaml.in/yaml/v2"
"k8s.io/apimachinery/pkg/util/wait"

"github.com/stackitcloud/cloud-provider-stackit/pkg/version"
Expand Down Expand Up @@ -123,39 +124,60 @@ func (os *iaasClient) GetBlockStorageOpts() BlockStorageOpts {
return os.bsOpts
}

type LoadBalancerOpts struct {
API string `yaml:"api"`
}

type BlockStorageOpts struct {
RescanOnResize bool `gcfg:"rescan-on-resize"`
RescanOnResize bool `yaml:"rescanOnResize"`
}

type GlobalOpts struct {
ProjectID string `gcfg:"project-id"`
IaasAPIURL string `gcfg:"iaas-api-url"`
ProjectID string `yaml:"projectId"`
IaasAPI string `yaml:"iaasApi"`
NetworkID string `yaml:"networkId"`
ExtraLabels map[string]string `yaml:"extraLabels"`
Region string `yaml:"region"`
}

type Config struct {
Global GlobalOpts
Metadata metadata.Opts
BlockStorage BlockStorageOpts
Global GlobalOpts `yaml:"global"`
Metadata metadata.Opts `yaml:"metadata"`
BlockStorage BlockStorageOpts `yaml:"blockStorage"`
LoadBalancer LoadBalancerOpts `yaml:"loadBalancer"`
}

func GetConfigFromFile(path string) (Config, error) {
func GetConfig(reader io.Reader) (Config, error) {
var cfg Config

config, err := os.Open(path)
content, err := io.ReadAll(reader)
if err != nil {
klog.ErrorS(err, "Failed to open config file", "path", path)
klog.ErrorS(err, "Failed to read config content")
return cfg, err
}
defer config.Close()

err = gcfg.FatalOnly(gcfg.ReadInto(&cfg, config))
err = yaml.Unmarshal(content, &cfg)
if err != nil {
klog.ErrorS(err, "Failed to parse config file", "path", path)
klog.ErrorS(err, "Failed to parse config as YAML")
return cfg, err
}

return cfg, nil
}

func GetConfigFromFile(path string) (Config, error) {
var cfg Config

config, err := os.Open(path)
if err != nil {
klog.ErrorS(err, "Failed to open config file", "path", path)
return cfg, err
}
defer config.Close()

return GetConfig(config)
}

// CreateSTACKITProvider creates STACKIT Instance
func CreateSTACKITProvider(client iaas.DefaultApi, cfg *Config) (IaasClient, error) {
region := os.Getenv("STACKIT_REGION")
Expand Down Expand Up @@ -183,8 +205,8 @@ func CreateIaaSClient(cfg *Config) (iaas.DefaultApi, error) {
}
klog.V(4).Infof("Using user-agent: %s", userAgent)

if cfg.Global.IaasAPIURL != "" {
opts = append(opts, sdkconfig.WithEndpoint(cfg.Global.IaasAPIURL))
if cfg.Global.IaasAPI != "" {
opts = append(opts, sdkconfig.WithEndpoint(cfg.Global.IaasAPI))
}

opts = append(opts, sdkconfig.WithUserAgent(strings.Join(userAgent, " ")))
Expand Down
Loading