Skip to content

Commit 9f82f7c

Browse files
yangxixing-yang
yangxi
authored andcommitted
Split controller based on snapshot beta APIs
1 parent 06794ef commit 9f82f7c

30 files changed

+8453
-22
lines changed

Dockerfile_common

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
FROM gcr.io/distroless/static:latest
2+
LABEL maintainers="Kubernetes Authors"
3+
LABEL description="CSI External Snapshotter Common"
4+
5+
COPY ./bin/csi-snapshotter-common csi-snapshotter-common
6+
ENTRYPOINT ["/csi-snapshotter-common"]

Dockerfile_sidecar

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
FROM gcr.io/distroless/static:latest
2+
LABEL maintainers="Kubernetes Authors"
3+
LABEL description="CSI External Snapshotter Sidecar"
4+
5+
COPY ./bin/csi-snapshotter-sidecar csi-snapshotter-sidecar
6+
ENTRYPOINT ["/csi-snapshotter-sidecar"]

Makefile

+2-2
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
1414

15-
.PHONY: all csi-snapshotter clean test
15+
.PHONY: all csi-snapshotter-common csi-snapshotter-sidecar clean test
1616

17-
CMDS=csi-snapshotter
17+
CMDS=csi-snapshotter-common csi-snapshotter-sidecar
1818
all: build
1919
include release-tools/build.make

Makefile_old

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# Copyright 2018 The Kubernetes Authors.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
.PHONY: all csi-snapshotter clean test
16+
17+
CMDS=csi-snapshotter
18+
all: build
19+
include release-tools/build.make

cmd/csi-snapshotter-common/main.go

+157
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
/*
2+
Copyright 2018 The Kubernetes Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package main
18+
19+
import (
20+
"context"
21+
"flag"
22+
"fmt"
23+
"os"
24+
"os/signal"
25+
"strings"
26+
"time"
27+
28+
"google.golang.org/grpc"
29+
30+
"k8s.io/client-go/kubernetes"
31+
"k8s.io/client-go/kubernetes/scheme"
32+
"k8s.io/client-go/rest"
33+
"k8s.io/client-go/tools/clientcmd"
34+
"k8s.io/klog"
35+
36+
"github.com/container-storage-interface/spec/lib/go/csi"
37+
"github.com/kubernetes-csi/csi-lib-utils/leaderelection"
38+
csirpc "github.com/kubernetes-csi/csi-lib-utils/rpc"
39+
controller "github.com/kubernetes-csi/external-snapshotter/pkg/common_controller"
40+
41+
clientset "github.com/kubernetes-csi/external-snapshotter/pkg/client/clientset/versioned"
42+
snapshotscheme "github.com/kubernetes-csi/external-snapshotter/pkg/client/clientset/versioned/scheme"
43+
informers "github.com/kubernetes-csi/external-snapshotter/pkg/client/informers/externalversions"
44+
coreinformers "k8s.io/client-go/informers"
45+
)
46+
47+
const (
48+
// Number of worker threads
49+
threads = 10
50+
)
51+
52+
// Command line flags
53+
var (
54+
kubeconfig = flag.String("kubeconfig", "", "Absolute path to the kubeconfig file. Required only when running out of cluster.")
55+
resyncPeriod = flag.Duration("resync-period", 60*time.Second, "Resync interval of the controller.")
56+
showVersion = flag.Bool("version", false, "Show version.")
57+
58+
leaderElection = flag.Bool("leader-election", false, "Enables leader election.")
59+
leaderElectionNamespace = flag.String("leader-election-namespace", "", "The namespace where the leader election resource exists. Defaults to the pod namespace if not set.")
60+
)
61+
62+
var (
63+
version = "unknown"
64+
prefix = "external-snapshotter-leader"
65+
)
66+
67+
func main() {
68+
klog.InitFlags(nil)
69+
flag.Set("logtostderr", "true")
70+
flag.Parse()
71+
72+
if *showVersion {
73+
fmt.Println(os.Args[0], version)
74+
os.Exit(0)
75+
}
76+
klog.Infof("Version: %s", version)
77+
78+
// Create the client config. Use kubeconfig if given, otherwise assume in-cluster.
79+
config, err := buildConfig(*kubeconfig)
80+
if err != nil {
81+
klog.Error(err.Error())
82+
os.Exit(1)
83+
}
84+
85+
kubeClient, err := kubernetes.NewForConfig(config)
86+
if err != nil {
87+
klog.Error(err.Error())
88+
os.Exit(1)
89+
}
90+
91+
snapClient, err := clientset.NewForConfig(config)
92+
if err != nil {
93+
klog.Errorf("Error building snapshot clientset: %s", err.Error())
94+
os.Exit(1)
95+
}
96+
97+
factory := informers.NewSharedInformerFactory(snapClient, *resyncPeriod)
98+
coreFactory := coreinformers.NewSharedInformerFactory(kubeClient, *resyncPeriod)
99+
100+
// Add Snapshot types to the defualt Kubernetes so events can be logged for them
101+
snapshotscheme.AddToScheme(scheme.Scheme)
102+
103+
klog.V(2).Infof("Start NewCSISnapshotController with kubeconfig [%s] resyncPeriod [%+v]", *kubeconfig, *resyncPeriod)
104+
105+
ctrl := controller.NewCSISnapshotCommonController(
106+
snapClient,
107+
kubeClient,
108+
factory.Snapshot().V1beta1().VolumeSnapshots(),
109+
factory.Snapshot().V1beta1().VolumeSnapshotContents(),
110+
factory.Snapshot().V1beta1().VolumeSnapshotClasses(),
111+
coreFactory.Core().V1().PersistentVolumeClaims(),
112+
*resyncPeriod,
113+
)
114+
115+
run := func(context.Context) {
116+
// run...
117+
stopCh := make(chan struct{})
118+
factory.Start(stopCh)
119+
coreFactory.Start(stopCh)
120+
go ctrl.Run(threads, stopCh)
121+
122+
// ...until SIGINT
123+
c := make(chan os.Signal, 1)
124+
signal.Notify(c, os.Interrupt)
125+
<-c
126+
close(stopCh)
127+
}
128+
129+
if !*leaderElection {
130+
run(context.TODO())
131+
} else {
132+
lockName := fmt.Sprintf("%s-%s", prefix, strings.Replace("common-snapshotter", "/", "-", -1))
133+
le := leaderelection.NewLeaderElection(kubeClient, lockName, run)
134+
if *leaderElectionNamespace != "" {
135+
le.WithNamespace(*leaderElectionNamespace)
136+
}
137+
if err := le.Run(); err != nil {
138+
klog.Fatalf("failed to initialize leader election: %v", err)
139+
}
140+
}
141+
}
142+
143+
func buildConfig(kubeconfig string) (*rest.Config, error) {
144+
if kubeconfig != "" {
145+
return clientcmd.BuildConfigFromFlags("", kubeconfig)
146+
}
147+
return rest.InClusterConfig()
148+
}
149+
150+
func supportsControllerCreateSnapshot(ctx context.Context, conn *grpc.ClientConn) (bool, error) {
151+
capabilities, err := csirpc.GetControllerCapabilities(ctx, conn)
152+
if err != nil {
153+
return false, err
154+
}
155+
156+
return capabilities[csi.ControllerServiceCapability_RPC_CREATE_DELETE_SNAPSHOT], nil
157+
}
+161
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
/*
2+
Copyright 2019 The Kubernetes Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package main
18+
19+
import (
20+
"context"
21+
"fmt"
22+
"testing"
23+
24+
"github.com/container-storage-interface/spec/lib/go/csi"
25+
"github.com/golang/mock/gomock"
26+
"github.com/kubernetes-csi/csi-lib-utils/connection"
27+
"github.com/kubernetes-csi/csi-test/driver"
28+
29+
"google.golang.org/grpc"
30+
)
31+
32+
func Test_supportsControllerCreateSnapshot(t *testing.T) {
33+
tests := []struct {
34+
name string
35+
output *csi.ControllerGetCapabilitiesResponse
36+
injectError bool
37+
expectError bool
38+
expectResult bool
39+
}{
40+
{
41+
name: "success",
42+
output: &csi.ControllerGetCapabilitiesResponse{
43+
Capabilities: []*csi.ControllerServiceCapability{
44+
{
45+
Type: &csi.ControllerServiceCapability_Rpc{
46+
Rpc: &csi.ControllerServiceCapability_RPC{
47+
Type: csi.ControllerServiceCapability_RPC_CREATE_DELETE_VOLUME,
48+
},
49+
},
50+
},
51+
{
52+
Type: &csi.ControllerServiceCapability_Rpc{
53+
Rpc: &csi.ControllerServiceCapability_RPC{
54+
Type: csi.ControllerServiceCapability_RPC_CREATE_DELETE_SNAPSHOT,
55+
},
56+
},
57+
},
58+
},
59+
},
60+
expectError: false,
61+
expectResult: true,
62+
},
63+
{
64+
name: "gRPC error",
65+
output: nil,
66+
injectError: true,
67+
expectError: true,
68+
expectResult: false,
69+
},
70+
{
71+
name: "no create snapshot",
72+
output: &csi.ControllerGetCapabilitiesResponse{
73+
Capabilities: []*csi.ControllerServiceCapability{
74+
{
75+
Type: &csi.ControllerServiceCapability_Rpc{
76+
Rpc: &csi.ControllerServiceCapability_RPC{
77+
Type: csi.ControllerServiceCapability_RPC_CREATE_DELETE_VOLUME,
78+
},
79+
},
80+
},
81+
},
82+
},
83+
expectError: false,
84+
expectResult: false,
85+
},
86+
{
87+
name: "empty capability",
88+
output: &csi.ControllerGetCapabilitiesResponse{
89+
Capabilities: []*csi.ControllerServiceCapability{
90+
{
91+
Type: nil,
92+
},
93+
},
94+
},
95+
expectError: false,
96+
expectResult: false,
97+
},
98+
{
99+
name: "no capabilities",
100+
output: &csi.ControllerGetCapabilitiesResponse{
101+
Capabilities: []*csi.ControllerServiceCapability{},
102+
},
103+
expectError: false,
104+
expectResult: false,
105+
},
106+
}
107+
108+
mockController, driver, _, controllerServer, csiConn, err := createMockServer(t)
109+
if err != nil {
110+
t.Fatal(err)
111+
}
112+
defer mockController.Finish()
113+
defer driver.Stop()
114+
defer csiConn.Close()
115+
116+
for _, test := range tests {
117+
118+
in := &csi.ControllerGetCapabilitiesRequest{}
119+
120+
out := test.output
121+
var injectedErr error
122+
if test.injectError {
123+
injectedErr = fmt.Errorf("mock error")
124+
}
125+
126+
// Setup expectation
127+
controllerServer.EXPECT().ControllerGetCapabilities(gomock.Any(), in).Return(out, injectedErr).Times(1)
128+
129+
ok, err := supportsControllerCreateSnapshot(context.Background(), csiConn)
130+
if test.expectError && err == nil {
131+
t.Errorf("test %q: Expected error, got none", test.name)
132+
}
133+
if !test.expectError && err != nil {
134+
t.Errorf("test %q: got error: %v", test.name, err)
135+
}
136+
if err == nil && test.expectResult != ok {
137+
t.Errorf("test fail expected result %t but got %t\n", test.expectResult, ok)
138+
}
139+
}
140+
}
141+
142+
func createMockServer(t *testing.T) (*gomock.Controller, *driver.MockCSIDriver, *driver.MockIdentityServer, *driver.MockControllerServer, *grpc.ClientConn, error) {
143+
// Start the mock server
144+
mockController := gomock.NewController(t)
145+
identityServer := driver.NewMockIdentityServer(mockController)
146+
controllerServer := driver.NewMockControllerServer(mockController)
147+
drv := driver.NewMockCSIDriver(&driver.MockCSIDriverServers{
148+
Identity: identityServer,
149+
Controller: controllerServer,
150+
})
151+
drv.Start()
152+
153+
// Create a client connection to it
154+
addr := drv.Address()
155+
csiConn, err := connection.Connect(addr)
156+
if err != nil {
157+
return nil, nil, nil, nil, nil, err
158+
}
159+
160+
return mockController, drv, identityServer, controllerServer, csiConn, nil
161+
}

0 commit comments

Comments
 (0)