From 56306c9cd7632019d71763a94d3cc39e022b8ca0 Mon Sep 17 00:00:00 2001 From: Eddie Torres Date: Tue, 5 Dec 2023 22:10:26 +0000 Subject: [PATCH] Enable CSI sanity/conformance tests Signed-off-by: Eddie Torres --- Makefile | 3 +- go.mod | 2 +- go.sum | 31 ++- pkg/driver/controller.go | 17 +- pkg/driver/driver.go | 29 +++ pkg/driver/sanity_test.go | 415 ------------------------------------ tests/sanity/sanity_test.go | 300 ++++++++++++++++++++++++++ 7 files changed, 373 insertions(+), 424 deletions(-) delete mode 100644 pkg/driver/sanity_test.go create mode 100644 tests/sanity/sanity_test.go diff --git a/Makefile b/Makefile index 409d668ae6..8a267304c2 100644 --- a/Makefile +++ b/Makefile @@ -150,8 +150,7 @@ test: .PHONY: test-sanity test-sanity: - #go test -v ./tests/sanity/... - echo "succeed" + go test -v ./tests/sanity/... .PHONY: test-e2e-single-az test-e2e-single-az: diff --git a/go.mod b/go.mod index 0218351e1e..efef796c04 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,6 @@ require ( github.com/golang/mock v1.6.0 github.com/google/go-cmp v0.6.0 github.com/kubernetes-csi/csi-proxy/client v1.1.3 - github.com/kubernetes-csi/csi-test v2.2.0+incompatible github.com/kubernetes-csi/external-snapshotter/client/v4 v4.2.0 github.com/onsi/ginkgo/v2 v2.13.0 github.com/onsi/gomega v1.28.0 @@ -71,6 +70,7 @@ require ( github.com/jmespath/go-jmespath v0.4.0 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect + github.com/kubernetes-csi/csi-test/v4 v4.4.0 github.com/mailru/easyjson v0.7.7 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect github.com/moby/spdystream v0.2.0 // indirect diff --git a/go.sum b/go.sum index 8c25074030..eace3bdfc6 100644 --- a/go.sum +++ b/go.sum @@ -13,6 +13,7 @@ github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5 github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= github.com/NYTimes/gziphandler v1.1.1 h1:ZUDjpQae29j0ryrS0u/B8HZfJBtBQHjqw2rQ2cqUQ3I= github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMomdKFjzJNB0c= +github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/antlr/antlr4/runtime/Go/antlr/v4 v4.0.0-20230305170008-8188dc5388df h1:7RFfzj4SSt6nnvCPbCqijJi1nWCd+TqAT3bYCStRC18= github.com/antlr/antlr4/runtime/Go/antlr/v4 v4.0.0-20230305170008-8188dc5388df/go.mod h1:pSwJ0fSY5KhvocuWSx4fz3BA8OrA1bQn+K1Eli3BRwM= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= @@ -33,15 +34,22 @@ github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2y github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM= github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= +github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4 h1:/inchEIKaYC1Akx+H+gqO04wryn5h75LSazbRlnya1k= github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/container-storage-interface/spec v1.6.0/go.mod h1:8K96oQNkJ7pFcC2R9Z1ynGGBB1I93kcS6PGg3SsOk8s= github.com/container-storage-interface/spec v1.8.0 h1:D0vhF3PLIZwlwZEf2eNbpujGCNwspwTYf2idJRJx4xI= github.com/container-storage-interface/spec v1.8.0/go.mod h1:ROLik+GhPslwwWRNFF1KasPzroNARibH2rfz1rkg4H0= github.com/coreos/go-semver v0.3.1 h1:yi21YpKnrx1gt5R+la8n5WgS0kCrsPp33dmEyHReZr4= @@ -63,7 +71,10 @@ github.com/emicklei/go-restful/v3 v3.10.2 h1:hIovbnmBTLjHXkqEBUz3HGpXZdM7ZrE9fJI github.com/emicklei/go-restful/v3 v3.10.2/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= +github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/envoyproxy/protoc-gen-validate v1.0.2 h1:QkIBuU5k+x7/QXPvPPnWXWlCdaBFApVqftFV6k087DA= github.com/envoyproxy/protoc-gen-validate v1.0.2/go.mod h1:GpiZQP3dDbg4JouG/NNS7QWXpgx6x8QiMKdmN72jogE= @@ -75,6 +86,7 @@ github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMo github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= +github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= @@ -112,6 +124,7 @@ github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+Licev github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= @@ -136,6 +149,7 @@ github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= @@ -194,8 +208,8 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kubernetes-csi/csi-proxy/client v1.1.3 h1:FdGU7NtxGhQX2wTfnuscmThG920hq0OaVVpuJW9t2k0= github.com/kubernetes-csi/csi-proxy/client v1.1.3/go.mod h1:SfK4HVKQdMH5KrffivddAWgX5hl3P5KmnuOTBbDNboU= -github.com/kubernetes-csi/csi-test v2.2.0+incompatible h1:ksIV60Q+4mY0Fg8LKvBssjEcvbyxo7nz0eAD6ZLMux0= -github.com/kubernetes-csi/csi-test v2.2.0+incompatible/go.mod h1:YxJ4UiuPWIhMBkxUKY5c267DyA0uDZ/MtAimhx/2TA0= +github.com/kubernetes-csi/csi-test/v4 v4.4.0 h1:r0mnAwDURI24Vw3a/LyA/ga11yD5ZGuU7+REO35Na9s= +github.com/kubernetes-csi/csi-test/v4 v4.4.0/go.mod h1:t1RzseMZJKy313nezI/d7TolbbiKpUZM3SXQvXxOX0w= github.com/kubernetes-csi/external-snapshotter/client/v4 v4.2.0 h1:nHHjmvjitIiyPlUHk/ofpgvBcNcawJLtf4PYHORLjAA= github.com/kubernetes-csi/external-snapshotter/client/v4 v4.2.0/go.mod h1:YBCo4DoEeDndqvAn6eeu0vWM7QdXmHEeI9cFWplmBys= github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= @@ -273,6 +287,7 @@ github.com/prometheus/common v0.44.0 h1:+5BrQJwiBB9xsMygAB3TNvpQKOwlkc25LbISbrdO github.com/prometheus/common v0.44.0/go.mod h1:ofAIvZbQ1e/nugmZGz4/qCb9Ap1VoSTIO7x0VV9VvuY= github.com/prometheus/procfs v0.10.1 h1:kYK1Va/YMlutzCGazswoHKo//tZVlFpKYh+PymziUAg= github.com/prometheus/procfs v0.10.1/go.mod h1:nwNm2aOCAYw8uTR/9bWRREkZFxAUcWzPHWJq+XBB/FM= +github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= @@ -345,6 +360,7 @@ go.opentelemetry.io/otel/sdk v1.19.0 h1:6USY6zH+L8uMH8L3t1enZPR3WFEmSTADlqldyHtJ go.opentelemetry.io/otel/sdk v1.19.0/go.mod h1:NedEbbS4w3C6zElbLdPJKOpJQOrGUJ+GfzpjUvI0v1A= go.opentelemetry.io/otel/trace v1.19.0 h1:DFVQmlVbfVeOuBRrwdtaehRrWiL1JoVs9CPIQ1Dzxpg= go.opentelemetry.io/otel/trace v1.19.0/go.mod h1:mfaSyvGyEJEI0nyV2I4qhNQnbBOUUmYZpYojqMnX2vo= +go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= go.opentelemetry.io/proto/otlp v1.0.0 h1:T0TX0tmXU8a3CbNXzEKGeU5mIVOdf0oykP+u2lIVU/I= go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v80hjKIs5JXpM= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= @@ -395,6 +411,7 @@ golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= @@ -444,6 +461,7 @@ golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -526,7 +544,9 @@ google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6 google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/genproto v0.0.0-20201209185603-f92720507ed4/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20230822172742-b8732ec3820d h1:VBu5YqKPv6XiJ199exd8Br+Aetz+o08F+PLMnwJQHAY= google.golang.org/genproto v0.0.0-20230822172742-b8732ec3820d/go.mod h1:yZTlhN0tQnXo3h00fuXNCxJdLdIdnVFVBaRJ5LWBbw4= google.golang.org/genproto/googleapis/api v0.0.0-20230822172742-b8732ec3820d h1:DoPTO70H+bcDXcd39vOqb2viZxgqeBeSGtZ55yZU4/Q= @@ -536,8 +556,12 @@ google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d/go. google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= +google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= +google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= +google.golang.org/grpc v1.47.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= google.golang.org/grpc v1.59.0 h1:Z5Iec2pjwb+LEOqzpB2MR12/eKFhDPhuqW91O+4bwUk= google.golang.org/grpc v1.59.0/go.mod h1:aUPDwccQo6OTjy7Hct4AfBPD1GptF4fyUjIkQ9YtF98= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= @@ -548,6 +572,7 @@ google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzi google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= @@ -569,6 +594,7 @@ gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYs gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= @@ -605,6 +631,7 @@ k8s.io/gengo v0.0.0-20210813121822-485abfe95c7c/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAE k8s.io/gengo v0.0.0-20220902162205-c0856e24416d/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE= k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= +k8s.io/klog/v2 v2.60.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= k8s.io/klog/v2 v2.80.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= k8s.io/klog/v2 v2.100.1 h1:7WCHKK6K8fNhTqfBhISHQ97KrnJNFZMcQvKp7gP/tmg= k8s.io/klog/v2 v2.100.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= diff --git a/pkg/driver/controller.go b/pkg/driver/controller.go index 09d508208f..d7542dad55 100644 --- a/pkg/driver/controller.go +++ b/pkg/driver/controller.go @@ -341,12 +341,14 @@ func (d *controllerService) CreateVolume(ctx context.Context, req *csi.CreateVol disk, err := d.cloud.CreateDisk(ctx, volName, opts) if err != nil { - errCode := codes.Internal - if errors.Is(err, cloud.ErrNotFound) { + var errCode codes.Code + switch { + case errors.Is(err, cloud.ErrNotFound): errCode = codes.NotFound - } - if errors.Is(err, cloud.ErrIdempotentParameterMismatch) { + case errors.Is(err, cloud.ErrIdempotentParameterMismatch), errors.Is(err, cloud.ErrAlreadyExists): errCode = codes.AlreadyExists + default: + errCode = codes.Internal } return nil, status.Errorf(errCode, "Could not create volume %q: %v", volName, err) } @@ -419,6 +421,10 @@ func (d *controllerService) ControllerPublishVolume(ctx context.Context, req *cs klog.V(2).InfoS("ControllerPublishVolume: attaching", "volumeID", volumeID, "nodeID", nodeID) devicePath, err := d.cloud.AttachDisk(ctx, volumeID, nodeID) if err != nil { + if errors.Is(err, cloud.ErrNotFound) { + klog.InfoS("ControllerPublishVolume: volume not found", "volumeID", volumeID, "nodeID", nodeID) + return nil, status.Errorf(codes.NotFound, "Volume %q not found", volumeID) + } return nil, status.Errorf(codes.Internal, "Could not attach volume %q to node %q: %v", volumeID, nodeID, err) } klog.InfoS("ControllerPublishVolume: attached", "volumeID", volumeID, "nodeID", nodeID, "devicePath", devicePath) @@ -752,6 +758,9 @@ func (d *controllerService) CreateSnapshot(ctx context.Context, req *csi.CreateS snapshot, err = d.cloud.CreateSnapshot(ctx, volumeID, opts) if err != nil { + if errors.Is(err, cloud.ErrAlreadyExists) { + return nil, status.Errorf(codes.AlreadyExists, "Snapshot %q already exists", snapshotName) + } return nil, status.Errorf(codes.Internal, "Could not create snapshot %q: %v", snapshotName, err) } diff --git a/pkg/driver/driver.go b/pkg/driver/driver.go index 8569e7d51c..897973b236 100644 --- a/pkg/driver/driver.go +++ b/pkg/driver/driver.go @@ -23,6 +23,8 @@ import ( "github.com/awslabs/volume-modifier-for-k8s/pkg/rpc" csi "github.com/container-storage-interface/spec/lib/go/csi" + "github.com/kubernetes-sigs/aws-ebs-csi-driver/pkg/cloud" + "github.com/kubernetes-sigs/aws-ebs-csi-driver/pkg/driver/internal" "github.com/kubernetes-sigs/aws-ebs-csi-driver/pkg/util" "go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc" "google.golang.org/grpc" @@ -108,6 +110,33 @@ func NewDriver(options ...func(*DriverOptions)) (*Driver, error) { return &driver, nil } +func NewFakeDriver(e string, c cloud.Cloud, md *cloud.Metadata, m Mounter) (*Driver, error) { + driverOptions := &DriverOptions{ + endpoint: e, + mode: AllMode, + } + driver := Driver{ + options: &DriverOptions{ + endpoint: e, + mode: AllMode, + }, + controllerService: controllerService{ + cloud: c, + inFlight: internal.NewInFlight(), + driverOptions: driverOptions, + modifyVolumeManager: newModifyVolumeManager(), + }, + nodeService: nodeService{ + metadata: md, + deviceIdentifier: newNodeDeviceIdentifier(), + inFlight: internal.NewInFlight(), + mounter: m, + driverOptions: driverOptions, + }, + } + return &driver, nil +} + func (d *Driver) Run() error { scheme, addr, err := util.ParseEndpoint(d.options.endpoint) if err != nil { diff --git a/pkg/driver/sanity_test.go b/pkg/driver/sanity_test.go deleted file mode 100644 index a6a3aeaeff..0000000000 --- a/pkg/driver/sanity_test.go +++ /dev/null @@ -1,415 +0,0 @@ -//go:build linux -// +build linux - -package driver - -import ( - "context" - "fmt" - "math/rand" - "os" - "path/filepath" - "testing" - "time" - - "github.com/aws/aws-sdk-go/service/ec2" - "github.com/kubernetes-csi/csi-test/pkg/sanity" - "github.com/kubernetes-sigs/aws-ebs-csi-driver/pkg/cloud" - "github.com/kubernetes-sigs/aws-ebs-csi-driver/pkg/driver/internal" - "github.com/kubernetes-sigs/aws-ebs-csi-driver/pkg/util" - "k8s.io/mount-utils" - mount_utils "k8s.io/mount-utils" -) - -func TestSanity(t *testing.T) { - // Setup the full driver and its environment - dir, err := os.MkdirTemp("", "sanity-ebs-csi") - if err != nil { - t.Fatalf("error creating directory %v", err) - } - defer os.RemoveAll(dir) - - targetPath := filepath.Join(dir, "mount") - stagingPath := filepath.Join(dir, "staging") - endpoint := "unix://" + filepath.Join(dir, "csi.sock") - - config := &sanity.Config{ - TargetPath: targetPath, - StagingPath: stagingPath, - Address: endpoint, - CreateTargetDir: createDir, - CreateStagingDir: createDir, - } - - driverOptions := &DriverOptions{ - endpoint: endpoint, - mode: AllMode, - } - - drv := &Driver{ - options: driverOptions, - controllerService: controllerService{ - cloud: newFakeCloudProvider(), - inFlight: internal.NewInFlight(), - driverOptions: driverOptions, - }, - nodeService: nodeService{ - metadata: &cloud.Metadata{ - InstanceID: "instanceID", - Region: "region", - AvailabilityZone: "az", - }, - mounter: newFakeMounter(), - deviceIdentifier: newNodeDeviceIdentifier(), - inFlight: internal.NewInFlight(), - driverOptions: &DriverOptions{}, - }, - } - defer func() { - if r := recover(); r != nil { - t.Fatalf("recover: %v", r) - } - }() - go func() { - if err := drv.Run(); err != nil { - panic(fmt.Sprintf("%v", err)) - } - }() - - // Now call the test suite - sanity.Test(t, config) -} - -func createDir(targetPath string) (string, error) { - if err := os.MkdirAll(targetPath, 0300); err != nil { - if os.IsNotExist(err) { - return "", err - } - } - return targetPath, nil -} - -type fakeCloudProvider struct { - disks map[string]*fakeDisk - // snapshots contains mapping from snapshot ID to snapshot - snapshots map[string]*fakeSnapshot - pub map[string]string - tokens map[string]int64 -} - -type fakeDisk struct { - *cloud.Disk - iops int - throughput int - volumeType string - tags map[string]string -} - -type fakeSnapshot struct { - *cloud.Snapshot - tags map[string]string -} - -func newFakeCloudProvider() *fakeCloudProvider { - return &fakeCloudProvider{ - disks: make(map[string]*fakeDisk), - snapshots: make(map[string]*fakeSnapshot), - pub: make(map[string]string), - tokens: make(map[string]int64), - } -} - -func (c *fakeCloudProvider) CreateDisk(ctx context.Context, volumeName string, diskOptions *cloud.DiskOptions) (*cloud.Disk, error) { - r1 := rand.New(rand.NewSource(time.Now().UnixNano())) - if len(diskOptions.SnapshotID) > 0 { - if _, ok := c.snapshots[diskOptions.SnapshotID]; !ok { - return nil, cloud.ErrNotFound - } - } - if existingDisk, ok := c.disks[volumeName]; ok { - //Already Created volume - if existingDisk.Disk.CapacityGiB != util.BytesToGiB(diskOptions.CapacityBytes) { - return nil, cloud.ErrIdempotentParameterMismatch - } else { - return existingDisk.Disk, nil - } - } - d := &fakeDisk{ - Disk: &cloud.Disk{ - VolumeID: fmt.Sprintf("vol-%d", r1.Uint64()), - CapacityGiB: util.BytesToGiB(diskOptions.CapacityBytes), - AvailabilityZone: diskOptions.AvailabilityZone, - SnapshotID: diskOptions.SnapshotID, - }, - iops: diskOptions.IOPS, - throughput: diskOptions.Throughput, - volumeType: diskOptions.VolumeType, - tags: diskOptions.Tags, - } - c.disks[volumeName] = d - return d.Disk, nil -} - -func (c *fakeCloudProvider) DeleteDisk(ctx context.Context, volumeID string) (bool, error) { - for volName, f := range c.disks { - if f.Disk.VolumeID == volumeID { - delete(c.disks, volName) - } - } - return true, nil -} - -func (c *fakeCloudProvider) AttachDisk(ctx context.Context, volumeID, nodeID string) (string, error) { - if _, ok := c.pub[volumeID]; ok { - return "", cloud.ErrAlreadyExists - } - c.pub[volumeID] = nodeID - return "/tmp", nil -} - -func (c *fakeCloudProvider) DetachDisk(ctx context.Context, volumeID, nodeID string) error { - return nil -} - -func (c *fakeCloudProvider) WaitForAttachmentState(ctx context.Context, volumeID, expectedState string, expectedInstance string, expectedDevice string, alreadyAssigned bool) (*ec2.VolumeAttachment, error) { - return nil, nil -} - -func (c *fakeCloudProvider) GetDiskByName(ctx context.Context, name string, capacityBytes int64) (*cloud.Disk, error) { - var disks []*fakeDisk - for _, d := range c.disks { - for key, value := range d.tags { - if key == cloud.VolumeNameTagKey && value == name { - disks = append(disks, d) - } - } - } - if len(disks) > 1 { - return nil, cloud.ErrMultiDisks - } else if len(disks) == 1 { - if capacityBytes != disks[0].Disk.CapacityGiB*util.GiB { - return nil, cloud.ErrDiskExistsDiffSize - } - return disks[0].Disk, nil - } - return nil, nil -} - -func (c *fakeCloudProvider) GetDiskByID(ctx context.Context, volumeID string) (*cloud.Disk, error) { - for _, f := range c.disks { - if f.Disk.VolumeID == volumeID { - return f.Disk, nil - } - } - return nil, cloud.ErrNotFound -} - -func (c *fakeCloudProvider) IsExistInstance(ctx context.Context, nodeID string) bool { - return nodeID == "instanceID" -} - -func (c *fakeCloudProvider) CreateSnapshot(ctx context.Context, volumeID string, snapshotOptions *cloud.SnapshotOptions) (snapshot *cloud.Snapshot, err error) { - r1 := rand.New(rand.NewSource(time.Now().UnixNano())) - snapshotID := fmt.Sprintf("snapshot-%d", r1.Uint64()) - - for _, existingSnapshot := range c.snapshots { - if existingSnapshot.Snapshot.SnapshotID == snapshotID && existingSnapshot.Snapshot.SourceVolumeID == volumeID { - return nil, cloud.ErrAlreadyExists - } - } - - s := &fakeSnapshot{ - Snapshot: &cloud.Snapshot{ - SnapshotID: snapshotID, - SourceVolumeID: volumeID, - Size: 1, - CreationTime: time.Now(), - }, - tags: snapshotOptions.Tags, - } - c.snapshots[snapshotID] = s - return s.Snapshot, nil - -} - -func (c *fakeCloudProvider) DeleteSnapshot(ctx context.Context, snapshotID string) (success bool, err error) { - delete(c.snapshots, snapshotID) - return true, nil - -} - -func (c *fakeCloudProvider) GetSnapshotByName(ctx context.Context, name string) (snapshot *cloud.Snapshot, err error) { - var snapshots []*fakeSnapshot - for _, s := range c.snapshots { - snapshotName, exists := s.tags[cloud.SnapshotNameTagKey] - if !exists { - continue - } - if snapshotName == name { - snapshots = append(snapshots, s) - } - } - if len(snapshots) == 0 { - return nil, cloud.ErrNotFound - } - - return snapshots[0].Snapshot, nil -} - -func (c *fakeCloudProvider) GetSnapshotByID(ctx context.Context, snapshotID string) (snapshot *cloud.Snapshot, err error) { - ret, exists := c.snapshots[snapshotID] - if !exists { - return nil, cloud.ErrNotFound - } - - return ret.Snapshot, nil -} - -func (c *fakeCloudProvider) AvailabilityZones(ctx context.Context) (map[string]struct{}, error) { - return nil, nil -} - -func (c *fakeCloudProvider) ListSnapshots(ctx context.Context, volumeID string, maxResults int64, nextToken string) (listSnapshotsResponse *cloud.ListSnapshotsResponse, err error) { - var snapshots []*cloud.Snapshot - var retToken string - for _, fakeSnapshot := range c.snapshots { - if fakeSnapshot.Snapshot.SourceVolumeID == volumeID || len(volumeID) == 0 { - snapshots = append(snapshots, fakeSnapshot.Snapshot) - } - } - if maxResults > 0 { - r1 := rand.New(rand.NewSource(time.Now().UnixNano())) - retToken = fmt.Sprintf("token-%d", r1.Uint64()) - c.tokens[retToken] = maxResults - snapshots = snapshots[0:maxResults] - fmt.Printf("%v\n", snapshots) - } - if len(nextToken) != 0 { - snapshots = snapshots[c.tokens[nextToken]:] - } - return &cloud.ListSnapshotsResponse{ - Snapshots: snapshots, - NextToken: retToken, - }, nil - -} - -func (c *fakeCloudProvider) EnableFastSnapshotRestores(ctx context.Context, availabilityZones []string, snapshotID string) (*ec2.EnableFastSnapshotRestoresOutput, error) { - return nil, nil -} - -func (c *fakeCloudProvider) ResizeOrModifyDisk(ctx context.Context, volumeID string, newSize int64, options *cloud.ModifyDiskOptions) (int64, error) { - if d, ok := c.disks[volumeID]; !ok { - return 0, cloud.ErrNotFound - } else { - d.iops = options.IOPS - d.throughput = options.Throughput - d.volumeType = options.VolumeType - d.Disk.CapacityGiB = newSize - return newSize, nil - } -} - -type fakeMounter struct { - mount_utils.Interface -} - -func newFakeMounter() *fakeMounter { - return &fakeMounter{} -} - -func (f *fakeMounter) IsCorruptedMnt(err error) bool { - return false -} - -func (f *fakeMounter) IsMountPoint(file string) (bool, error) { - return false, nil -} - -func (f *fakeMounter) Mount(source string, target string, fstype string, options []string) error { - return nil -} - -func (f *fakeMounter) MountSensitive(source string, target string, fstype string, options []string, sensitiveOptions []string) error { - return nil -} - -func (f *fakeMounter) MountSensitiveWithoutSystemd(source string, target string, fstype string, options []string, sensitiveOptions []string) error { - return nil -} - -func (f *fakeMounter) MountSensitiveWithoutSystemdWithMountFlags(source string, target string, fstype string, options []string, sensitiveOptions []string, mountFlags []string) error { - return nil -} - -func (f *fakeMounter) Unmount(target string) error { - return nil -} - -func (f *fakeMounter) Unstage(target string) error { - return nil -} - -func (f *fakeMounter) Unpublish(target string) error { - return nil -} - -func (f *fakeMounter) NewResizeFs() (Resizefs, error) { - return nil, nil -} - -func (f *fakeMounter) List() ([]mount.MountPoint, error) { - return []mount.MountPoint{}, nil -} - -func (f *fakeMounter) IsLikelyNotMountPoint(file string) (bool, error) { - return false, nil -} - -func (f *fakeMounter) GetMountRefs(pathname string) ([]string, error) { - return []string{}, nil -} - -func (f *fakeMounter) FormatAndMountSensitiveWithFormatOptions(source string, target string, fstype string, options []string, sensitiveOptions []string, formatOptions []string) error { - return nil -} - -func (f *fakeMounter) GetDeviceNameFromMount(mountPath string) (string, int, error) { - return "", 0, nil -} - -func (f *fakeMounter) MakeFile(pathname string) error { - file, err := os.OpenFile(pathname, os.O_CREATE, os.FileMode(0644)) - if err != nil { - if !os.IsExist(err) { - return err - } - } - if err = file.Close(); err != nil { - return err - } - return nil -} - -func (f *fakeMounter) MakeDir(pathname string) error { - err := os.MkdirAll(pathname, os.FileMode(0755)) - if err != nil { - if !os.IsExist(err) { - return err - } - } - return nil -} - -func (f *fakeMounter) PathExists(filename string) (bool, error) { - if _, err := os.Stat(filename); os.IsNotExist(err) { - return false, nil - } else if err != nil { - return false, err - } - return true, nil -} - -func (f *fakeMounter) NeedResize(source string, path string) (bool, error) { - return false, nil -} diff --git a/tests/sanity/sanity_test.go b/tests/sanity/sanity_test.go new file mode 100644 index 0000000000..2171926521 --- /dev/null +++ b/tests/sanity/sanity_test.go @@ -0,0 +1,300 @@ +//go:build linux +// +build linux + +package sanity + +import ( + "context" + "fmt" + "math/rand" + "os" + "path" + "strconv" + "testing" + "time" + + "github.com/aws/aws-sdk-go/aws" + "github.com/golang/mock/gomock" + csisanity "github.com/kubernetes-csi/csi-test/v4/pkg/sanity" + "github.com/kubernetes-sigs/aws-ebs-csi-driver/pkg/cloud" + d "github.com/kubernetes-sigs/aws-ebs-csi-driver/pkg/driver" + "github.com/kubernetes-sigs/aws-ebs-csi-driver/pkg/util" + "google.golang.org/grpc" + "google.golang.org/grpc/credentials/insecure" +) + +const ( + instanceId = "i-1234567890abcdef0" + region = "us-west-2" +) + +var ( + disks = make(map[string]*cloud.Disk) + snapshots = make(map[string]*cloud.Snapshot) + snapshotNameToID = make(map[string]string) + + fakeMetaData = &cloud.Metadata{ + InstanceID: instanceId, + Region: region, + } +) + +func TestSanity(t *testing.T) { + defer func() { + if r := recover(); r != nil { + t.Errorf("Test panicked: %v", r) + } + }() + + mockCtrl := gomock.NewController(t) + defer mockCtrl.Finish() + + tmpDir, err := os.MkdirTemp("", "csi-sanity-") + if err != nil { + t.Fatalf("Failed to create sanity temp working dir: %v", err) + } + defer os.RemoveAll(tmpDir) + + defer func() { + if err = os.RemoveAll(tmpDir); err != nil { + t.Fatalf("Failed to clean up sanity temp working dir %s: %v", tmpDir, err.Error()) + } + }() + + endpoint := fmt.Sprintf("unix:%s/csi.sock", tmpDir) + mountPath := path.Join(tmpDir, "mount") + stagePath := path.Join(tmpDir, "stage") + + fakeMounter, fakeIdentifier, fakeResizeFs, fakeCloud := createMockObjects(mockCtrl) + + mockNodeService(fakeMounter, fakeIdentifier, fakeResizeFs, mountPath) + mockControllerService(fakeCloud, mountPath) + + drv, err := d.NewFakeDriver(endpoint, fakeCloud, fakeMetaData, fakeMounter) + if err != nil { + t.Fatalf("Failed to create fake driver: %v", err.Error()) + } + go func() { + if err := drv.Run(); err != nil { + panic(fmt.Sprintf("%v", err)) + } + }() + + config := csisanity.TestConfig{ + TargetPath: mountPath, + StagingPath: stagePath, + Address: endpoint, + DialOptions: []grpc.DialOption{grpc.WithTransportCredentials(insecure.NewCredentials())}, + IDGen: csisanity.DefaultIDGenerator{}, + TestVolumeSize: 10 * util.GiB, + TestVolumeAccessType: "mount", + } + csisanity.Test(t, config) +} + +func createMockObjects(mockCtrl *gomock.Controller) (*d.MockMounter, *d.MockDeviceIdentifier, *d.MockResizefs, *cloud.MockCloud) { + fakeMounter := d.NewMockMounter(mockCtrl) + fakeIdentifier := d.NewMockDeviceIdentifier(mockCtrl) + fakeResizeFs := d.NewMockResizefs(mockCtrl) + fakeCloud := cloud.NewMockCloud(mockCtrl) + + return fakeMounter, fakeIdentifier, fakeResizeFs, fakeCloud +} + +func mockNodeService(m *d.MockMounter, i *d.MockDeviceIdentifier, r *d.MockResizefs, mountPath string) { + m.EXPECT().Unpublish(gomock.Any()).Return(nil).AnyTimes() + m.EXPECT().GetDeviceNameFromMount(gomock.Any()).Return("", 0, nil).AnyTimes() + m.EXPECT().Unstage(gomock.Any()).Return(nil).AnyTimes() + m.EXPECT().FormatAndMountSensitiveWithFormatOptions(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(nil).AnyTimes() + m.EXPECT().NeedResize(gomock.Any(), gomock.Any()).Return(false, nil).AnyTimes() + m.EXPECT().MakeDir(gomock.Any()).Return(nil).AnyTimes() + m.EXPECT().IsLikelyNotMountPoint(gomock.Any()).Return(true, nil).AnyTimes() + m.EXPECT().Mount(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(nil).AnyTimes() + + m.EXPECT().PathExists(gomock.Any()).DoAndReturn( + func(targetPath string) (bool, error) { + if targetPath == mountPath { + return true, nil + } + return false, nil + }, + ).AnyTimes() + + m.EXPECT().NewResizeFs().Return(r, nil).AnyTimes() + i.EXPECT().Lstat(gomock.Any()).Return(nil, nil).AnyTimes() + r.EXPECT().Resize(gomock.Any(), gomock.Any()).Return(true, nil).AnyTimes() +} + +func mockControllerService(c *cloud.MockCloud, mountPath string) { + // CreateDisk + c.EXPECT().CreateDisk(gomock.Any(), gomock.Any(), gomock.Any()).DoAndReturn( + func(ctx context.Context, volumeID string, diskOptions *cloud.DiskOptions) (*cloud.Disk, error) { + for _, existingDisk := range disks { + if existingDisk.VolumeID == volumeID && existingDisk.CapacityGiB != util.BytesToGiB(diskOptions.CapacityBytes) { + return nil, cloud.ErrAlreadyExists + } + } + + if diskOptions.SnapshotID != "" { + if _, exists := snapshots[diskOptions.SnapshotID]; !exists { + return nil, cloud.ErrNotFound + } + } + + newDisk := &cloud.Disk{ + VolumeID: volumeID, + AvailabilityZone: diskOptions.AvailabilityZone, + CapacityGiB: util.BytesToGiB(diskOptions.CapacityBytes), + } + disks[volumeID] = newDisk + return newDisk, nil + }, + ).AnyTimes() + + // DeleteDisk + c.EXPECT().DeleteDisk(gomock.Any(), gomock.Any()).DoAndReturn( + func(ctx context.Context, volumeID string) (bool, error) { + _, exists := disks[volumeID] + if !exists { + return false, cloud.ErrNotFound + } + delete(disks, volumeID) + return true, nil + }, + ).AnyTimes() + + // GetDiskByID + c.EXPECT().GetDiskByID(gomock.Any(), gomock.Any()).DoAndReturn( + func(ctx context.Context, volumeID string) (*cloud.Disk, error) { + disk, exists := disks[volumeID] + if !exists { + return nil, cloud.ErrNotFound + } + return disk, nil + }, + ).AnyTimes() + + // CreateSnapshot + c.EXPECT(). + CreateSnapshot(gomock.Any(), gomock.Any(), gomock.Any()). + DoAndReturn(func(ctx context.Context, volumeID string, opts *cloud.SnapshotOptions) (*cloud.Snapshot, error) { + snapshotID := fmt.Sprintf("snapshot-%d", rand.New(rand.NewSource(time.Now().UnixNano())).Uint64()) + + _, exists := snapshots[snapshotID] + if exists { + return nil, cloud.ErrAlreadyExists + } + newSnapshot := &cloud.Snapshot{ + SnapshotID: snapshotID, + SourceVolumeID: volumeID, + CreationTime: time.Now(), + } + snapshots[snapshotID] = newSnapshot + snapshotNameToID[opts.Tags["CSIVolumeSnapshotName"]] = snapshotID + return newSnapshot, nil + }).AnyTimes() + + // DeleteSnapshot + c.EXPECT().DeleteSnapshot(gomock.Any(), gomock.Any()).DoAndReturn( + func(ctx context.Context, snapshotID string) (bool, error) { + if _, exists := snapshots[snapshotID]; !exists { + return false, cloud.ErrNotFound + } + for name, id := range snapshotNameToID { + if id == snapshotID { + delete(snapshotNameToID, name) + break + } + } + delete(snapshots, snapshotID) + return true, nil + }, + ).AnyTimes() + + // GetSnapshotByID + c.EXPECT().GetSnapshotByID(gomock.Any(), gomock.Any()).DoAndReturn( + func(ctx context.Context, snapshotID string) (*cloud.Snapshot, error) { + snapshot, exists := snapshots[snapshotID] + if !exists { + return nil, cloud.ErrNotFound + } + return snapshot, nil + }, + ).AnyTimes() + + // GetSnapshotByName + c.EXPECT().GetSnapshotByName(gomock.Any(), gomock.Any()).DoAndReturn( + func(ctx context.Context, name string) (*cloud.Snapshot, error) { + if snapshotID, exists := snapshotNameToID[name]; exists { + return snapshots[snapshotID], nil + } + return nil, cloud.ErrNotFound + }, + ).AnyTimes() + + // ListSnapshots + c.EXPECT(). + ListSnapshots(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()). + DoAndReturn(func(ctx context.Context, sourceVolumeID string, maxResults int64, nextToken string) (*cloud.ListSnapshotsResponse, error) { + var s []*cloud.Snapshot + startIndex := 0 + var err error + + if nextToken != "" { + startIndex, err = strconv.Atoi(nextToken) + if err != nil { + return nil, fmt.Errorf("invalid next token %s", nextToken) + } + } + + var nextTokenStr string + count := 0 + for _, snap := range snapshots { + if snap.SourceVolumeID == sourceVolumeID || sourceVolumeID == "" { + if startIndex <= count { + s = append(s, snap) + if maxResults > 0 && int64(len(s)) >= maxResults { + nextTokenStr = strconv.Itoa(startIndex + int(maxResults)) + break + } + } + count++ + } + } + + return &cloud.ListSnapshotsResponse{ + Snapshots: s, + NextToken: nextTokenStr, + }, nil + }). + AnyTimes() + + // AttachDisk + c.EXPECT().AttachDisk(gomock.Any(), gomock.Any(), gomock.Any()).DoAndReturn( + func(ctx context.Context, volumeID string, instanceID string) (string, error) { + _, diskExists := disks[volumeID] + if !diskExists || instanceID != fakeMetaData.InstanceID { + return "", cloud.ErrNotFound + } + return mountPath, nil + }, + ).AnyTimes() + + // DetachDisk + c.EXPECT().DetachDisk(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil).AnyTimes() + + // ResizeOrModifyDisk + c.EXPECT().ResizeOrModifyDisk(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).DoAndReturn( + func(ctx context.Context, volumeID string, newSizeBytes int64, modifyOptions *cloud.ModifyDiskOptions) (int64, error) { + disk, exists := disks[volumeID] + if !exists { + return 0, cloud.ErrNotFound + } + newSizeGiB := util.BytesToGiB(newSizeBytes) + disk.CapacityGiB = newSizeGiB + disks[volumeID] = disk + realSizeGiB := aws.Int64Value(&newSizeGiB) + return realSizeGiB, nil + }, + ).AnyTimes() +}