From dbe149722c734419dc9e90f187e44646975829a2 Mon Sep 17 00:00:00 2001 From: Lingxian Kong Date: Tue, 17 Aug 2021 22:38:00 +1200 Subject: [PATCH] [manila-csi-plugin] pass CreateVolumeRequest.parameters as Volume.volume_context (#1616) (#1624) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * validator: added Validator.Fields exposing recognized field names * options: added NodeVolumeContextFields() to expose nodeVolumeCtxValidator.Fields * CreateVolume: pass all recognized CreateVolumeRequest.parameters fields as Volume.volume_context Co-authored-by: Róbert Vašek --- pkg/csi/manila/controllerserver.go | 22 +++++++++++---- pkg/csi/manila/options/shareoptions.go | 4 +++ pkg/csi/manila/validator/validator.go | 13 +++++++++ pkg/csi/manila/validator/validator_test.go | 31 ++++++++++++++++++++++ 4 files changed, 65 insertions(+), 5 deletions(-) diff --git a/pkg/csi/manila/controllerserver.go b/pkg/csi/manila/controllerserver.go index 4cf8a0cd39..116b000944 100644 --- a/pkg/csi/manila/controllerserver.go +++ b/pkg/csi/manila/controllerserver.go @@ -61,6 +61,18 @@ func getVolumeCreator(source *csi.VolumeContentSource, shareOpts *options.Contro return nil, status.Error(codes.InvalidArgument, "invalid volume content source") } +func filterParametersForVolumeContext(params map[string]string, recognizedFields []string) map[string]string { + volCtx := make(map[string]string) + + for _, fieldName := range recognizedFields { + if val, ok := params[fieldName]; ok { + volCtx[fieldName] = val + } + } + + return volCtx +} + func (cs *controllerServer) CreateVolume(ctx context.Context, req *csi.CreateVolumeRequest) (*csi.CreateVolumeResponse, error) { if err := validateCreateVolumeRequest(req); err != nil { return nil, status.Error(codes.InvalidArgument, err.Error()) @@ -150,17 +162,17 @@ func (cs *controllerServer) CreateVolume(ctx context.Context, req *csi.CreateVol accessibleTopology = req.GetAccessibilityRequirements().GetPreferred() } + volCtx := filterParametersForVolumeContext(params, options.NodeVolumeContextFields()) + volCtx["shareID"] = share.ID + volCtx["shareAccessID"] = accessRight.ID + return &csi.CreateVolumeResponse{ Volume: &csi.Volume{ VolumeId: share.ID, ContentSource: req.GetVolumeContentSource(), AccessibleTopology: accessibleTopology, CapacityBytes: int64(sizeInGiB) * bytesInGiB, - VolumeContext: map[string]string{ - "shareID": share.ID, - "shareAccessID": accessRight.ID, - "cephfs-mounter": shareOpts.CephfsMounter, - }, + VolumeContext: volCtx, }, }, nil } diff --git a/pkg/csi/manila/options/shareoptions.go b/pkg/csi/manila/options/shareoptions.go index ceab39a8c1..a3b539a793 100644 --- a/pkg/csi/manila/options/shareoptions.go +++ b/pkg/csi/manila/options/shareoptions.go @@ -70,3 +70,7 @@ func NewNodeVolumeContext(data map[string]string) (*NodeVolumeContext, error) { return opts, nil } + +func NodeVolumeContextFields() []string { + return nodeVolumeCtxValidator.Fields +} diff --git a/pkg/csi/manila/validator/validator.go b/pkg/csi/manila/validator/validator.go index 96d9981d0a..e4240e26f4 100644 --- a/pkg/csi/manila/validator/validator.go +++ b/pkg/csi/manila/validator/validator.go @@ -48,6 +48,9 @@ type Validator struct { nameIdxMap nameIndexMap idxNameMap indexNameMap + // Field names in the struct. + Fields []string + valueExprs *valueExpressions depsMap dependenciesMap preclsMap preclusionsMap @@ -67,6 +70,7 @@ func New(stringStruct interface{}) *Validator { t: t, nameIdxMap: nameIdxMap, idxNameMap: idxNameMap, + Fields: buildFieldNames(idxNameMap), valueExprs: buildValueExpressions(t, idxNameMap, nameIdxMap), depsMap: buildDependenciesMap(t, idxNameMap, nameIdxMap), preclsMap: buildPreclusionsMap(t, idxNameMap, nameIdxMap), @@ -74,6 +78,15 @@ func New(stringStruct interface{}) *Validator { } } +func buildFieldNames(m indexNameMap) []string { + s := make([]string, 0, len(m)) + for _, fieldName := range m { + s = append(s, string(fieldName)) + } + + return s +} + // Populate validates input data and populates the output struct. func (v *Validator) Populate(data map[string]string, out interface{}) error { if reflect.TypeOf(out).Elem() != v.t { diff --git a/pkg/csi/manila/validator/validator_test.go b/pkg/csi/manila/validator/validator_test.go index 1d38db7575..c6643c45fd 100644 --- a/pkg/csi/manila/validator/validator_test.go +++ b/pkg/csi/manila/validator/validator_test.go @@ -193,3 +193,34 @@ func TestMatches(t *testing.T) { t.Error(`matches:"true|false" violated, should succeed on matching parameter`) } } + +func TestFieldNames(t *testing.T) { + type s struct { + A string `name:"a"` + B string `name:"b"` + } + + v := New(&s{}) + + expected := []string{"a", "b"} + + findElem := func(x string, xs []string) bool { + for _, e := range xs { + if e == x { + return true + } + } + return false + } + + if len(expected) != len(v.Fields) { + t.Errorf("expected number of entries %d (%v), got %d (%v)", + len(expected), expected, len(v.Fields), v.Fields) + } + + for i := range v.Fields { + if !findElem(v.Fields[i], expected) { + t.Error("found unexpected field", v.Fields[i], "; expected fields", expected, "actual fields", v.Fields) + } + } +}