Skip to content

Commit c9929b8

Browse files
MartinForRealcvvz
authored andcommitted
Refactor: Extract kubeclient from cloud provider
Signed-off-by: Fan Shang Xiang <[email protected]>
1 parent 62e7115 commit c9929b8

File tree

9 files changed

+196
-184
lines changed

9 files changed

+196
-184
lines changed

pkg/blob/azure.go

Lines changed: 5 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ limitations under the License.
1717
package blob
1818

1919
import (
20-
"errors"
2120
"fmt"
2221
"os"
2322
"strings"
@@ -27,9 +26,7 @@ import (
2726
"github.com/Azure/azure-sdk-for-go/storage"
2827
"github.com/Azure/go-autorest/autorest"
2928
"golang.org/x/net/context"
30-
clientset "k8s.io/client-go/kubernetes"
31-
"k8s.io/client-go/rest"
32-
"k8s.io/client-go/tools/clientcmd"
29+
"k8s.io/client-go/kubernetes"
3330
"k8s.io/klog/v2"
3431
"k8s.io/utils/pointer"
3532
"sigs.k8s.io/cloud-provider-azure/pkg/azclient/configloader"
@@ -45,36 +42,20 @@ var (
4542

4643
// IsAzureStackCloud decides whether the driver is running on Azure Stack Cloud.
4744
func IsAzureStackCloud(cloud *azure.Cloud) bool {
48-
return !cloud.Config.DisableAzureStackCloud && strings.EqualFold(cloud.Config.Cloud, "AZURESTACKCLOUD")
45+
return !cloud.DisableAzureStackCloud && strings.EqualFold(cloud.Cloud, "AZURESTACKCLOUD")
4946
}
5047

5148
// getCloudProvider get Azure Cloud Provider
52-
func GetCloudProvider(ctx context.Context, kubeconfig, nodeID, secretName, secretNamespace, userAgent string, allowEmptyCloudConfig bool, kubeAPIQPS float64, kubeAPIBurst int) (*azure.Cloud, error) {
49+
func GetCloudProvider(ctx context.Context, kubeClient kubernetes.Interface, nodeID, secretName, secretNamespace, userAgent string, allowEmptyCloudConfig bool) (*azure.Cloud, error) {
5350
var (
5451
config *azure.Config
55-
kubeClient *clientset.Clientset
5652
fromSecret bool
53+
err error
5754
)
5855

5956
az := &azure.Cloud{}
6057
az.Environment.StorageEndpointSuffix = storage.DefaultBaseURL
6158

62-
kubeCfg, err := getKubeConfig(kubeconfig)
63-
if err == nil && kubeCfg != nil {
64-
// set QPS and QPS Burst as higher values
65-
klog.V(2).Infof("set QPS(%f) and QPS Burst(%d) for driver kubeClient", float32(kubeAPIQPS), kubeAPIBurst)
66-
kubeCfg.QPS = float32(kubeAPIQPS)
67-
kubeCfg.Burst = kubeAPIBurst
68-
if kubeClient, err = clientset.NewForConfig(kubeCfg); err != nil {
69-
klog.Warningf("NewForConfig failed with error: %v", err)
70-
}
71-
} else {
72-
klog.Warningf("get kubeconfig(%s) failed with error: %v", kubeconfig, err)
73-
if !os.IsNotExist(err) && !errors.Is(err, rest.ErrNotInCluster) {
74-
return az, fmt.Errorf("failed to get KubeClient: %w", err)
75-
}
76-
}
77-
7859
if kubeClient != nil {
7960
az.KubeClient = kubeClient
8061
klog.V(2).Infof("reading cloud config from secret %s/%s", secretNamespace, secretName)
@@ -180,7 +161,7 @@ func (d *Driver) initializeKvClient() (*kv.BaseClient, error) {
180161
func (d *Driver) getKeyvaultToken() (authorizer autorest.Authorizer, err error) {
181162
env := d.cloud.Environment
182163
kvEndPoint := strings.TrimSuffix(env.KeyVaultEndpoint, "/")
183-
servicePrincipalToken, err := providerconfig.GetServicePrincipalToken(&d.cloud.Config.AzureAuthConfig, &env, kvEndPoint)
164+
servicePrincipalToken, err := providerconfig.GetServicePrincipalToken(&d.cloud.AzureAuthConfig, &env, kvEndPoint)
184165
if err != nil {
185166
return nil, err
186167
}
@@ -254,16 +235,3 @@ func (d *Driver) updateSubnetServiceEndpoints(ctx context.Context, vnetResourceG
254235

255236
return nil
256237
}
257-
258-
func getKubeConfig(kubeconfig string) (config *rest.Config, err error) {
259-
if kubeconfig != "" {
260-
if config, err = clientcmd.BuildConfigFromFlags("", kubeconfig); err != nil {
261-
return nil, err
262-
}
263-
} else {
264-
if config, err = rest.InClusterConfig(); err != nil {
265-
return nil, err
266-
}
267-
}
268-
return config, err
269-
}

pkg/blob/azure_test.go

Lines changed: 10 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ import (
3131
"github.com/Azure/go-autorest/autorest/azure"
3232
"github.com/stretchr/testify/assert"
3333

34+
"sigs.k8s.io/blob-csi-driver/pkg/util"
3435
"sigs.k8s.io/cloud-provider-azure/pkg/azureclients/subnetclient/mocksubnetclient"
3536
azureprovider "sigs.k8s.io/cloud-provider-azure/pkg/provider"
3637

@@ -114,7 +115,7 @@ users:
114115
kubeconfig: emptyKubeConfig,
115116
nodeID: "",
116117
allowEmptyCloudConfig: true,
117-
expectedErr: fmt.Errorf("failed to get KubeClient: invalid configuration: no configuration has been provided, try setting KUBERNETES_MASTER environment variable"),
118+
expectedErr: fmt.Errorf("invalid configuration: no configuration has been provided, try setting KUBERNETES_MASTER environment variable"),
118119
},
119120
{
120121
desc: "[failure] out of cluster & in cluster, specify a fake kubeconfig, no credential file",
@@ -168,7 +169,14 @@ users:
168169
}
169170
os.Setenv(DefaultAzureCredentialFileEnv, fakeCredFile)
170171
}
171-
cloud, err := GetCloudProvider(context.Background(), test.kubeconfig, test.nodeID, "", "", test.userAgent, test.allowEmptyCloudConfig, 25.0, 50)
172+
kubeClient, err := util.GetKubeClient(test.kubeconfig, 25.0, 50, "")
173+
if err != nil {
174+
if !reflect.DeepEqual(err, test.expectedErr) && test.expectedErr != nil && !strings.Contains(err.Error(), test.expectedErr.Error()) {
175+
t.Errorf("desc: %s,\n input: %q, GetCloudProvider err: %v, expectedErr: %v", test.desc, test.kubeconfig, err, test.expectedErr)
176+
}
177+
continue
178+
}
179+
cloud, err := GetCloudProvider(context.Background(), kubeClient, test.nodeID, "", "", test.userAgent, test.allowEmptyCloudConfig)
172180
if !reflect.DeepEqual(err, test.expectedErr) && test.expectedErr != nil && !strings.Contains(err.Error(), test.expectedErr.Error()) {
173181
t.Errorf("desc: %s,\n input: %q, GetCloudProvider err: %v, expectedErr: %v", test.desc, test.kubeconfig, err, test.expectedErr)
174182
}
@@ -374,86 +382,3 @@ func TestUpdateSubnetServiceEndpoints(t *testing.T) {
374382
t.Run(tc.name, tc.testFunc)
375383
}
376384
}
377-
378-
func TestGetKubeConfig(t *testing.T) {
379-
emptyKubeConfig := "empty-Kube-Config"
380-
validKubeConfig := "valid-Kube-Config"
381-
fakeContent := `
382-
apiVersion: v1
383-
clusters:
384-
- cluster:
385-
server: https://localhost:8080
386-
name: foo-cluster
387-
contexts:
388-
- context:
389-
cluster: foo-cluster
390-
user: foo-user
391-
namespace: bar
392-
name: foo-context
393-
current-context: foo-context
394-
kind: Config
395-
users:
396-
- name: foo-user
397-
user:
398-
exec:
399-
apiVersion: client.authentication.k8s.io/v1beta1
400-
args:
401-
- arg-1
402-
- arg-2
403-
command: foo-command
404-
`
405-
err := createTestFile(emptyKubeConfig)
406-
if err != nil {
407-
t.Error(err)
408-
}
409-
defer func() {
410-
if err := os.Remove(emptyKubeConfig); err != nil {
411-
t.Error(err)
412-
}
413-
}()
414-
415-
err = createTestFile(validKubeConfig)
416-
if err != nil {
417-
t.Error(err)
418-
}
419-
defer func() {
420-
if err := os.Remove(validKubeConfig); err != nil {
421-
t.Error(err)
422-
}
423-
}()
424-
425-
if err := os.WriteFile(validKubeConfig, []byte(fakeContent), 0666); err != nil {
426-
t.Error(err)
427-
}
428-
429-
tests := []struct {
430-
desc string
431-
kubeconfig string
432-
expectError bool
433-
envVariableHasConfig bool
434-
envVariableConfigIsValid bool
435-
}{
436-
{
437-
desc: "[success] valid kube config passed",
438-
kubeconfig: validKubeConfig,
439-
expectError: false,
440-
envVariableHasConfig: false,
441-
envVariableConfigIsValid: false,
442-
},
443-
{
444-
desc: "[failure] invalid kube config passed",
445-
kubeconfig: emptyKubeConfig,
446-
expectError: true,
447-
envVariableHasConfig: false,
448-
envVariableConfigIsValid: false,
449-
},
450-
}
451-
452-
for _, test := range tests {
453-
_, err := getKubeConfig(test.kubeconfig)
454-
receiveError := (err != nil)
455-
if test.expectError != receiveError {
456-
t.Errorf("desc: %s,\n input: %q, GetCloudProvider err: %v, expectErr: %v", test.desc, test.kubeconfig, err, test.expectError)
457-
}
458-
}
459-
}

pkg/blob/blob.go

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ limitations under the License.
1717
package blob
1818

1919
import (
20+
"context"
21+
"flag"
2022
"fmt"
2123
"os"
2224
"strconv"
@@ -29,8 +31,6 @@ import (
2931
az "github.com/Azure/go-autorest/autorest/azure"
3032
"github.com/container-storage-interface/spec/lib/go/csi"
3133
"github.com/pborman/uuid"
32-
"golang.org/x/net/context"
33-
3434
v1 "k8s.io/api/core/v1"
3535
"k8s.io/apimachinery/pkg/api/errors"
3636
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -43,6 +43,7 @@ import (
4343
csicommon "sigs.k8s.io/blob-csi-driver/pkg/csi-common"
4444
"sigs.k8s.io/blob-csi-driver/pkg/util"
4545
azcache "sigs.k8s.io/cloud-provider-azure/pkg/cache"
46+
"sigs.k8s.io/cloud-provider-azure/pkg/provider"
4647
azure "sigs.k8s.io/cloud-provider-azure/pkg/provider"
4748
)
4849

@@ -167,11 +168,29 @@ type DriverOptions struct {
167168
SasTokenExpirationMinutes int
168169
}
169170

171+
func (option *DriverOptions) AddFlags() {
172+
flag.StringVar(&option.BlobfuseProxyEndpoint, "blobfuse-proxy-endpoint", "unix://tmp/blobfuse-proxy.sock", "blobfuse-proxy endpoint")
173+
flag.StringVar(&option.NodeID, "nodeid", "", "node id")
174+
flag.StringVar(&option.DriverName, "drivername", DefaultDriverName, "name of the driver")
175+
flag.BoolVar(&option.EnableBlobfuseProxy, "enable-blobfuse-proxy", false, "using blobfuse proxy for mounts")
176+
flag.IntVar(&option.BlobfuseProxyConnTimout, "blobfuse-proxy-connect-timeout", 5, "blobfuse proxy connection timeout(seconds)")
177+
flag.BoolVar(&option.EnableBlobMockMount, "enable-blob-mock-mount", false, "enable mock mount(only for testing)")
178+
flag.BoolVar(&option.EnableGetVolumeStats, "enable-get-volume-stats", false, "allow GET_VOLUME_STATS on agent node")
179+
flag.BoolVar(&option.AppendTimeStampInCacheDir, "append-timestamp-cache-dir", false, "append timestamp into cache directory on agent node")
180+
flag.Uint64Var(&option.MountPermissions, "mount-permissions", 0777, "mounted folder permissions")
181+
flag.BoolVar(&option.AllowInlineVolumeKeyAccessWithIdentity, "allow-inline-volume-key-access-with-idenitity", false, "allow accessing storage account key using cluster identity for inline volume")
182+
flag.BoolVar(&option.AppendMountErrorHelpLink, "append-mount-error-help-link", true, "Whether to include a link for help with mount errors when a mount error occurs.")
183+
flag.BoolVar(&option.EnableAznfsMount, "enable-aznfs-mount", false, "replace nfs mount with aznfs mount")
184+
flag.IntVar(&option.VolStatsCacheExpireInMinutes, "vol-stats-cache-expire-in-minutes", 10, "The cache expire time in minutes for volume stats cache")
185+
flag.IntVar(&option.SasTokenExpirationMinutes, "sas-token-expiration-minutes", 1440, "sas token expiration minutes during volume cloning")
186+
}
187+
170188
// Driver implements all interfaces of CSI drivers
171189
type Driver struct {
172190
csicommon.CSIDriver
173191

174192
cloud *azure.Cloud
193+
KubeClient kubernetes.Interface
175194
blobfuseProxyEndpoint string
176195
// enableBlobMockMount is only for testing, DO NOT set as true in non-testing scenario
177196
enableBlobMockMount bool
@@ -208,7 +227,8 @@ type Driver struct {
208227

209228
// NewDriver Creates a NewCSIDriver object. Assumes vendor version is equal to driver version &
210229
// does not support optional driver plugin info manifest field. Refer to CSI spec for more details.
211-
func NewDriver(options *DriverOptions, cloud *azure.Cloud) *Driver {
230+
func NewDriver(options *DriverOptions, kubeClient kubernetes.Interface, cloud *provider.Cloud) *Driver {
231+
var err error
212232
d := Driver{
213233
volLockMap: util.NewLockMap(),
214234
subnetLockMap: util.NewLockMap(),
@@ -224,12 +244,13 @@ func NewDriver(options *DriverOptions, cloud *azure.Cloud) *Driver {
224244
enableAznfsMount: options.EnableAznfsMount,
225245
sasTokenExpirationMinutes: options.SasTokenExpirationMinutes,
226246
azcopy: &util.Azcopy{},
247+
KubeClient: kubeClient,
248+
cloud: cloud,
227249
}
228250
d.Name = options.DriverName
229251
d.Version = driverVersion
230252
d.NodeID = options.NodeID
231253

232-
var err error
233254
getter := func(key string) (interface{}, error) { return nil, nil }
234255
if d.accountSearchCache, err = azcache.NewTimedCache(time.Minute, getter, false); err != nil {
235256
klog.Fatalf("%v", err)
@@ -247,7 +268,6 @@ func NewDriver(options *DriverOptions, cloud *azure.Cloud) *Driver {
247268
if d.volStatsCache, err = azcache.NewTimedCache(time.Duration(options.VolStatsCacheExpireInMinutes)*time.Minute, getter, false); err != nil {
248269
klog.Fatalf("%v", err)
249270
}
250-
d.cloud = cloud
251271
d.mounter = &mount.SafeFormatAndMount{
252272
Interface: mount.New(""),
253273
Exec: utilexec.New(),

pkg/blob/blob_test.go

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ package blob
1919
import (
2020
"context"
2121
"errors"
22+
"flag"
2223
"fmt"
2324
"os"
2425
"reflect"
@@ -29,12 +30,10 @@ import (
2930
"github.com/Azure/azure-sdk-for-go/services/storage/mgmt/2021-09-01/storage"
3031
"github.com/golang/mock/gomock"
3132
"github.com/stretchr/testify/assert"
32-
3333
v1api "k8s.io/api/core/v1"
3434
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
3535
"k8s.io/client-go/kubernetes"
3636
"k8s.io/client-go/kubernetes/fake"
37-
3837
"sigs.k8s.io/blob-csi-driver/pkg/util"
3938
"sigs.k8s.io/cloud-provider-azure/pkg/azureclients/storageaccountclient/mockstorageaccountclient"
4039
azure "sigs.k8s.io/cloud-provider-azure/pkg/provider"
@@ -56,7 +55,7 @@ func NewFakeDriver() *Driver {
5655
BlobfuseProxyConnTimout: 5,
5756
EnableBlobMockMount: false,
5857
}
59-
driver := NewDriver(&driverOptions, &azure.Cloud{})
58+
driver := NewDriver(&driverOptions, nil, &azure.Cloud{})
6059
driver.Name = fakeDriverName
6160
driver.Version = vendorVersion
6261
driver.subnetLockMap = util.NewLockMap()
@@ -72,7 +71,7 @@ func TestNewFakeDriver(t *testing.T) {
7271
BlobfuseProxyConnTimout: 5,
7372
EnableBlobMockMount: false,
7473
}
75-
d := NewDriver(&driverOptions, &azure.Cloud{})
74+
d := NewDriver(&driverOptions, nil, &azure.Cloud{})
7675
assert.NotNil(t, d)
7776
}
7877

@@ -85,7 +84,7 @@ func TestNewDriver(t *testing.T) {
8584
BlobfuseProxyConnTimout: 5,
8685
EnableBlobMockMount: false,
8786
}
88-
driver := NewDriver(&driverOptions, &azure.Cloud{})
87+
driver := NewDriver(&driverOptions, nil, &azure.Cloud{})
8988
fakedriver := NewFakeDriver()
9089
fakedriver.Name = DefaultDriverName
9190
fakedriver.Version = driverVersion
@@ -1231,7 +1230,7 @@ func TestGetSubnetResourceID(t *testing.T) {
12311230
d.cloud.VnetResourceGroup = "foo"
12321231
actualOutput := d.getSubnetResourceID("", "", "")
12331232
expectedOutput := fmt.Sprintf(subnetTemplate, d.cloud.SubscriptionID, "foo", d.cloud.VnetName, d.cloud.SubnetName)
1234-
assert.Equal(t, actualOutput, expectedOutput, "cloud.SubscriptionID should be used as the SubID")
1233+
assert.Equal(t, actualOutput, expectedOutput, "config.SubscriptionID should be used as the SubID")
12351234
},
12361235
},
12371236
{
@@ -1259,7 +1258,7 @@ func TestGetSubnetResourceID(t *testing.T) {
12591258
d.cloud.VnetResourceGroup = ""
12601259
actualOutput := d.getSubnetResourceID("", "", "")
12611260
expectedOutput := fmt.Sprintf(subnetTemplate, "bar", d.cloud.ResourceGroup, d.cloud.VnetName, d.cloud.SubnetName)
1262-
assert.Equal(t, actualOutput, expectedOutput, "cloud.Resourcegroup should be used as the rg")
1261+
assert.Equal(t, actualOutput, expectedOutput, "config.ResourceGroup should be used as the rg")
12631262
},
12641263
},
12651264
{
@@ -1273,7 +1272,7 @@ func TestGetSubnetResourceID(t *testing.T) {
12731272
d.cloud.VnetResourceGroup = "fakeVnetResourceGroup"
12741273
actualOutput := d.getSubnetResourceID("", "", "")
12751274
expectedOutput := fmt.Sprintf(subnetTemplate, "bar", d.cloud.VnetResourceGroup, d.cloud.VnetName, d.cloud.SubnetName)
1276-
assert.Equal(t, actualOutput, expectedOutput, "cloud.VnetResourceGroup should be used as the rg")
1275+
assert.Equal(t, actualOutput, expectedOutput, "config.VnetResourceGroup should be used as the rg")
12771276
},
12781277
},
12791278
{
@@ -1749,3 +1748,21 @@ func TestIsNFSProtocol(t *testing.T) {
17491748
}
17501749
}
17511750
}
1751+
1752+
func TestDriverOptions_AddFlags(t *testing.T) {
1753+
t.Run("test options", func(t *testing.T) {
1754+
option := DriverOptions{}
1755+
option.AddFlags()
1756+
typeInfo := reflect.TypeOf(option)
1757+
numOfExpectedOptions := typeInfo.NumField()
1758+
count := 0
1759+
flag.CommandLine.VisitAll(func(f *flag.Flag) {
1760+
if !strings.Contains(f.Name, "test") {
1761+
count++
1762+
}
1763+
})
1764+
if numOfExpectedOptions != count {
1765+
t.Errorf("expected %d flags, but found %d flag in DriverOptions", numOfExpectedOptions, count)
1766+
}
1767+
})
1768+
}

0 commit comments

Comments
 (0)