mirror of
https://github.com/outbackdingo/proxmox-cloud-controller-manager.git
synced 2026-01-27 10:20:13 +00:00
feat: enable support for capmox
This makes ccm compatible with cluster api and cluster api provider proxmox (capmox) Signed-off-by: Matthias Teich <matthias.teich@gdata.de>
This commit is contained in:
@@ -16,7 +16,7 @@ maintainers:
|
||||
# This is the chart version. This version number should be incremented each time you make changes
|
||||
# to the chart and its templates, including the app version.
|
||||
# Versions are expected to follow Semantic Versioning (https://semver.org/)
|
||||
version: 0.2.9
|
||||
version: 0.2.10
|
||||
# This is the version number of the application being deployed. This version number should be
|
||||
# incremented each time you make changes to the application. Versions are not expected to
|
||||
# follow Semantic Versioning. They should reflect the version the application is using.
|
||||
|
||||
@@ -40,6 +40,9 @@ existingConfigSecretKey: config.yaml
|
||||
|
||||
# -- Proxmox cluster config.
|
||||
config:
|
||||
features:
|
||||
# specify provider: proxmox if you are using capmox (cluster api provider for proxmox)
|
||||
provider: 'default'
|
||||
clusters: []
|
||||
# - url: https://cluster-api-1.exmple.com:8006/api2/json
|
||||
# insecure: false
|
||||
|
||||
@@ -26,8 +26,20 @@ import (
|
||||
yaml "gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
// Provider specifies the provider. Can be 'default' or 'capmox'
|
||||
type Provider string
|
||||
|
||||
// ProviderDefault is the default provider
|
||||
const ProviderDefault Provider = "default"
|
||||
|
||||
// ProviderCapmox is the Provider for capmox
|
||||
const ProviderCapmox Provider = "capmox"
|
||||
|
||||
// ClustersConfig is proxmox multi-cluster cloud config.
|
||||
type ClustersConfig struct {
|
||||
Features struct {
|
||||
Provider Provider `yaml:"provider,omitempty"`
|
||||
} `yaml:"features,omitempty"`
|
||||
Clusters []struct {
|
||||
URL string `yaml:"url"`
|
||||
Insecure bool `yaml:"insecure,omitempty"`
|
||||
@@ -67,6 +79,10 @@ func ReadCloudConfig(config io.Reader) (ClustersConfig, error) {
|
||||
}
|
||||
}
|
||||
|
||||
if cfg.Features.Provider == "" {
|
||||
cfg.Features.Provider = ProviderDefault
|
||||
}
|
||||
|
||||
return cfg, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -69,7 +69,7 @@ clusters:
|
||||
assert.NotNil(t, cfg)
|
||||
assert.Equal(t, 1, len(cfg.Clusters))
|
||||
|
||||
// Valid config with one cluster (username/password)
|
||||
// Valid config with one cluster (username/password), implicit default provider
|
||||
cfg, err = cluster.ReadCloudConfig(strings.NewReader(`
|
||||
clusters:
|
||||
- url: https://example.com
|
||||
@@ -81,6 +81,39 @@ clusters:
|
||||
assert.Nil(t, err)
|
||||
assert.NotNil(t, cfg)
|
||||
assert.Equal(t, 1, len(cfg.Clusters))
|
||||
assert.Equal(t, cluster.ProviderDefault, cfg.Features.Provider)
|
||||
|
||||
// Valid config with one cluster (username/password), explicit provider default
|
||||
cfg, err = cluster.ReadCloudConfig(strings.NewReader(`
|
||||
features:
|
||||
provider: 'default'
|
||||
clusters:
|
||||
- url: https://example.com
|
||||
insecure: false
|
||||
username: "user@pam"
|
||||
password: "secret"
|
||||
region: cluster-1
|
||||
`))
|
||||
assert.Nil(t, err)
|
||||
assert.NotNil(t, cfg)
|
||||
assert.Equal(t, 1, len(cfg.Clusters))
|
||||
assert.Equal(t, cluster.ProviderDefault, cfg.Features.Provider)
|
||||
|
||||
// Valid config with one cluster (username/password), explicit provider capmox
|
||||
cfg, err = cluster.ReadCloudConfig(strings.NewReader(`
|
||||
features:
|
||||
provider: 'capmox'
|
||||
clusters:
|
||||
- url: https://example.com
|
||||
insecure: false
|
||||
username: "user@pam"
|
||||
password: "secret"
|
||||
region: cluster-1
|
||||
`))
|
||||
assert.Nil(t, err)
|
||||
assert.NotNil(t, cfg)
|
||||
assert.Equal(t, 1, len(cfg.Clusters))
|
||||
assert.Equal(t, cluster.ProviderCapmox, cfg.Features.Provider)
|
||||
}
|
||||
|
||||
func TestReadCloudConfigFromFile(t *testing.T) {
|
||||
|
||||
@@ -38,6 +38,11 @@ func GetProviderID(region string, vmr *pxapi.VmRef) string {
|
||||
return fmt.Sprintf("%s://%s/%d", ProviderName, region, vmr.VmId())
|
||||
}
|
||||
|
||||
// GetProviderIDFromUUID returns the magic providerID for kubernetes node.
|
||||
func GetProviderIDFromUUID(uuid string) string {
|
||||
return fmt.Sprintf("%s://%s", ProviderName, uuid)
|
||||
}
|
||||
|
||||
// GetVMID returns the VM ID from the providerID.
|
||||
func GetVMID(providerID string) (int, error) {
|
||||
if !strings.HasPrefix(providerID, ProviderName) {
|
||||
|
||||
@@ -65,7 +65,7 @@ func newCloud(config *cluster.ClustersConfig) (cloudprovider.Interface, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
instancesInterface := newInstances(client)
|
||||
instancesInterface := newInstances(client, config.Features.Provider)
|
||||
|
||||
return &cloud{
|
||||
client: client,
|
||||
|
||||
@@ -34,12 +34,14 @@ import (
|
||||
)
|
||||
|
||||
type instances struct {
|
||||
c *cluster.Cluster
|
||||
c *cluster.Cluster
|
||||
provider cluster.Provider
|
||||
}
|
||||
|
||||
func newInstances(client *cluster.Cluster) *instances {
|
||||
func newInstances(client *cluster.Cluster, provider cluster.Provider) *instances {
|
||||
return &instances{
|
||||
c: client,
|
||||
c: client,
|
||||
provider: provider,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -149,6 +151,12 @@ func (i *instances) InstanceMetadata(_ context.Context, node *v1.Node) (*cloudpr
|
||||
return nil, fmt.Errorf("instances.InstanceMetadata() - failed to find instance by name/uuid %s: %v, skipped", node.Name, err)
|
||||
}
|
||||
}
|
||||
|
||||
if i.provider == cluster.ProviderCapmox {
|
||||
providerID = provider.GetProviderIDFromUUID(uuid)
|
||||
} else {
|
||||
providerID = provider.GetProviderID(region, vmRef)
|
||||
}
|
||||
} else if !strings.HasPrefix(node.Spec.ProviderID, provider.ProviderName) {
|
||||
klog.V(4).InfoS("instances.InstanceMetadata() omitting unmanaged node", "node", klog.KObj(node), "providerID", node.Spec.ProviderID)
|
||||
|
||||
@@ -178,7 +186,7 @@ func (i *instances) InstanceMetadata(_ context.Context, node *v1.Node) (*cloudpr
|
||||
}
|
||||
|
||||
return &cloudprovider.InstanceMetadata{
|
||||
ProviderID: provider.GetProviderID(region, vmRef),
|
||||
ProviderID: providerID,
|
||||
NodeAddresses: addresses,
|
||||
InstanceType: instanceType,
|
||||
Zone: vmRef.Node(),
|
||||
@@ -192,6 +200,17 @@ func (i *instances) InstanceMetadata(_ context.Context, node *v1.Node) (*cloudpr
|
||||
}
|
||||
|
||||
func (i *instances) getInstance(node *v1.Node) (*pxapi.VmRef, string, error) {
|
||||
if i.provider == cluster.ProviderCapmox {
|
||||
uuid := node.Status.NodeInfo.SystemUUID
|
||||
|
||||
vmRef, region, err := i.c.FindVMByUUID(uuid)
|
||||
if err != nil {
|
||||
return nil, "", fmt.Errorf("instances.getInstance() error: %v", err)
|
||||
}
|
||||
|
||||
return vmRef, region, nil
|
||||
}
|
||||
|
||||
vm, region, err := provider.ParseProviderID(node.Spec.ProviderID)
|
||||
if err != nil {
|
||||
return nil, "", fmt.Errorf("instances.getInstance() error: %v", err)
|
||||
|
||||
@@ -28,8 +28,8 @@ import (
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/suite"
|
||||
|
||||
"github.com/sergelogvinov/proxmox-cloud-controller-manager/pkg/cluster"
|
||||
provider "github.com/sergelogvinov/proxmox-cloud-controller-manager/pkg/provider"
|
||||
proxmoxcluster "github.com/sergelogvinov/proxmox-cloud-controller-manager/pkg/cluster"
|
||||
"github.com/sergelogvinov/proxmox-cloud-controller-manager/pkg/provider"
|
||||
|
||||
v1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
@@ -44,7 +44,7 @@ type ccmTestSuite struct {
|
||||
}
|
||||
|
||||
func (ts *ccmTestSuite) SetupTest() {
|
||||
cfg, err := cluster.ReadCloudConfig(strings.NewReader(`
|
||||
cfg, err := proxmoxcluster.ReadCloudConfig(strings.NewReader(`
|
||||
clusters:
|
||||
- url: https://127.0.0.1:8006/api2/json
|
||||
insecure: false
|
||||
@@ -123,12 +123,12 @@ clusters:
|
||||
},
|
||||
)
|
||||
|
||||
cluster, err := cluster.NewCluster(&cfg, &http.Client{})
|
||||
cluster, err := proxmoxcluster.NewCluster(&cfg, &http.Client{})
|
||||
if err != nil {
|
||||
ts.T().Fatalf("failed to create cluster client: %v", err)
|
||||
}
|
||||
|
||||
ts.i = newInstances(cluster)
|
||||
ts.i = newInstances(cluster, proxmoxcluster.ProviderDefault)
|
||||
}
|
||||
|
||||
func (ts *ccmTestSuite) TearDownTest() {
|
||||
|
||||
Reference in New Issue
Block a user