Skip to content

Commit

Permalink
chore: fix tests
Browse files Browse the repository at this point in the history
  • Loading branch information
olevski committed Aug 31, 2024
1 parent f44a47a commit 9538027
Show file tree
Hide file tree
Showing 15 changed files with 299 additions and 77 deletions.
2 changes: 2 additions & 0 deletions .github/workflows/test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ jobs:
local-deploy
get-kind-kubeconfig
go test -v test/sanity_test.go
go test -v test/sanity_custom_secret_test.go
- name: Print rclone log
if: ${{ failure() }}
run: cat /tmp/rclone.log
Expand Down Expand Up @@ -68,6 +69,7 @@ jobs:
local-deploy
get-kind-kubeconfig
go test -v test/sanity_with_decrypt_test.go
go test -v test/sanity_with_decrypt_custom_secret_test.go
- name: Print rclone log
if: ${{ failure() }}
run: cat /tmp/rclone.log
12 changes: 12 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
FROM golang:1.23.0-bookworm AS build
COPY . .
RUN go build -o /csi-rclone cmd/csi-rclone-plugin/main.go
RUN apt-get update && apt-get install -y unzip && \
curl -O https://downloads.rclone.org/rclone-current-linux-amd64.zip && \
unzip rclone-current-linux-amd64.zip && \
cp rclone-*-linux-amd64/rclone /rclone

FROM debian:bookworm-slim
COPY --from=build /csi-rclone /csi-rclone
COPY --from=build /rclone /usr/bin/rclone
ENTRYPOINT ["/csi-rclone"]
32 changes: 29 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ kind: PersistentVolumeClaim
metadata:
name: csi-rclone-example
namespace: csi-rclone-example
annotations:
csi-rclone.dev/secretName: csi-rclone-example-secret
spec:
accessModes:
- ReadWriteMany
Expand All @@ -25,8 +27,8 @@ spec:
storageClassName: csi-rclone
```
The driver will look for and read a secret with the same name as the PVC in the same namespace
as the PVC above and will use the configuration from the secret as well as any credentials.
You have to provide a secret with the rclone configuration. The secret has to have a specific format explained below.
The secret can be passed to the CSI driver via the annotation `csi-rclone.dev/secretName`.

The secret requires the following fields:
- `remote`: The name of the remote that should be mounted - has to match the section name in the `configData` field
Expand All @@ -38,7 +40,7 @@ The secret requires the following fields:
apiVersion: v1
kind: Secret
metadata:
name: csi-rclone-example
name: csi-rclone-example-secret
namespace: csi-rclone-example
type: Opaque
stringData:
Expand All @@ -51,6 +53,30 @@ stringData:
```

### Skip provisioning and create PV directly

This is more complicated but doable. Here you have to specify the secret name in the CSI parameters.
Assuming that the secret that contains the configuration is called `csi-rclone-example-secret` and
is located in the namespace `csi-rclone-example-secret-namespace`, then the PV specification would look as follows.

```yaml
apiVersion: v1
kind: PersistentVolume
metadata:
name: csi-rclone-pv-example
spec:
accessModes:
- ReadWriteMany
capacity:
storage: 10Gi
csi:
driver: csi-rclone
volumeAttributes:
nodePublishSecretRef: csi-rclone-example-secret
nodePublisSecretRefNamespace: csi-rclone-example-secret-namespace
persistentVolumeReclaimPolicy: Delete
```

## Installation

You can install the CSI plugin via Helm. Please checkout the default values file at `deploy/csi-rclone/values.yaml`
Expand Down
8 changes: 5 additions & 3 deletions deploy/chartpress.yaml → chartpress.yaml
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
charts:
- name: csi-rclone
- name: deploy/csi-rclone
imagePrefix: renku/
resetTag: ""
resetVersion: 0.2.0
repo:
git: SwissDataScienceCenter/helm-charts
published: https://swissdatasciencecenter.github.io/helm-charts
paths:
- ./
images:
csi-rclone:
contextPath: ../
dockerFilePath: ../Dockerfile
contextPath: ./
dockerFilePath: Dockerfile
valuesPath:
- csiControllerRclone.rclone.image
- csiNodepluginRclone.rclone.image
5 changes: 4 additions & 1 deletion cmd/csi-rclone-plugin/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,5 +67,8 @@ func handle() {
panic(err)
}
d := rclone.NewDriver(nodeID, endpoint, kubeClient)
d.Run()
err = d.Run()
if err != nil {
panic(err)
}
}
1 change: 0 additions & 1 deletion deploy/csi-rclone/templates/csi-controller-rclone.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,6 @@ spec:
mountPath: /csi
- name: rclone
args:
- /bin/csi-rclone-plugin
- run
- --nodeid=$(NODE_ID)
- --endpoint=$(CSI_ENDPOINT)
Expand Down
1 change: 0 additions & 1 deletion deploy/csi-rclone/templates/csi-nodeplugin-rclone.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,6 @@ spec:
name: plugin-dir
- name: rclone
args:
- /bin/csi-rclone-plugin
- run
- --nodeid=$(NODE_ID)
- --endpoint=$(CSI_ENDPOINT)
Expand Down
6 changes: 2 additions & 4 deletions pkg/rclone/controllerserver.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,10 @@ func (cs *controllerServer) ValidateVolumeCapabilities(ctx context.Context, req
}

cs.mutex.Lock()
defer cs.mutex.Unlock()
if _, ok := cs.active_volumes[volId]; !ok {
cs.mutex.Unlock()
return nil, status.Errorf(codes.NotFound, "Volume %s not found", volId)
}
cs.mutex.Unlock()
return &csi.ValidateVolumeCapabilitiesResponse{
Confirmed: &csi.ValidateVolumeCapabilitiesResponse_Confirmed{
VolumeContext: req.VolumeContext,
Expand Down Expand Up @@ -75,7 +74,6 @@ func (cs *controllerServer) CreateVolume(ctx context.Context, req *csi.CreateVol
cs.mutex.Lock()
defer cs.mutex.Unlock()
if val, ok := cs.active_volumes[volumeName]; ok && val != volSizeBytes {
cs.mutex.Unlock()
return nil, status.Errorf(codes.AlreadyExists, "Volume operation already exists for volume %s", volumeName)
}
cs.active_volumes[volumeName] = volSizeBytes
Expand Down Expand Up @@ -110,8 +108,8 @@ func (cs *controllerServer) DeleteVolume(ctx context.Context, req *csi.DeleteVol
return nil, status.Error(codes.InvalidArgument, "DeteleVolume must be provided volume id")
}
cs.mutex.Lock()
defer cs.mutex.Unlock()
delete(cs.active_volumes, volId)
cs.mutex.Unlock()

return &csi.DeleteVolumeResponse{}, nil
}
Expand Down
45 changes: 39 additions & 6 deletions pkg/rclone/driver.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package rclone

import (
"net"
"os"
"sync"

Expand All @@ -21,12 +22,25 @@ type Driver struct {
cap []*csi.VolumeCapability_AccessMode
cscap []*csi.ControllerServiceCapability
RcloneOps Operations
Server csicommon.NonBlockingGRPCServer
}

var (
DriverVersion = "SwissDataScienceCenter"
)

func getFreePort() (port int, err error) {
var a *net.TCPAddr
if a, err = net.ResolveTCPAddr("tcp", "localhost:0"); err == nil {
var l *net.TCPListener
if l, err = net.ListenTCP("tcp", a); err == nil {
defer l.Close()
return l.Addr().(*net.TCPAddr).Port, nil
}
}
return
}

func NewDriver(nodeID, endpoint string, kubeClient *kubernetes.Clientset) *Driver {
driverName := os.Getenv("DRIVER_NAME")
if driverName == "" {
Expand All @@ -36,7 +50,11 @@ func NewDriver(nodeID, endpoint string, kubeClient *kubernetes.Clientset) *Drive

d := &Driver{}
d.endpoint = endpoint
d.RcloneOps = NewRclone(kubeClient)
rclonePort, err := getFreePort()
if err != nil {
panic("Cannot get a free TCP port to run rclone")
}
d.RcloneOps = NewRclone(kubeClient, rclonePort)

d.csiDriver = csicommon.NewCSIDriver(driverName, DriverVersion, nodeID)
d.csiDriver.AddVolumeCapabilityAccessModes([]csi.VolumeCapability_AccessMode_Mode{
Expand Down Expand Up @@ -72,12 +90,27 @@ func NewControllerServer(d *Driver) *controllerServer {
}
}

func (d *Driver) Run() {
func (d *Driver) Run() error {
s := csicommon.NewNonBlockingGRPCServer()
defer d.RcloneOps.Cleanup()
s.Start(d.endpoint,
s.Start(
d.endpoint,
csicommon.NewDefaultIdentityServer(d.csiDriver),
NewControllerServer(d),
NewNodeServer(d))
s.Wait()
NewNodeServer(d),
)
d.Server = s
go s.Wait()
err := d.RcloneOps.Run()
if err != nil {
return err
}
return nil
}

func (d *Driver) Stop() error {
err := d.RcloneOps.Cleanup()
if d.Server != nil {
d.Server.Stop()
}
return err
}
14 changes: 0 additions & 14 deletions pkg/rclone/nodeserver.go
Original file line number Diff line number Diff line change
Expand Up @@ -200,10 +200,6 @@ func extractFlags(volumeContext map[string]string, secret map[string]string, pvc
}
}

if e := validateFlags(flags); e != nil {
return "", "", "", flags, e
}

remote := flags["remote"]
remotePath := flags["remotePath"]

Expand Down Expand Up @@ -267,16 +263,6 @@ func updateConfigData(remote string, configData string, savedSecrets map[string]
return buf.String(), nil
}

func validateFlags(flags map[string]string) error {
if _, ok := flags["remote"]; !ok {
return status.Errorf(codes.InvalidArgument, "missing volume context value: remote")
}
if _, ok := flags["remotePath"]; !ok {
return status.Errorf(codes.InvalidArgument, "missing volume context value: remotePath")
}
return nil
}

func extractConfigData(parameters map[string]string) (string, map[string]string) {
flags := make(map[string]string)
for k, v := range parameters {
Expand Down
Loading

0 comments on commit 9538027

Please sign in to comment.