Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: enable support for capmox #302

Merged
merged 1 commit into from
Jan 16, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
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 charts/proxmox-csi-plugin/Chart.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ maintainers:
url: https://github.com/sergelogvinov
#
# Versions are expected to follow Semantic Versioning (https://semver.org/)
version: 0.3.1
version: 0.3.2
# 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.
Expand Down
3 changes: 3 additions & 0 deletions charts/proxmox-csi-plugin/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,9 @@ configFile: /etc/proxmox/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
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ require (
github.com/golang/protobuf v1.5.4
github.com/jarcoal/httpmock v1.3.1
github.com/kubernetes-csi/csi-lib-utils v0.20.0
github.com/sergelogvinov/proxmox-cloud-controller-manager v0.5.1
github.com/sergelogvinov/proxmox-cloud-controller-manager v0.7.0
github.com/siderolabs/go-blockdevice v0.4.8
github.com/siderolabs/go-retry v0.3.3
github.com/sirupsen/logrus v1.9.3
Expand Down
9 changes: 6 additions & 3 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -102,8 +102,11 @@ github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoG
github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/sergelogvinov/proxmox-cloud-controller-manager v0.5.1 h1:RM4D/VCreZr22pTuJHd97Rz8DrDUYMAxlv6/xf65EoA=
github.com/sergelogvinov/proxmox-cloud-controller-manager v0.5.1/go.mod h1:m9Ip+Wu/kDNwsemzlQlqOMUrCmvsxA1zbI32dQHgPCw=
github.com/sergelogvinov/proxmox-cloud-controller-manager v0.6.1-0.20250107152926-956a30a46389 h1:Ui8MUcSqpPgJm9E6gnxtyA6Pf7KkDNmkwfHe0gynlyk=
github.com/sergelogvinov/proxmox-cloud-controller-manager v0.6.1-0.20250107152926-956a30a46389/go.mod h1:LePNcAZ6SA+yh5WttDmxFgs1CUJLu07tOajAzyuiKhI=
github.com/sergelogvinov/proxmox-cloud-controller-manager v0.7.0 h1:RUxT3QVyVR2nMiSwopTP0rlbqWHbYy53AyMnE1qz0so=
github.com/sergelogvinov/proxmox-cloud-controller-manager v0.7.0/go.mod h1:LePNcAZ6SA+yh5WttDmxFgs1CUJLu07tOajAzyuiKhI=
github.com/siderolabs/go-blockdevice v0.4.8 h1:KfdWvIx0Jft5YVuCsFIJFwjWEF1oqtzkgX9PeU9cX4c=
github.com/siderolabs/go-blockdevice v0.4.8/go.mod h1:4PeOuk71pReJj1JQEXDE7kIIQJPVe8a+HZQa+qjxSEA=
github.com/siderolabs/go-cmd v0.1.3 h1:JrgZwqhJQeoec3QRON0LK+fv+0y7d0DyY7zsfkO6ciw=
Expand Down Expand Up @@ -142,8 +145,8 @@ go.opentelemetry.io/otel/trace v1.33.0/go.mod h1:uIcdVUZMpTAmz0tI1z04GoVSezK37Cb
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/exp v0.0.0-20240909161429-701f63a606c0 h1:e66Fs6Z+fZTbFBAxKfP3PALWBtpfqks2bwGcexMxgtk=
golang.org/x/exp v0.0.0-20240909161429-701f63a606c0/go.mod h1:2TbTHSBQa924w8M6Xs1QcRcFwyucIwBGpK1p2f1YFFY=
golang.org/x/exp v0.0.0-20241217172543-b2144cdd0a67 h1:1UoZQm6f0P/ZO0w1Ri+f+ifG/gXhegadRdwBIXEFWDo=
golang.org/x/exp v0.0.0-20241217172543-b2144cdd0a67/go.mod h1:qj5a5QZpwLU2NLQudwIN5koi3beDhSAlJwa67PuM98c=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
Expand Down
17 changes: 10 additions & 7 deletions pkg/csi/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,9 @@ var controllerCaps = []csi.ControllerServiceCapability_RPC_Type{

// ControllerService is the controller service for the CSI driver
type ControllerService struct {
Cluster *proxmox.Cluster
Kclient clientkubernetes.Interface

Cluster *proxmox.Cluster
Kclient clientkubernetes.Interface
Provider proxmox.Provider
volumeLocks sync.Mutex

csi.UnimplementedControllerServer
Expand All @@ -78,8 +78,9 @@ func NewControllerService(kclient *clientkubernetes.Clientset, cloudConfig strin
}

return &ControllerService{
Cluster: cluster,
Kclient: kclient,
Cluster: cluster,
Kclient: kclient,
Provider: cfg.Features.Provider,
}, nil
}

Expand Down Expand Up @@ -342,7 +343,8 @@ func (d *ControllerService) ControllerPublishVolume(ctx context.Context, request

var vmr *pxapi.VmRef

vmrid, zone, err := tools.ProxmoxVMID(ctx, d.Kclient, nodeID)
vmrid, zone, err := tools.ProxmoxVMID(ctx, d.Kclient, cl, nodeID, d.Provider)

if err != nil {
klog.InfoS("ControllerPublishVolume: failed to get proxmox vmrID from ProviderID", "cluster", vol.Cluster(), "nodeID", nodeID)

Expand Down Expand Up @@ -466,7 +468,8 @@ func (d *ControllerService) ControllerUnpublishVolume(ctx context.Context, reque

var vmr *pxapi.VmRef

vmrid, zone, err := tools.ProxmoxVMID(ctx, d.Kclient, nodeID)
vmrid, zone, err := tools.ProxmoxVMID(ctx, d.Kclient, cl, nodeID, d.Provider)

if err != nil {
klog.InfoS("ControllerUnpublishVolume: failed to get proxmox vmrID from ProviderID", "cluster", vol.Cluster(), "nodeID", nodeID)

Expand Down
127 changes: 99 additions & 28 deletions pkg/csi/controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,14 +41,25 @@ import (

var _ proto.ControllerServer = (*csi.ControllerService)(nil)

type csiTestSuite struct {
type baseCSITestSuite struct {
suite.Suite

s *csi.ControllerService
}

func (ts *csiTestSuite) SetupTest() {
cfg, err := proxmox.ReadCloudConfig(strings.NewReader(`
type configTestCase struct {
name string
config string
providerID string
}

func getTestConfigs() []configTestCase {
return []configTestCase{
{
name: "CapMoxProvider",
providerID: "proxmox://11833f4c-341f-4bd3-aad7-f7abeda472e6",
config: `
features:
provider: capmox
clusters:
- url: https://127.0.0.1:8006/api2/json
insecure: false
Expand All @@ -59,12 +70,36 @@ clusters:
insecure: false
token_id: "user!token-id"
token_secret: "secret"
region: cluster-2
`))
if err != nil {
ts.T().Fatalf("failed to read config: %v", err)
region: cluster-2`,
},
{
name: "ExplicitDefaultProvider",
providerID: "proxmox://cluster-1/101",
config: `
features:
provider: capmox
clusters:
- url: https://127.0.0.1:8006/api2/json
insecure: false
token_id: "user!token-id"
token_secret: "secret"
region: cluster-1`,
},
{
name: "ImplicitDefaultProvider",
providerID: "proxmox://cluster-1/101",
config: `
clusters:
- url: https://127.0.0.1:8006/api2/json
insecure: false
token_id: "user!token-id"
token_secret: "secret"
region: cluster-1`,
},
}
}

func setupMockResponders() {
httpmock.RegisterResponder("GET", "https://127.0.0.1:8006/api2/json/cluster/resources",
func(_ *http.Request) (*http.Response, error) {
return httpmock.NewJsonResponse(200, map[string]interface{}{
Expand Down Expand Up @@ -286,10 +321,12 @@ clusters:
})
},
)
}

cluster, err := proxmox.NewCluster(&cfg, &http.Client{})
func (ts *baseCSITestSuite) setupTestSuite(config string, providerID string) error {
cfg, err := proxmox.ReadCloudConfig(strings.NewReader(config))
if err != nil {
ts.T().Fatalf("failed to create proxmox cluster client: %v", err)
return fmt.Errorf("failed to read config: %v", err)
}

nodes := &corev1.NodeList{
Expand All @@ -303,22 +340,56 @@ clusters:
Name: "cluster-1-node-2",
},
Spec: corev1.NodeSpec{
ProviderID: "proxmox://cluster-1/101",
ProviderID: providerID,
},
},
},
}

kclient := fake.NewSimpleClientset(nodes)

cluster, err := proxmox.NewCluster(&cfg, &http.Client{})
if err != nil {
return fmt.Errorf("failed to create proxmox cluster client: %v", err)
}

ts.s = &csi.ControllerService{
Cluster: cluster,
Kclient: kclient,
Cluster: cluster,
Kclient: kclient,
Provider: cfg.Features.Provider,
}

return nil
}

// TestSuiteCSI runs all test configurations
func TestSuiteCSI(t *testing.T) {
configs := getTestConfigs()
for _, cfg := range configs {
// Create a new test suite for each configuration
ts := &baseCSITestSuite{}

// Run the suite with the current configuration
suite.Run(t, &configuredTestSuite{
baseCSITestSuite: ts,
configCase: cfg,
})
}
}

func TestSuiteCCM(t *testing.T) {
suite.Run(t, new(csiTestSuite))
// configuredTestSuite wraps the base suite with a specific configuration
type configuredTestSuite struct {
*baseCSITestSuite
configCase configTestCase
}

func (ts *configuredTestSuite) SetupTest() {
setupMockResponders()

err := ts.setupTestSuite(ts.configCase.config, ts.configCase.providerID)
if err != nil {
ts.T().Fatalf("Failed to setup test suite: %v", err)
}
}

func TestNewControllerService(t *testing.T) {
Expand All @@ -333,7 +404,7 @@ func TestNewControllerService(t *testing.T) {
}

//nolint:dupl
func (ts *csiTestSuite) TestCreateVolume() {
func (ts *configuredTestSuite) TestCreateVolume() {
httpmock.Activate()
defer httpmock.DeactivateAndReset()

Expand Down Expand Up @@ -682,7 +753,7 @@ func (ts *csiTestSuite) TestCreateVolume() {
}

//nolint:dupl
func (ts *csiTestSuite) TestDeleteVolume() {
func (ts *configuredTestSuite) TestDeleteVolume() {
httpmock.Activate()
defer httpmock.DeactivateAndReset()

Expand Down Expand Up @@ -758,7 +829,7 @@ func (ts *csiTestSuite) TestDeleteVolume() {
}
}

func (ts *csiTestSuite) TestControllerServiceControllerGetCapabilities() {
func (ts *configuredTestSuite) TestControllerServiceControllerGetCapabilities() {
resp, err := ts.s.ControllerGetCapabilities(context.Background(), &proto.ControllerGetCapabilitiesRequest{})
ts.Require().NoError(err)
ts.Require().NotNil(resp)
Expand All @@ -769,7 +840,7 @@ func (ts *csiTestSuite) TestControllerServiceControllerGetCapabilities() {
}

//nolint:dupl
func (ts *csiTestSuite) TestControllerPublishVolumeError() {
func (ts *configuredTestSuite) TestControllerPublishVolumeError() {
httpmock.Activate()
defer httpmock.DeactivateAndReset()

Expand Down Expand Up @@ -903,7 +974,7 @@ func (ts *csiTestSuite) TestControllerPublishVolumeError() {
}

//nolint:dupl
func (ts *csiTestSuite) TestControllerUnpublishVolumeError() {
func (ts *configuredTestSuite) TestControllerUnpublishVolumeError() {
httpmock.Activate()
defer httpmock.DeactivateAndReset()

Expand Down Expand Up @@ -975,19 +1046,19 @@ func (ts *csiTestSuite) TestControllerUnpublishVolumeError() {
}
}

func (ts *csiTestSuite) TestValidateVolumeCapabilities() {
func (ts *configuredTestSuite) TestValidateVolumeCapabilities() {
_, err := ts.s.ValidateVolumeCapabilities(context.Background(), &proto.ValidateVolumeCapabilitiesRequest{})
ts.Require().Error(err)
ts.Require().Equal(status.Error(codes.Unimplemented, ""), err)
}

func (ts *csiTestSuite) TestListVolumes() {
func (ts *configuredTestSuite) TestListVolumes() {
_, err := ts.s.ListVolumes(context.Background(), &proto.ListVolumesRequest{})
ts.Require().Error(err)
ts.Require().Equal(status.Error(codes.Unimplemented, ""), err)
}

func (ts *csiTestSuite) TestGetCapacity() {
func (ts *configuredTestSuite) TestGetCapacity() {
httpmock.Activate()
defer httpmock.DeactivateAndReset()

Expand Down Expand Up @@ -1115,25 +1186,25 @@ func (ts *csiTestSuite) TestGetCapacity() {
}
}

func (ts *csiTestSuite) TestCreateSnapshot() {
func (ts *configuredTestSuite) TestCreateSnapshot() {
_, err := ts.s.CreateSnapshot(context.Background(), &proto.CreateSnapshotRequest{})
ts.Require().Error(err)
ts.Require().Equal(status.Error(codes.Unimplemented, ""), err)
}

func (ts *csiTestSuite) TestDeleteSnapshot() {
func (ts *configuredTestSuite) TestDeleteSnapshot() {
_, err := ts.s.DeleteSnapshot(context.Background(), &proto.DeleteSnapshotRequest{})
ts.Require().Error(err)
ts.Require().Equal(status.Error(codes.Unimplemented, ""), err)
}

func (ts *csiTestSuite) TestListSnapshots() {
func (ts *configuredTestSuite) TestListSnapshots() {
_, err := ts.s.ListSnapshots(context.Background(), &proto.ListSnapshotsRequest{})
ts.Require().Error(err)
ts.Require().Equal(status.Error(codes.Unimplemented, ""), err)
}

func (ts *csiTestSuite) TestControllerExpandVolumeError() {
func (ts *configuredTestSuite) TestControllerExpandVolumeError() {
httpmock.Activate()
defer httpmock.DeactivateAndReset()

Expand Down Expand Up @@ -1249,7 +1320,7 @@ func (ts *csiTestSuite) TestControllerExpandVolumeError() {
}
}

func (ts *csiTestSuite) TestControllerGetVolume() {
func (ts *configuredTestSuite) TestControllerGetVolume() {
_, err := ts.s.ControllerGetVolume(context.Background(), &proto.ControllerGetVolumeRequest{})
ts.Require().Error(err)
ts.Require().Equal(status.Error(codes.Unimplemented, ""), err)
Expand Down
Loading
Loading