diff --git a/Dockerfile b/Dockerfile index 78d8a93e..dfe60a56 100644 --- a/Dockerfile +++ b/Dockerfile @@ -13,7 +13,7 @@ ARG GOIMAGE ARG BASEIMAGE -ARG VERSION="2.16.0" +ARG VERSION="2.17.0" FROM $GOIMAGE AS builder ARG VERSION @@ -36,7 +36,7 @@ LABEL vendor="Dell Technologies" \ name="csi-unity" \ summary="CSI Driver for Dell Unity XT" \ description="CSI Driver for provisioning persistent storage from Dell Unity XT" \ - release="1.15.0" \ + release="1.17.0" \ version=$VERSION \ license="Apache-2.0" COPY licenses /licenses diff --git a/README.md b/README.md index 82bd033e..778b5801 100644 --- a/README.md +++ b/README.md @@ -62,4 +62,3 @@ Both the Controller and the Node portions of the driver can only be run on nodes For more detailed information on the driver, please refer to [Container Storage Modules documentation](https://dell.github.io/csm-docs/). - diff --git a/core/semver/semver_test.go b/core/semver/semver_test.go index 2a2f93b3..54242b42 100644 --- a/core/semver/semver_test.go +++ b/core/semver/semver_test.go @@ -271,7 +271,7 @@ func TestErrorExit(t *testing.T) { return } // call the test again with INVOKE_ERROR_EXIT=1 so the errorExit function is invoked and we can check the return code - cmd := exec.Command(os.Args[0], "-test.run=TestErrorExit") // #nosec G204 + cmd := exec.Command(os.Args[0], "-test.run=TestErrorExit") // #nosec G204,G702 cmd.Env = append(os.Environ(), "INVOKE_ERROR_EXIT=1") stderr, err := cmd.StderrPipe() diff --git a/dell-csi-helm-installer/README.md b/dell-csi-helm-installer/README.md index b6ec778d..36974ddd 100644 --- a/dell-csi-helm-installer/README.md +++ b/dell-csi-helm-installer/README.md @@ -49,7 +49,7 @@ This project provides the following capabilitites, each one is discussed in deta Most of these usages require the creation/specification of a values file. These files specify configuration settings that are passed into the driver and configure it for use. To create one of these files, the following steps should be followed: -1. Download a template file for the driver to a new location, naming this new file is at the users discretion. The template files are always found at `https://github.com/dell/helm-charts/raw/csi-unity-2.16.0/charts/csi-unity/values.yaml` +1. Download a template file for the driver to a new location, naming this new file is at the users discretion. The template files are always found at `https://github.com/dell/helm-charts/raw/csi-unity-2.17.0/charts/csi-unity/values.yaml` 2. Edit the file such that it contains the proper configuration settings for the specific environment. These files are yaml formatted so maintaining the file structure is important. For example, to create a values file for the Unity XT driver the following steps can be executed @@ -58,7 +58,7 @@ For example, to create a values file for the Unity XT driver the following steps cd dell-csi-helm-installer # download the template file -wget -O my-unity-settings.yaml https://github.com/dell/helm-charts/raw/csi-unity-2.16.0/charts/csi-unity/values.yaml +wget -O my-unity-settings.yaml https://github.com/dell/helm-charts/raw/csi-unity-2.17.0/charts/csi-unity/values.yaml # edit the newly created values file vi my-unity-settings.yaml diff --git a/dell-csi-helm-installer/csi-install.sh b/dell-csi-helm-installer/csi-install.sh index 146c46b3..e897434e 100755 --- a/dell-csi-helm-installer/csi-install.sh +++ b/dell-csi-helm-installer/csi-install.sh @@ -16,11 +16,9 @@ PROG="${0}" NODE_VERIFY=1 VERIFY=1 MODE="install" -DEFAULT_DRIVER_VERSION="v2.16.0" +DEFAULT_VERSION="v2.17.0" WATCHLIST="" -DRIVERVERSION="csi-unity-2.16.0" - # usage will print command execution help and then exit function usage() { echo @@ -125,6 +123,9 @@ while getopts ":h-:" optchar; do esac done +# Derive helm chart version from DEFAULT_VERSION (single source of truth) +DRIVERVERSION="${DRIVER}-${DEFAULT_VERSION#v}" + if [ -n "$HELMCHARTVERSION" ]; then DRIVERVERSION=$HELMCHARTVERSION fi @@ -145,7 +146,6 @@ DRIVERDIR="${SCRIPTDIR}/../helm-charts/charts" DRIVER="csi-unity" VERIFYSCRIPT="${SCRIPTDIR}/verify.sh" - # export the name of the debug log, so child processes will see it export DEBUGLOG="${SCRIPTDIR}/install-debug.log" declare -a VALIDDRIVERS @@ -398,7 +398,7 @@ RELEASE=$(get_release_name "${DRIVER}") # by default, NODEUSER is root NODEUSER="${NODEUSER:-root}" if [[ -z ${DRIVER_VERSION} ]]; then - DRIVER_VERSION=${DEFAULT_DRIVER_VERSION} + DRIVER_VERSION=${DEFAULT_VERSION} fi @@ -416,8 +416,8 @@ helm --help >&/dev/null || { OPENSHIFT=$(isOpenShift) # Get the kubernetes major and minor version numbers. -kMajorVersion=$(run_command kubectl version | grep 'Server Version' | sed -E 's/.*v([0-9]+)\.[0-9]+\.[0-9]+.*/\1/') -kMinorVersion=$(run_command kubectl version | grep 'Server Version' | sed -E 's/.*v[0-9]+\.([0-9]+)\.[0-9]+.*/\1/') +kMajorVersion=$(run_command kubectl version -o="yaml" | grep -A8 'serverVersion:' | grep 'major'| egrep -o '[0-9]+') +kMinorVersion=$(run_command kubectl version -o="yaml" | grep -A8 'serverVersion:' | grep 'minor'| egrep -o '[0-9]+') kNonGAVersion=$(run_command kubectl version | grep 'Server Version' | sed -n 's/.*\(-[alpha|beta][^ ]*\).*/\1/p') # validate the parameters passed in diff --git a/dell-csi-helm-installer/csi-offline-bundle.md b/dell-csi-helm-installer/csi-offline-bundle.md index e7024f88..0532957e 100644 --- a/dell-csi-helm-installer/csi-offline-bundle.md +++ b/dell-csi-helm-installer/csi-offline-bundle.md @@ -91,30 +91,9 @@ For example, here is the output of a request to build an offline bundle for the * * Pulling and saving container images - quay.io/dell/container-storage-modules/csi-isilon:v2.16.0 - quay.io/dell/container-storage-modules/csi-metadata-retriever:v1.11.0 - quay.io/dell/container-storage-modules/csipowermax-reverseproxy:v2.14.0 - quay.io/dell/container-storage-modules/csi-powermax:v2.16.0 - quay.io/dell/container-storage-modules/csi-powerstore:v2.16.0 - quay.io/dell/container-storage-modules/csi-unity:v2.16.0 - quay.io/dell/container-storage-modules/csi-vxflexos:v2.16.0 - quay.io/dell/container-storage-modules/csm-authorization-sidecar:v1.14.0 - quay.io/dell/container-storage-modules/csm-metrics-powerflex:v1.14.0 - quay.io/dell/container-storage-modules/csm-metrics-powerscale:v1.11.0 - quay.io/dell/container-storage-modules/csm-topology:v1.12.0 - quay.io/dell/container-storage-modules/dell-csi-replicator:v1.14.0 - quay.io/dell/container-storage-modules/dell-replication-controller:v1.14.0 - dellemc/sdc:4.5.2.1 - quay.io/dell/container-storage-modules/dell-csm-operator:v1.11.0 - registry.redhat.io/openshift4/ose-kube-rbac-proxy-rhel9:v4.16.0-202409051837.p0.g8ea2c99.assembly.stream.el9 - nginxinc/nginx-unprivileged:1.27 - otel/opentelemetry-collector:0.42.0 - registry.k8s.io/sig-storage/csi-attacher:v4.8.0 - registry.k8s.io/sig-storage/csi-external-health-monitor-controller:v0.14.0 - registry.k8s.io/sig-storage/csi-node-driver-registrar:v2.13.0 - registry.k8s.io/sig-storage/csi-provisioner:v5.1.0 - registry.k8s.io/sig-storage/csi-resizer:v1.13.1 - registry.k8s.io/sig-storage/csi-snapshotter:v8.2.0 +... + quay.io/dell/container-storage-modules/csi-unity:v2.17.0 +... * * Copying necessary files @@ -189,32 +168,20 @@ Preparing a offline bundle for installation * * Loading docker images -Loaded image: quay.io/dell/container-storage-modules/csi-powerstore:v2.16.0 -Loaded image: quay.io/dell/container-storage-modules/csi-isilon:v2.16.0 -... +Loaded image: quay.io/dell/container-storage-modules/csi-unity:v2.17.0 ... -Loaded image: registry.k8s.io/sig-storage/csi-resizer:v1.9.2 -Loaded image: registry.k8s.io/sig-storage/csi-snapshotter:v6.3.2 * * Tagging and pushing images - quay.io/dell/container-storage-modules/csi-isilon:v2.16.0 -> localregistry:5000/dell-csm-operator/csi-isilon:v2.16.0 - quay.io/dell/container-storage-modules/csi-metadata-retriever:v1.9.0 -> localregistry:5000/dell-csm-operator/csi-metadata-retriever:v1.9.0 + quay.io/dell/container-storage-modules/csi-unity:v2.17.0 -> localregistry:5000/dell-csm-operator/csi-unity:v2.17.0 ... - ... - registry.k8s.io/sig-storage/csi-resizer:v1.9.2 -> localregistry:5000/dell-csm-operator/csi-resizer:v1.9.2 - registry.k8s.io/sig-storage/csi-snapshotter:v6.3.2 -> localregistry:5000/dell-csm-operator/csi-snapshotter:v6.3.2 * * Preparing files within /root/dell-csm-operator-bundle - changing: quay.io/dell/container-storage-modules/csi-isilon:v2.16.0 -> localregistry:5000/dell-csm-operator/csi-isilon:v2.16.0 - changing: quay.io/dell/container-storage-modules/csi-metadata-retriever:v1.9.0 -> localregistry:5000/dell-csm-operator/csi-metadata-retriever:v1.9.0 - ... + changing: quay.io/dell/container-storage-modules/csi-unity:v2.17.0 -> localregistry:5000/dell-csm-operator/csi-unity:v2.17.0 ... - changing: registry.k8s.io/sig-storage/csi-resizer:v1.9.2 -> localregistry:5000/dell-csm-operator/csi-resizer:v1.9.2 - changing: registry.k8s.io/sig-storage/csi-snapshotter:v6.3.2 -> localregistry:5000/dell-csm-operator/csi-snapshotter:v6.3.2 * * Complete diff --git a/dell-csi-helm-installer/csi-offline-bundle.sh b/dell-csi-helm-installer/csi-offline-bundle.sh index cce01a01..72c1c8e2 100755 --- a/dell-csi-helm-installer/csi-offline-bundle.sh +++ b/dell-csi-helm-installer/csi-offline-bundle.sh @@ -227,13 +227,12 @@ CREATE="false" PREPARE="false" REGISTRY="" DRIVER="csi-unity" +DEFAULT_VERSION="v2.17.0" # some directories SCRIPTDIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)" REPODIR="$( dirname "${SCRIPTDIR}" )" -DRIVERVERSION="csi-unity-2.16.0" - while getopts "cprv:h" opt; do case $opt in c) @@ -264,6 +263,10 @@ while getopts "cprv:h" opt; do esac done +# Derive DRIVERVERSION from DEFAULT_VERSION (single source of truth) +DRIVERVERSION="${DRIVER}-${DEFAULT_VERSION#v}" + +# Allow override via -v option if [ -n "$HELMCHARTVERSION" ]; then DRIVERVERSION=$HELMCHARTVERSION fi diff --git a/dell-csi-helm-installer/verify-csi-unity.sh b/dell-csi-helm-installer/verify-csi-unity.sh index 3db0b85a..03cb317a 100644 --- a/dell-csi-helm-installer/verify-csi-unity.sh +++ b/dell-csi-helm-installer/verify-csi-unity.sh @@ -10,8 +10,8 @@ # verify-csi-unity method function verify-csi-unity() { - verify_k8s_versions "1.33" "1.35" - verify_openshift_versions "4.18" "4.20" + verify_k8s_versions "1.34" "1.36" + verify_openshift_versions "4.18" "4.21" verify_namespace "${NS}" verify_required_secrets "${RELEASE}-creds" verify_optional_secrets "${RELEASE}-certs" diff --git a/dell-csi-helm-installer/verify.sh b/dell-csi-helm-installer/verify.sh index c6a89c3e..682628bf 100755 --- a/dell-csi-helm-installer/verify.sh +++ b/dell-csi-helm-installer/verify.sh @@ -581,8 +581,8 @@ kubectl --help >&/dev/null || { MINION_NODES=$(run_command kubectl get nodes -o wide | grep -v -e master -e INTERNAL | awk ' { print $6; }') MASTER_NODES=$(run_command kubectl get nodes -o wide | awk ' /master/{ print $6; }') # Get the kubernetes major and minor version numbers. -kMajorVersion=$(run_command kubectl version | grep 'Server Version' | sed -E 's/.*v([0-9]+)\.[0-9]+\.[0-9]+.*/\1/') -kMinorVersion=$(run_command kubectl version | grep 'Server Version' | sed -E 's/.*v[0-9]+\.([0-9]+)\.[0-9]+.*/\1/') +kMajorVersion=$(run_command kubectl version -o="yaml" | grep -A8 'serverVersion:' | grep 'major'| egrep -o '[0-9]+') +kMinorVersion=$(run_command kubectl version -o="yaml" | grep -A8 'serverVersion:' | grep 'minor'| egrep -o '[0-9]+') kNonGAVersion=$(run_command kubectl version | grep 'Server Version' | sed -n 's/.*\(-[alpha|beta][^ ]*\).*/\1/p') while getopts ":h-:" optchar; do diff --git a/go.mod b/go.mod index 1047a234..25192279 100644 --- a/go.mod +++ b/go.mod @@ -1,25 +1,24 @@ module github.com/dell/csi-unity -go 1.25.0 +go 1.26 require ( bou.ke/monkey v1.0.2 - github.com/dell/dell-csi-extensions/podmon v1.10.0 - github.com/dell/gobrick v1.16.0 - github.com/dell/gocsi v1.16.0 - github.com/dell/gofsutil v1.21.0 - github.com/dell/goiscsi v1.14.0 - github.com/dell/gounity v1.23.0 - github.com/container-storage-interface/spec v1.6.0 + github.com/dell/dell-csi-extensions/podmon v1.11.0 + github.com/dell/gobrick v1.17.0 + github.com/dell/gocsi v1.17.0 + github.com/dell/gofsutil v1.22.0 + github.com/dell/goiscsi v1.15.0 + github.com/dell/gounity v1.24.0 + github.com/container-storage-interface/spec v1.11.0 github.com/cucumber/godog v0.15.0 - github.com/fsnotify/fsnotify v1.9.0 + github.com/fsnotify/fsnotify v1.10.1 github.com/kubernetes-csi/csi-lib-utils v0.11.0 github.com/sirupsen/logrus v1.9.3 github.com/spf13/viper v1.21.0 github.com/stretchr/testify v1.11.1 - golang.org/x/net v0.48.0 - google.golang.org/grpc v1.78.0 - google.golang.org/protobuf v1.36.10 + google.golang.org/grpc v1.81.0 + google.golang.org/protobuf v1.36.11 gopkg.in/yaml.v2 v2.4.0 gopkg.in/yaml.v3 v3.0.1 k8s.io/apimachinery v0.34.1 @@ -27,7 +26,7 @@ require ( ) require ( - github.com/dell/gonvme v1.13.0 // indirect + github.com/dell/gonvme v1.14.0 // indirect github.com/akutz/gosync v0.1.0 // indirect github.com/coreos/go-semver v0.3.1 // indirect github.com/coreos/go-systemd/v22 v22.6.0 // indirect @@ -68,15 +67,16 @@ require ( go.uber.org/zap v1.27.1 // indirect go.yaml.in/yaml/v2 v2.4.3 // indirect go.yaml.in/yaml/v3 v3.0.4 // indirect - golang.org/x/crypto v0.46.0 // indirect - golang.org/x/oauth2 v0.33.0 // indirect - golang.org/x/sync v0.19.0 // indirect - golang.org/x/sys v0.39.0 // indirect - golang.org/x/term v0.38.0 // indirect - golang.org/x/text v0.32.0 // indirect + golang.org/x/crypto v0.51.0 // indirect + golang.org/x/net v0.54.0 // indirect + golang.org/x/oauth2 v0.36.0 // indirect + golang.org/x/sync v0.20.0 // indirect + golang.org/x/sys v0.44.0 // indirect + golang.org/x/term v0.43.0 // indirect + golang.org/x/text v0.37.0 // indirect golang.org/x/time v0.14.0 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20251202230838-ff82c1b0f217 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20251202230838-ff82c1b0f217 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20260226221140-a57be14db171 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20260226221140-a57be14db171 // indirect gopkg.in/inf.v0 v0.9.1 // indirect k8s.io/api v0.34.1 // indirect k8s.io/klog/v2 v2.130.1 // indirect diff --git a/go.sum b/go.sum index 01ca304d..33975251 100644 --- a/go.sum +++ b/go.sum @@ -23,20 +23,20 @@ cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiy cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= -github.com/dell/dell-csi-extensions/podmon v1.10.0 h1:YeM9OmgJHE+n6aNaeEC96EuVev5x3pddggcM7Ws7pkk= -github.com/dell/dell-csi-extensions/podmon v1.10.0/go.mod h1:+g7fdyw1Zx74NBJQgi1BCtsywqk37MJd9JN86IPJJu0= -github.com/dell/gobrick v1.16.0 h1:z/a9qXnT3hx3D4I+SJUMnIgJtcCx0j3gzmPPDUWtoYs= -github.com/dell/gobrick v1.16.0/go.mod h1:9uoH8EsNi9yAsUZj2gZFgB5kqdlyvArqx0tYC7Qg9IM= -github.com/dell/gocsi v1.16.0 h1:avhQPD11rYzT6/dPxpZfFsJV+T/T0x1GJqqbco45W8c= -github.com/dell/gocsi v1.16.0/go.mod h1:Fz5dQv/kWf5Y1EXZEzxLBQSsnW2HE/WY95R0WCDQLO4= -github.com/dell/gofsutil v1.21.0 h1:SeusAYjiO/1ogvg/TapvCyHcrM9z+OvdaMU5i9Ijn3M= -github.com/dell/gofsutil v1.21.0/go.mod h1:qBGEz1wMOtqTODuJfiBZhUHT0JjexBblu2oa+sEclNs= -github.com/dell/goiscsi v1.14.0 h1:kNDqOlpJ3cLSJh7Hfyn/Kz/FMCKHzV0s/xx4EqnelFw= -github.com/dell/goiscsi v1.14.0/go.mod h1:SCSC8dJCqTosU7SspaoLv6ICTKNEz08rt/I8nZ3+ptc= -github.com/dell/gonvme v1.13.0 h1:j8A1BzYA48gelih3xWd/J6LQ71CbC8Lbdyv0jG8uUNU= -github.com/dell/gonvme v1.13.0/go.mod h1:L5K7V4JZTf12m3k2wdwKwP+/eA6pr8DvlCsJU1QTGOQ= -github.com/dell/gounity v1.23.0 h1:AxLbzsdrt+IBTz13kjPnNOpy3D4u3laN26kYVOtCp7I= -github.com/dell/gounity v1.23.0/go.mod h1:Rb2xvElfN4f9h0WWUXtGDSd86Vhnh5/TN+QIirjtbwU= +github.com/dell/dell-csi-extensions/podmon v1.11.0 h1:K7THnQ6ckhuHwAO59hM/kjpqZVi99XYIdgzLT6Eq35U= +github.com/dell/dell-csi-extensions/podmon v1.11.0/go.mod h1:vQrJUiJhxysGLl7TN5edroct3bXrnTn+12wbDwL4NQs= +github.com/dell/gobrick v1.17.0 h1:bfbNMhHmoiDLLrQbAlXxbSwCYp8RXO85OXKKF+XkpcM= +github.com/dell/gobrick v1.17.0/go.mod h1:omT0QLeai8b7NP+e/bQLUcuhaRQiKDgZQX6TOfweaLg= +github.com/dell/gocsi v1.17.0 h1:nrpnwiVgi0d+1Babpo+mFTbHRw/J8bBAIw9jcb/2zWE= +github.com/dell/gocsi v1.17.0/go.mod h1:GNJIfINdAzlScBdy2kkqcJNDL272dgJtrk5Xe/9/7I8= +github.com/dell/gofsutil v1.22.0 h1:g1ALo2Y7xbljPw3nCGZ6S0VXf4WR1HIuz1dP4fh8M7E= +github.com/dell/gofsutil v1.22.0/go.mod h1:dnFY+zuE79FGv76g8RdUMqmhBNllvu5e/crZt56xJx0= +github.com/dell/goiscsi v1.15.0 h1:71QzLLm4X8XrEkGLnZshpGEDdkgbFuZ8NiwARFwaCtY= +github.com/dell/goiscsi v1.15.0/go.mod h1:jlkRplXgeJHMZZ/dLUkWAnNcOrkIXxuibi9vDbPKYk4= +github.com/dell/gonvme v1.14.0 h1:dRyS0o+3B+cnnncgblb/H0qUJkNzjkPAq/82oqt/eMc= +github.com/dell/gonvme v1.14.0/go.mod h1:bx/tqYBKuY8SHxEpw9b8SiD/98+4TQdMYkYWES39Dgw= +github.com/dell/gounity v1.24.0 h1:2ZtZt3oflJc+igV+qCfTmoq28eQJqisLqgi0CrdxXsw= +github.com/dell/gounity v1.24.0/go.mod h1:DjQbCWN1XnvcsmHa/KsHWisZt9Aqzg9DsnQ9sN92E7o= github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= github.com/Azure/go-autorest/autorest v0.11.1/go.mod h1:JFgpikqFJ/MleTTxwepExTKnFUKKszPS8UavbQYUMuw= @@ -76,8 +76,8 @@ github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMn github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/container-storage-interface/spec v1.5.0/go.mod h1:8K96oQNkJ7pFcC2R9Z1ynGGBB1I93kcS6PGg3SsOk8s= -github.com/container-storage-interface/spec v1.6.0 h1:vwN9uCciKygX/a0toYryoYD5+qI9ZFeAMuhEEKO+JBA= -github.com/container-storage-interface/spec v1.6.0/go.mod h1:8K96oQNkJ7pFcC2R9Z1ynGGBB1I93kcS6PGg3SsOk8s= +github.com/container-storage-interface/spec v1.11.0 h1:H/YKTOeUZwHtyPOr9raR+HgFmGluGCklulxDYxSdVNM= +github.com/container-storage-interface/spec v1.11.0/go.mod h1:DtUvaQszPml1YJfIK7c00mlv6/g4wNMLanLgiUbKFRI= github.com/coreos/go-semver v0.3.1 h1:yi21YpKnrx1gt5R+la8n5WgS0kCrsPp33dmEyHReZr4= github.com/coreos/go-semver v0.3.1/go.mod h1:irMmmIw/7yzSRPWryHsK7EYSg09caPQL03VsM8rvUec= github.com/coreos/go-systemd/v22 v22.6.0 h1:aGVa/v8B7hpb0TKl0MWoAavPDmHvobFe5R5zn0bCJWo= @@ -112,8 +112,8 @@ github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHk github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= -github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k= -github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= +github.com/fsnotify/fsnotify v1.10.1 h1:b0/UzAf9yR5rhf3RPm9gf3ehBPpf0oZKIjtpKrx59Ho= +github.com/fsnotify/fsnotify v1.10.1/go.mod h1:TLheqan6HD6GBK6PrDWyDPBaEV8LspOxvPSjC+bVfgo= github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= @@ -298,8 +298,8 @@ github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= -github.com/onsi/gomega v1.39.0 h1:y2ROC3hKFmQZJNFeGAMeHZKkjBL65mIZcvrLQBF9k6Q= -github.com/onsi/gomega v1.39.0/go.mod h1:ZCU1pkQcXDO5Sl9/VVEGlDyp+zm0m1cmeG5TOzLgdh4= +github.com/onsi/gomega v1.40.0 h1:Vtol0e1MghCD2ZVIilPDIg44XSL9l2QAn8ZNaljWcJc= +github.com/onsi/gomega v1.40.0/go.mod h1:M/Uqpu/8qTjtzCLUA2zJHX9Iilrau25x1PdoSRbWh5A= github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4= github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY= github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= @@ -410,20 +410,20 @@ go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.59.0 h1:rgMkmiGfix9vFJDcDi1PK8WEQP4FLQwLDfhp5ZLpFeE= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.59.0/go.mod h1:ijPqXp5P6IRRByFVVg9DY8P5HkxkHE5ARIa+86aXPf4= -go.opentelemetry.io/otel v1.38.0 h1:RkfdswUDRimDg0m2Az18RKOsnI8UDzppJAtj01/Ymk8= -go.opentelemetry.io/otel v1.38.0/go.mod h1:zcmtmQ1+YmQM9wrNsTGV/q/uyusom3P8RxwExxkZhjM= +go.opentelemetry.io/otel v1.43.0 h1:mYIM03dnh5zfN7HautFE4ieIig9amkNANT+xcVxAj9I= +go.opentelemetry.io/otel v1.43.0/go.mod h1:JuG+u74mvjvcm8vj8pI5XiHy1zDeoCS2LB1spIq7Ay0= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.34.0 h1:OeNbIYk/2C15ckl7glBlOBp5+WlYsOElzTNmiPW/x60= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.34.0/go.mod h1:7Bept48yIeqxP2OZ9/AqIpYS94h2or0aB4FypJTc8ZM= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.34.0 h1:tgJ0uaNS4c98WRNUEx5U3aDlrDOI5Rs+1Vifcw4DJ8U= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.34.0/go.mod h1:U7HYyW0zt/a9x5J1Kjs+r1f/d4ZHnYFclhYY2+YbeoE= -go.opentelemetry.io/otel/metric v1.38.0 h1:Kl6lzIYGAh5M159u9NgiRkmoMKjvbsKtYRwgfrA6WpA= -go.opentelemetry.io/otel/metric v1.38.0/go.mod h1:kB5n/QoRM8YwmUahxvI3bO34eVtQf2i4utNVLr9gEmI= -go.opentelemetry.io/otel/sdk v1.38.0 h1:l48sr5YbNf2hpCUj/FoGhW9yDkl+Ma+LrVl8qaM5b+E= -go.opentelemetry.io/otel/sdk v1.38.0/go.mod h1:ghmNdGlVemJI3+ZB5iDEuk4bWA3GkTpW+DOoZMYBVVg= -go.opentelemetry.io/otel/sdk/metric v1.38.0 h1:aSH66iL0aZqo//xXzQLYozmWrXxyFkBJ6qT5wthqPoM= -go.opentelemetry.io/otel/sdk/metric v1.38.0/go.mod h1:dg9PBnW9XdQ1Hd6ZnRz689CbtrUp0wMMs9iPcgT9EZA= -go.opentelemetry.io/otel/trace v1.38.0 h1:Fxk5bKrDZJUH+AMyyIXGcFAPah0oRcT+LuNtJrmcNLE= -go.opentelemetry.io/otel/trace v1.38.0/go.mod h1:j1P9ivuFsTceSWe1oY+EeW3sc+Pp42sO++GHkg4wwhs= +go.opentelemetry.io/otel/metric v1.43.0 h1:d7638QeInOnuwOONPp4JAOGfbCEpYb+K6DVWvdxGzgM= +go.opentelemetry.io/otel/metric v1.43.0/go.mod h1:RDnPtIxvqlgO8GRW18W6Z/4P462ldprJtfxHxyKd2PY= +go.opentelemetry.io/otel/sdk v1.43.0 h1:pi5mE86i5rTeLXqoF/hhiBtUNcrAGHLKQdhg4h4V9Dg= +go.opentelemetry.io/otel/sdk v1.43.0/go.mod h1:P+IkVU3iWukmiit/Yf9AWvpyRDlUeBaRg6Y+C58QHzg= +go.opentelemetry.io/otel/sdk/metric v1.43.0 h1:S88dyqXjJkuBNLeMcVPRFXpRw2fuwdvfCGLEo89fDkw= +go.opentelemetry.io/otel/sdk/metric v1.43.0/go.mod h1:C/RJtwSEJ5hzTiUz5pXF1kILHStzb9zFlIEe85bhj6A= +go.opentelemetry.io/otel/trace v1.43.0 h1:BkNrHpup+4k4w+ZZ86CZoHHEkohws8AY+WTX09nk+3A= +go.opentelemetry.io/otel/trace v1.43.0/go.mod h1:/QJhyVBUUswCphDVxq+8mld+AvhXZLhe+8WVFxiFff0= go.opentelemetry.io/proto/otlp v1.5.0 h1:xJvq7gMzB31/d406fB8U5CBdyQGw4P399D1aQWU/3i4= go.opentelemetry.io/proto/otlp v1.5.0/go.mod h1:keN8WnHxOy8PG0rQZjJJ5A2ebUoafqWp0eVQ4yIXvJ4= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= @@ -447,8 +447,8 @@ golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.46.0 h1:cKRW/pmt1pKAfetfu+RCEvjvZkA9RimPbh7bhFjGVBU= -golang.org/x/crypto v0.46.0/go.mod h1:Evb/oLKmMraqjZ2iQTwDwvCtJkczlDuTmdJXoZVzqU0= +golang.org/x/crypto v0.51.0 h1:IBPXwPfKxY7cWQZ38ZCIRPI50YLeevDLlLnyC5wRGTI= +golang.org/x/crypto v0.51.0/go.mod h1:8AdwkbraGNABw2kOX6YFPs3WM22XqI4EXEd8g+x7Oc8= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -506,15 +506,15 @@ golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwY golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210520170846-37e1c6afe023/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.48.0 h1:zyQRTTrjc33Lhh0fBgT/H3oZq9WuvRR5gPC70xpDiQU= -golang.org/x/net v0.48.0/go.mod h1:+ndRgGjkh8FGtu1w1FGbEC31if4VrNVMuKTgcAAnQRY= +golang.org/x/net v0.54.0 h1:2zJIZAxAHV/OHCDTCOHAYehQzLfSXuf/5SoL/Dv6w/w= +golang.org/x/net v0.54.0/go.mod h1:Sj4oj8jK6XmHpBZU/zWHw3BV3abl4Kvi+Ut7cQcY+cQ= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.33.0 h1:4Q+qn+E5z8gPRJfmRy7C2gGG3T4jIprK6aSYgTXGRpo= -golang.org/x/oauth2 v0.33.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA= +golang.org/x/oauth2 v0.36.0 h1:peZ/1z27fi9hUOFCAZaHyrpWG5lwe0RJEEEeH0ThlIs= +golang.org/x/oauth2 v0.36.0/go.mod h1:YDBUJMTkDnJS+A4BP4eZBjCqtokkg1hODuPjwiGPO7Q= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -523,8 +523,8 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4= -golang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= +golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4= +golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -559,11 +559,11 @@ golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7w 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= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.39.0 h1:CvCKL8MeisomCi6qNZ+wbb0DN9E5AATixKsvNtMoMFk= -golang.org/x/sys v0.39.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/sys v0.44.0 h1:ildZl3J4uzeKP07r2F++Op7E9B29JRUy+a27EibtBTQ= +golang.org/x/sys v0.44.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.38.0 h1:PQ5pkm/rLO6HnxFR7N2lJHOZX6Kez5Y1gDSJla6jo7Q= -golang.org/x/term v0.38.0/go.mod h1:bSEAKrOT1W+VSu9TSCMtoGEOUcKxOKgl3LE5QEF/xVg= +golang.org/x/term v0.43.0 h1:S4RLU2sB31O/NCl+zFN9Aru9A/Cq2aqKpTZJ6B+DwT4= +golang.org/x/term v0.43.0/go.mod h1:lrhlHNdQJHO+1qVYiHfFKVuVioJIheAc3fBSMFYEIsk= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -571,8 +571,8 @@ golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.32.0 h1:ZD01bjUt1FQ9WJ0ClOL5vxgxOI/sVCNgX1YtKwcY0mU= -golang.org/x/text v0.32.0/go.mod h1:o/rUWzghvpD5TXrTIBuJU77MTaN0ljMWE47kxGJQ7jY= +golang.org/x/text v0.37.0 h1:Cqjiwd9eSg8e0QAkyCaQTNHFIIzWtidPahFWR83rTrc= +golang.org/x/text v0.37.0/go.mod h1:a5sjxXGs9hsn/AJVwuElvCAo9v8QYLzvavO5z2PiM38= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -619,8 +619,8 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk= -gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E= +gonum.org/v1/gonum v0.17.0 h1:VbpOemQlsSMrYmn7T2OUvQ4dqxQXU+ouZFQsZOx50z4= +gonum.org/v1/gonum v0.17.0/go.mod h1:El3tOrEuMpv2UdMrbNlKEh9vd86bmQ6vqIcDwxEOc1E= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= @@ -656,10 +656,10 @@ google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfG google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= google.golang.org/genproto v0.0.0-20201019141844-1ed22bb0c154/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto/googleapis/api v0.0.0-20251202230838-ff82c1b0f217 h1:fCvbg86sFXwdrl5LgVcTEvNC+2txB5mgROGmRL5mrls= -google.golang.org/genproto/googleapis/api v0.0.0-20251202230838-ff82c1b0f217/go.mod h1:+rXWjjaukWZun3mLfjmVnQi18E1AsFbDN9QdJ5YXLto= -google.golang.org/genproto/googleapis/rpc v0.0.0-20251202230838-ff82c1b0f217 h1:gRkg/vSppuSQoDjxyiGfN4Upv/h/DQmIR10ZU8dh4Ww= -google.golang.org/genproto/googleapis/rpc v0.0.0-20251202230838-ff82c1b0f217/go.mod h1:7i2o+ce6H/6BluujYR+kqX3GKH+dChPTQU19wjRPiGk= +google.golang.org/genproto/googleapis/api v0.0.0-20260226221140-a57be14db171 h1:tu/dtnW1o3wfaxCOjSLn5IRX4YDcJrtlpzYkhHhGaC4= +google.golang.org/genproto/googleapis/api v0.0.0-20260226221140-a57be14db171/go.mod h1:M5krXqk4GhBKvB596udGL3UyjL4I1+cTbK0orROM9ng= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260226221140-a57be14db171 h1:ggcbiqK8WWh6l1dnltU4BgWGIGo+EVYxCaAPih/zQXQ= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260226221140-a57be14db171/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= @@ -669,8 +669,8 @@ google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8 google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= -google.golang.org/grpc v1.78.0 h1:K1XZG/yGDJnzMdd/uZHAkVqJE+xIDOcmdSFZkBUicNc= -google.golang.org/grpc v1.78.0/go.mod h1:I47qjTo4OKbMkjA/aOOwxDIiPSBofUtQUI5EfpWvW7U= +google.golang.org/grpc v1.81.0 h1:W3G9N3KQf3BU+YuCtGKJk0CmxQNbAISICD/9AORxLIw= +google.golang.org/grpc v1.81.0/go.mod h1:xGH9GfzOyMTGIOXBJmXt+BX/V0kcdQbdcuwQ/zNw42I= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -683,8 +683,8 @@ google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGj 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= -google.golang.org/protobuf v1.36.10 h1:AYd7cD/uASjIL6Q9LiTjz8JLcrh/88q5UObnmY3aOOE= -google.golang.org/protobuf v1.36.10/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= +google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE= +google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/helper.mk b/helper.mk index 22dec8d7..4528f786 100644 --- a/helper.mk +++ b/helper.mk @@ -5,7 +5,7 @@ # owners. download-csm-common: - git clone --depth 1 git@github.com:CSM/csm.git temp-repo + git clone --depth 1 git@github.com:dell/csm.git temp-repo cp temp-repo/config/csm-common.mk . rm -rf temp-repo diff --git a/k8sutils/k8sutils_test.go b/k8sutils/k8sutils_test.go index 53bdb8f6..0de247dc 100644 --- a/k8sutils/k8sutils_test.go +++ b/k8sutils/k8sutils_test.go @@ -18,7 +18,6 @@ import ( "context" "errors" "fmt" - "io/ioutil" "os" "testing" "time" @@ -148,7 +147,7 @@ func TestCreateKubeClientSet(t *testing.T) { t.Run(tt.name, func(t *testing.T) { // Create a temporary kubeconfig file for the valid kubeconfig test case if tt.name == "Valid kubeconfig" || tt.name == "New for config error with valid kubeconfig" { - tmpFile, err := ioutil.TempFile("", "kubeconfig") + tmpFile, err := os.CreateTemp("", "kubeconfig") require.NoError(t, err) defer os.Remove(tmpFile.Name()) @@ -171,7 +170,7 @@ users: user: token: test-token ` - err = ioutil.WriteFile(tmpFile.Name(), []byte(kubeconfigContent), 0o600) + err = os.WriteFile(tmpFile.Name(), []byte(kubeconfigContent), 0o600) require.NoError(t, err) tt.kubeconfig = tmpFile.Name() } diff --git a/service/controller.go b/service/controller.go index 4c340d9e..f98edafd 100644 --- a/service/controller.go +++ b/service/controller.go @@ -15,6 +15,7 @@ package service import ( + "context" "errors" "fmt" "strconv" @@ -25,11 +26,11 @@ import ( "google.golang.org/protobuf/types/known/timestamppb" "github.com/dell/csi-unity/service/csiutils" + "github.com/dell/csi-unity/service/logging" "github.com/dell/gounity" types "github.com/dell/gounity/apitypes" "github.com/container-storage-interface/spec/lib/go/csi" "github.com/sirupsen/logrus" - "golang.org/x/net/context" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" "google.golang.org/protobuf/types/known/wrapperspb" @@ -97,7 +98,7 @@ const ( func (s *service) CreateVolume(ctx context.Context, req *csi.CreateVolumeRequest) (*csi.CreateVolumeResponse, error) { ctx, log, rid := GetRunidLog(ctx) - log.Debugf("Executing CreateVolume with args: %+v", *req) + log.Debugf("Executing CreateVolume with args: %+v", logging.LogRequestFields(req)) params := req.GetParameters() arrayID := strings.ToLower(strings.TrimSpace(params[keyArrayID])) if arrayID == "" { @@ -283,7 +284,7 @@ func (s *service) DeleteVolume( *csi.DeleteVolumeResponse, error, ) { ctx, log, rid := GetRunidLog(ctx) - log.Debugf("Executing DeleteVolume with args: %+v", *req) + log.Debugf("Executing DeleteVolume with args: %+v", logging.LogRequestFields(req)) var snapErr error volID, protocol, arrayID, unity, err := s.validateAndGetResourceDetails(ctx, req.GetVolumeId(), volumeType) if err != nil { @@ -332,7 +333,7 @@ func (s *service) ControllerPublishVolume( *csi.ControllerPublishVolumeResponse, error, ) { ctx, log, _ := GetRunidLog(ctx) - log.Debugf("Executing ControllerPublishVolume with args: %+v", *req) + log.Debugf("Executing ControllerPublishVolume with args: %+v", logging.LogRequestFields(req)) volID, protocol, arrayID, unity, err := s.validateAndGetResourceDetails(ctx, req.GetVolumeId(), volumeType) if err != nil { @@ -380,7 +381,7 @@ func (s *service) ControllerUnpublishVolume( *csi.ControllerUnpublishVolumeResponse, error, ) { ctx, log, rid := GetRunidLog(ctx) - log.Debugf("Executing ControllerUnpublishVolume with args: %+v", *req) + log.Debugf("Executing ControllerUnpublishVolume with args: %+v", logging.LogRequestFields(req)) volID, protocol, arrayID, unity, err := s.validateAndGetResourceDetails(ctx, req.GetVolumeId(), volumeType) if err != nil { @@ -455,7 +456,7 @@ func (s *service) ControllerUnpublishVolume( func (s *service) ValidateVolumeCapabilities(ctx context.Context, req *csi.ValidateVolumeCapabilitiesRequest) (*csi.ValidateVolumeCapabilitiesResponse, error) { ctx, log, rid := GetRunidLog(ctx) - log.Debugf("Executing ValidateVolumeCapabilities with args: %+v", *req) + log.Debugf("Executing ValidateVolumeCapabilities with args: %+v", logging.LogRequestFields(req)) volID, _, arrayID, unity, err := s.validateAndGetResourceDetails(ctx, req.GetVolumeId(), volumeType) if err != nil { @@ -502,7 +503,7 @@ func (s *service) GetCapacity( *csi.GetCapacityResponse, error, ) { ctx, log, rid := GetRunidLog(ctx) - log.Debugf("Executing GetCapacity with args: %+v", *req) + log.Debugf("Executing GetCapacity with args: %+v", logging.LogRequestFields(req)) params := req.GetParameters() @@ -556,7 +557,7 @@ func (s *service) getMaximumVolumeSize(ctx context.Context, arrayID string) (int func (s *service) CreateSnapshot(ctx context.Context, req *csi.CreateSnapshotRequest) (*csi.CreateSnapshotResponse, error) { ctx, log, rid := GetRunidLog(ctx) - log.Debugf("Executing CreateSnapshot with args: %+v", *req) + log.Debugf("Executing CreateSnapshot with args: %+v", logging.LogRequestFields(req)) if len(req.SourceVolumeId) == 0 { return nil, status.Error(codes.InvalidArgument, csiutils.GetMessageWithRunID(rid, "Storage Resource ID cannot be empty")) @@ -588,7 +589,7 @@ func (s *service) CreateSnapshot(ctx context.Context, req *csi.CreateSnapshotReq func (s *service) DeleteSnapshot(ctx context.Context, req *csi.DeleteSnapshotRequest) (*csi.DeleteSnapshotResponse, error) { ctx, log, rid := GetRunidLog(ctx) - log.Debugf("Executing DeleteSnapshot with args: %+v", *req) + log.Debugf("Executing DeleteSnapshot with args: %+v", logging.LogRequestFields(req)) snapID, _, arrayID, unity, err := s.validateAndGetResourceDetails(ctx, req.SnapshotId, snapshotType) if err != nil { @@ -620,7 +621,7 @@ func (s *service) DeleteSnapshot(ctx context.Context, req *csi.DeleteSnapshotReq func (s *service) ListSnapshots(ctx context.Context, req *csi.ListSnapshotsRequest) (*csi.ListSnapshotsResponse, error) { ctx, log, rid := GetRunidLog(ctx) - log.Infof("Executing ListSnapshot with args: %+v", *req) + log.Infof("Executing ListSnapshot with args: %+v", logging.LogRequestFields(req)) var ( startToken int @@ -675,7 +676,7 @@ func (s *service) controllerProbe(ctx context.Context, arrayID string) error { // Default supports all capabilities func (s *service) ControllerGetCapabilities(ctx context.Context, req *csi.ControllerGetCapabilitiesRequest) (*csi.ControllerGetCapabilitiesResponse, error) { ctx, log, _ := GetRunidLog(ctx) - log.Debugf("Executing ControllerGetCapabilities with args: %+v", *req) + log.Debugf("Executing ControllerGetCapabilities with args: %+v", logging.LogRequestFields(req)) capabilities := []*csi.ControllerServiceCapability{ { Type: &csi.ControllerServiceCapability_Rpc{ @@ -774,7 +775,7 @@ func (s *service) ControllerGetCapabilities(ctx context.Context, req *csi.Contro func (s *service) ControllerExpandVolume(ctx context.Context, req *csi.ControllerExpandVolumeRequest) (*csi.ControllerExpandVolumeResponse, error) { ctx, log, rid := GetRunidLog(ctx) - log.Debugf("Executing ControllerExpandVolume with args: %+v", *req) + log.Debugf("Executing ControllerExpandVolume with args: %+v", logging.LogRequestFields(req)) if req.VolumeId == "" { return nil, status.Error(codes.InvalidArgument, csiutils.GetMessageWithRunID(rid, "volumeId is mandatory parameter")) @@ -1864,7 +1865,7 @@ func (s *service) ControllerGetVolume(ctx context.Context, req *csi.ControllerGetVolumeRequest, ) (*csi.ControllerGetVolumeResponse, error) { ctx, log, rid := GetRunidLog(ctx) - log.Debugf("Executing ControllerGetVolume with args: %+v", *req) + log.Debugf("Executing ControllerGetVolume with args: %+v", logging.LogRequestFields(req)) volID, protocol, arrayID, unity, err := s.validateAndGetResourceDetails(ctx, req.GetVolumeId(), volumeType) if err != nil { diff --git a/service/identity.go b/service/identity.go index 86d83532..9171f9e0 100644 --- a/service/identity.go +++ b/service/identity.go @@ -15,10 +15,11 @@ package service import ( + "context" "strings" + "github.com/dell/csi-unity/service/logging" "github.com/container-storage-interface/spec/lib/go/csi" - "golang.org/x/net/context" ) func (s *service) Probe( @@ -27,7 +28,7 @@ func (s *service) Probe( *csi.ProbeResponse, error, ) { ctx, log, _ := GetRunidLog(ctx) - log.Infof("Executing Probe with args: %+v", *req) + log.Infof("Executing Probe with args: %+v", logging.LogRequestFields(req)) if strings.EqualFold(s.mode, "controller") { if err := s.controllerProbe(ctx, ""); err != nil { log.Error("Identity probe failed:", err) @@ -64,7 +65,7 @@ func (s *service) GetPluginCapabilities( *csi.GetPluginCapabilitiesResponse, error, ) { ctx, log, _ := GetRunidLog(ctx) - log.Infof("Executing GetPluginCapabilities with args: %+v", *req) + log.Infof("Executing GetPluginCapabilities with args: %+v", logging.LogRequestFields(req)) return &csi.GetPluginCapabilitiesResponse{ Capabilities: []*csi.PluginCapability{ { diff --git a/service/logging/logging.go b/service/logging/logging.go index cf66ddfb..8d95edda 100644 --- a/service/logging/logging.go +++ b/service/logging/logging.go @@ -211,3 +211,64 @@ func GetRunidAndLogger(ctx context.Context) (string, *logrus.Entry) { var GetRunidAndLoggerWrapper = func(ctx context.Context) (string, *logrus.Entry) { return GetRunidAndLogger(ctx) } + +// LogRequestFields safely logs request fields without copying mutex-containing structs +func LogRequestFields(req interface{}) logrus.Fields { + fields := logrus.Fields{} + + if req == nil { + return fields + } + + v := reflect.ValueOf(req) + if v.Kind() == reflect.Ptr { //nolint:govet + v = v.Elem() + } + + if v.Kind() != reflect.Struct { + return fields + } + + t := v.Type() + for i := 0; i < v.NumField(); i++ { + field := t.Field(i) + fieldValue := v.Field(i) + + // Skip unexported fields + if !fieldValue.CanInterface() { + continue + } + + // Skip fields that might contain mutexes or complex types + fieldType := field.Type.String() + if strings.Contains(fieldType, "protoimpl") || + strings.Contains(fieldType, "sync.Mutex") || + strings.Contains(fieldType, "sync.RWMutex") { + continue + } + + // Get the field value safely + val := fieldValue.Interface() + + // Only log simple types to avoid complex nested structures + switch typedVal := val.(type) { + case string, int, int32, int64, uint, uint32, uint64, bool, float32, float64: + fields[field.Name] = val + case []string: + if len(typedVal) > 0 { + fields[field.Name] = fmt.Sprintf("%v", val) + } + case []byte: + if len(typedVal) > 0 { + fields[field.Name] = fmt.Sprintf("data(%d bytes)", len(typedVal)) + } + default: + // For complex types, just log the type name + if val != nil { + fields[field.Name] = fmt.Sprintf("<%s>", fieldType) + } + } + } + + return fields +} diff --git a/service/logging/logging_test.go b/service/logging/logging_test.go index d7ce357a..7ddacc45 100644 --- a/service/logging/logging_test.go +++ b/service/logging/logging_test.go @@ -236,3 +236,320 @@ func TestFormatter_Format(t *testing.T) { assert.NoError(t, err, "Formatter should not return an error") assert.Equal(t, expectedOutput, string(output), "Formatted output should match expected output") } + +// Test structs for LogRequestFields testing +type TestSimpleStruct struct { + StringField string + IntField int + BoolField bool +} + +type TestStructWithMutex struct { + StringField string + MutexField sync.Mutex +} + +type TestStructWithProtoImpl struct { + StringField string + ProtoImplField interface{} // This will simulate protoimpl.MessageState +} + +type TestUnexportedFieldsStruct struct { + StringField string + unexportedField string + UnexportedMutex sync.Mutex +} + +type TestNestedStruct struct { + StringField string + NestedField struct { + InnerField string + } +} + +type TestPointerStruct struct { + StringField *string + IntField *int +} + +type TestInterfaceStruct struct { + StringField string + InterfaceField interface{} +} + +func TestLogRequestFields(t *testing.T) { + tests := []struct { + name string + req interface{} + expected logrus.Fields + }{ + { + name: "Nil request", + req: nil, + expected: logrus.Fields{}, + }, + { + name: "Simple struct with basic types", + req: TestSimpleStruct{ + StringField: "test", + IntField: 42, + BoolField: true, + }, + expected: logrus.Fields{ + "StringField": "test", + "IntField": 42, + "BoolField": true, + }, + }, + { + name: "Struct with mutex field should skip mutex", + req: TestStructWithMutex{ + StringField: "test", + MutexField: sync.Mutex{}, + }, + expected: logrus.Fields{ + "StringField": "test", + }, + }, + { + name: "Struct with protoimpl field should log protoimpl as type name", + req: TestStructWithProtoImpl{ + StringField: "test", + ProtoImplField: struct{}{}, // Simulate protoimpl.MessageState + }, + expected: logrus.Fields{ + "StringField": "test", + "ProtoImplField": "", + }, + }, + { + name: "Struct with unexported fields should skip unexported", + req: TestUnexportedFieldsStruct{ + StringField: "test", + unexportedField: "hidden", + UnexportedMutex: sync.Mutex{}, + }, + expected: logrus.Fields{ + "StringField": "test", + }, + }, + { + name: "Pointer to struct", + req: &TestSimpleStruct{ + StringField: "test", + IntField: 42, + BoolField: true, + }, + expected: logrus.Fields{ + "StringField": "test", + "IntField": 42, + "BoolField": true, + }, + }, + { + name: "Non-struct type should return empty", + req: "just a string", + expected: logrus.Fields{}, + }, + { + name: "Slice should return empty", + req: []string{"test"}, + expected: logrus.Fields{}, + }, + { + name: "Map should return empty", + req: map[string]string{"key": "value"}, + expected: logrus.Fields{}, + }, + { + name: "Struct with pointer fields", + req: TestPointerStruct{ + StringField: func() *string { s := "test"; return &s }(), + IntField: func() *int { i := 42; return &i }(), + }, + expected: logrus.Fields{ + "StringField": "<*string>", + "IntField": "<*int>", + }, + }, + { + name: "Struct with interface field should log interface as type name", + req: TestInterfaceStruct{ + StringField: "test", + InterfaceField: fmt.Errorf("error interface"), + }, + expected: logrus.Fields{ + "StringField": "test", + "InterfaceField": "", + }, + }, + { + name: "Empty struct", + req: struct{}{}, + expected: logrus.Fields{}, + }, + { + name: "Struct with zero values", + req: TestSimpleStruct{ + StringField: "", + IntField: 0, + BoolField: false, + }, + expected: logrus.Fields{ + "StringField": "", + "IntField": 0, + "BoolField": false, + }, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + result := LogRequestFields(test.req) + assert.Equal(t, test.expected, result, "LogRequestFields should return expected fields for test: %s", test.name) + }) + } +} + +func TestLogRequestFields_SkipProtoImplTypes(t *testing.T) { + // Test specific protoimpl type patterns that should be skipped + tests := []struct { + name string + req interface{} + expected logrus.Fields + }{ + { + name: "Skip protoimpl.MessageState", + req: struct { + SafeField string + UnsafeField interface{} // Simulate protoimpl.MessageState + }{ + SafeField: "safe", + UnsafeField: struct{}{}, + }, + expected: logrus.Fields{ + "SafeField": "safe", + "UnsafeField": "", + }, + }, + { + name: "Skip sync.Mutex", + req: struct { + SafeField string + UnsafeField sync.Mutex + }{ + SafeField: "safe", + UnsafeField: sync.Mutex{}, + }, + expected: logrus.Fields{ + "SafeField": "safe", + }, + }, + { + name: "Skip sync.RWMutex", + req: struct { + SafeField string + UnsafeField sync.RWMutex + }{ + SafeField: "safe", + UnsafeField: sync.RWMutex{}, + }, + expected: logrus.Fields{ + "SafeField": "safe", + }, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + result := LogRequestFields(test.req) + assert.Equal(t, test.expected, result, "Should skip unsafe fields for test: %s", test.name) + }) + } +} + +func TestLogRequestFields_ComplexTypes(t *testing.T) { + // Test handling of complex nested structures + tests := []struct { + name string + req interface{} + expected logrus.Fields + }{ + { + name: "Nested struct should be logged as type name", + req: TestNestedStruct{ + StringField: "safe", + NestedField: struct { + InnerField string + }{ + InnerField: "inner", + }, + }, + expected: logrus.Fields{ + "StringField": "safe", + "NestedField": "", + }, + }, + { + name: "Channel field should be logged as type name", + req: struct { + SafeField string + UnsafeField chan int + }{ + SafeField: "safe", + UnsafeField: make(chan int), + }, + expected: logrus.Fields{ + "SafeField": "safe", + "UnsafeField": "", + }, + }, + { + name: "Function field should be logged as type name", + req: struct { + SafeField string + UnsafeField func() + }{ + SafeField: "safe", + UnsafeField: func() {}, + }, + expected: logrus.Fields{ + "SafeField": "safe", + "UnsafeField": "", + }, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + result := LogRequestFields(test.req) + assert.Equal(t, test.expected, result, "Should handle complex types correctly for test: %s", test.name) + }) + } +} + +func TestLogRequestFields_RealWorldScenario(t *testing.T) { + // Test with a structure that mimics a real CSI request + type MockCSIRequest struct { + VolumeID string + Secrets map[string]string + ProtoImplState interface{} // Exported field to test logging + SizeCache sync.Mutex + UnknownFields sync.RWMutex + } + + req := &MockCSIRequest{ + VolumeID: "vol-123", + Secrets: map[string]string{"key": "value"}, + ProtoImplState: struct{}{}, + } + + expected := logrus.Fields{ // #nosec G101 + "VolumeID": "vol-123", + "Secrets": "", + "ProtoImplState": "", + } + + result := LogRequestFields(req) + assert.Equal(t, expected, result, "Should handle real-world CSI request structure correctly") +} diff --git a/service/mount.go b/service/mount.go index 9c86a5d3..f6748355 100644 --- a/service/mount.go +++ b/service/mount.go @@ -876,7 +876,7 @@ func removeWithRetry(ctx context.Context, target string) error { err = os.Remove(target) if err != nil && !os.IsNotExist(err) { log.Warnf("Error removing private mount target: %v", err) - cmd := exec.Command("/usr/bin/rmdir", target) + cmd := exec.Command("/usr/bin/rmdir", target) // #nosec G204 textBytes, err := cmd.CombinedOutput() if err != nil { log.Errorf("error calling rmdir: %v", err) diff --git a/service/node.go b/service/node.go index 72115880..9e60620f 100644 --- a/service/node.go +++ b/service/node.go @@ -43,18 +43,19 @@ import ( // Variables that can be used across module var ( - targetMountRecheckSleepTime = 3 * time.Second - disconnectVolumeRetryTime = 1 * time.Second - nodeStartTimeout = 3 * time.Second - lunzMutex sync.Mutex - nodeMutex sync.Mutex - sysBlock = "/sys/block" - syncNodeInfoChan chan bool - connectedSystemID = make([]string, 0) - VolumeNameLengthConstraint = 63 - initiatorsValidationAttempts = 30 - funcGetFCInitiators = csiutils.GetFCInitiators - maxDisconnectRetries = 3 + targetMountRecheckSleepTime = 3 * time.Second + disconnectVolumeRetryTime = 1 * time.Second + nodeStartTimeout = 3 * time.Second + lunzMutex sync.Mutex + nodeMutex sync.Mutex + sysBlock = "/sys/block" + syncNodeInfoChan chan bool + connectedSystemID = make([]string, 0) + VolumeNameLengthConstraint = 63 + initiatorsValidationAttempts = 30 + initiatorsValidationTimePerAttempt = 10 + funcGetFCInitiators = csiutils.GetFCInitiators + maxDisconnectRetries = 3 ) const ( @@ -76,7 +77,7 @@ func (s *service) NodeStageVolume( *csi.NodeStageVolumeResponse, error, ) { ctx, log, rid := GetRunidLog(ctx) - log.Debugf("Executing NodeStageVolume with args: %+v", *req) + log.Debugf("Executing NodeStageVolume with args: %+v", logging.LogRequestFields(req)) volID, protocol, arrayID, unity, err := s.validateAndGetResourceDetails(ctx, req.GetVolumeId(), volumeType) if err != nil { return nil, err @@ -232,7 +233,7 @@ func (s *service) NodeUnstageVolume( *csi.NodeUnstageVolumeResponse, error, ) { ctx, log, rid := GetRunidLog(ctx) - log.Debugf("Executing NodeUnstageVolume with args: %+v", *req) + log.Debugf("Executing NodeUnstageVolume with args: %+v", logging.LogRequestFields(req)) // Get the VolumeID and parse it volID, protocol, arrayID, unity, err := s.validateAndGetResourceDetails(ctx, req.GetVolumeId(), volumeType) @@ -360,7 +361,7 @@ func (s *service) NodePublishVolume( *csi.NodePublishVolumeResponse, error, ) { ctx, log, rid := GetRunidLog(ctx) - log.Debugf("Executing NodePublishVolume with args: %+v", *req) + log.Debugf("Executing NodePublishVolume with args: %+v", logging.LogRequestFields(req)) var ephemeralVolume bool ephemeral, ok := req.VolumeContext["csi.storage.k8s.io/ephemeral"] @@ -569,7 +570,7 @@ func (s *service) NodeUnpublishVolume( *csi.NodeUnpublishVolumeResponse, error, ) { ctx, log, rid := GetRunidLog(ctx) - log.Debugf("Executing NodeUnpublishVolume with args: %+v", *req) + log.Debugf("Executing NodeUnpublishVolume with args: %+v", logging.LogRequestFields(req)) var isEphemeralVolume bool volName := req.VolumeId @@ -709,7 +710,7 @@ func (s *service) NodeGetInfo( *csi.NodeGetInfoResponse, error, ) { ctx, log, rid := GetRunidLog(ctx) - log.Debugf("Executing NodeGetInfo with args: %+v", *req) + log.Debugf("Executing NodeGetInfo with args: %+v", logging.LogRequestFields(req)) arraysList := s.getStorageArrayList() @@ -738,7 +739,10 @@ func (s *service) NodeGetInfo( } } - s.validateProtocols(ctx, arraysList) + s.validateProtocolOnce.Do(func() { + s.validateProtocols(ctx, arraysList) + }) + topology := getTopology() // If topology keys are empty then this node is not capable of either iSCSI/FC but can still provision NFS volumes by default log.Debugf("Topology Keys--->%+v", topology) @@ -781,7 +785,7 @@ func (s *service) NodeGetCapabilities( *csi.NodeGetCapabilitiesResponse, error, ) { ctx, log, _ := GetRunidLog(ctx) - log.Infof("Executing NodeGetCapabilities with args: %+v", *req) + log.Infof("Executing NodeGetCapabilities with args: %+v", logging.LogRequestFields(req)) capabilities := []*csi.NodeServiceCapability{ { Type: &csi.NodeServiceCapability_Rpc{ @@ -842,7 +846,7 @@ func (s *service) NodeGetVolumeStats( *csi.NodeGetVolumeStatsResponse, error, ) { ctx, log, rid := GetRunidLog(ctx) - log.Debugf("Executing NodeGetVolumeStats with args: %+v", *req) + log.Debugf("Executing NodeGetVolumeStats with args: %+v", logging.LogRequestFields(req)) if req.VolumeId == "" { return nil, status.Error(codes.InvalidArgument, csiutils.GetMessageWithRunID(rid, "volumeId is mandatory parameter")) @@ -952,7 +956,7 @@ func (s *service) NodeGetVolumeStats( func (s *service) NodeExpandVolume(ctx context.Context, req *csi.NodeExpandVolumeRequest) (*csi.NodeExpandVolumeResponse, error) { ctx, log, rid := GetRunidLog(ctx) - log.Debugf("Executing NodeExpandVolume with args: %+v", *req) + log.Debugf("Executing NodeExpandVolume with args: %+v", logging.LogRequestFields(req)) if req.VolumeId == "" { return nil, status.Error(codes.InvalidArgument, csiutils.GetMessageWithRunID(rid, "volumeId is mandatory parameter")) @@ -1945,15 +1949,19 @@ func (s *service) validateProtocols(ctx context.Context, arraysList []*StorageAr fcHealthy := false iscsiHealthy := false - // Wait for up to 5 minutes for the initiators to appear as logged in on the array + // Wait for up to initiatorsValidationTimePerAttemptSec*initiatorsValidationAttempts for the + // initiators to appear as logged in on the array. + log.Infof("Re-trying initiators health validation for %d seconds.", + initiatorsValidationTimePerAttempt*initiatorsValidationAttempts) for attempt := 1; attempt <= initiatorsValidationAttempts; attempt++ { if attempt > 1 { // First attempt does not need to wait - // Sleep 10 seconds or until context is closed + // Sleep initiatorsValidationTimePerAttemptSec seconds or until context is closed select { case <-ctx.Done(): log.Errorf("Context is closed") return - case <-time.After(10 * time.Second): + + case <-time.After(time.Duration(initiatorsValidationTimePerAttempt) * time.Second): log.Infof("Re-trying initiators health validation (%d)", attempt) } } diff --git a/service/node_test.go b/service/node_test.go index 0f034eec..6a174428 100644 --- a/service/node_test.go +++ b/service/node_test.go @@ -22,6 +22,7 @@ import ( "reflect" "strconv" "sync" + "sync/atomic" "testing" "time" @@ -895,6 +896,46 @@ func TestNodeGetInfo(t *testing.T) { assert.Nil(t, res) } +func TestNodeGetInfoValidateProtocolsCalledOnce(t *testing.T) { + // Create a fresh service so validateProtocolOnce has not yet fired. + // arrays is empty so the unProcessedArrays loop exits immediately. + s := &service{ + iscsiClient: goiscsi.NewMockISCSI(nil), + arrays: new(sync.Map), + opts: Opts{ + NodeName: "test-node", + LongNodeName: "long-test-node", + }, + } + + // funcGetFCInitiators is called exactly once at the start of + // validateProtocols, so counting its invocations tells us how + // many times validateProtocols was entered. + origGetFCInitiators := funcGetFCInitiators + var callCount atomic.Int32 + funcGetFCInitiators = func(_ context.Context) ([]string, error) { + callCount.Add(1) + return nil, nil + } + defer func() { funcGetFCInitiators = origGetFCInitiators }() + + const numGoroutines = 10 + var wg sync.WaitGroup + wg.Add(numGoroutines) + + for i := 0; i < numGoroutines; i++ { + go func() { + defer wg.Done() + _, err := s.NodeGetInfo(context.Background(), &csi.NodeGetInfoRequest{}) + assert.NoError(t, err) + }() + } + + wg.Wait() + assert.Equal(t, int32(1), callCount.Load(), + "validateProtocols should be called exactly once across parallel NodeGetInfo calls") +} + func TestNodeUnpublishVolume(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() diff --git a/service/service.go b/service/service.go index 96d07d4c..fbccb1a0 100644 --- a/service/service.go +++ b/service/service.go @@ -138,12 +138,19 @@ type Opts struct { } type service struct { - opts Opts - arrays *sync.Map - mode string - iscsiClient goiscsi.ISCSIinterface - fcConnector fcConnector // gobrick connectors - iscsiConnector iSCSIConnector + // satisfies the Service interface and provides unimplemented defaults to functions not implemented + csi.UnimplementedControllerServer + csi.UnimplementedGroupControllerServer + csi.UnimplementedIdentityServer + csi.UnimplementedNodeServer + + opts Opts + arrays *sync.Map + mode string + iscsiClient goiscsi.ISCSIinterface + fcConnector fcConnector // gobrick connectors + iscsiConnector iSCSIConnector + validateProtocolOnce sync.Once } type iSCSIConnector interface { diff --git a/service/service_test.go b/service/service_test.go index 14e5eef1..a0789abb 100644 --- a/service/service_test.go +++ b/service/service_test.go @@ -17,7 +17,6 @@ package service import ( "context" "errors" - "io/ioutil" "net/http" "net/http/httptest" "os" @@ -533,7 +532,7 @@ func TestGetNodeLabels(t *testing.T) { defer mockServer.Close() // Create kubeconfig file - tmpFile, err := ioutil.TempFile("", "kubeconfig") + tmpFile, err := os.CreateTemp("", "kubeconfig") require.NoError(t, err) defer os.Remove(tmpFile.Name()) kubeconfigContent := ` @@ -555,7 +554,7 @@ users: user: token: test-token ` - err = ioutil.WriteFile(tmpFile.Name(), []byte(kubeconfigContent), 0o600) + err = os.WriteFile(tmpFile.Name(), []byte(kubeconfigContent), 0o600) require.NoError(t, err) testConf.service.opts.KubeConfigPath = tmpFile.Name() testConf.service.opts.LongNodeName = "test-node" diff --git a/service/validator.go b/service/validator.go index 0587dd4c..b5ee4dee 100644 --- a/service/validator.go +++ b/service/validator.go @@ -15,6 +15,7 @@ package service import ( + "context" "fmt" "strconv" @@ -22,7 +23,6 @@ import ( "github.com/dell/csi-unity/service/logging" types "github.com/dell/gounity/apitypes" "github.com/container-storage-interface/spec/lib/go/csi" - "golang.org/x/net/context" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" ) diff --git a/service/validator_test.go b/service/validator_test.go index 83639e77..1a8bcfae 100644 --- a/service/validator_test.go +++ b/service/validator_test.go @@ -20,8 +20,8 @@ import ( "testing" "bou.ke/monkey" - "github.com/container-storage-interface/spec/lib/go/csi" types "github.com/dell/gounity/apitypes" + "github.com/container-storage-interface/spec/lib/go/csi" "github.com/stretchr/testify/assert" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" diff --git a/test/bdd-test/bdd_main_test.go b/test/bdd-test/bdd_main_test.go index 6ef17925..4312f255 100644 --- a/test/bdd-test/bdd_main_test.go +++ b/test/bdd-test/bdd_main_test.go @@ -25,12 +25,12 @@ import ( "gopkg.in/yaml.v2" - "github.com/container-storage-interface/spec/lib/go/csi" - "github.com/cucumber/godog" - "github.com/cucumber/godog/colors" "github.com/dell/csi-unity/provider" "github.com/dell/csi-unity/service" csiutils "github.com/dell/gocsi/utils/csi" + "github.com/container-storage-interface/spec/lib/go/csi" + "github.com/cucumber/godog" + "github.com/cucumber/godog/colors" "google.golang.org/grpc" ) @@ -56,12 +56,12 @@ type StorageArrayConfig struct { func TestMain(m *testing.M) { os.Setenv("X_CSI_MODE", "") - file, err := os.ReadFile(os.Getenv("DRIVER_SECRET")) + file, err := os.ReadFile(os.Getenv("DRIVER_SECRET")) // #nosec G703 if err != nil { panic("Driver Config missing") } arrayIDList := StorageArrayList{} - _ = yaml.Unmarshal([]byte(file), &arrayIDList) + _ = yaml.Unmarshal([]byte(file), &arrayIDList) // #nosec G709 if len(arrayIDList.StorageArrayList) == 0 { panic("Array Info not provided") } diff --git a/test/bdd-test/bdd_test.go b/test/bdd-test/bdd_test.go index 4d79f5fc..1e92e44b 100644 --- a/test/bdd-test/bdd_test.go +++ b/test/bdd-test/bdd_test.go @@ -1176,12 +1176,12 @@ func (f *feature) whenICallNodeGetInfo() error { } func (f *feature) iValidateTopologyIsCorrectlySet() error { - file, err := os.ReadFile(os.Getenv("DRIVER_SECRET")) + file, err := os.ReadFile(os.Getenv("DRIVER_SECRET")) // #nosec G703 if err != nil { panic("Driver Config missing") } arrayIDList := StorageArrayList{} - _ = yaml.Unmarshal([]byte(file), &arrayIDList) + _ = yaml.Unmarshal([]byte(file), &arrayIDList) // #nosec G709 for _, array := range arrayIDList.StorageArrayList { topology := "csi-unity.dellemc.com/" + strings.ToLower(array.ArrayID) + "-nfs" diff --git a/test/integration-test/integration_main_test.go b/test/integration-test/integration_main_test.go index 4bd7f352..f36f62d2 100644 --- a/test/integration-test/integration_main_test.go +++ b/test/integration-test/integration_main_test.go @@ -23,11 +23,11 @@ import ( "testing" "time" - "github.com/container-storage-interface/spec/lib/go/csi" - "github.com/cucumber/godog" "github.com/dell/csi-unity/provider" "github.com/dell/csi-unity/service" csiutils "github.com/dell/gocsi/utils/csi" + "github.com/container-storage-interface/spec/lib/go/csi" + "github.com/cucumber/godog" "google.golang.org/grpc" ) @@ -46,7 +46,7 @@ func TestMain(m *testing.M) { var stop func() os.Setenv("X_CSI_MODE", "") - file, err := os.ReadFile(os.Getenv("DRIVER_CONFIG")) + file, err := os.ReadFile(os.Getenv("DRIVER_CONFIG")) // #nosec G703 if err != nil { panic("Driver Config missing") }