diff --git a/Dockerfile b/Dockerfile index 5df4d63..8b0f9fd 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,25 +1,25 @@ # SPDX-License-Identifier: Apache-2.0 -# Copyright (c) 2022-2023 Dell Inc, or its subsidiaries. - -FROM docker.io/library/golang:1.21.4-alpine as builder - -WORKDIR /app - -# Download necessary Go modules -COPY go.mod ./ -COPY go.sum ./ -RUN go mod download - -# build an app -COPY cmd/ cmd/ -COPY pkg/ pkg/ -RUN go build -v -o /opi-cni /app/cmd/... - -# second stage to reduce image size -FROM alpine:3.18 -RUN apk add --no-cache --no-check-certificate hwdata && rm -rf /var/cache/apk/* -COPY --from=builder /opi-cni / -COPY --from=docker.io/fullstorydev/grpcurl:v1.8.9-alpine /bin/grpcurl /usr/local/bin/ -EXPOSE 50051 8082 -CMD [ "/opi-cni", "-grpc_port=50051", "-http_port=8082" ] -HEALTHCHECK CMD grpcurl -plaintext localhost:50051 list || exit 1 +# Copyright (C) 2023 Network Plumping Working Group +# Copyright (C) 2023 Nordix Foundation. + +FROM golang:alpine as builder + +COPY . /usr/src/opi-cni + +ENV HTTP_PROXY $http_proxy +ENV HTTPS_PROXY $https_proxy + +WORKDIR /usr/src/opi-cni +RUN apk add --no-cache --virtual build-dependencies build-base=~0.5 && \ + make clean && \ + make build + +FROM alpine:3 +COPY --from=builder /usr/src/opi-cni/build/opi /usr/bin/ +WORKDIR / + +LABEL io.k8s.display-name="OPI CNI" + +COPY ./images/entrypoint.sh / + +ENTRYPOINT ["/entrypoint.sh"] \ No newline at end of file diff --git a/Makefile b/Makefile index 5bf6672..d0fc850 100644 --- a/Makefile +++ b/Makefile @@ -1,51 +1,166 @@ # SPDX-License-Identifier: Apache-2.0 -# Copyright (c) 2023 Dell Inc, or its subsidiaries. +# Copyright (C) 2023 Network Plumping Working Group +# Copyright (C) 2023 Nordix Foundation. -ROOT_DIR='.' -PROJECTNAME=$(shell basename "$(PWD)") +# +# Credit: +# This makefile was adapted from: https://github.com/vincentbernat/hellogopher/blob/feature/glide/Makefile +# -# Make is verbose in Linux. Make it silent. -MAKEFLAGS += --silent +# This Makefile is based on: https://github.com/k8snetworkplumbingwg/sriov-cni/tree/v2.7.0 -compile: get build +# Package related +BINARY_NAME=opi +PACKAGE=opi-cni +ORG_PATH=github.com/opiproject +REPO_PATH=$(ORG_PATH)/$(PACKAGE) +GOPATH=$(CURDIR)/.gopath +GOBIN=$(CURDIR)/bin +BUILDDIR=$(CURDIR)/build +BASE=$(GOPATH)/src/$(REPO_PATH) +GOFILES = $(shell find . -name *.go | grep -vE "(\/vendor\/)|(_test.go)") +PKGS = $(or $(PKG),$(shell cd $(BASE) && env GOPATH=$(GOPATH) $(GO) list ./... | grep -v "^$(PACKAGE)/vendor/")) +TESTPKGS = $(shell env GOPATH=$(GOPATH) $(GO) list -f '{{ if or .TestGoFiles .XTestGoFiles }}{{ .ImportPath }}{{ end }}' $(PKGS)) -build: - @echo " > Building binaries..." - @CGO_ENABLED=0 go build -o ${PROJECTNAME} ./cmd/... +export GOPATH +export GOBIN +export GO111MODULE=on +# Docker +IMAGEDIR=$(BASE)/images +DOCKERFILE=$(CURDIR)/Dockerfile +TAG=ghcr.io/opiproject/opi-cni +# Accept proxy settings for docker +DOCKERARGS= +ifdef HTTP_PROXY + DOCKERARGS += --build-arg http_proxy=$(HTTP_PROXY) +endif +ifdef HTTPS_PROXY + DOCKERARGS += --build-arg https_proxy=$(HTTPS_PROXY) +endif -get: - @echo " > Checking if there are any missing dependencies..." - @CGO_ENABLED=0 go get ./... +# Go tools +GO = go +GODOC = godoc +GOFMT = gofmt +TIMEOUT = 15 +V ?= 0 +Q = $(if $(filter 1,$V),,@) -tools: - go get golang.org/x/tools/cmd/goimports - go get github.com/kisielk/errcheck - go get github.com/axw/gocov/gocov - go get github.com/matm/gocov-html - go get github.com/tools/godep - go get github.com/mitchellh/gox - go get github.com/golang/lint/golint +.PHONY: all +all: fmt lint build -test: - @echo " > Running ginkgo test suites..." - # can replace with a recursive command ginkgo suites are defined for all packages - ginkgo grpc pkg +$(BASE): ; $(info Setting GOPATH...) + @mkdir -p $(dir $@) + @ln -sf $(CURDIR) $@ -vet: - @CGO_ENABLED=0 go vet -v ./... +$(GOBIN): + @mkdir -p $@ -errors: - errcheck -ignoretests -blank ./... +$(BUILDDIR): | $(BASE) ; $(info Creating build directory...) + @cd $(BASE) && mkdir -p $@ -lint: - golint ./... +build: $(BUILDDIR)/$(BINARY_NAME) ; $(info Building $(BINARY_NAME)...) @ ## Build OPI CNI plugin + $(info Done!) -imports: - goimports -l -w . +$(BUILDDIR)/$(BINARY_NAME): $(GOFILES) | $(BUILDDIR) + @cd $(BASE)/cmd/$(BINARY_NAME) && CGO_ENABLED=0 $(GO) build -o $(BUILDDIR)/$(BINARY_NAME) -tags no_openssl -v -fmt: - @CGO_ENABLED=0 go fmt ./... -mock-generate: - @echo " > Starting mock code generation..." - # Generate mocks for exported interfaces +# Tools + +GOLANGCILINT = $(GOBIN)/golangci-lint +$(GOLANGCILINT): | $(BASE) ; $(info Installing golangci-lint...) + $Q go install github.com/golangci/golangci-lint/cmd/golangci-lint@v1.55.2 + +GOCOVMERGE = $(GOBIN)/gocovmerge +$(GOCOVMERGE): | $(BASE) ; $(info Building gocovmerge...) + $Q go install github.com/wadey/gocovmerge@latest + +GOCOV = $(GOBIN)/gocov +$(GOCOV): | $(BASE) ; $(info Building gocov...) + $Q go install github.com/axw/gocov/gocov@v1.1.0 + +GOCOVXML = $(GOBIN)/gocov-xml +$(GOCOVXML): | $(BASE) ; $(info Building gocov-xml...) + $Q go install github.com/AlekSi/gocov-xml@latest + +GCOV2LCOV = $(GOBIN)/gcov2lcov +$(GCOV2LCOV): | $(BASE) ; $(info building gcov2lcov...) + $Q go install github.com/jandelgado/gcov2lcov@latest + +GO2XUNIT = $(GOBIN)/go2xunit +$(GO2XUNIT): | $(BASE) ; $(info Building go2xunit...) + $Q go install github.com/tebeka/go2xunit@latest + + +# Tests + +TEST_TARGETS := test-default test-bench test-short test-verbose test-race +.PHONY: $(TEST_TARGETS) test-xml check test tests +test-bench: ARGS=-run=__absolutelynothing__ -bench=. ## Run benchmarks +test-short: ARGS=-short ## Run only short tests +test-verbose: ARGS=-v ## Run tests in verbose mode with coverage reporting +test-race: ARGS=-race ## Run tests with race detector +$(TEST_TARGETS): NAME=$(MAKECMDGOALS:test-%=%) +$(TEST_TARGETS): test +check test tests: fmt lint | $(BASE) ; $(info Running $(NAME:%=% )tests...) @ ## Run tests + $Q cd $(BASE) && $(GO) test -timeout $(TIMEOUT)s $(ARGS) $(TESTPKGS) + +test-xml: fmt lint | $(BASE) $(GO2XUNIT) ; $(info Running $(NAME:%=% )tests...) @ ## Run tests with xUnit output + $Q cd $(BASE) && 2>&1 $(GO) test -timeout 20s -v $(TESTPKGS) | tee test/tests.output + $(GO2XUNIT) -fail -input test/tests.output -output test/tests.xml + +COVERAGE_DIR = $(CURDIR)/test/coverage +COVERAGE_MODE = atomic +COVERAGE_PROFILE = $(COVERAGE_DIR)/profile.out +COVERAGE_XML = $(COVERAGE_DIR)/coverage.xml +COVERAGE_HTML = $(COVERAGE_DIR)/index.html +.PHONY: test-coverage test-coverage-tools +test-coverage-tools: | $(GOCOVMERGE) $(GOCOV) $(GOCOVXML) $(GCOV2LCOV) +test-coverage: fmt test-coverage-tools | $(BASE) ; $(info Running coverage tests...) @ ## Run coverage tests + $Q mkdir -p $(COVERAGE_DIR)/pkgs + $Q cd $(BASE) && for pkg in $(TESTPKGS); do \ + $(GO) test \ + -coverpkg=$(REPO_PATH)/... \ + -covermode=$(COVERAGE_MODE) \ + -coverprofile="$(COVERAGE_DIR)/pkgs/`echo $$pkg | tr "/" "-"`.cover" $$pkg ;\ + done + $Q $(GOCOVMERGE) $(COVERAGE_DIR)/pkgs/*.cover > $(COVERAGE_PROFILE) + $Q $(GO) tool cover -html=$(COVERAGE_PROFILE) -o $(COVERAGE_HTML) + $Q $(GOCOV) convert $(COVERAGE_PROFILE) | $(GOCOVXML) > $(COVERAGE_XML) + $Q $(GCOV2LCOV) -infile $(COVERAGE_PROFILE) -outfile $(COVERAGE_DIR)/lcov.info + +.PHONY: lint +lint: | $(BASE) $(GOLANGCILINT) ; $(info Running golangci-lint...) @ ## Run golint on all source files + $Q $(GOLANGCILINT) run ./... + +.PHONY: fmt +fmt: ; $(info Running gofmt...) @ ## Run gofmt on all source files + @ret=0 && for d in $$($(GO) list -f '{{.Dir}}' ./... | grep -v /vendor/); do \ + $(GOFMT) -l -w $$d/*.go || ret=$$? ; \ + done ; exit $$ret + +# Docker image +# To pass proxy for Docker invoke it as 'make image HTTP_POXY=http://192.168.0.1:8080' +.PHONY: image +image: | $(BASE) ; $(info Building Docker image...) @ ## Build OPI CNI docker image + @docker build -t $(TAG) -f $(DOCKERFILE) $(CURDIR) $(DOCKERARGS) + +# Misc + +.PHONY: deps-update +deps-update: ; $(info Updating dependencies...) @ ## Update dependencies + @go mod tidy && go mod vendor + +.PHONY: clean +clean: | $(BASE) ; $(info Cleaning...) @ ## Cleanup everything + @cd $(BASE) && $(GO) clean --modcache --cache --testcache + @rm -rf $(GOPATH) + @rm -rf $(BUILDDIR) + @rm -rf $(GOBIN) + @rm -rf test/ + +.PHONY: help +help: ; @ ## Display this help message + @grep -E '^[ a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | \ + awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-15s\033[0m %s\n", $$1, $$2}' diff --git a/NOTICE b/NOTICE new file mode 100644 index 0000000..432b533 --- /dev/null +++ b/NOTICE @@ -0,0 +1,12 @@ +OPI CNI +Copyright (C) 2023 Nordix Foundation + +This product includes software developed at +Nordix Foundation (http://www.nordix.org). + +This project contains code developed by the participants of the Network Plumbing Working Group +(https://github.com/k8snetworkplumbingwg/community) + +The getFileNamesFromPath function in +utils/utils.go was created by NVIDIA CORPORATION & AFFILIATES (http://www.nvidia.com/) +Copyright 2023 NVIDIA CORPORATION & AFFILIATES \ No newline at end of file diff --git a/README.md b/README.md index 0524ffb..b644216 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,18 @@ -# Opi CNI is a new CNI for DPUs +- [OPI CNI plugin](#opi-cni-plugin) + - [Build](#build) + - [Kubernetes Quick Start](#kubernetes-quick-start) + - [Usage](#usage) + - [Basic configuration parameters](#basic-configuration-parameters) + - [Example NADs](#example-nads) + - [Access type](#access-type) + - [Selective trunk type](#selective-trunk-type) + - [Transparent trunk type](#transparent-trunk-type) + - [Kernel driver device](#kernel-driver-device) + - [DPDK userspace driver device](#dpdk-userspace-driver-device) + - [CNI Configuration](#cni-configuration) + - [I Want To Contribute](#i-want-to-contribute) + +# OPI CNI plugin [![Linters](https://github.com/opiproject/opi-cni/actions/workflows/linters.yml/badge.svg)](https://github.com/opiproject/opi-cni/actions/workflows/linters.yml) [![CodeQL](https://github.com/opiproject/opi-cni/actions/workflows/codeql.yml/badge.svg)](https://github.com/opiproject/opi-cni/actions/workflows/codeql.yml) @@ -14,20 +28,177 @@ [![GitHub stars](https://img.shields.io/github/stars/opiproject/opi-cni.svg?style=flat-square&label=github%20stars)](https://github.com/opiproject/opi-cni) [![GitHub Contributors](https://img.shields.io/github/contributors/opiproject/opi-cni.svg?style=flat-square)](https://github.com/opiproject/opi-cni/graphs/contributors) -This repo includes OPI CNI code for K8S to allow offloading CNI to DPUs. +This plugin integrates with the different xPU cards in order to enable secondary xPU VF interfaces in the Kubernetes Pods which will terminate traffic that runs through an xPU pipeline. -## I Want To Contribute +It has two main sections. The first one attaches xPU VFs into Pods the same way as any SR-IOV VF. The second part contacts the [opi-evpn-bridge](https://github.com/opiproject/opi-evpn-bridge) component in order to create a `BridgePort` which will act as the abstracted port representor of the previously attached VF in the Pod. The `BridgePort` can be of type `access` attaching to only one `LogicalBridge` or of type `trunk` attaching to multiple `LogicalBridges`. This way the `opi-evpn-bridge` component will offload all the appropriate rules into the xPU forwarding pipeline which will result in traffic flowing from and towards the Pod using the attached xPU VF which acts as secondary interface in the Pod's networking namespace. -This project welcomes contributions and suggestions. We are happy to have the Community involved via submission of **Issues and Pull Requests** (with substantive content or even just fixes). We are hoping for the documents, test framework, etc. to become a community process with active engagement. PRs can be reviewed by by any number of people, and a maintainer may accept. +The plugin is heavily integrated with the [EVPN GW API](https://github.com/opiproject/opi-api/tree/main/network/evpn-gw) in OPI and is used to serve the EVPN GW offload Use Case into an xPU. The only xPU that is supported currently is the Intel Mt.Evans IPU card. + + + +OPI CNI plugin works with [SR-IOV device plugin](https://github.com/k8snetworkplumbingwg/sriov-network-device-plugin) for VF allocation in Kubernetes. A metaplugin such as [Multus](https://github.com/intel/multus-cni) gets the allocated VF's `deviceID` (PCI address) and is responsible for invoking the OPI CNI plugin with that `deviceID`. + +The CNI has been tested against Multus v4.0.1, v3.9.1 versions + +## Build + +This plugin uses Go modules for dependency management and requires Go 1.20.x to build. + +To build the plugin binary: + +`` +make +`` + +Upon successful build the plugin binary will be available in `build/opi`. + +## Kubernetes Quick Start +A full guide on orchestrating SR-IOV virtual functions in Kubernetes can be found at the [SR-IOV Device Plugin project.](https://github.com/k8snetworkplumbingwg/sriov-network-device-plugin#quick-start) + +Creating VFs is outside the scope of the OPI CNI plugin. [More information about allocating VFs on different NICs can be found here](https://github.com/k8snetworkplumbingwg/sriov-network-device-plugin/blob/master/docs/vf-setup.md) + +To deploy OPI CNI by itself on a Kubernetes 1.23+ cluster + +Build the OPI CNI docker image: + +`make image` + +Deploy the OPI CNI daemonset: + +`kubectl apply -f images/opi-cni-daemonset.yaml` + +**Note** The above deployment is not sufficient to manage and configure SR-IOV virtual functions. [See the full orchestration guide for more information.](https://github.com/k8snetworkplumbingwg/sriov-network-device-plugin#sr-iov-network-device-plugin) + + +## Usage +OPI CNI networks are commonly configured using Multus and SR-IOV Device Plugin using Network Attachment Definitions. More information about configuring Kubernetes networks using this pattern can be found in the [Multus configuration reference document.](https://github.com/k8snetworkplumbingwg/multus-cni/blob/master/docs/configuration.md) -See [CONTRIBUTING](https://github.com/opiproject/opi/blob/main/CONTRIBUTING.md) and [GitHub Basic Process](https://github.com/opiproject/opi/blob/main/doc-github-rules.md) for more details. +A Network Attachment Definition for OPI CNI takes the form: -## Getting started +``` +apiVersion: "k8s.cni.cncf.io/v1" +kind: NetworkAttachmentDefinition +metadata: + name: nad-access + annotations: + k8s.v1.cni.cncf.io/resourceName: intel.com/intel_sriov_mev +spec: + config: '{ + "cniVersion": "0.4.0", + "type": "opi", + "logical_bridge": "//network.opiproject.org/bridges/vlan10", + "ipam": { + "type": "static" + } + }' +``` -:exclamation: `docker-compose` is deprecated. For details, see [Migrate to Compose V2](https://docs.docker.com/compose/migrate/). +The `.spec.config` field contains the configuration information used by the OPI CNI. -Run `docker-compose up -d` or `docker compose up -d` +### Basic configuration parameters -## Diagrams +The following parameters are generic parameters which are not specific to the OPI CNI configuration, though (with the exception of ipam) they need to be included in the config. + +* `cniVersion` : the version of the CNI spec used. +* `type` : CNI plugin used. "opi" corresponds to OPI CNI. +* `ipam` (optional) : the configuration of the IP Address Management plugin. Required to designate an IP for a kernel interface. + +### Example NADs +The following examples show the config needed to set up basic secondary networking in a container using OPI CNI. Each of the json config objects below can be placed in the `.spec.config` field of a Network Attachment Definition to integrate with Multus. + +#### Access type +To allow untagged vlan access type of traffic flowing from and towards the attached XPU VF of the Pod then a NAD is needed that will refer to just one `LogicalBridge`. This way the `BridgePort` that will be created by OPI CNI will be of type `Access` + +``` +apiVersion: "k8s.cni.cncf.io/v1" +kind: NetworkAttachmentDefinition +metadata: + name: nad-access + annotations: + k8s.v1.cni.cncf.io/resourceName: intel.com/intel_sriov_mev +spec: + config: '{ + "cniVersion": "0.4.0", + "type": "xpu", + "logical_bridge": "//network.opiproject.org/bridges/vlan10", + "ipam": { + "type": "static" + } + }' +``` + +#### Selective trunk type +To allow selective vlan tagged type of traffic flowing from and towards the attached xPU VF of the Pod then a NAD is needed that will refer to multiple `LogicalBridges`. This way the `BridgePort` that will be created by OPI CNI will be of type `Trunk` but only for selective range of VLANs + +``` +apiVersion: "k8s.cni.cncf.io/v1" +kind: NetworkAttachmentDefinition +metadata: + name: nad-selective-trunk + annotations: + k8s.v1.cni.cncf.io/resourceName: intel.com/intel_sriov_mev +spec: + config: '{ + "cniVersion": "0.4.0", + "type": "opi", + "logical_bridges": ["//network.opiproject.org/bridges/vlan10","//network.opiproject.org/bridges/vlan20","//network.opiproject.org/bridges/vlan40"] + }' +``` + +#### Transparent trunk type +To allow transparent vlan tagged type of traffic flowing from and towards the attached xPU VF of the Pod then a NAD is needed without any `LogicalBridges`. This way the `BridgePort` that will be created by OPI CNI will be of type `Trunk` and will allow transparent vlan tagged traffic. + +``` +apiVersion: "k8s.cni.cncf.io/v1" +kind: NetworkAttachmentDefinition +metadata: + name: nad-trunk + annotations: + k8s.v1.cni.cncf.io/resourceName: intel.com/intel_sriov_mev +spec: + config: '{ + "cniVersion": "0.4.0", + "type": "opi" + }' +``` + +### Kernel driver device + +All the above examples can work implicitly when xPU VFs using a kernel driver are configured as secondary interfaces into containers. Also when the VF is handled by a kernel driver any IPAM configuration that is passed will be configured into the attached VF in the container. + +### DPDK userspace driver device + +The above examples will configure also a xPU VF using a userspace driver (uio/vfio) for use in a container. If this plugin is used with a xPU VF bound to a dpdk driver then the IPAM configuration will still be respected, but it will only allocate IP address(es) using the specified IPAM plugin, not apply the IP address(es) to container interface. In order for the OPI CNI to configure a userspace driver bound xPU VF the only thing that needs to be changed in the above example NADs is the annotation so the correct device pool is used. + +### CNI Configuration +Due to a limitation on Intel Mt.Evans for the dpdk use case to work +we need a `pci_to_mac.conf` file that looks like this: + +```json +{ + "0000:b0:00.1": "00:21:00:00:03:14", + "0000:b0:00.0": "00:20:00:00:03:14", + "0000:b0:00.3": "00:23:00:00:03:14", + "0000:b0:00.2": "00:22:00:00:03:14" +} +``` + +in the path: `/etc/cni/net.d/opi.d/` + +The OPI CNI plugin needs a `opi.conf` configuration file in order to know where to find the `pci_to_mac.conf` file and also how to contact the `opi-evpn-bridge` grpc server (It is a component of the bigger xpu_infra_mgr system) for the creation of the `BridgePorts`. The file looks like this: + +```json +{ + "xpu_infra_mgr_conn": ":", + "pci_to_mac_path": "/etc/cni/net.d/opi.d/pci_to_mac.conf" +} +``` + +and should be putted in the path: `/etc/cni/net.d/opi.d/` + +**Note** [DHCP](https://github.com/containernetworking/plugins/tree/master/plugins/ipam/dhcp) IPAM plugin can not be used for VF bound to a dpdk driver (uio/vfio). + +### I Want To Contribute +This project welcomes contributions and suggestions. We are happy to have the Community involved via submission of **Issues and Pull Requests** (with substantive content or even just fixes). We are hoping for the documents, test framework, etc. to become a community process with active engagement. PRs can be reviewed by by any number of people, and a maintainer may accept. -Tbd +See [CONTRIBUTING](https://github.com/opiproject/opi/blob/main/CONTRIBUTING.md) and [GitHub Basic Process](https://github.com/opiproject/opi/blob/main/doc-github-rules.md) for more details. \ No newline at end of file diff --git a/cmd/main.go b/cmd/main.go deleted file mode 100644 index ac28402..0000000 --- a/cmd/main.go +++ /dev/null @@ -1,5 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// Copyright (c) 2022-2023 Dell Inc, or its subsidiaries. -// Copyright (C) 2023 Nordix Foundation. - -package main \ No newline at end of file diff --git a/cmd/opi/main.go b/cmd/opi/main.go new file mode 100644 index 0000000..8224d8d --- /dev/null +++ b/cmd/opi/main.go @@ -0,0 +1,326 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright (C) 2023 Network Plumping Working Group +// Copyright (c) 2022-2023 Dell Inc, or its subsidiaries. +// Copyright (C) 2023 Nordix Foundation. + +// package main holds the main functionality of opi-cni +package main + +import ( + "errors" + "fmt" + "runtime" + + "github.com/opiproject/opi-cni/pkg/config" + "github.com/opiproject/opi-cni/pkg/sriov" + opitypes "github.com/opiproject/opi-cni/pkg/types" + "github.com/opiproject/opi-cni/pkg/utils" + "github.com/opiproject/opi-cni/pkg/xpu" + + "github.com/containernetworking/cni/pkg/skel" + "github.com/containernetworking/cni/pkg/types" + current "github.com/containernetworking/cni/pkg/types/100" + "github.com/containernetworking/cni/pkg/version" + "github.com/containernetworking/plugins/pkg/ipam" + "github.com/containernetworking/plugins/pkg/ns" +) + +type envArgs struct { + types.CommonArgs + MAC types.UnmarshallableString `json:"mac,omitempty"` +} + +//nolint:gochecknoinits +func init() { + // this ensures that main runs only on main thread (thread group leader). + // since namespace ops (unshare, setns) are done for a single thread, we + // must ensure that the goroutine does not jump from OS thread to thread + runtime.LockOSThread() +} + +func getEnvArgs(envArgsString string) (*envArgs, error) { + if envArgsString != "" { + e := envArgs{} + err := types.LoadArgs(envArgsString, &e) + if err != nil { + return nil, err + } + return &e, nil + } + return nil, nil +} + +func deleteResources(args *skel.CmdArgs, netConf *opitypes.NetConf) error { + var err error + + if netConf == nil { + // if there is no netConf object there is no point + // of continuing as all the subsequent calls depend on the + // netConf object + return nil + } + + sm := sriov.NewSriovManager() + + if netConf.IPAM.Type != "" { + err = ipam.ExecDel(netConf.IPAM.Type, args.StdinData) + if err != nil { + return err + } + } + + // Delete Bridge Port. + err = xpu.DeleteBridgePort(netConf) + if err != nil { + return fmt.Errorf("deleteResources() error deleting Bridge Port: %q", err) + } + + /* ResetVFConfig resets a VF administratively. We must run ResetVFConfig + before ReleaseVF because some drivers will error out if we try to + reset netdev VF with trust off. So, reset VF MAC address via PF first. + */ + err = sm.ResetVFConfig(netConf) + if err != nil { + return fmt.Errorf("deleteResources() error resetting VF administratively: %q", err) + } + + if !netConf.DPDKMode { + if args.Netns == "" { + // Reset netdev VF to its original state + err = sm.ResetVF(netConf) + if err != nil { + return fmt.Errorf("deleteResources() error Resetting VF to original state: %q", err) + } + } else { + var netns ns.NetNS + netns, err = ns.GetNS(args.Netns) + if err != nil { + _, ok := err.(ns.NSPathNotExistErr) + if ok { + // Reset netdev VF to its original state if NS Path not exist + err = sm.ResetVF(netConf) + if err != nil { + return fmt.Errorf("deleteResources() error Resetting VF to original state: %q", err) + } + } else { + return fmt.Errorf("deleteResources() failed to open netns %s: %q", netns, err) + } + } else { + defer func() { + _ = netns.Close() + }() + + // Release VF from Pods namespace and rename it to the original name + err = sm.ReleaseVF(netConf, netns, args.Netns) + if err != nil { + return fmt.Errorf("deleteResources() error releasing VF: %q", err) + } + // Reset VF to its original state. + // This one will run mostly for the case where the VF is not found in the container NS from the previous function + // so we assume that the VF will be on the host namespace. + err = sm.ResetVF(netConf) + if err != nil { + return fmt.Errorf("deleteResources() error Resetting VF to original state: %q", err) + } + } + } + } + + // Mark the pci address as released + allocator := utils.NewPCIAllocator(config.DefaultCNIDir) + if err = allocator.DeleteAllocatedPCI(netConf.DeviceID); err != nil { + return fmt.Errorf("deleteResources() error cleaning the pci allocation for vf pci address %s: %v", netConf.DeviceID, err) + } + + return nil +} + +//nolint:funlen,gocognit +func cmdAdd(args *skel.CmdArgs) error { + var macAddr string + var err error + var netConf *opitypes.NetConf + + defer func() { + // Call deleteResources() in case of error. + if err != nil { + _ = deleteResources(args, netConf) + } + }() + + netConf, err = config.LoadConf(args.StdinData) + if err != nil { + return fmt.Errorf("opi-cni failed to load netconf: %v", err) + } + + envArgs, err := getEnvArgs(args.Args) + if err != nil { + return fmt.Errorf("opi-cni failed to parse args: %v", err) + } + + if envArgs != nil { + MAC := string(envArgs.MAC) + if MAC != "" { + netConf.MAC = MAC + } + } + + // RuntimeConfig takes preference than envArgs. + // This maintains compatibility of using envArgs + // for MAC config. + if netConf.RuntimeConfig.Mac != "" { + netConf.MAC = netConf.RuntimeConfig.Mac + } + + netns, err := ns.GetNS(args.Netns) + if err != nil { + return fmt.Errorf("failed to open netns %q: %v", netns, err) + } + defer func() { + _ = netns.Close() + }() + + sm := sriov.NewSriovManager() + err = sm.FillOriginalVfInfo(netConf) + if err != nil { + return fmt.Errorf("failed to get original vf information: %v", err) + } + + if err = sm.ApplyVFConfig(netConf); err != nil { + return fmt.Errorf("opi-cni failed to configure VF %q", err) + } + + result := ¤t.Result{} + result.Interfaces = []*current.Interface{{ + Name: args.IfName, + Sandbox: netns.Path(), + }} + + if !netConf.DPDKMode { + macAddr, err = sm.SetupVF(netConf, args.IfName, netns) + if err != nil { + return fmt.Errorf("failed to set up pod interface %q from the device %q: %v", args.IfName, netConf.Master, err) + } + + result.Interfaces[0].Mac = macAddr + } else { + // Handle here the dpdk case for the VF + if netConf.PciToMacPath == "" { + return errors.New("PciToMacPath cannot be empty when the device is not NetDev") + } + macAddr, err = utils.RetrieveMacFromPci(netConf.DeviceID, netConf.PciToMacPath) + if err != nil { + return fmt.Errorf("error in retrieving the Mac from PciToMac %s file for pci %s : %q", netConf.PciToMacPath, netConf.DeviceID, err) + } + + result.Interfaces[0].Mac = macAddr + } + + // Create Bridge Port representor for xPU VF + + // Create BridgePort + err = xpu.CreateBridgePort(netConf, result.Interfaces[0].Mac) + if err != nil { + return err + } + + // run the IPAM plugin + if netConf.IPAM.Type != "" { + var r types.Result + r, err = ipam.ExecAdd(netConf.IPAM.Type, args.StdinData) + if err != nil { + return fmt.Errorf("failed to set up IPAM plugin type %q from the device %q: %v", netConf.IPAM.Type, netConf.Master, err) + } + + // Convert the IPAM result into the current Result type + var newResult *current.Result + newResult, err = current.NewResultFromResult(r) + if err != nil { + return err + } + + if len(newResult.IPs) == 0 { + err = errors.New("IPAM plugin returned missing IP config") + return err + } + + newResult.Interfaces = result.Interfaces + + for _, ipc := range newResult.IPs { + // All addresses apply to the container interface (move from host) + ipc.Interface = current.Int(0) + } + + if !netConf.DPDKMode { + err = netns.Do(func(_ ns.NetNS) error { + err := ipam.ConfigureIface(args.IfName, newResult) + if err != nil { + return err + } + + /* After IPAM configuration is done, the following needs to handle the case of an IP address being reused by a different pods. + * This is achieved by sending Gratuitous ARPs and/or Unsolicited Neighbor Advertisements unconditionally. + * Although we set arp_notify and ndisc_notify unconditionally on the interface (please see EnableArpAndNdiscNotify()), the kernel + * only sends GARPs/Unsolicited NA when the interface goes from down to up, or when the link-layer address changes on the interfaces. + * These scenarios are perfectly valid and recommended to be enabled for optimal network performance. + * However for our specific case, which the kernel is unaware of, is the reuse of IP addresses across pods where each pod has a different + * link-layer address for it's SRIOV interface. The ARP/Neighbor cache residing in neighbors would be invalid if an IP address is reused. + * In order to update the cache, the GARP/Unsolicited NA packets should be sent for performance reasons. Otherwise, the neighbors + * may be sending packets with the incorrect link-layer address. Eventually, most network stacks would send ARPs and/or Neighbor + * Solicitation packets when the connection is unreachable. This would correct the invalid cache; however this may take a significant + * amount of time to complete. + * + * The error is ignored here because enabling this feature is only a performance enhancement. + */ + _ = utils.AnnounceIPs(args.IfName, newResult.IPs) + return nil + }) + if err != nil { + return err + } + } + result = newResult + } + + allocator := utils.NewPCIAllocator(config.DefaultCNIDir) + // Mark the pci address as in used + if err = allocator.SaveAllocatedPCI(netConf.DeviceID, args.Netns); err != nil { + return fmt.Errorf("error saving the pci allocation for vf pci address %s: %v", netConf.DeviceID, err) + } + + // Cache NetConf for CmdDel + if err = utils.SaveNetConf(args.ContainerID, config.DefaultCNIDir, args.IfName, netConf); err != nil { + return fmt.Errorf("error saving NetConf %q", err) + } + + return types.PrintResult(result, netConf.CNIVersion) +} + +func cmdDel(args *skel.CmdArgs) error { + netConf, cRefPath, err := config.LoadConfFromCache(args) + if err != nil { + // There is no point of continuing if there is no cached Netconf + // as all the subsequent calls depend on that. + return nil + } + + err = deleteResources(args, netConf) + if err != nil { + return fmt.Errorf("cmdDel() error deleting resources: %q", err) + } + + err = utils.CleanCachedNetConf(cRefPath) + if err != nil { + return fmt.Errorf("cmdDel() error cleaning up cached NetConf file: %q", err) + } + + return nil +} + +func cmdCheck(_ *skel.CmdArgs) error { + return nil +} + +func main() { + skel.PluginMain(cmdAdd, cmdCheck, cmdDel, version.All, "") +} diff --git a/go.mod b/go.mod index 2c16fae..a212da6 100644 --- a/go.mod +++ b/go.mod @@ -1,238 +1,27 @@ module github.com/opiproject/opi-cni -go 1.19 +go 1.20 require ( - github.com/golangci/golangci-lint v1.55.2 - github.com/google/uuid v1.4.0 - github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.0.1 - github.com/grpc-ecosystem/grpc-gateway/v2 v2.18.1 - github.com/onsi/ginkgo/v2 v2.13.1 - github.com/opiproject/opi-api v0.0.0-20231120071940-7b62be4a63bd - github.com/opiproject/opi-smbios-bridge v0.1.3-0.20231125032256-38107633f91d - github.com/philippgille/gokv v0.6.0 - github.com/philippgille/gokv/gomap v0.6.0 - github.com/philippgille/gokv/redis v0.6.0 - github.com/stretchr/testify v1.8.4 - github.com/vektra/mockery/v2 v2.37.1 + github.com/containernetworking/cni v1.1.2 + github.com/containernetworking/plugins v1.2.0 + github.com/imdario/mergo v0.3.15 + github.com/k8snetworkplumbingwg/sriovnet v1.2.0 + github.com/opiproject/opi-api v0.0.0-20231016162146-d81cc5ee60d4 github.com/vishvananda/netlink v1.2.1-beta.2 - github.com/ziutek/telnet v0.0.0-20180329124119-c3b780dc415b - go.einride.tech/aip v0.65.0 - go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.46.1 - go.opentelemetry.io/otel v1.21.0 - go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.21.0 - go.opentelemetry.io/otel/sdk v1.21.0 - go.opentelemetry.io/otel/trace v1.21.0 - golang.org/x/tools v0.15.0 - google.golang.org/grpc v1.59.0 - google.golang.org/protobuf v1.31.0 + golang.org/x/net v0.8.0 + google.golang.org/grpc v1.55.0 ) require ( - 4d63.com/gocheckcompilerdirectives v1.2.1 // indirect - 4d63.com/gochecknoglobals v0.2.1 // indirect - github.com/4meepo/tagalign v1.3.3 // indirect - github.com/Abirdcfly/dupword v0.0.13 // indirect - github.com/Antonboom/errname v0.1.12 // indirect - github.com/Antonboom/nilnil v0.1.7 // indirect - github.com/Antonboom/testifylint v0.2.3 // indirect - github.com/BurntSushi/toml v1.3.2 // indirect - github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24 // indirect - github.com/GaijinEntertainment/go-exhaustruct/v3 v3.1.0 // indirect - github.com/Masterminds/semver v1.5.0 // indirect - github.com/OpenPeeDeeP/depguard/v2 v2.1.0 // indirect - github.com/StackExchange/wmi v1.2.1 // indirect - github.com/alecthomas/go-check-sumtype v0.1.3 // indirect - github.com/alexkohler/nakedret/v2 v2.0.2 // indirect - github.com/alexkohler/prealloc v1.0.0 // indirect - github.com/alingse/asasalint v0.0.11 // indirect - github.com/ashanbrown/forbidigo v1.6.0 // indirect - github.com/ashanbrown/makezero v1.1.1 // indirect - github.com/beorn7/perks v1.0.1 // indirect - github.com/bkielbasa/cyclop v1.2.1 // indirect - github.com/blizzy78/varnamelen v0.8.0 // indirect - github.com/bombsimon/wsl/v3 v3.4.0 // indirect - github.com/breml/bidichk v0.2.7 // indirect - github.com/breml/errchkjson v0.3.6 // indirect - github.com/butuzov/ireturn v0.2.2 // indirect - github.com/butuzov/mirror v1.1.0 // indirect - github.com/catenacyber/perfsprint v0.2.0 // indirect - github.com/ccojocar/zxcvbn-go v1.0.1 // indirect - github.com/cenkalti/backoff/v4 v4.2.1 // indirect - github.com/cespare/xxhash/v2 v2.2.0 // indirect - github.com/charithe/durationcheck v0.0.10 // indirect - github.com/chavacava/garif v0.1.0 // indirect - github.com/chigopher/pathlib v0.15.0 // indirect - github.com/curioswitch/go-reassign v0.2.0 // indirect - github.com/daixiang0/gci v0.11.2 // indirect - github.com/davecgh/go-spew v1.1.1 // indirect - github.com/denis-tingaikin/go-header v0.4.3 // indirect - github.com/esimonov/ifshort v1.0.4 // indirect - github.com/ettle/strcase v0.1.1 // indirect - github.com/fatih/color v1.15.0 // indirect - github.com/fatih/structtag v1.2.0 // indirect - github.com/firefart/nonamedreturns v1.0.4 // indirect - github.com/fsnotify/fsnotify v1.6.0 // indirect - github.com/fzipp/gocyclo v0.6.0 // indirect - github.com/ghodss/yaml v1.0.0 // indirect - github.com/ghostiam/protogetter v0.2.3 // indirect - github.com/go-critic/go-critic v0.9.0 // indirect - github.com/go-logr/logr v1.3.0 // indirect - github.com/go-logr/stdr v1.2.2 // indirect - github.com/go-ole/go-ole v1.3.0 // indirect - github.com/go-redis/redis v6.15.9+incompatible // indirect - github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect - github.com/go-toolsmith/astcast v1.1.0 // indirect - github.com/go-toolsmith/astcopy v1.1.0 // indirect - github.com/go-toolsmith/astequal v1.1.0 // indirect - github.com/go-toolsmith/astfmt v1.1.0 // indirect - github.com/go-toolsmith/astp v1.1.0 // indirect - github.com/go-toolsmith/strparse v1.1.0 // indirect - github.com/go-toolsmith/typep v1.1.0 // indirect - github.com/go-xmlfmt/xmlfmt v1.1.2 // indirect - github.com/gobwas/glob v0.2.3 // indirect - github.com/gofrs/flock v0.8.1 // indirect + github.com/coreos/go-iptables v0.6.0 // indirect github.com/golang/protobuf v1.5.3 // indirect - github.com/golangci/check v0.0.0-20180506172741-cfe4005ccda2 // indirect - github.com/golangci/dupl v0.0.0-20180902072040-3e9179ac440a // indirect - github.com/golangci/go-misc v0.0.0-20220329215616-d24fe342adfe // indirect - github.com/golangci/gofmt v0.0.0-20231018234816-f50ced29576e // indirect - github.com/golangci/lint-1 v0.0.0-20191013205115-297bf364a8e0 // indirect - github.com/golangci/maligned v0.0.0-20180506175553-b1d89398deca // indirect - github.com/golangci/misspell v0.4.1 // indirect - github.com/golangci/revgrep v0.5.2 // indirect - github.com/golangci/unconvert v0.0.0-20180507085042-28b1c447d1f4 // indirect - github.com/google/go-cmp v0.6.0 // indirect - github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 // indirect - github.com/gordonklaus/ineffassign v0.0.0-20230610083614-0e73809eb601 // indirect - github.com/gostaticanalysis/analysisutil v0.7.1 // indirect - github.com/gostaticanalysis/comment v1.4.2 // indirect - github.com/gostaticanalysis/forcetypeassert v0.1.0 // indirect - github.com/gostaticanalysis/nilerr v0.1.1 // indirect - github.com/hashicorp/errwrap v1.0.0 // indirect - github.com/hashicorp/go-multierror v1.1.1 // indirect - github.com/hashicorp/go-version v1.6.0 // indirect - github.com/hashicorp/hcl v1.0.0 // indirect - github.com/hexops/gotextdiff v1.0.3 // indirect - github.com/huandu/xstrings v1.4.0 // indirect - github.com/iancoleman/strcase v0.2.0 // indirect - github.com/inconshreveable/mousetrap v1.1.0 // indirect - github.com/jaypipes/ghw v0.12.0 // indirect - github.com/jaypipes/pcidb v1.0.0 // indirect - github.com/jgautheron/goconst v1.6.0 // indirect - github.com/jingyugao/rowserrcheck v1.1.1 // indirect - github.com/jinzhu/copier v0.3.5 // indirect - github.com/jirfag/go-printf-func-name v0.0.0-20200119135958-7558a9eaa5af // indirect - github.com/julz/importas v0.1.0 // indirect - github.com/kisielk/errcheck v1.6.3 // indirect - github.com/kisielk/gotool v1.0.0 // indirect - github.com/kkHAIKE/contextcheck v1.1.4 // indirect - github.com/kulti/thelper v0.6.3 // indirect - github.com/kunwardeep/paralleltest v1.0.8 // indirect - github.com/kyoh86/exportloopref v0.1.11 // indirect - github.com/ldez/gomoddirectives v0.2.3 // indirect - github.com/ldez/tagliatelle v0.5.0 // indirect - github.com/leonklingele/grouper v1.1.1 // indirect - github.com/lufeee/execinquery v1.2.1 // indirect - github.com/macabu/inamedparam v0.1.2 // indirect - github.com/magiconair/properties v1.8.7 // indirect - github.com/maratori/testableexamples v1.0.0 // indirect - github.com/maratori/testpackage v1.1.1 // indirect - github.com/matoous/godox v0.0.0-20230222163458-006bad1f9d26 // indirect - github.com/mattn/go-colorable v0.1.13 // indirect - github.com/mattn/go-isatty v0.0.17 // indirect - github.com/mattn/go-runewidth v0.0.9 // indirect - github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect - github.com/mbilski/exhaustivestruct v1.2.0 // indirect - github.com/mgechev/revive v1.3.4 // indirect - github.com/mitchellh/go-homedir v1.1.0 // indirect - github.com/mitchellh/mapstructure v1.5.0 // indirect - github.com/moricho/tparallel v0.3.1 // indirect - github.com/nakabonne/nestif v0.3.1 // indirect - github.com/nishanths/exhaustive v0.11.0 // indirect - github.com/nishanths/predeclared v0.2.2 // indirect - github.com/nunnatsa/ginkgolinter v0.14.1 // indirect - github.com/olekukonko/tablewriter v0.0.5 // indirect - github.com/pelletier/go-toml/v2 v2.0.6 // indirect - github.com/philippgille/gokv/encoding v0.6.0 // indirect - github.com/philippgille/gokv/util v0.6.0 // indirect - github.com/pkg/errors v0.9.1 // indirect - github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/polyfloyd/go-errorlint v1.4.5 // indirect - github.com/prometheus/client_golang v1.12.1 // indirect - github.com/prometheus/client_model v0.2.0 // indirect - github.com/prometheus/common v0.32.1 // indirect - github.com/prometheus/procfs v0.7.3 // indirect - github.com/quasilyte/go-ruleguard v0.4.0 // indirect - github.com/quasilyte/gogrep v0.5.0 // indirect - github.com/quasilyte/regex/syntax v0.0.0-20210819130434-b3f0c404a727 // indirect - github.com/quasilyte/stdinfo v0.0.0-20220114132959-f7386bf02567 // indirect - github.com/rs/zerolog v1.29.0 // indirect - github.com/ryancurrah/gomodguard v1.3.0 // indirect - github.com/ryanrolds/sqlclosecheck v0.5.1 // indirect - github.com/sanposhiho/wastedassign/v2 v2.0.7 // indirect - github.com/sashamelentyev/interfacebloat v1.1.0 // indirect - github.com/sashamelentyev/usestdlibvars v1.24.0 // indirect - github.com/securego/gosec/v2 v2.18.2 // indirect - github.com/shazow/go-diff v0.0.0-20160112020656-b6b7b6733b8c // indirect - github.com/sirupsen/logrus v1.9.3 // indirect - github.com/sivchari/containedctx v1.0.3 // indirect - github.com/sivchari/nosnakecase v1.7.0 // indirect - github.com/sivchari/tenv v1.7.1 // indirect - github.com/sonatard/noctx v0.0.2 // indirect - github.com/sourcegraph/go-diff v0.7.0 // indirect - github.com/spf13/afero v1.9.3 // indirect - github.com/spf13/cast v1.5.0 // indirect - github.com/spf13/cobra v1.7.0 // indirect - github.com/spf13/jwalterweatherman v1.1.0 // indirect - github.com/spf13/pflag v1.0.5 // indirect - github.com/spf13/viper v1.15.0 // indirect - github.com/ssgreg/nlreturn/v2 v2.2.1 // indirect - github.com/stbenjam/no-sprintf-host-port v0.1.1 // indirect - github.com/stretchr/objx v0.5.0 // indirect - github.com/subosito/gotenv v1.4.2 // indirect - github.com/t-yuki/gocover-cobertura v0.0.0-20180217150009-aaee18c8195c // indirect - github.com/tdakkota/asciicheck v0.2.0 // indirect - github.com/tetafro/godot v1.4.15 // indirect - github.com/timakin/bodyclose v0.0.0-20230421092635-574207250966 // indirect - github.com/timonwong/loggercheck v0.9.4 // indirect - github.com/tomarrell/wrapcheck/v2 v2.8.1 // indirect - github.com/tommy-muehle/go-mnd/v2 v2.5.1 // indirect - github.com/ultraware/funlen v0.1.0 // indirect - github.com/ultraware/whitespace v0.0.5 // indirect - github.com/uudashr/gocognit v1.1.2 // indirect + github.com/google/uuid v1.3.0 // indirect + github.com/safchain/ethtool v0.2.0 // indirect + github.com/spf13/afero v1.9.4 // indirect github.com/vishvananda/netns v0.0.4 // indirect - github.com/xen0n/gosmopolitan v1.2.2 // indirect - github.com/yagipy/maintidx v1.0.0 // indirect - github.com/yeya24/promlinter v0.2.0 // indirect - github.com/ykadowak/zerologlint v0.1.3 // indirect - gitlab.com/bosi/decorder v0.4.1 // indirect - go-simpler.org/sloglint v0.1.2 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.21.0 // indirect - go.opentelemetry.io/otel/metric v1.21.0 // indirect - go.opentelemetry.io/proto/otlp v1.0.0 // indirect - go.tmz.dev/musttag v0.7.2 // indirect - go.uber.org/atomic v1.9.0 // indirect - go.uber.org/multierr v1.8.0 // indirect - go.uber.org/zap v1.24.0 // indirect - golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1 // indirect - golang.org/x/exp/typeparams v0.0.0-20230307190834-24139beb5833 // indirect - golang.org/x/mod v0.14.0 // indirect - golang.org/x/net v0.18.0 // indirect - golang.org/x/sync v0.5.0 // indirect - golang.org/x/sys v0.14.0 // indirect - golang.org/x/term v0.14.0 // indirect - golang.org/x/text v0.14.0 // indirect - google.golang.org/genproto v0.0.0-20231030173426-d783a09b4405 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20231106174013-bbf56f31fb17 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20231030173426-d783a09b4405 // indirect - gopkg.in/ini.v1 v1.67.0 // indirect - gopkg.in/yaml.v2 v2.4.0 // indirect - gopkg.in/yaml.v3 v3.0.1 // indirect - honnef.co/go/tools v0.4.6 // indirect - howett.net/plist v1.0.0 // indirect - mvdan.cc/gofumpt v0.5.0 // indirect - mvdan.cc/interfacer v0.0.0-20180901003855-c20040233aed // indirect - mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b // indirect - mvdan.cc/unparam v0.0.0-20221223090309-7455f1af531d // indirect + golang.org/x/sys v0.6.0 // indirect + golang.org/x/text v0.8.0 // indirect + google.golang.org/genproto v0.0.0-20230306155012-7f2fa6fef1f4 // indirect + google.golang.org/protobuf v1.30.0 // indirect ) diff --git a/go.sum b/go.sum index ccbca06..0cd985c 100644 --- a/go.sum +++ b/go.sum @@ -1,7 +1,3 @@ -4d63.com/gocheckcompilerdirectives v1.2.1 h1:AHcMYuw56NPjq/2y615IGg2kYkBdTvOaojYCBcRE7MA= -4d63.com/gocheckcompilerdirectives v1.2.1/go.mod h1:yjDJSxmDTtIHHCqX0ufRYZDL6vQtMG7tJdKVeWwsqvs= -4d63.com/gochecknoglobals v0.2.1 h1:1eiorGsgHOFOuoOiJDy2psSrQbRdIHrlge0IJIkUgDc= -4d63.com/gochecknoglobals v0.2.1/go.mod h1:KRE8wtJB3CXCsb1xy421JfTHIIbmT3U5ruxw2Qu8fSU= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= @@ -21,15 +17,12 @@ cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHOb cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk= cloud.google.com/go v0.75.0/go.mod h1:VGuuCn7PG0dwsd5XPVm2Mm3wlh3EL55/79EKB6hlPTY= -cloud.google.com/go v0.110.9 h1:e7ITSqGFFk4rbz/JFIqZh3G4VEHguhAL4BQcFlWtU68= cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= -cloud.google.com/go/compute v1.23.2 h1:nWEMDhgbBkBJjfpVySqU4jgWdc22PLR0o4vEexZHers= -cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY= cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= @@ -43,85 +36,9 @@ cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RX cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= -github.com/4meepo/tagalign v1.3.3 h1:ZsOxcwGD/jP4U/aw7qeWu58i7dwYemfy5Y+IF1ACoNw= -github.com/4meepo/tagalign v1.3.3/go.mod h1:Q9c1rYMZJc9dPRkbQPpcBNCLEmY2njbAsXhQOZFE2dE= -github.com/Abirdcfly/dupword v0.0.13 h1:SMS17YXypwP000fA7Lr+kfyBQyW14tTT+nRv9ASwUUo= -github.com/Abirdcfly/dupword v0.0.13/go.mod h1:Ut6Ue2KgF/kCOawpW4LnExT+xZLQviJPE4klBPMK/5Y= -github.com/Antonboom/errname v0.1.12 h1:oh9ak2zUtsLp5oaEd/erjB4GPu9w19NyoIskZClDcQY= -github.com/Antonboom/errname v0.1.12/go.mod h1:bK7todrzvlaZoQagP1orKzWXv59X/x0W0Io2XT1Ssro= -github.com/Antonboom/nilnil v0.1.7 h1:ofgL+BA7vlA1K2wNQOsHzLJ2Pw5B5DpWRLdDAVvvTow= -github.com/Antonboom/nilnil v0.1.7/go.mod h1:TP+ScQWVEq0eSIxqU8CbdT5DFWoHp0MbP+KMUO1BKYQ= -github.com/Antonboom/testifylint v0.2.3 h1:MFq9zyL+rIVpsvLX4vDPLojgN7qODzWsrnftNX2Qh60= -github.com/Antonboom/testifylint v0.2.3/go.mod h1:IYaXaOX9NbfAyO+Y04nfjGI8wDemC1rUyM/cYolz018= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8= -github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= -github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24 h1:sHglBQTwgx+rWPdisA5ynNEsoARbiCBOyGcJM4/OzsM= -github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24/go.mod h1:4UJr5HIiMZrwgkSPdsjy2uOQExX/WEILpIrO9UPGuXs= -github.com/GaijinEntertainment/go-exhaustruct/v3 v3.1.0 h1:3ZBs7LAezy8gh0uECsA6CGU43FF3zsx5f4eah5FxTMA= -github.com/GaijinEntertainment/go-exhaustruct/v3 v3.1.0/go.mod h1:rZLTje5A9kFBe0pzhpe2TdhRniBF++PRHQuRpR8esVc= -github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww= -github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y= -github.com/OpenPeeDeeP/depguard/v2 v2.1.0 h1:aQl70G173h/GZYhWf36aE5H0KaujXfVMnn/f1kSDVYY= -github.com/OpenPeeDeeP/depguard/v2 v2.1.0/go.mod h1:PUBgk35fX4i7JDmwzlJwJ+GMe6NfO1723wmJMgPThNQ= -github.com/StackExchange/wmi v1.2.1 h1:VIkavFPXSjcnS+O8yTq7NI32k0R5Aj+v39y29VYDOSA= -github.com/StackExchange/wmi v1.2.1/go.mod h1:rcmrprowKIVzvc+NUiLncP2uuArMWLCbu9SBzvHz7e8= -github.com/alecthomas/assert/v2 v2.2.2 h1:Z/iVC0xZfWTaFNE6bA3z07T86hd45Xe2eLt6WVy2bbk= -github.com/alecthomas/go-check-sumtype v0.1.3 h1:M+tqMxB68hcgccRXBMVCPI4UJ+QUfdSx0xdbypKCqA8= -github.com/alecthomas/go-check-sumtype v0.1.3/go.mod h1:WyYPfhfkdhyrdaligV6svFopZV8Lqdzn5pyVBaV6jhQ= -github.com/alecthomas/repr v0.2.0 h1:HAzS41CIzNW5syS8Mf9UwXhNH1J9aix/BvDRf1Ml2Yk= -github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= -github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= -github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= -github.com/alexkohler/nakedret/v2 v2.0.2 h1:qnXuZNvv3/AxkAb22q/sEsEpcA99YxLFACDtEw9TPxE= -github.com/alexkohler/nakedret/v2 v2.0.2/go.mod h1:2b8Gkk0GsOrqQv/gPWjNLDSKwG8I5moSXG1K4VIBcTQ= -github.com/alexkohler/prealloc v1.0.0 h1:Hbq0/3fJPQhNkN0dR95AVrr6R7tou91y0uHG5pOcUuw= -github.com/alexkohler/prealloc v1.0.0/go.mod h1:VetnK3dIgFBBKmg0YnD9F9x6Icjd+9cvfHR56wJVlKE= -github.com/alingse/asasalint v0.0.11 h1:SFwnQXJ49Kx/1GghOFz1XGqHYKp21Kq1nHad/0WQRnw= -github.com/alingse/asasalint v0.0.11/go.mod h1:nCaoMhw7a9kSJObvQyVzNTPBDbNpdocqrSP7t/cW5+I= -github.com/ashanbrown/forbidigo v1.6.0 h1:D3aewfM37Yb3pxHujIPSpTf6oQk9sc9WZi8gerOIVIY= -github.com/ashanbrown/forbidigo v1.6.0/go.mod h1:Y8j9jy9ZYAEHXdu723cUlraTqbzjKF1MUyfOKL+AjcU= -github.com/ashanbrown/makezero v1.1.1 h1:iCQ87C0V0vSyO+M9E/FZYbu65auqH0lnsOkf5FcB28s= -github.com/ashanbrown/makezero v1.1.1/go.mod h1:i1bJLCRSCHOcOa9Y6MyF2FTfMZMFdHvxKHxgO5Z1axI= -github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= -github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= -github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= -github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= -github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= -github.com/bkielbasa/cyclop v1.2.1 h1:AeF71HZDob1P2/pRm1so9cd1alZnrpyc4q2uP2l0gJY= -github.com/bkielbasa/cyclop v1.2.1/go.mod h1:K/dT/M0FPAiYjBgQGau7tz+3TMh4FWAEqlMhzFWCrgM= -github.com/blizzy78/varnamelen v0.8.0 h1:oqSblyuQvFsW1hbBHh1zfwrKe3kcSj0rnXkKzsQ089M= -github.com/blizzy78/varnamelen v0.8.0/go.mod h1:V9TzQZ4fLJ1DSrjVDfl89H7aMnTvKkApdHeyESmyR7k= -github.com/bombsimon/wsl/v3 v3.4.0 h1:RkSxjT3tmlptwfgEgTgU+KYKLI35p/tviNXNXiL2aNU= -github.com/bombsimon/wsl/v3 v3.4.0/go.mod h1:KkIB+TXkqy6MvK9BDZVbZxKNYsE1/oLRJbIFtf14qqo= -github.com/breml/bidichk v0.2.7 h1:dAkKQPLl/Qrk7hnP6P+E0xOodrq8Us7+U0o4UBOAlQY= -github.com/breml/bidichk v0.2.7/go.mod h1:YodjipAGI9fGcYM7II6wFvGhdMYsC5pHDlGzqvEW3tQ= -github.com/breml/errchkjson v0.3.6 h1:VLhVkqSBH96AvXEyclMR37rZslRrY2kcyq+31HCsVrA= -github.com/breml/errchkjson v0.3.6/go.mod h1:jhSDoFheAF2RSDOlCfhHO9KqhZgAYLyvHe7bRCX8f/U= -github.com/butuzov/ireturn v0.2.2 h1:jWI36dxXwVrI+RnXDwux2IZOewpmfv930OuIRfaBUJ0= -github.com/butuzov/ireturn v0.2.2/go.mod h1:RfGHUvvAuFFxoHKf4Z8Yxuh6OjlCw1KvR2zM1NFHeBk= -github.com/butuzov/mirror v1.1.0 h1:ZqX54gBVMXu78QLoiqdwpl2mgmoOJTk7s4p4o+0avZI= -github.com/butuzov/mirror v1.1.0/go.mod h1:8Q0BdQU6rC6WILDiBM60DBfvV78OLJmMmixe7GF45AE= -github.com/catenacyber/perfsprint v0.2.0 h1:azOocHLscPjqXVJ7Mf14Zjlkn4uNua0+Hcg1wTR6vUo= -github.com/catenacyber/perfsprint v0.2.0/go.mod h1:/wclWYompEyjUD2FuIIDVKNkqz7IgBIWXIH3V0Zol50= -github.com/ccojocar/zxcvbn-go v1.0.1 h1:+sxrANSCj6CdadkcMnvde/GWU1vZiiXRbqYSCalV4/4= -github.com/ccojocar/zxcvbn-go v1.0.1/go.mod h1:g1qkXtUSvHP8lhHp5GrSmTz6uWALGRMQdw6Qnz/hi60= -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.1.2/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/charithe/durationcheck v0.0.10 h1:wgw73BiocdBDQPik+zcEoBG/ob8uyBHf2iyoHGPf5w4= -github.com/charithe/durationcheck v0.0.10/go.mod h1:bCWXb7gYRysD1CU3C+u4ceO49LoGOY1C1L6uouGNreQ= -github.com/chavacava/garif v0.1.0 h1:2JHa3hbYf5D9dsgseMKAmc/MZ109otzgNFk5s87H9Pc= -github.com/chavacava/garif v0.1.0/go.mod h1:XMyYCkEL58DF0oyW4qDjjnPWONs2HBqYKI+UIPD+Gww= -github.com/chigopher/pathlib v0.15.0 h1:1pg96WL3iC1/YyWV4UJSl3E0GBf4B+h5amBtsbAAieY= -github.com/chigopher/pathlib v0.15.0/go.mod h1:3+YPPV21mU9vyw8Mjp+F33CyCfE6iOzinpiqBcccv7I= 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= @@ -129,97 +46,28 @@ github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDk github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= -github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4 h1:/inchEIKaYC1Akx+H+gqO04wryn5h75LSazbRlnya1k= -github.com/coreos/go-systemd/v22 v22.3.3-0.20220203105225-a9a7ef127534/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= -github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= -github.com/curioswitch/go-reassign v0.2.0 h1:G9UZyOcpk/d7Gd6mqYgd8XYWFMw/znxwGDUstnC9DIo= -github.com/curioswitch/go-reassign v0.2.0/go.mod h1:x6OpXuWvgfQaMGks2BZybTngWjT84hqJfKoO8Tt/Roc= -github.com/daixiang0/gci v0.11.2 h1:Oji+oPsp3bQ6bNNgX30NBAVT18P4uBH4sRZnlOlTj7Y= -github.com/daixiang0/gci v0.11.2/go.mod h1:xtHP9N7AHdNvtRNfcx9gwTDfw7FRJx4bZUsiEfiNNAI= +github.com/containernetworking/cni v1.1.2 h1:wtRGZVv7olUHMOqouPpn3cXJWpJgM6+EUl31EQbXALQ= +github.com/containernetworking/cni v1.1.2/go.mod h1:sDpYKmGVENF3s6uvMvGgldDWeG8dMxakj/u+i9ht9vw= +github.com/containernetworking/plugins v1.2.0 h1:SWgg3dQG1yzUo4d9iD8cwSVh1VqI+bP7mkPDoSfP9VU= +github.com/containernetworking/plugins v1.2.0/go.mod h1:/VjX4uHecW5vVimFa1wkG4s+r/s9qIfPdqlLF4TW8c4= +github.com/coreos/go-iptables v0.6.0 h1:is9qnZMPYjLd8LYqmm/qlE+wwEgJIkTYdhV3rfZo4jk= +github.com/coreos/go-iptables v0.6.0/go.mod h1:Qe8Bv2Xik5FyTXwgIbLAnv2sWSBmvWdFETJConOQ//Q= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/denis-tingaikin/go-header v0.4.3 h1:tEaZKAlqql6SKCY++utLmkPLd6K8IBM20Ha7UVm+mtU= -github.com/denis-tingaikin/go-header v0.4.3/go.mod h1:0wOCWuN71D5qIgE2nz9KrKmuYBAC2Mra5RassOIQ2/c= 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.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= 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/esimonov/ifshort v1.0.4 h1:6SID4yGWfRae/M7hkVDVVyppy8q/v9OuxNdmjLQStBA= -github.com/esimonov/ifshort v1.0.4/go.mod h1:Pe8zjlRrJ80+q2CxHLfEOfTwxCZ4O+MuhcHcfgNWTk0= -github.com/ettle/strcase v0.1.1 h1:htFueZyVeE1XNnMEfbqp5r67qAN/4r6ya1ysq8Q+Zcw= -github.com/ettle/strcase v0.1.1/go.mod h1:hzDLsPC7/lwKyBOywSHEP89nt2pDgdy+No1NBA9o9VY= -github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs= -github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw= -github.com/fatih/structtag v1.2.0 h1:/OdNE99OxoI/PqaW/SuSK9uxxT3f/tcSZgon/ssNSx4= -github.com/fatih/structtag v1.2.0/go.mod h1:mBJUNpUnHmRKrKlQQlmCrh5PuhftFbNv8Ys4/aAZl94= -github.com/firefart/nonamedreturns v1.0.4 h1:abzI1p7mAEPYuR4A+VLKn4eNDOycjYo2phmY9sfv40Y= -github.com/firefart/nonamedreturns v1.0.4/go.mod h1:TDhe/tjI1BXo48CmYbUduTV7BdIga8MAO/xbKdcVsGI= -github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= -github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= -github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= -github.com/fzipp/gocyclo v0.6.0 h1:lsblElZG7d3ALtGMx9fmxeTKZaLLpU8mET09yN4BBLo= -github.com/fzipp/gocyclo v0.6.0/go.mod h1:rXPyn8fnlpa0R2csP/31uerbiVBugk5whMdlyaLkLoA= -github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= -github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= -github.com/ghostiam/protogetter v0.2.3 h1:qdv2pzo3BpLqezwqfGDLZ+nHEYmc5bUpIdsMbBVwMjw= -github.com/ghostiam/protogetter v0.2.3/go.mod h1:KmNLOsy1v04hKbvZs8EfGI1fk39AgTdRDxWNYPfXVc4= -github.com/go-critic/go-critic v0.9.0 h1:Pmys9qvU3pSML/3GEQ2Xd9RZ/ip+aXHKILuxczKGV/U= -github.com/go-critic/go-critic v0.9.0/go.mod h1:5P8tdXL7m/6qnyG6oRAlYLORvoXH0WDypYgAEmagT40= +github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= +github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= 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= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= -github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= -github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= -github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= -github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.3.0 h1:2y3SDp0ZXuc6/cjLSZ+Q3ir+QB9T/iG5yYRXqsagWSY= -github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= -github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= -github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= -github.com/go-ole/go-ole v1.2.5/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= -github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE= -github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78= -github.com/go-redis/redis v6.15.6+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA= -github.com/go-redis/redis v6.15.9+incompatible h1:K0pv1D7EQUjfyoMql+r/jZqCLizCGKFlFgcHWWmHQjg= -github.com/go-redis/redis v6.15.9+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA= -github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= -github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= -github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls= -github.com/go-test/deep v1.0.4 h1:u2CU3YKy9I2pmu9pX0eq50wCgjfGIt539SqR7FbHiho= -github.com/go-test/deep v1.0.4/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= -github.com/go-toolsmith/astcast v1.1.0 h1:+JN9xZV1A+Re+95pgnMgDboWNVnIMMQXwfBwLRPgSC8= -github.com/go-toolsmith/astcast v1.1.0/go.mod h1:qdcuFWeGGS2xX5bLM/c3U9lewg7+Zu4mr+xPwZIB4ZU= -github.com/go-toolsmith/astcopy v1.1.0 h1:YGwBN0WM+ekI/6SS6+52zLDEf8Yvp3n2seZITCUBt5s= -github.com/go-toolsmith/astcopy v1.1.0/go.mod h1:hXM6gan18VA1T/daUEHCFcYiW8Ai1tIwIzHY6srfEAw= -github.com/go-toolsmith/astequal v1.0.3/go.mod h1:9Ai4UglvtR+4up+bAD4+hCj7iTo4m/OXVTSLnCyTAx4= -github.com/go-toolsmith/astequal v1.1.0 h1:kHKm1AWqClYn15R0K1KKE4RG614D46n+nqUQ06E1dTw= -github.com/go-toolsmith/astequal v1.1.0/go.mod h1:sedf7VIdCL22LD8qIvv7Nn9MuWJruQA/ysswh64lffQ= -github.com/go-toolsmith/astfmt v1.1.0 h1:iJVPDPp6/7AaeLJEruMsBUlOYCmvg0MoCfJprsOmcco= -github.com/go-toolsmith/astfmt v1.1.0/go.mod h1:OrcLlRwu0CuiIBp/8b5PYF9ktGVZUjlNMV634mhwuQ4= -github.com/go-toolsmith/astp v1.1.0 h1:dXPuCl6u2llURjdPLLDxJeZInAeZ0/eZwFJmqZMnpQA= -github.com/go-toolsmith/astp v1.1.0/go.mod h1:0T1xFGz9hicKs8Z5MfAqSUitoUYS30pDMsRVIDHs8CA= -github.com/go-toolsmith/pkgload v1.2.2 h1:0CtmHq/02QhxcF7E9N5LIFcYFsMR5rdovfqTtRKkgIk= -github.com/go-toolsmith/strparse v1.0.0/go.mod h1:YI2nUKP9YGZnL/L1/DLFBfixrcjslWct4wyljWhSRy8= -github.com/go-toolsmith/strparse v1.1.0 h1:GAioeZUK9TGxnLS+qfdqNbA4z0SSm5zVNtCQiyP2Bvw= -github.com/go-toolsmith/strparse v1.1.0/go.mod h1:7ksGy58fsaQkGQlY8WVoBFNyEPMGuJin1rfoPS4lBSQ= -github.com/go-toolsmith/typep v1.1.0 h1:fIRYDyF+JywLfqzyhdiHzRop/GQDxxNhLGQ6gFUNHus= -github.com/go-toolsmith/typep v1.1.0/go.mod h1:fVIw+7zjdsMxDA3ITWnH1yOiw1rnTQKCsF/sk2H/qig= -github.com/go-xmlfmt/xmlfmt v1.1.2 h1:Nea7b4icn8s57fTx1M5AI4qQT5HEM3rVUO8MuE6g80U= -github.com/go-xmlfmt/xmlfmt v1.1.2/go.mod h1:aUCEOzzezBEjDBbFBoSiya/gduyIiWYRP6CnSFIV8AM= -github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= -github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= -github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= -github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw= -github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= -github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -249,26 +97,6 @@ github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaS github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/golangci/check v0.0.0-20180506172741-cfe4005ccda2 h1:23T5iq8rbUYlhpt5DB4XJkc6BU31uODLD1o1gKvZmD0= -github.com/golangci/check v0.0.0-20180506172741-cfe4005ccda2/go.mod h1:k9Qvh+8juN+UKMCS/3jFtGICgW8O96FVaZsaxdzDkR4= -github.com/golangci/dupl v0.0.0-20180902072040-3e9179ac440a h1:w8hkcTqaFpzKqonE9uMCefW1WDie15eSP/4MssdenaM= -github.com/golangci/dupl v0.0.0-20180902072040-3e9179ac440a/go.mod h1:ryS0uhF+x9jgbj/N71xsEqODy9BN81/GonCZiOzirOk= -github.com/golangci/go-misc v0.0.0-20220329215616-d24fe342adfe h1:6RGUuS7EGotKx6J5HIP8ZtyMdiDscjMLfRBSPuzVVeo= -github.com/golangci/go-misc v0.0.0-20220329215616-d24fe342adfe/go.mod h1:gjqyPShc/m8pEMpk0a3SeagVb0kaqvhscv+i9jI5ZhQ= -github.com/golangci/gofmt v0.0.0-20231018234816-f50ced29576e h1:ULcKCDV1LOZPFxGZaA6TlQbiM3J2GCPnkx/bGF6sX/g= -github.com/golangci/gofmt v0.0.0-20231018234816-f50ced29576e/go.mod h1:Pm5KhLPA8gSnQwrQ6ukebRcapGb/BG9iUkdaiCcGHJM= -github.com/golangci/golangci-lint v1.55.2 h1:yllEIsSJ7MtlDBwDJ9IMBkyEUz2fYE0b5B8IUgO1oP8= -github.com/golangci/golangci-lint v1.55.2/go.mod h1:H60CZ0fuqoTwlTvnbyjhpZPWp7KmsjwV2yupIMiMXbM= -github.com/golangci/lint-1 v0.0.0-20191013205115-297bf364a8e0 h1:MfyDlzVjl1hoaPzPD4Gpb/QgoRfSBR0jdhwGyAWwMSA= -github.com/golangci/lint-1 v0.0.0-20191013205115-297bf364a8e0/go.mod h1:66R6K6P6VWk9I95jvqGxkqJxVWGFy9XlDwLwVz1RCFg= -github.com/golangci/maligned v0.0.0-20180506175553-b1d89398deca h1:kNY3/svz5T29MYHubXix4aDDuE3RWHkPvopM/EDv/MA= -github.com/golangci/maligned v0.0.0-20180506175553-b1d89398deca/go.mod h1:tvlJhZqDe4LMs4ZHD0oMUlt9G2LWuDGoisJTBzLMV9o= -github.com/golangci/misspell v0.4.1 h1:+y73iSicVy2PqyX7kmUefHusENlrP9YwuHZHPLGQj/g= -github.com/golangci/misspell v0.4.1/go.mod h1:9mAN1quEo3DlpbaIKKyEvRxK1pwqR9s/Sea1bJCtlNI= -github.com/golangci/revgrep v0.5.2 h1:EndcWoRhcnfj2NHQ+28hyuXpLMF+dQmCN+YaeeIl4FU= -github.com/golangci/revgrep v0.5.2/go.mod h1:bjAMA+Sh/QUfTDcHzxfyHxr4xKvllVr/0sCv2e7jJHA= -github.com/golangci/unconvert v0.0.0-20180507085042-28b1c447d1f4 h1:zwtduBRr5SSWhqsYNgcuWO2kFlpdOZbP0+yRjmvPGys= -github.com/golangci/unconvert v0.0.0-20180507085042-28b1c447d1f4/go.mod h1:Izgrg8RkN3rCIMLGE9CyYmU9pY2Jer6DgANEnZ/L/cQ= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= @@ -281,11 +109,7 @@ github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.4/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.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= -github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= @@ -299,422 +123,83 @@ github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hf github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 h1:yAJXTCF9TqKcTiHJAE8dj7HMvPfh66eeA2JYW7eFpSE= github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4= -github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= +github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= -github.com/gordonklaus/ineffassign v0.0.0-20230610083614-0e73809eb601 h1:mrEEilTAUmaAORhssPPkxj84TsHrPMLBGW2Z4SoTxm8= -github.com/gordonklaus/ineffassign v0.0.0-20230610083614-0e73809eb601/go.mod h1:Qcp2HIAYhR7mNUVSIxZww3Guk4it82ghYcEXIAk+QT0= -github.com/gostaticanalysis/analysisutil v0.7.1 h1:ZMCjoue3DtDWQ5WyU16YbjbQEQ3VuzwxALrpYd+HeKk= -github.com/gostaticanalysis/analysisutil v0.7.1/go.mod h1:v21E3hY37WKMGSnbsw2S/ojApNWb6C1//mXO48CXbVc= -github.com/gostaticanalysis/comment v1.4.1/go.mod h1:ih6ZxzTHLdadaiSnF5WY3dxUoXfXAlTaRzuaNDlSado= -github.com/gostaticanalysis/comment v1.4.2 h1:hlnx5+S2fY9Zo9ePo4AhgYsYHbM2+eAv8m/s1JiCd6Q= -github.com/gostaticanalysis/comment v1.4.2/go.mod h1:KLUTGDv6HOCotCH8h2erHKmpci2ZoR8VPu34YA2uzdM= -github.com/gostaticanalysis/forcetypeassert v0.1.0 h1:6eUflI3DiGusXGK6X7cCcIgVCpZ2CiZ1Q7jl6ZxNV70= -github.com/gostaticanalysis/forcetypeassert v0.1.0/go.mod h1:qZEedyP/sY1lTGV1uJ3VhWZ2mqag3IkWsDHVbplHXak= -github.com/gostaticanalysis/nilerr v0.1.1 h1:ThE+hJP0fEp4zWLkWHWcRyI2Od0p7DlgYG3Uqrmrcpk= -github.com/gostaticanalysis/nilerr v0.1.1/go.mod h1:wZYb6YI5YAxxq0i1+VJbY0s2YONW0HU0GPE3+5PWN4A= -github.com/gostaticanalysis/testutil v0.3.1-0.20210208050101-bfb5c8eec0e4/go.mod h1:D+FIZ+7OahH3ePw/izIEeH5I06eKs1IKI4Xr64/Am3M= -github.com/gostaticanalysis/testutil v0.4.0 h1:nhdCmubdmDF6VEatUNjgUZBJKWRqugoISdUv3PPQgHY= -github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.0.1 h1:HcUWd006luQPljE73d5sk+/VgYPGUReEVz2y1/qylwY= -github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.0.1/go.mod h1:w9Y7gY31krpLmrVU5ZPG9H7l9fZuRu5/3R3S3FMtVQ4= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.18.1 h1:6UKoz5ujsI55KNpsJH3UwCq3T8kKbZwNZBNPuTTje8U= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.18.1/go.mod h1:YvJ2f6MplWDhfxiUC3KpyTy76kYUZA4W3pTv/wdKQ9Y= -github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA= -github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= -github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= -github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= -github.com/hashicorp/go-version v1.2.1/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= -github.com/hashicorp/go-version v1.6.0 h1:feTTfFNnjP967rlCxM/I9g701jU+RN74YKx2mOkIeek= -github.com/hashicorp/go-version v1.6.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= -github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= -github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM= -github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg= -github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= -github.com/huandu/xstrings v1.4.0 h1:D17IlohoQq4UcpqD7fDk80P7l+lwAmlFaBHgOipl2FU= -github.com/huandu/xstrings v1.4.0/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= -github.com/iancoleman/strcase v0.2.0 h1:05I4QRnGpI0m37iZQRuskXh+w77mr6Z41lwQzuHLwW0= -github.com/iancoleman/strcase v0.2.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= -github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= -github.com/jaypipes/ghw v0.12.0 h1:xU2/MDJfWmBhJnujHY9qwXQLs3DBsf0/Xa9vECY0Tho= -github.com/jaypipes/ghw v0.12.0/go.mod h1:jeJGbkRB2lL3/gxYzNYzEDETV1ZJ56OKr+CSeSEym+g= -github.com/jaypipes/pcidb v1.0.0 h1:vtZIfkiCUE42oYbJS0TAq9XSfSmcsgo9IdxSm9qzYU8= -github.com/jaypipes/pcidb v1.0.0/go.mod h1:TnYUvqhPBzCKnH34KrIX22kAeEbDCSRJ9cqLRCuNDfk= -github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= -github.com/jgautheron/goconst v1.6.0 h1:gbMLWKRMkzAc6kYsQL6/TxaoBUg3Jm9LSF/Ih1ADWGA= -github.com/jgautheron/goconst v1.6.0/go.mod h1:aAosetZ5zaeC/2EfMeRswtxUFBpe2Hr7HzkgX4fanO4= -github.com/jingyugao/rowserrcheck v1.1.1 h1:zibz55j/MJtLsjP1OF4bSdgXxwL1b+Vn7Tjzq7gFzUs= -github.com/jingyugao/rowserrcheck v1.1.1/go.mod h1:4yvlZSDb3IyDTUZJUmpZfm2Hwok+Dtp+nu2qOq+er9c= -github.com/jinzhu/copier v0.3.5 h1:GlvfUwHk62RokgqVNvYsku0TATCF7bAHVwEXoBh3iJg= -github.com/jinzhu/copier v0.3.5/go.mod h1:DfbEm0FYsaqBcKcFuvmOZb218JkPGtvSHsKg8S8hyyg= -github.com/jirfag/go-printf-func-name v0.0.0-20200119135958-7558a9eaa5af h1:KA9BjwUk7KlCh6S9EAGWBt1oExIUv9WyNCiRz5amv48= -github.com/jirfag/go-printf-func-name v0.0.0-20200119135958-7558a9eaa5af/go.mod h1:HEWGJkRDzjJY2sqdDwxccsGicWEf9BQOZsq2tV+xzM0= -github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= -github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= -github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= +github.com/imdario/mergo v0.3.15 h1:M8XP7IuFNsqUx6VPK2P9OSmsYsI/YFaGil0uD21V3dM= +github.com/imdario/mergo v0.3.15/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= -github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= -github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= -github.com/julz/importas v0.1.0 h1:F78HnrsjY3cR7j0etXy5+TU1Zuy7Xt08X/1aJnH5xXY= -github.com/julz/importas v0.1.0/go.mod h1:oSFU2R4XK/P7kNBrnL/FEQlDGN1/6WoxXEjSSXO0DV0= -github.com/kisielk/errcheck v1.6.3 h1:dEKh+GLHcWm2oN34nMvDzn1sqI0i0WxPvrgiJA5JuM8= -github.com/kisielk/errcheck v1.6.3/go.mod h1:nXw/i/MfnvRHqXa7XXmQMUB0oNFGuBrNI8d8NLy0LPw= -github.com/kisielk/gotool v1.0.0 h1:AV2c/EiW3KqPNT9ZKl07ehoAGi4C5/01Cfbblndcapg= +github.com/k8snetworkplumbingwg/sriovnet v1.2.0 h1:6ELfAxCB1dvosGUy3DVRmfH+HWTzmPD3W67HKQvMR1M= +github.com/k8snetworkplumbingwg/sriovnet v1.2.0/go.mod h1:jyWzGe6ZtYiPq6ih6aXCOy6mZ49Y9mNyBOLBBXnli+k= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/kkHAIKE/contextcheck v1.1.4 h1:B6zAaLhOEEcjvUgIYEqystmnFk1Oemn8bvJhbt0GMb8= -github.com/kkHAIKE/contextcheck v1.1.4/go.mod h1:1+i/gWqokIa+dm31mqGLZhZJ7Uh44DJGZVmr6QRBNJg= -github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= -github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= -github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= -github.com/kulti/thelper v0.6.3 h1:ElhKf+AlItIu+xGnI990no4cE2+XaSu1ULymV2Yulxs= -github.com/kulti/thelper v0.6.3/go.mod h1:DsqKShOvP40epevkFrvIwkCMNYxMeTNjdWL4dqWHZ6I= -github.com/kunwardeep/paralleltest v1.0.8 h1:Ul2KsqtzFxTlSU7IP0JusWlLiNqQaloB9vguyjbE558= -github.com/kunwardeep/paralleltest v1.0.8/go.mod h1:2C7s65hONVqY7Q5Efj5aLzRCNLjw2h4eMc9EcypGjcY= -github.com/kyoh86/exportloopref v0.1.11 h1:1Z0bcmTypkL3Q4k+IDHMWTcnCliEZcaPiIe0/ymEyhQ= -github.com/kyoh86/exportloopref v0.1.11/go.mod h1:qkV4UF1zGl6EkF1ox8L5t9SwyeBAZ3qLMd6up458uqA= -github.com/ldez/gomoddirectives v0.2.3 h1:y7MBaisZVDYmKvt9/l1mjNCiSA1BVn34U0ObUcJwlhA= -github.com/ldez/gomoddirectives v0.2.3/go.mod h1:cpgBogWITnCfRq2qGoDkKMEVSaarhdBr6g8G04uz6d0= -github.com/ldez/tagliatelle v0.5.0 h1:epgfuYt9v0CG3fms0pEgIMNPuFf/LpPIfjk4kyqSioo= -github.com/ldez/tagliatelle v0.5.0/go.mod h1:rj1HmWiL1MiKQuOONhd09iySTEkUuE/8+5jtPYz9xa4= -github.com/leonklingele/grouper v1.1.1 h1:suWXRU57D4/Enn6pXR0QVqqWWrnJ9Osrz+5rjt8ivzU= -github.com/leonklingele/grouper v1.1.1/go.mod h1:uk3I3uDfi9B6PeUjsCKi6ndcf63Uy7snXgR4yDYQVDY= -github.com/lufeee/execinquery v1.2.1 h1:hf0Ems4SHcUGBxpGN7Jz78z1ppVkP/837ZlETPCEtOM= -github.com/lufeee/execinquery v1.2.1/go.mod h1:EC7DrEKView09ocscGHC+apXMIaorh4xqSxS/dy8SbM= -github.com/macabu/inamedparam v0.1.2 h1:RR5cnayM6Q7cDhQol32DE2BGAPGMnffJ31LFE+UklaU= -github.com/macabu/inamedparam v0.1.2/go.mod h1:Xg25QvY7IBRl1KLPV9Rbml8JOMZtF/iAkNkmV7eQgjw= -github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= -github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= -github.com/maratori/testableexamples v1.0.0 h1:dU5alXRrD8WKSjOUnmJZuzdxWOEQ57+7s93SLMxb2vI= -github.com/maratori/testableexamples v1.0.0/go.mod h1:4rhjL1n20TUTT4vdh3RDqSizKLyXp7K2u6HgraZCGzE= -github.com/maratori/testpackage v1.1.1 h1:S58XVV5AD7HADMmD0fNnziNHqKvSdDuEKdPD1rNTU04= -github.com/maratori/testpackage v1.1.1/go.mod h1:s4gRK/ym6AMrqpOa/kEbQTV4Q4jb7WeLZzVhVVVOQMc= -github.com/matoous/godox v0.0.0-20230222163458-006bad1f9d26 h1:gWg6ZQ4JhDfJPqlo2srm/LN17lpybq15AryXIRcWYLE= -github.com/matoous/godox v0.0.0-20230222163458-006bad1f9d26/go.mod h1:1BELzlh859Sh1c6+90blK8lbYy0kwQf1bYlBhBysy1s= -github.com/matryer/is v1.4.0 h1:sosSmIWwkYITGrxZ25ULNDeKiMNzFSr4V/eqBQP0PeE= -github.com/matryer/is v1.4.0/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU= -github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= -github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= -github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= -github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= -github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= -github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng= -github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= -github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0= -github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= -github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= -github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/mbilski/exhaustivestruct v1.2.0 h1:wCBmUnSYufAHO6J4AVWY6ff+oxWxsVFrwgOdMUQePUo= -github.com/mbilski/exhaustivestruct v1.2.0/go.mod h1:OeTBVxQWoEmB2J2JCHmXWPJ0aksxSUOUy+nvtVEfzXc= -github.com/mgechev/revive v1.3.4 h1:k/tO3XTaWY4DEHal9tWBkkUMJYO/dLDVyMmAQxmIMDc= -github.com/mgechev/revive v1.3.4/go.mod h1:W+pZCMu9qj8Uhfs1iJMQsEFLRozUfvwFwqVvRbSNLVw= -github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= -github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= -github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= -github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= -github.com/moricho/tparallel v0.3.1 h1:fQKD4U1wRMAYNngDonW5XupoB/ZGJHdpzrWqgyg9krA= -github.com/moricho/tparallel v0.3.1/go.mod h1:leENX2cUv7Sv2qDgdi0D0fCftN8fRC67Bcn8pqzeYNI= -github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/nakabonne/nestif v0.3.1 h1:wm28nZjhQY5HyYPx+weN3Q65k6ilSBxDb8v5S81B81U= -github.com/nakabonne/nestif v0.3.1/go.mod h1:9EtoZochLn5iUprVDmDjqGKPofoUEBL8U4Ngq6aY7OE= -github.com/nishanths/exhaustive v0.11.0 h1:T3I8nUGhl/Cwu5Z2hfc92l0e04D2GEW6e0l8pzda2l0= -github.com/nishanths/exhaustive v0.11.0/go.mod h1:RqwDsZ1xY0dNdqHho2z6X+bgzizwbLYOWnZbbl2wLB4= -github.com/nishanths/predeclared v0.2.2 h1:V2EPdZPliZymNAn79T8RkNApBjMmVKh5XRpLm/w98Vk= -github.com/nishanths/predeclared v0.2.2/go.mod h1:RROzoN6TnGQupbC+lqggsOlcgysk3LMK/HI84Mp280c= -github.com/nunnatsa/ginkgolinter v0.14.1 h1:khx0CqR5U4ghsscjJ+lZVthp3zjIFytRXPTaQ/TMiyA= -github.com/nunnatsa/ginkgolinter v0.14.1/go.mod h1:nY0pafUSst7v7F637e7fymaMlQqI9c0Wka2fGsDkzWg= -github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= -github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= +github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= +github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= +github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.10.2 h1:uqH7bpe+ERSiDa34FDOF7RikN6RzXgduUF8yarlZp94= -github.com/onsi/ginkgo v1.10.2/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo/v2 v2.13.1 h1:LNGfMbR2OVGBfXjvRZIZ2YCTQdGKtPLvuI1rMCCj3OU= -github.com/onsi/ginkgo/v2 v2.13.1/go.mod h1:XStQ8QcGwLyF4HdfcZB8SFOS/MWCgDuXMSBe6zrvLgM= -github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= -github.com/onsi/gomega v1.29.0 h1:KIA/t2t5UBzoirT4H9tsML45GEbo3ouUnBHsCfD2tVg= -github.com/opiproject/opi-api v0.0.0-20231106063049-7979f3e83669 h1:KUPG9eDkL6loowjRSwcfP1PS0pJ2u1ikAw+JiQ7v77c= -github.com/opiproject/opi-api v0.0.0-20231106063049-7979f3e83669/go.mod h1:92pv4ulvvPMuxCJ9ND3aYbmBfEMLx0VCjpkiR7ZTqPY= -github.com/opiproject/opi-api v0.0.0-20231113071405-8df008ba93b3 h1:xVv7oXmxKbhi00DNeC+3Pja2bUtSqBToLSEXT1Ld3hE= -github.com/opiproject/opi-api v0.0.0-20231113071405-8df008ba93b3/go.mod h1:92pv4ulvvPMuxCJ9ND3aYbmBfEMLx0VCjpkiR7ZTqPY= -github.com/opiproject/opi-api v0.0.0-20231120071940-7b62be4a63bd h1:CCS0COZX9ZM4JAW90EW0EioF95d/kbPGB4rabXRxv1A= -github.com/opiproject/opi-api v0.0.0-20231120071940-7b62be4a63bd/go.mod h1:92pv4ulvvPMuxCJ9ND3aYbmBfEMLx0VCjpkiR7ZTqPY= -github.com/opiproject/opi-smbios-bridge v0.1.3-0.20231111031817-70db7728f3b6 h1:HZ3VgCWRK99nHo5/s78lcteGFnTowU8NnzlbK6XSCKo= -github.com/opiproject/opi-smbios-bridge v0.1.3-0.20231111031817-70db7728f3b6/go.mod h1:ll8ym8zS/YuWfTJ1kVlhVHHhRDlJeTQt3C3VVIt1YC0= -github.com/opiproject/opi-smbios-bridge v0.1.3-0.20231118051054-0082ec96846c h1:5PkCTf2qNO8BvQdj/O+P/M37oxPswNOTFMkFhfcLtOM= -github.com/opiproject/opi-smbios-bridge v0.1.3-0.20231118051054-0082ec96846c/go.mod h1:GuxppHaNF+Oi+yJMaY6BqiwpQdpB1w7O/OW5WCcQhI4= -github.com/opiproject/opi-smbios-bridge v0.1.3-0.20231125032256-38107633f91d h1:KQvz3rey2fmUopLf/eYWOsIm03HfIUPsCNVjLJ7kNYU= -github.com/opiproject/opi-smbios-bridge v0.1.3-0.20231125032256-38107633f91d/go.mod h1:VQd0p8m/c676n8Fafl+7w4XwuvTbotv28tbBLbG5pVA= -github.com/otiai10/copy v1.2.0/go.mod h1:rrF5dJ5F0t/EWSYODDu4j9/vEeYHMkc8jt0zJChqQWw= -github.com/otiai10/copy v1.11.0 h1:OKBD80J/mLBrwnzXqGtFCzprFSGioo30JcmR4APsNwc= -github.com/otiai10/curr v0.0.0-20150429015615-9b4961190c95/go.mod h1:9qAhocn7zKJG+0mI8eUu6xqkFDYS2kb2saOteoSB3cE= -github.com/otiai10/curr v1.0.0/go.mod h1:LskTG5wDwr8Rs+nNQ+1LlxRjAtTZZjtJW4rMXl6j4vs= -github.com/otiai10/mint v1.3.0/go.mod h1:F5AjcsTsWUqX+Na9fpHb52P8pcRX2CI6A3ctIT91xUo= -github.com/otiai10/mint v1.3.1/go.mod h1:/yxELlJQ0ufhjUwhshSj+wFjZ78CnZ48/1wtmBH1OTc= -github.com/pelletier/go-toml/v2 v2.0.6 h1:nrzqCb7j9cDFj2coyLNLaZuJTLjWjlaz6nvTvIwycIU= -github.com/pelletier/go-toml/v2 v2.0.6/go.mod h1:eumQOmlWiOPt5WriQQqoM5y18pDHwha2N+QD+EUNTek= -github.com/philippgille/gokv v0.0.0-20191001201555-5ac9a20de634/go.mod h1:OCoWPt+mbYuTO1FUVrQ2SxQU0oaaHBsn6lRhFX3JHOc= -github.com/philippgille/gokv v0.6.0 h1:fNEx/tSwV73nzlYd3iRYB8F+SEVJNNFzH1gsaT8SK2c= -github.com/philippgille/gokv v0.6.0/go.mod h1:tjXRFw9xDHgxLS8WJdfYotKGWp8TWqu4RdXjMDG/XBo= -github.com/philippgille/gokv/encoding v0.0.0-20191011213304-eb77f15b9c61/go.mod h1:SjxSrCoeYrYn85oTtroyG1ePY8aE72nvLQlw8IYwAN8= -github.com/philippgille/gokv/encoding v0.6.0 h1:P1TN+Aulpd6Qd7qcLqgPwoxzOQ42UHBXOovWvFxJRI8= -github.com/philippgille/gokv/encoding v0.6.0/go.mod h1:/yKvq2BKJlKJsH7KMDrhDlEw2Pt3V1nKyFhs4iOqz5U= -github.com/philippgille/gokv/gomap v0.6.0 h1:h2FbYBtchscVWoaN3PhQvq5jAgRYtUPII4czP0zSF2U= -github.com/philippgille/gokv/gomap v0.6.0/go.mod h1:TlbiKOc/8KIqTNw4oEaHRB7MZ0eVCkp6syUrm0XF3OM= -github.com/philippgille/gokv/redis v0.6.0 h1:pDv93IIr6Lcb+ffA+D+Z82iB3s13gvYGlz/y3LcMwW4= -github.com/philippgille/gokv/redis v0.6.0/go.mod h1:fk4ZJfW1/CF47FzL9jly9CAPgKHMGbxDPsm7PMfam24= -github.com/philippgille/gokv/test v0.0.0-20191011213304-eb77f15b9c61 h1:4tVyBgfpK0NSqu7tNZTwYfC/pbyWUR2y+O7mxEg5BTQ= -github.com/philippgille/gokv/test v0.0.0-20191011213304-eb77f15b9c61/go.mod h1:EUc+s9ONc1+VOr9NUEd8S0YbGRrQd/gz/p+2tvwt12s= -github.com/philippgille/gokv/util v0.0.0-20191011213304-eb77f15b9c61/go.mod h1:2dBhsJgY/yVIkjY5V3AnDUxUbEPzT6uQ3LvoVT8TR20= -github.com/philippgille/gokv/util v0.6.0 h1:GrTxVENzKBxs8lB3tnaA88mKOuVPT7atZPplxX+PNmo= -github.com/philippgille/gokv/util v0.6.0/go.mod h1:ovoDHZ2Svr7YX972SPPJQRXbhHEy3Gb20HRH/Tr9BiQ= -github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= +github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= +github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= +github.com/onsi/ginkgo/v2 v2.1.3 h1:e/3Cwtogj0HA+25nMP1jCMDIf8RtRYbGwGGuBIFztkc= +github.com/onsi/ginkgo/v2 v2.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c= +github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= +github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= +github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= +github.com/onsi/gomega v1.24.2 h1:J/tulyYK6JwBldPViHJReihxxZ+22FHs0piGjQAvoUE= +github.com/opiproject/opi-api v0.0.0-20231016162146-d81cc5ee60d4 h1:q20p6Hg4Un2St+vnw1b1sMSYTDg6bK0PbNrMb5xi7QU= +github.com/opiproject/opi-api v0.0.0-20231016162146-d81cc5ee60d4/go.mod h1:92pv4ulvvPMuxCJ9ND3aYbmBfEMLx0VCjpkiR7ZTqPY= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/polyfloyd/go-errorlint v1.4.5 h1:70YWmMy4FgRHehGNOUask3HtSFSOLKgmDn7ryNe7LqI= -github.com/polyfloyd/go-errorlint v1.4.5/go.mod h1:sIZEbFoDOCnTYYZoVkjc4hTnM459tuWA9H/EkdXwsKk= -github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= -github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= -github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= -github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= -github.com/prometheus/client_golang v1.12.1 h1:ZiaPsmm9uiBeaSMRznKsCDNtPCS0T3JVDGF+06gjBzk= -github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= -github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= -github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M= -github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= -github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= -github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= -github.com/prometheus/common v0.32.1 h1:hWIdL3N2HoUx3B8j3YN9mWor0qhY/NlEKZEaXxuIRh4= -github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= -github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= -github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= -github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/prometheus/procfs v0.7.3 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0VU= -github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/quasilyte/go-ruleguard v0.4.0 h1:DyM6r+TKL+xbKB4Nm7Afd1IQh9kEUKQs2pboWGKtvQo= -github.com/quasilyte/go-ruleguard v0.4.0/go.mod h1:Eu76Z/R8IXtViWUIHkE3p8gdH3/PKk1eh3YGfaEof10= -github.com/quasilyte/gogrep v0.5.0 h1:eTKODPXbI8ffJMN+W2aE0+oL0z/nh8/5eNdiO34SOAo= -github.com/quasilyte/gogrep v0.5.0/go.mod h1:Cm9lpz9NZjEoL1tgZ2OgeUKPIxL1meE7eo60Z6Sk+Ng= -github.com/quasilyte/regex/syntax v0.0.0-20210819130434-b3f0c404a727 h1:TCg2WBOl980XxGFEZSS6KlBGIV0diGdySzxATTWoqaU= -github.com/quasilyte/regex/syntax v0.0.0-20210819130434-b3f0c404a727/go.mod h1:rlzQ04UMyJXu/aOvhd8qT+hvDrFpiwqp8MRXDY9szc0= -github.com/quasilyte/stdinfo v0.0.0-20220114132959-f7386bf02567 h1:M8mH9eK4OUR4lu7Gd+PU1fV2/qnDNfzT635KRSObncs= -github.com/quasilyte/stdinfo v0.0.0-20220114132959-f7386bf02567/go.mod h1:DWNGW8A4Y+GyBgPuaQJuWiy0XYftx4Xm/y5Jqk9I6VQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= -github.com/rs/xid v1.4.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= -github.com/rs/zerolog v1.29.0 h1:Zes4hju04hjbvkVkOhdl2HpZa+0PmVwigmo8XoORE5w= -github.com/rs/zerolog v1.29.0/go.mod h1:NILgTygv/Uej1ra5XxGf82ZFSLk58MFGAUS2o6usyD0= -github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/ryancurrah/gomodguard v1.3.0 h1:q15RT/pd6UggBXVBuLps8BXRvl5GPBcwVA7BJHMLuTw= -github.com/ryancurrah/gomodguard v1.3.0/go.mod h1:ggBxb3luypPEzqVtq33ee7YSN35V28XeGnid8dnni50= -github.com/ryanrolds/sqlclosecheck v0.5.1 h1:dibWW826u0P8jNLsLN+En7+RqWWTYrjCB9fJfSfdyCU= -github.com/ryanrolds/sqlclosecheck v0.5.1/go.mod h1:2g3dUjoS6AL4huFdv6wn55WpLIDjY7ZgUR4J8HOO/XQ= -github.com/sanposhiho/wastedassign/v2 v2.0.7 h1:J+6nrY4VW+gC9xFzUc+XjPD3g3wF3je/NsJFwFK7Uxc= -github.com/sanposhiho/wastedassign/v2 v2.0.7/go.mod h1:KyZ0MWTwxxBmfwn33zh3k1dmsbF2ud9pAAGfoLfjhtI= -github.com/sashamelentyev/interfacebloat v1.1.0 h1:xdRdJp0irL086OyW1H/RTZTr1h/tMEOsumirXcOJqAw= -github.com/sashamelentyev/interfacebloat v1.1.0/go.mod h1:+Y9yU5YdTkrNvoX0xHc84dxiN1iBi9+G8zZIhPVoNjQ= -github.com/sashamelentyev/usestdlibvars v1.24.0 h1:MKNzmXtGh5N0y74Z/CIaJh4GlB364l0K1RUT08WSWAc= -github.com/sashamelentyev/usestdlibvars v1.24.0/go.mod h1:9cYkq+gYJ+a5W2RPdhfaSCnTVUC1OQP/bSiiBhq3OZE= -github.com/securego/gosec/v2 v2.18.2 h1:DkDt3wCiOtAHf1XkiXZBhQ6m6mK/b9T/wD257R3/c+I= -github.com/securego/gosec/v2 v2.18.2/go.mod h1:xUuqSF6i0So56Y2wwohWAmB07EdBkUN6crbLlHwbyJs= -github.com/shazow/go-diff v0.0.0-20160112020656-b6b7b6733b8c h1:W65qqJCIOVP4jpqPQ0YvHYKwcMEMVWIzWC5iNQQfBTU= -github.com/shazow/go-diff v0.0.0-20160112020656-b6b7b6733b8c/go.mod h1:/PevMnwAxekIXwN8qQyfc5gl2NlkB3CQlkizAbOkeBs= -github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk= -github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041/go.mod h1:N5mDOmsrJOB+vfqUK+7DmDyjhSLIIBnXo9lvZJj3MWQ= -github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= -github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= -github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= -github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= -github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= -github.com/sivchari/containedctx v1.0.3 h1:x+etemjbsh2fB5ewm5FeLNi5bUjK0V8n0RB+Wwfd0XE= -github.com/sivchari/containedctx v1.0.3/go.mod h1:c1RDvCbnJLtH4lLcYD/GqwiBSSf4F5Qk0xld2rBqzJ4= -github.com/sivchari/nosnakecase v1.7.0 h1:7QkpWIRMe8x25gckkFd2A5Pi6Ymo0qgr4JrhGt95do8= -github.com/sivchari/nosnakecase v1.7.0/go.mod h1:CwDzrzPea40/GB6uynrNLiorAlgFRvRbFSgJx2Gs+QY= -github.com/sivchari/tenv v1.7.1 h1:PSpuD4bu6fSmtWMxSGWcvqUUgIn7k3yOJhOIzVWn8Ak= -github.com/sivchari/tenv v1.7.1/go.mod h1:64yStXKSOxDfX47NlhVwND4dHwfZDdbp2Lyl018Icvg= -github.com/sonatard/noctx v0.0.2 h1:L7Dz4De2zDQhW8S0t+KUjY0MAQJd6SgVwhzNIc4ok00= -github.com/sonatard/noctx v0.0.2/go.mod h1:kzFz+CzWSjQ2OzIm46uJZoXuBpa2+0y3T36U18dWqIo= -github.com/sourcegraph/go-diff v0.7.0 h1:9uLlrd5T46OXs5qpp8L/MTltk0zikUGi0sNNyCpA8G0= -github.com/sourcegraph/go-diff v0.7.0/go.mod h1:iBszgVvyxdc8SFZ7gm69go2KDdt3ag071iBaWPF6cjs= -github.com/spf13/afero v1.9.3 h1:41FoI0fD7OR7mGcKE/aOiLkGreyf8ifIOQmJANWogMk= -github.com/spf13/afero v1.9.3/go.mod h1:iUV7ddyEEZPO5gA3zD4fJt6iStLlL+Lg4m2cihcDf8Y= -github.com/spf13/cast v1.5.0 h1:rj3WzYc11XZaIZMPKmwP96zkFEnnAmV8s6XbB2aY32w= -github.com/spf13/cast v1.5.0/go.mod h1:SpXXQ5YoyJw6s3/6cMTQuxvgRl3PCJiyaX9p6b155UU= -github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I= -github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0= -github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk= -github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= -github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= -github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/spf13/viper v1.15.0 h1:js3yy885G8xwJa6iOISGFwd+qlUo5AvyXb7CiihdtiU= -github.com/spf13/viper v1.15.0/go.mod h1:fFcTBJxvhhzSJiZy8n+PeW6t8l+KeT/uTARa0jHOQLA= -github.com/ssgreg/nlreturn/v2 v2.2.1 h1:X4XDI7jstt3ySqGU86YGAURbxw3oTDPK9sPEi6YEwQ0= -github.com/ssgreg/nlreturn/v2 v2.2.1/go.mod h1:E/iiPB78hV7Szg2YfRgyIrk1AD6JVMTRkkxBiELzh2I= -github.com/stbenjam/no-sprintf-host-port v0.1.1 h1:tYugd/yrm1O0dV+ThCbaKZh195Dfm07ysF0U6JQXczc= -github.com/stbenjam/no-sprintf-host-port v0.1.1/go.mod h1:TLhvtIvONRzdmkFiio4O8LHsN9N74I+PhRquPsxpL0I= +github.com/safchain/ethtool v0.2.0 h1:dILxMBqDnQfX192cCAPjZr9v2IgVXeElHPy435Z/IdE= +github.com/safchain/ethtool v0.2.0/go.mod h1:WkKB1DnNtvsMlDmQ50sgwowDJV/hGbJSOvJoEXs1AJQ= +github.com/spf13/afero v1.9.4 h1:Sd43wM1IWz/s1aVXdOBkjJvuP8UdyqioeE4AmM0QsBs= +github.com/spf13/afero v1.9.4/go.mod h1:iUV7ddyEEZPO5gA3zD4fJt6iStLlL+Lg4m2cihcDf8Y= +github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= -github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= -github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= -github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= -github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= -github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -github.com/subosito/gotenv v1.4.2 h1:X1TuBLAMDFbaTAChgCBLu3DU3UPyELpnF2jjJ2cz/S8= -github.com/subosito/gotenv v1.4.2/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0= -github.com/t-yuki/gocover-cobertura v0.0.0-20180217150009-aaee18c8195c h1:+aPplBwWcHBo6q9xrfWdMrT9o4kltkmmvpemgIjep/8= -github.com/t-yuki/gocover-cobertura v0.0.0-20180217150009-aaee18c8195c/go.mod h1:SbErYREK7xXdsRiigaQiQkI9McGRzYMvlKYaP3Nimdk= -github.com/tdakkota/asciicheck v0.2.0 h1:o8jvnUANo0qXtnslk2d3nMKTFNlOnJjRrNcj0j9qkHM= -github.com/tdakkota/asciicheck v0.2.0/go.mod h1:Qb7Y9EgjCLJGup51gDHFzbI08/gbGhL/UVhYIPWG2rg= -github.com/tenntenn/modver v1.0.1 h1:2klLppGhDgzJrScMpkj9Ujy3rXPUspSjAcev9tSEBgA= -github.com/tenntenn/modver v1.0.1/go.mod h1:bePIyQPb7UeioSRkw3Q0XeMhYZSMx9B8ePqg6SAMGH0= -github.com/tenntenn/text/transform v0.0.0-20200319021203-7eef512accb3 h1:f+jULpRQGxTSkNYKJ51yaw6ChIqO+Je8UqsTKN/cDag= -github.com/tenntenn/text/transform v0.0.0-20200319021203-7eef512accb3/go.mod h1:ON8b8w4BN/kE1EOhwT0o+d62W65a6aPw1nouo9LMgyY= -github.com/tetafro/godot v1.4.15 h1:QzdIs+XB8q+U1WmQEWKHQbKmCw06QuQM7gLx/dky2RM= -github.com/tetafro/godot v1.4.15/go.mod h1:2oVxTBSftRTh4+MVfUaUXR6bn2GDXCaMcOG4Dk3rfio= -github.com/timakin/bodyclose v0.0.0-20230421092635-574207250966 h1:quvGphlmUVU+nhpFa4gg4yJyTRJ13reZMDHrKwYw53M= -github.com/timakin/bodyclose v0.0.0-20230421092635-574207250966/go.mod h1:27bSVNWSBOHm+qRp1T9qzaIpsWEP6TbUnei/43HK+PQ= -github.com/timonwong/loggercheck v0.9.4 h1:HKKhqrjcVj8sxL7K77beXh0adEm6DLjV/QOGeMXEVi4= -github.com/timonwong/loggercheck v0.9.4/go.mod h1:caz4zlPcgvpEkXgVnAJGowHAMW2NwHaNlpS8xDbVhTg= -github.com/tomarrell/wrapcheck/v2 v2.8.1 h1:HxSqDSN0sAt0yJYsrcYVoEeyM4aI9yAm3KQpIXDJRhQ= -github.com/tomarrell/wrapcheck/v2 v2.8.1/go.mod h1:/n2Q3NZ4XFT50ho6Hbxg+RV1uyo2Uow/Vdm9NQcl5SE= -github.com/tommy-muehle/go-mnd/v2 v2.5.1 h1:NowYhSdyE/1zwK9QCLeRb6USWdoif80Ie+v+yU8u1Zw= -github.com/tommy-muehle/go-mnd/v2 v2.5.1/go.mod h1:WsUAkMJMYww6l/ufffCD3m+P7LEvr8TnZn9lwVDlgzw= -github.com/ultraware/funlen v0.1.0 h1:BuqclbkY6pO+cvxoq7OsktIXZpgBSkYTQtmwhAK81vI= -github.com/ultraware/funlen v0.1.0/go.mod h1:XJqmOQja6DpxarLj6Jj1U7JuoS8PvL4nEqDaQhy22p4= -github.com/ultraware/whitespace v0.0.5 h1:hh+/cpIcopyMYbZNVov9iSxvJU3OYQg78Sfaqzi/CzI= -github.com/ultraware/whitespace v0.0.5/go.mod h1:aVMh/gQve5Maj9hQ/hg+F75lr/X5A89uZnzAmWSineA= -github.com/uudashr/gocognit v1.1.2 h1:l6BAEKJqQH2UpKAPKdMfZf5kE4W/2xk8pfU1OVLvniI= -github.com/uudashr/gocognit v1.1.2/go.mod h1:aAVdLURqcanke8h3vg35BC++eseDm66Z7KmchI5et4k= -github.com/vektra/mockery/v2 v2.37.0 h1:5BnOkD/uiHG63R6Q5kAHLEHyV/xxImjmFdAR7h1B4go= -github.com/vektra/mockery/v2 v2.37.0/go.mod h1:diB13hxXG6QrTR0ol2Rk8s2dRMftzvExSvPDKr+IYKk= -github.com/vektra/mockery/v2 v2.37.1/go.mod h1:diB13hxXG6QrTR0ol2Rk8s2dRMftzvExSvPDKr+IYKk= github.com/vishvananda/netlink v1.2.1-beta.2 h1:Llsql0lnQEbHj0I1OuKyp8otXp0r3q0mPkuhwHfStVs= github.com/vishvananda/netlink v1.2.1-beta.2/go.mod h1:twkDnbuQxJYemMlGd4JFIcuhgX83tXhKS2B/PRMpOho= github.com/vishvananda/netns v0.0.0-20200728191858-db3c7e526aae/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0= github.com/vishvananda/netns v0.0.4 h1:Oeaw1EM2JMxD51g9uhtC0D7erkIjgmj8+JZc26m1YX8= github.com/vishvananda/netns v0.0.4/go.mod h1:SpkAiCQRtJ6TvvxPnOSyH3BMl6unz3xZlaprSwhNNJM= -github.com/xen0n/gosmopolitan v1.2.2 h1:/p2KTnMzwRexIW8GlKawsTWOxn7UHA+jCMF/V8HHtvU= -github.com/xen0n/gosmopolitan v1.2.2/go.mod h1:7XX7Mj61uLYrj0qmeN0zi7XDon9JRAEhYQqAPLVNTeg= -github.com/yagipy/maintidx v1.0.0 h1:h5NvIsCz+nRDapQ0exNv4aJ0yXSI0420omVANTv3GJM= -github.com/yagipy/maintidx v1.0.0/go.mod h1:0qNf/I/CCZXSMhsRsrEPDZ+DkekpKLXAJfsTACwgXLk= -github.com/yeya24/promlinter v0.2.0 h1:xFKDQ82orCU5jQujdaD8stOHiv8UN68BSdn2a8u8Y3o= -github.com/yeya24/promlinter v0.2.0/go.mod h1:u54lkmBOZrpEbQQ6gox2zWKKLKu2SGe+2KOiextY+IA= -github.com/ykadowak/zerologlint v0.1.3 h1:TLy1dTW3Nuc+YE3bYRPToG1Q9Ej78b5UUN6bjbGdxPE= -github.com/ykadowak/zerologlint v0.1.3/go.mod h1:KaUskqF3e/v59oPmdq1U1DnKcuHokl2/K1U4pmIELKg= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= -github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= -github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= -github.com/ziutek/telnet v0.0.0-20180329124119-c3b780dc415b h1:VfPXB/wCGGt590QhD1bOpv2J/AmC/RJNTg/Q59HKSB0= -github.com/ziutek/telnet v0.0.0-20180329124119-c3b780dc415b/go.mod h1:IZpXDfkJ6tWD3PhBK5YzgQT+xJWh7OsdwiG8hA2MkO4= -gitlab.com/bosi/decorder v0.4.1 h1:VdsdfxhstabyhZovHafFw+9eJ6eU0d2CkFNJcZz/NU4= -gitlab.com/bosi/decorder v0.4.1/go.mod h1:jecSqWUew6Yle1pCr2eLWTensJMmsxHsBwt+PVbkAqA= -go-simpler.org/assert v0.6.0 h1:QxSrXa4oRuo/1eHMXSBFHKvJIpWABayzKldqZyugG7E= -go-simpler.org/sloglint v0.1.2 h1:IjdhF8NPxyn0Ckn2+fuIof7ntSnVUAqBFcQRrnG9AiM= -go-simpler.org/sloglint v0.1.2/go.mod h1:2LL+QImPfTslD5muNPydAEYmpXIj6o/WYcqnJjLi4o4= -go.einride.tech/aip v0.65.0 h1:aqKEV1g9diXcR6DAxBVZoJn6ho8SuC+TOZFXzuu7kLU= -go.einride.tech/aip v0.65.0/go.mod h1:wcRZ57XFEvERWLPy9VqDBtXc/ZFj7ugsd32F5o8Th+s= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.46.0 h1:PzIubN4/sjByhDRHLviCjJuweBXWFZWhghjg7cS28+M= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.46.0/go.mod h1:Ct6zzQEuGK3WpJs2n4dn+wfJYzd/+hNnxMRTWjGn30M= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.46.1 h1:SpGay3w+nEwMpfVnbqOLH5gY52/foP8RE8UzTZ1pdSE= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.46.1/go.mod h1:4UoMYEZOC0yN/sPGH76KPkkU7zgiEWYWL9vwmbnTJPE= -go.opentelemetry.io/otel v1.20.0 h1:vsb/ggIY+hUjD/zCAQHpzTmndPqv/ml2ArbsbfBYTAc= -go.opentelemetry.io/otel v1.20.0/go.mod h1:oUIGj3D77RwJdM6PPZImDpSZGDvkD9fhesHny69JFrs= -go.opentelemetry.io/otel v1.21.0 h1:hzLeKBZEL7Okw2mGzZ0cc4k/A7Fta0uoPgaJCr8fsFc= -go.opentelemetry.io/otel v1.21.0/go.mod h1:QZzNPQPm1zLX4gZK4cMi+71eaorMSGT3A4znnUvNNEo= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.20.0 h1:DeFD0VgTZ+Cj6hxravYYZE2W4GlneVH81iAOPjZkzk8= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.20.0/go.mod h1:GijYcYmNpX1KazD5JmWGsi4P7dDTTTnfv1UbGn84MnU= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.21.0 h1:cl5P5/GIfFh4t6xyruOgJP5QiA1pw4fYYdv6nc6CBWw= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.21.0/go.mod h1:zgBdWWAu7oEEMC06MMKc5NLbA/1YDXV1sMpSqEeLQLg= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.20.0 h1:gvmNvqrPYovvyRmCSygkUDyL8lC5Tl845MLEwqpxhEU= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.20.0/go.mod h1:vNUq47TGFioo+ffTSnKNdob241vePmtNZnAODKapKd0= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.21.0 h1:tIqheXEFWAZ7O8A7m+J0aPTmpJN3YQ7qetUAdkkkKpk= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.21.0/go.mod h1:nUeKExfxAQVbiVFn32YXpXZZHZ61Cc3s3Rn1pDBGAb0= -go.opentelemetry.io/otel/metric v1.20.0 h1:ZlrO8Hu9+GAhnepmRGhSU7/VkpjrNowxRN9GyKR4wzA= -go.opentelemetry.io/otel/metric v1.20.0/go.mod h1:90DRw3nfK4D7Sm/75yQ00gTJxtkBxX+wu6YaNymbpVM= -go.opentelemetry.io/otel/metric v1.21.0 h1:tlYWfeo+Bocx5kLEloTjbcDwBuELRrIFxwdQ36PlJu4= -go.opentelemetry.io/otel/metric v1.21.0/go.mod h1:o1p3CA8nNHW8j5yuQLdc1eeqEaPfzug24uvsyIEJRWM= -go.opentelemetry.io/otel/sdk v1.20.0 h1:5Jf6imeFZlZtKv9Qbo6qt2ZkmWtdWx/wzcCbNUlAWGM= -go.opentelemetry.io/otel/sdk v1.20.0/go.mod h1:rmkSx1cZCm/tn16iWDn1GQbLtsW/LvsdEEFzCSRM6V0= -go.opentelemetry.io/otel/sdk v1.21.0 h1:FTt8qirL1EysG6sTQRZ5TokkU8d0ugCj8htOgThZXQ8= -go.opentelemetry.io/otel/sdk v1.21.0/go.mod h1:Nna6Yv7PWTdgJHVRD9hIYywQBRx7pbox6nwBnZIxl/E= -go.opentelemetry.io/otel/trace v1.20.0 h1:+yxVAPZPbQhbC3OfAkeIVTky6iTFpcr4SiY9om7mXSQ= -go.opentelemetry.io/otel/trace v1.20.0/go.mod h1:HJSK7F/hA5RlzpZ0zKDCHCDHm556LCDtKaAo6JmBFUU= -go.opentelemetry.io/otel/trace v1.21.0 h1:WD9i5gzvoUPuXIXH24ZNBudiarZDKuekPqi/E8fpfLc= -go.opentelemetry.io/otel/trace v1.21.0/go.mod h1:LGbsEB0f9LGjN+OZaQQ26sohbOmiMR+BaslueVtS/qQ= -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.tmz.dev/musttag v0.7.2 h1:1J6S9ipDbalBSODNT5jCep8dhZyMr4ttnjQagmGYR5s= -go.tmz.dev/musttag v0.7.2/go.mod h1:m6q5NiiSKMnQYokefa2xGoyoXnrswCbJ0AWYzf4Zs28= -go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= -go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE= -go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= -go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= -go.uber.org/multierr v1.8.0 h1:dg6GjLku4EH+249NNmoIciG9N/jURbDG+pFlTkhzIC8= -go.uber.org/multierr v1.8.0/go.mod h1:7EAYxJLBy9rStEaz58O2t4Uvip6FSURkq8/ppBp95ak= -go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60= -go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg= -golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 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-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= -golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw= 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= @@ -725,12 +210,6 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0 golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= -golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1 h1:k/i9J1pBpvlfR+9QsetwPyERsqu1GIbi967PQMq3Ivc= -golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1/go.mod h1:V1LtkGg67GoY2N1AnLN78QLrzxkLyJw7RJb1gzOOz9w= -golang.org/x/exp/typeparams v0.0.0-20220428152302-39d4317da171/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk= -golang.org/x/exp/typeparams v0.0.0-20230203172020-98cc5a0785f9/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk= -golang.org/x/exp/typeparams v0.0.0-20230307190834-24139beb5833 h1:jWGQJV4niP+CCmFW9ekjA9Zx8vYORzOUH2/Nl5WPuLQ= -golang.org/x/exp/typeparams v0.0.0-20230307190834-24139beb5833/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -754,19 +233,9 @@ golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= -golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY= -golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI= -golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0= -golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= @@ -774,7 +243,6 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= -golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -788,6 +256,7 @@ golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/ golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= @@ -797,16 +266,9 @@ golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwY golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= 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= -golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= -golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= -golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws= -golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -golang.org/x/net v0.18.0 h1:mIYleuAkSbHh0tCv7RvjL3F6ZVbLjq4+R7zbOn3Kokg= -golang.org/x/net v0.18.0/go.mod h1:/czyP5RqHAH4odGYxBJ1qz0+CE5WZ+2j1YgoEo8F2jQ= +golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= +golang.org/x/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ= +golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= 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= @@ -816,8 +278,6 @@ golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.13.0 h1:jDDenyj+WgFtmV3zYVoi8aE2BwtXFLWOA67ZfNWftiY= 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= @@ -828,29 +288,22 @@ golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/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-20201207232520-09787c993a3a/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.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE= -golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= 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= -golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -864,8 +317,6 @@ golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200728102440-3e129f6d46b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -873,40 +324,16 @@ golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/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-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/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-20210423185535-09eb48e85fd7/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-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211105183446-c75c47738b0c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220702020025-31831981b65f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q= -golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= -golang.org/x/term v0.4.0/go.mod h1:9P2UbLfCdcvo3p/nzKvsmas4TnlujnuoV9hGgYzW1lQ= -golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= -golang.org/x/term v0.14.0 h1:LGK9IlZ8T9jvdy6cTdfKUCltatMFOehAQo9SRC46UQ8= -golang.org/x/term v0.14.0/go.mod h1:TySc+nGkYR6qt8km8wUhuFRTVSMIX3XPR58y2lC8vww= 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= @@ -914,12 +341,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.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= -golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68= +golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= 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= @@ -929,7 +352,6 @@ golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3 golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190321232350-e250d351ecad/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= @@ -937,10 +359,8 @@ golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgw golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20190910044552-dd2b5c81c578/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= @@ -958,41 +378,22 @@ golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapK golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -golang.org/x/tools v0.0.0-20200324003944-a576cf524670/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= -golang.org/x/tools v0.0.0-20200329025819-fd4102a86c65/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200724022722-7017fd6b1305/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200820010801-b793a1359eac/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= -golang.org/x/tools v0.0.0-20201001104356-43ebab892c4c/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU= -golang.org/x/tools v0.0.0-20201023174141-c8cfbd0f21e6/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= -golang.org/x/tools v0.1.1-0.20210205202024-ef80cdb6ec6d/go.mod h1:9bzcO0MWcOuT0tm1iBGzDVPshzfwoVvREIui8C+MHqU= -golang.org/x/tools v0.1.1-0.20210302220138-2ac05c832e1a/go.mod h1:9bzcO0MWcOuT0tm1iBGzDVPshzfwoVvREIui8C+MHqU= -golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.9/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= -golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E= -golang.org/x/tools v0.1.11/go.mod h1:SgwaegtQh8clINPpECJMqnxLv9I09HLqnW3RMqW0CA4= -golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA= -golang.org/x/tools v0.3.0/go.mod h1:/rWhSS2+zyEVwoJf8YAX6L2f0ntZ7Kn/mGgAWcipA5k= -golang.org/x/tools v0.5.0/go.mod h1:N+Kgy78s5I24c24dU8OfWNEotWjutIs8SnJvn5IDq+k= -golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= -golang.org/x/tools v0.15.0 h1:zdAyfUGbYmuVokhzVmghFl2ZJh5QhcfebBgmVPFYA+8= -golang.org/x/tools v0.15.0/go.mod h1:hpksKq4dtpQWS1uQ61JkdqWM3LscIS6Slf+VVkm+wQk= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 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= @@ -1022,7 +423,6 @@ google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7 google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= 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-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= @@ -1060,12 +460,8 @@ google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6D google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20231030173426-d783a09b4405 h1:I6WNifs6pF9tNdSob2W24JtyxIYjzFB9qDlpUC76q+U= -google.golang.org/genproto v0.0.0-20231030173426-d783a09b4405/go.mod h1:3WDQMjmJk36UQhjQ89emUzb1mdaHcPeeAh4SCBKznB4= -google.golang.org/genproto/googleapis/api v0.0.0-20231106174013-bbf56f31fb17 h1:JpwMPBpFN3uKhdaekDpiNlImDdkUAyiJ6ez/uxGaUSo= -google.golang.org/genproto/googleapis/api v0.0.0-20231106174013-bbf56f31fb17/go.mod h1:0xJLfVdJqpAPl8tDg1ujOCGzx6LFLttXT5NhllGOXY4= -google.golang.org/genproto/googleapis/rpc v0.0.0-20231030173426-d783a09b4405 h1:AB/lmRny7e2pLhFEYIbl5qkDAUt2h0ZRO4wGPhZf+ik= -google.golang.org/genproto/googleapis/rpc v0.0.0-20231030173426-d783a09b4405/go.mod h1:67X1fPuzjcrkymZzZV1vvkFeTn2Rvc6lYF9MYFGCcwE= +google.golang.org/genproto v0.0.0-20230306155012-7f2fa6fef1f4 h1:DdoeryqhaXp1LtT/emMP1BRJPHHKFi5akj/nbx/zNTA= +google.golang.org/genproto v0.0.0-20230306155012-7f2fa6fef1f4/go.mod h1:NWraEVixdDnqcqQ30jipen1STv2r/n24Wb7twVTGR4s= 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= @@ -1082,8 +478,8 @@ google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -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/grpc v1.55.0 h1:3Oj82/tFSCeUrRTg/5E/7d/W5A1tj6Ky1ABAuZuv5ag= +google.golang.org/grpc v1.55.0/go.mod h1:iYEXKGkEBhg1PjZQvoYEVPTDkHo1/bjTnfwTeGONTY8= 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= @@ -1096,33 +492,21 @@ 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.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= -google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= +google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng= +google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= 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= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= -gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= -gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= -gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= 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.v1 v1.0.0-20140924161607-9f9df34309c0/go.mod h1:WDnlLJ4WF5VGsH/HVa3CI79GS0ol3YnhVnKP89i0kNg= -gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/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.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gotest.tools/v3 v3.5.1 h1:EENdUnS3pdur5nybKYIh2Vfgc8IUNBjxDPSjtiJcOzU= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= @@ -1130,18 +514,6 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -honnef.co/go/tools v0.4.6 h1:oFEHCKeID7to/3autwsWfnuv69j3NsfcXbvJKuIcep8= -honnef.co/go/tools v0.4.6/go.mod h1:+rnGS1THNh8zMwnd2oVOTL9QF6vmfyG6ZXBULae2uc0= -howett.net/plist v1.0.0 h1:7CrbWYbPPO/PyNy38b2EB/+gYbjCe2DXBxgtOOZbSQM= -howett.net/plist v1.0.0/go.mod h1:lqaXoTrLY4hg8tnEzNru53gicrbv7rrk+2xJA/7hw9g= -mvdan.cc/gofumpt v0.5.0 h1:0EQ+Z56k8tXjj/6TQD25BFNKQXpCvT0rnansIc7Ug5E= -mvdan.cc/gofumpt v0.5.0/go.mod h1:HBeVDtMKRZpXyxFciAirzdKklDlGu8aAy1wEbH5Y9js= -mvdan.cc/interfacer v0.0.0-20180901003855-c20040233aed h1:WX1yoOaKQfddO/mLzdV4wptyWgoH/6hwLs7QHTixo0I= -mvdan.cc/interfacer v0.0.0-20180901003855-c20040233aed/go.mod h1:Xkxe497xwlCKkIaQYRfC7CSLworTXY9RMqwhhCm+8Nc= -mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b h1:DxJ5nJdkhDlLok9K6qO+5290kphDJbHOQO1DFFFTeBo= -mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b/go.mod h1:2odslEg/xrtNQqCYg2/jCoyKnw3vv5biOc3JnIcYfL4= -mvdan.cc/unparam v0.0.0-20221223090309-7455f1af531d h1:3rvTIIM22r9pvXk+q3swxUQAQOxksVMGK7sml4nG57w= -mvdan.cc/unparam v0.0.0-20221223090309-7455f1af531d/go.mod h1:IeHQjmn6TOD+e4Z3RFiZMMsLVL+A96Nvptar8Fj71is= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= diff --git a/images/build_docker.sh b/images/build_docker.sh new file mode 100644 index 0000000..0940995 --- /dev/null +++ b/images/build_docker.sh @@ -0,0 +1,9 @@ +#!/usr/bin/env bash +# SPDX-License-Identifier: Apache-2.0 +# Copyright (C) 2023 Network Plumping Working Group +# Copyright (C) 2023 Nordix Foundation. + +set -e + +## Build docker image +docker build -t opi-cni -f ../Dockerfile ../ \ No newline at end of file diff --git a/images/entrypoint.sh b/images/entrypoint.sh new file mode 100755 index 0000000..3222103 --- /dev/null +++ b/images/entrypoint.sh @@ -0,0 +1,68 @@ +#!/bin/sh +# SPDX-License-Identifier: Apache-2.0 +# Copyright (C) 2023 Network Plumping Working Group +# Copyright (C) 2023 Nordix Foundation. + +# Always exit on errors. +set -e + +# Set known directories. +CNI_BIN_DIR="/host/opt/cni/bin" +OPI_BIN_FILE="/usr/bin/opi" + +# Give help text for parameters. +usage() +{ + printf "This is an entrypoint script for OPI CNI to overlay its\n" + printf "binary into location in a filesystem. The binary file will\n" + printf "be copied to the corresponding directory.\n" + printf "\n" + printf "./entrypoint.sh\n" + printf "\t-h --help\n" + printf "\t--cni-bin-dir=%s\n" $CNI_BIN_DIR + printf "\t--opi-bin-file=%s\n" $OPI_BIN_FILE +} + +# Parse parameters given as arguments to this script. +while [ "$1" != "" ]; do + PARAM=$(echo "$1" | awk -F= '{print $1}') + VALUE=$(echo "$1" | awk -F= '{print $2}') + case $PARAM in + -h | --help) + usage + exit + ;; + --cni-bin-dir) + CNI_BIN_DIR=$VALUE + ;; + --opi-bin-file) + OPI_BIN_FILE=$VALUE + ;; + *) + /bin/echo "ERROR: unknown parameter \"$PARAM\"" + usage + exit 1 + ;; + esac + shift +done + + +# Loop through and verify each location each. +for i in $CNI_BIN_DIR $OPI_BIN_FILE +do + if [ ! -e "$i" ]; then + /bin/echo "Location $i does not exist" + exit 1; + fi +done + +# Copy file into proper place. +cp -f "$OPI_BIN_FILE" "$CNI_BIN_DIR" + +echo "Entering sleep... (success)" +trap : TERM INT + +# Sleep forever. +# sleep infinity is not available in alpine; instead lets go sleep for ~68 years. Hopefully that's enough sleep +sleep 2147483647 & wait \ No newline at end of file diff --git a/images/opi-cni-daemonset.yaml b/images/opi-cni-daemonset.yaml new file mode 100644 index 0000000..34e8476 --- /dev/null +++ b/images/opi-cni-daemonset.yaml @@ -0,0 +1,55 @@ +# SPDX-License-Identifier: Apache-2.0 +# Copyright (C) 2023 Network Plumping Working Group +# Copyright (C) 2023 Nordix Foundation. + +--- +apiVersion: apps/v1 +kind: DaemonSet +metadata: + name: kube-opi-cni-ds-amd64 + namespace: kube-system + labels: + tier: node + app: opi-cni +spec: + selector: + matchLabels: + name: opi-cni + template: + metadata: + labels: + name: opi-cni + tier: node + app: opi-cni + spec: + nodeSelector: + kubernetes.io/arch: amd64 + tolerations: + - key: node-role.kubernetes.io/master + operator: Exists + effect: NoSchedule + containers: + - name: kube-opi-cni + image: ghcr.io/opiproject/opi-cni + imagePullPolicy: Never + securityContext: + allowPrivilegeEscalation: false + privileged: false + readOnlyRootFilesystem: true + capabilities: + drop: + - ALL + resources: + requests: + cpu: "100m" + memory: "50Mi" + limits: + cpu: "100m" + memory: "50Mi" + volumeMounts: + - name: cnibin + mountPath: /host/opt/cni/bin + volumes: + - name: cnibin + hostPath: + path: /opt/cni/bin diff --git a/pkg/config/config.go b/pkg/config/config.go new file mode 100644 index 0000000..c8e959f --- /dev/null +++ b/pkg/config/config.go @@ -0,0 +1,204 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright (C) 2023 Network Plumping Working Group +// Copyright (C) 2023 Nordix Foundation. + +// Package config handles the configuration part of opi-cni +package config + +import ( + "encoding/json" + "fmt" + "io" + "os" + "path/filepath" + "strings" + + "github.com/containernetworking/cni/pkg/skel" + opitypes "github.com/opiproject/opi-cni/pkg/types" + "github.com/opiproject/opi-cni/pkg/utils" + + "github.com/imdario/mergo" +) + +// UnsupportedFields currently. Maybe will be supported in the future. +const UnsupportedFields = "MinTxRate, MaxTxRate, SpoofChk, Trust, LinkState" + +var ( + // DefaultCNIDir used for caching NetConf + DefaultCNIDir = "/var/lib/cni/opi" +) + +// LoadConf parses and validates stdin netconf and returns NetConf object +func LoadConf(bytes []byte) (*opitypes.NetConf, error) { + n, err := loadNetConf(bytes) + if err != nil { + return nil, fmt.Errorf("LoadConf(): failed to load netconf: %v", err) + } + flatNetConf, err := loadFlatNetConf(n.ConfigurationPath) + if err != nil { + return nil, fmt.Errorf("LoadConf(): failed to load flat netconf: %v", err) + } + n, err = mergeConf(n, flatNetConf) + if err != nil { + return nil, fmt.Errorf("LoadConf(): failed to merge netconf and flat netconf: %v", err) + } + + // DeviceID takes precedence; if we are given a VF pciaddr then work from there + if n.DeviceID != "" { + // Get rest of the VF information + pfName, vfID, err := getVfInfo(n.DeviceID) + if err != nil { + return nil, fmt.Errorf("LoadConf(): failed to get VF information: %q", err) + } + n.VFID = vfID + n.Master = pfName + } else { + return nil, fmt.Errorf("LoadConf(): VF pci addr is required") + } + + allocator := utils.NewPCIAllocator(DefaultCNIDir) + // Check if the device is already allocated. + // This is to prevent issues where kubelet request to delete a pod and in the same time a new pod using the same + // vf is started. we can have an issue where the cmdDel of the old pod is called AFTER the cmdAdd of the new one + // This will block the new pod creation until the cmdDel is done. + isAllocated, err := allocator.IsAllocated(n.DeviceID) + if err != nil { + // Here the SRIOV CNI was returning the NetConf object instead of nil. + // I do not see the point of that so I have changed that to return nil + return nil, err + } + + if isAllocated { + // Here the SRIOV CNI was returning the NetConf object instead of nil. + // I do not see the point of that so I have changed that to return nil + return nil, fmt.Errorf("pci address %s is already allocated", n.DeviceID) + } + + // Assuming VF is netdev interface; Get interface name(s) + hostIFNames, err := utils.GetVFLinkNames(n.DeviceID) + if err != nil || hostIFNames == "" { + // VF interface not found; check if VF has dpdk driver + hasDpdkDriver, err := utils.HasDpdkDriver(n.DeviceID) + if err != nil { + return nil, fmt.Errorf("LoadConf(): failed to detect if VF %s has dpdk driver %q", n.DeviceID, err) + } + n.DPDKMode = hasDpdkDriver + } + + if hostIFNames != "" { + n.OrigVfState.HostIFName = hostIFNames + } + + if hostIFNames == "" && !n.DPDKMode { + return nil, fmt.Errorf("LoadConf(): the VF %s does not have a interface name or a dpdk driver", n.DeviceID) + } + + if n.LogicalBridge != "" && len(n.LogicalBridges) > 0 { + return nil, fmt.Errorf("LoadConf(): can not define both LogicalBridge and LogicalBridges. Have to pick one of those") + } + + // validate that link state is one of supported values + /*if n.LinkState != "" && n.LinkState != "auto" && n.LinkState != "enable" && n.LinkState != "disable" { + return nil, fmt.Errorf("LoadConf(): invalid link_state value: %s", n.LinkState) + }*/ + + // This block of code should be removed when the parameters are supported by XPU. + // Also uncomment the related code blocks for the supported fields here and in the sriov pkg + if n.MinTxRate != nil || n.MaxTxRate != nil || n.SpoofChk != "" || n.Trust != "" || n.LinkState != "" { + fmt.Printf("LoadConf(): The %s configuration fields are not supported currently", UnsupportedFields) + fmt.Printf("LoadConf(): The %s configuration fields will be ignored", UnsupportedFields) + } + + return n, nil +} + +func getVfInfo(vfPci string) (string, int, error) { + var vfID int + + pf, err := utils.GetPfName(vfPci) + if err != nil { + return "", vfID, err + } + + vfID, err = utils.GetVfid(vfPci, pf) + if err != nil { + return "", vfID, err + } + + return pf, vfID, nil +} + +// LoadConfFromCache retrieves cached NetConf returns it along with a handle for removal +func LoadConfFromCache(args *skel.CmdArgs) (*opitypes.NetConf, string, error) { + netConf := &opitypes.NetConf{} + + s := []string{args.ContainerID, args.IfName} + cRef := strings.Join(s, "-") + cRefPath := filepath.Join(DefaultCNIDir, cRef) + + netConfBytes, err := utils.ReadScratchNetConf(cRefPath) + if err != nil { + return nil, "", fmt.Errorf("error reading cached NetConf in %s with name %s", DefaultCNIDir, cRef) + } + + if err = json.Unmarshal(netConfBytes, netConf); err != nil { + return nil, "", fmt.Errorf("failed to parse NetConf: %q", err) + } + + return netConf, cRefPath, nil +} + +func loadNetConf(bytes []byte) (*opitypes.NetConf, error) { + netconf := &opitypes.NetConf{} + if err := json.Unmarshal(bytes, netconf); err != nil { + return nil, fmt.Errorf("failed to load netconf: %v", err) + } + + return netconf, nil +} + +func loadFlatNetConf(configPath string) (*opitypes.NetConf, error) { + confFiles := getOpiConfFiles() + if configPath != "" { + confFiles = append([]string{configPath}, confFiles...) + } + + // loop through the path and parse the JSON config + flatNetConf := &opitypes.NetConf{} + for _, confFile := range confFiles { + confExists, err := utils.PathExists(confFile) + if err != nil { + return nil, fmt.Errorf("error checking opi-cni config file: error: %v", err) + } + if confExists { + jsonFile, err := os.Open(filepath.Clean(confFile)) + if err != nil { + return nil, fmt.Errorf("open opi-cni config file %s error: %v", confFile, err) + } + defer func() { + _ = jsonFile.Close() + }() + jsonBytes, err := io.ReadAll(jsonFile) + if err != nil { + return nil, fmt.Errorf("load opi-cni config file %s: error: %v", confFile, err) + } + if err := json.Unmarshal(jsonBytes, flatNetConf); err != nil { + return nil, fmt.Errorf("parse opi-cni config file %s: error: %v", confFile, err) + } + break + } + } + + return flatNetConf, nil +} + +func mergeConf(netconf, flatNetConf *opitypes.NetConf) (*opitypes.NetConf, error) { + if err := mergo.Merge(netconf, flatNetConf); err != nil { + return nil, fmt.Errorf("merge with opi-cni config file: error: %v", err) + } + return netconf, nil +} + +func getOpiConfFiles() []string { + return []string{"/etc/kubernetes/cni/net.d/opi.d/opi.conf", "/etc/cni/net.d/opi.d/opi.conf"} +} diff --git a/pkg/sriov/sriov.go b/pkg/sriov/sriov.go new file mode 100644 index 0000000..b4f7758 --- /dev/null +++ b/pkg/sriov/sriov.go @@ -0,0 +1,478 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright (C) 2023 Network Plumping Working Group +// Copyright (C) 2023 Nordix Foundation. + +// Package sriov handles VF plumbing +package sriov + +import ( + "fmt" + "os/exec" + "strings" + + "github.com/containernetworking/plugins/pkg/ns" + "github.com/k8snetworkplumbingwg/sriovnet" + + opitypes "github.com/opiproject/opi-cni/pkg/types" + "github.com/opiproject/opi-cni/pkg/utils" +) + +type pciUtils interface { + GetSriovNumVfs(ifName string) (int, error) + GetVFLinkNamesFromVFID(pfName string, vfID int) ([]string, error) + GetPciAddress(ifName string, vf int) (string, error) + EnableArpAndNdiscNotify(ifName string) error +} + +type pciUtilsImpl struct{} + +func (p *pciUtilsImpl) GetSriovNumVfs(ifName string) (int, error) { + return utils.GetSriovNumVfs(ifName) +} + +func (p *pciUtilsImpl) GetVFLinkNamesFromVFID(pfName string, vfID int) ([]string, error) { + return utils.GetVFLinkNamesFromVFID(pfName, vfID) +} + +func (p *pciUtilsImpl) GetPciAddress(ifName string, vf int) (string, error) { + return utils.GetPciAddress(ifName, vf) +} + +func (p *pciUtilsImpl) EnableArpAndNdiscNotify(ifName string) error { + return utils.EnableArpAndNdiscNotify(ifName) +} + +// Manager provides interface invoke sriov nic related operations +type Manager interface { + SetupVF(conf *opitypes.NetConf, podifName string, netns ns.NetNS) (string, error) + ReleaseVF(conf *opitypes.NetConf, netns ns.NetNS, netNSPath string) error + ResetVFConfig(conf *opitypes.NetConf) error + ResetVF(conf *opitypes.NetConf) error + ApplyVFConfig(conf *opitypes.NetConf) error + FillOriginalVfInfo(conf *opitypes.NetConf) error +} + +type sriovManager struct { + nLink utils.NetlinkManager + utils pciUtils +} + +// NewSriovManager returns an instance of SriovManager +func NewSriovManager() Manager { + return &sriovManager{ + nLink: &utils.MyNetlink{}, + utils: &pciUtilsImpl{}, + } +} + +// SetupVF sets up a VF in Pod netns +func (s *sriovManager) SetupVF(conf *opitypes.NetConf, podifName string, netns ns.NetNS) (string, error) { + linkName := conf.OrigVfState.HostIFName + + linkObj, err := s.nLink.LinkByName(linkName) + if err != nil { + return "", fmt.Errorf("error getting VF netdevice with name %s", linkName) + } + + // tempName used as intermediary name to avoid name conflicts + tempName := fmt.Sprintf("%s%d", "temp_", linkObj.Attrs().Index) + + // 1. Set link down + if err := s.nLink.LinkSetDown(linkObj); err != nil { + return "", fmt.Errorf("failed to down vf device %q: %v", linkName, err) + } + + // 2. Set temp name + if err := s.nLink.LinkSetName(linkObj, tempName); err != nil { + return "", fmt.Errorf("error setting temp IF name %s for %s", tempName, linkName) + } + + macAddress := linkObj.Attrs().HardwareAddr.String() + if conf.MAC != "" { + fmt.Printf("SetupVF(): MAC address configuration functionality is not supported currently") + fmt.Printf("SetupVF(): MAC address %s will be ignored", conf.MAC) + } + // 3. Set MAC address + // Identation is wrong here. Has been mixed up during the commenting out of functionality. + // Everything under if conf.Mac should be one level in + /*if conf.MAC != "" { + hwaddr, err := net.ParseMAC(conf.MAC) + if err != nil { + return "", fmt.Errorf("failed to parse MAC address %s: %v", conf.MAC, err) + } + + // Save the original effective MAC address before overriding it + conf.OrigVfState.EffectiveMAC = linkObj.Attrs().HardwareAddr.String()*/ + + /* Some NIC drivers (i.e. i40e/iavf) set VF MAC address asynchronously + via PF. This means that while the PF could already show the VF with + the desired MAC address, the netdev VF may still have the original + one. If in this window we issue a netdev VF MAC address set, the driver + will return an error and the pod will fail to create. + Other NICs (Mellanox) require explicit netdev VF MAC address so we + cannot skip this part. + Retry up to 5 times; wait 200 milliseconds between retries + */ + /*err = utils.Retry(5, 200*time.Millisecond, func() error { + return s.nLink.LinkSetHardwareAddr(linkObj, hwaddr) + }) + + if err != nil { + return "", fmt.Errorf("failed to set netlink MAC address to %s: %v", hwaddr, err) + } + macAddress = conf.MAC + }*/ + + // 4. Change netns + if err := s.nLink.LinkSetNsFd(linkObj, int(netns.Fd())); err != nil { + return "", fmt.Errorf("failed to move IF %s to netns: %q", tempName, err) + } + + if err := netns.Do(func(_ ns.NetNS) error { + // 5. Set Pod IF name + if err := s.nLink.LinkSetName(linkObj, podifName); err != nil { + return fmt.Errorf("error setting container interface name %s for %s", linkName, tempName) + } + + // 6. Enable IPv4 ARP notify and IPv6 Network Discovery notify + // Error is ignored here because enabling this feature is only a performance enhancement. + _ = s.utils.EnableArpAndNdiscNotify(podifName) + + // 7. Bring IF up in Pod netns + if err := s.nLink.LinkSetUp(linkObj); err != nil { + return fmt.Errorf("error bringing interface up in container ns: %q", err) + } + + return nil + }); err != nil { + return "", fmt.Errorf("error setting up interface in container namespace: %q", err) + } + + return macAddress, nil +} + +// ReleaseVF reset a VF from Pod netns and return it to init netns +func (s *sriovManager) ReleaseVF(conf *opitypes.NetConf, netns ns.NetNS, netNSPath string) error { + initns, err := ns.GetCurrentNS() + if err != nil { + return fmt.Errorf("ReleaseVF(): failed to get init netns: %v", err) + } + + // get VF netdevice from PCI that is attached to container. This is executed on the host namespace accessing + // the containers filesystem through the /proc/ path on the host. + vfNetdevices, err := utils.GetContainerNetDevFromPci(netNSPath, conf.DeviceID) + if err != nil { + return fmt.Errorf("ReleaseVF(): failed to get VF netdevice from PCI %s : %v", conf.DeviceID, err) + } + + if len(vfNetdevices) == 0 { + // The VF has not been found in the Container namespace so no point to continue + return nil + } + + podifName := vfNetdevices[0] + return netns.Do(func(_ ns.NetNS) error { + // get VF device + linkObj, err := s.nLink.LinkByName(podifName) + if err != nil { + return fmt.Errorf("ReleaseVF(): failed to get netlink device with name %s: %q", podifName, err) + } + + // shutdown VF device + if err = s.nLink.LinkSetDown(linkObj); err != nil { + return fmt.Errorf("ReleaseVF(): failed to set link %s down: %q", podifName, err) + } + + // rename VF device + err = s.nLink.LinkSetName(linkObj, conf.OrigVfState.HostIFName) + if err != nil { + return fmt.Errorf("ReleaseVF(): failed to rename link %s to host name %s: %q", podifName, conf.OrigVfState.HostIFName, err) + } + + // Bring VF device UP + err = s.nLink.LinkSetUp(linkObj) + if err != nil { + return fmt.Errorf("ReleaseVF(): failed to set link %s up: %q", podifName, err) + } + + // reset effective MAC address + if conf.MAC != "" { + fmt.Printf("ReleaseVF(): MAC address configuration functionality is not supported currently") + fmt.Printf("ReleaseVF(): MAC address %s will be ignored", conf.MAC) + } + /*if conf.MAC != "" { + hwaddr, err := net.ParseMAC(conf.OrigVfState.EffectiveMAC) + if err != nil { + return fmt.Errorf("failed to parse original effective MAC address %s: %v", conf.OrigVfState.EffectiveMAC, err) + } + + if err = s.nLink.LinkSetHardwareAddr(linkObj, hwaddr); err != nil { + return fmt.Errorf("failed to restore original effective netlink MAC address %s: %v", hwaddr, err) + } + }*/ + + // move VF device to init netns + if err = s.nLink.LinkSetNsFd(linkObj, int(initns.Fd())); err != nil { + return fmt.Errorf("ReleaseVF(): failed to move interface %s to init netns: %v", conf.OrigVfState.HostIFName, err) + } + + return nil + }) +} + +// This is an unused function for now. Comment it out but keep it +// in case is needed in the future +/*func getVfInfo(link netlink.Link, id int) *netlink.VfInfo { + attrs := link.Attrs() + for _, vf := range attrs.Vfs { + if vf.ID == id { + return &vf + } + } + return nil +}*/ + +// ApplyVFConfig configure a VF with parameters given in NetConf +func (s *sriovManager) ApplyVFConfig(conf *opitypes.NetConf) error { + if conf.MAC != "" { + fmt.Printf("ApplyVFConfig(): MAC address configuration functionality is not supported currently") + fmt.Printf("ApplyVFConfig(): MAC address %s will be ignored", conf.MAC) + } + + /*pfLink, err := s.nLink.LinkByName(conf.Master) + if err != nil { + return fmt.Errorf("failed to lookup master %q: %v", conf.Master, err) + } + + // 1. Set mac address + if conf.MAC != "" { + hwaddr, err := net.ParseMAC(conf.MAC) + if err != nil { + return fmt.Errorf("failed to parse MAC address %s: %v", conf.MAC, err) + } + + if err = s.nLink.LinkSetVfHardwareAddr(pfLink, conf.VFID, hwaddr); err != nil { + return fmt.Errorf("failed to set MAC address to %s: %v", hwaddr, err) + } + } + + // 2. Set min/max tx link rate. 0 means no rate limiting. Support depends on NICs and driver. + var minTxRate, maxTxRate int + rateConfigured := false + if conf.MinTxRate != nil { + minTxRate = *conf.MinTxRate + rateConfigured = true + } + + if conf.MaxTxRate != nil { + maxTxRate = *conf.MaxTxRate + rateConfigured = true + } + + if rateConfigured { + if err = s.nLink.LinkSetVfRate(pfLink, conf.VFID, minTxRate, maxTxRate); err != nil { + return fmt.Errorf("failed to set vf %d min_tx_rate to %d Mbps: max_tx_rate to %d Mbps: %v", + conf.VFID, minTxRate, maxTxRate, err) + } + } + + // 3. Set spoofchk flag + if conf.SpoofChk != "" { + spoofChk := false + if conf.SpoofChk == "on" { + spoofChk = true + } + if err = s.nLink.LinkSetVfSpoofchk(pfLink, conf.VFID, spoofChk); err != nil { + return fmt.Errorf("failed to set vf %d spoofchk flag to %s: %v", conf.VFID, conf.SpoofChk, err) + } + } + + // 4. Set trust flag + if conf.Trust != "" { + trust := false + if conf.Trust == "on" { + trust = true + } + if err = s.nLink.LinkSetVfTrust(pfLink, conf.VFID, trust); err != nil { + return fmt.Errorf("failed to set vf %d trust flag to %s: %v", conf.VFID, conf.Trust, err) + } + } + + // 5. Set link state + if conf.LinkState != "" { + var state uint32 + switch conf.LinkState { + case "auto": + state = netlink.VF_LINK_STATE_AUTO + case "enable": + state = netlink.VF_LINK_STATE_ENABLE + case "disable": + state = netlink.VF_LINK_STATE_DISABLE + default: + // the value should have been validated earlier, return error if we somehow got here + return fmt.Errorf("unknown link state %s when setting it for vf %d: %v", conf.LinkState, conf.VFID, err) + } + if err = s.nLink.LinkSetVfState(pfLink, conf.VFID, state); err != nil { + return fmt.Errorf("failed to set vf %d link state to %d: %v", conf.VFID, state, err) + } + }*/ + + return nil +} + +// FillOriginalVfInfo fills the original vf info +/*func (s *sriovManager) FillOriginalVfInfo(conf *opitypes.NetConf) error { + pfLink, err := s.nLink.LinkByName(conf.Master) + if err != nil { + return fmt.Errorf("failed to lookup master %q: %v", conf.Master, err) + } + // Save current the VF state before modifying it + vfState := getVfInfo(pfLink, conf.VFID) + if vfState == nil { + return fmt.Errorf("failed to find vf %d", conf.VFID) + } + conf.OrigVfState.FillFromVfInfo(vfState) + return err +}*/ + +// FillOriginalVfInfo fills the original vf info +func (s *sriovManager) FillOriginalVfInfo(_ *opitypes.NetConf) error { + return nil +} + +// ResetVFConfig reset a VF to its original administrative state +func (s *sriovManager) ResetVFConfig(conf *opitypes.NetConf) error { + if conf.MAC != "" { + fmt.Printf("ResetVFConfig(): MAC address configuration functionality is not supported currently") + fmt.Printf("ResetVFConfig(): MAC address %s will be ignored", conf.MAC) + } + /*pfLink, err := s.nLink.LinkByName(conf.Master) + if err != nil { + return fmt.Errorf("failed to lookup master %q: %v", conf.Master, err) + }*/ + + // Restore the original administrative MAC address + // Identation is wrong here. Has been mixed up during the commenting out of functionality. + // Everything under if conf.Mac should be one level in + /*if conf.MAC != "" { + hwaddr, err := net.ParseMAC(conf.OrigVfState.AdminMAC) + if err != nil { + return fmt.Errorf("failed to parse original administrative MAC address %s: %v", conf.OrigVfState.AdminMAC, err) + }*/ + + /* Some NIC drivers (i.e. i40e/iavf) set VF MAC address asynchronously + via PF. This means that while the PF could already show the VF with + the desired MAC address, the netdev VF may still have the original + one. If in this window we issue a netdev VF MAC address set, the driver + will return an error and the pod will fail to create. + Other NICs (Mellanox) require explicit netdev VF MAC address so we + cannot skip this part. + Retry up to 5 times; wait 200 milliseconds between retries + */ + /*err = utils.Retry(5, 200*time.Millisecond, func() error { + return s.nLink.LinkSetVfHardwareAddr(pfLink, conf.VFID, hwaddr) + }) + if err != nil { + return fmt.Errorf("failed to restore original administrative MAC address %s: %v", hwaddr, err) + } + }*/ + + // Restore VF trust + /*if conf.Trust != "" { + // TODO: netlink go implementation does not support getting VF trust, need to add support there first + // for now, just set VF trust to off if it was specified by the user in netconf + if err = s.nLink.LinkSetVfTrust(pfLink, conf.VFID, false); err != nil { + return fmt.Errorf("failed to disable trust for vf %d: %v", conf.VFID, err) + } + } + + // Restore rate limiting + if conf.MinTxRate != nil || conf.MaxTxRate != nil { + if err = s.nLink.LinkSetVfRate(pfLink, conf.VFID, conf.OrigVfState.MinTxRate, conf.OrigVfState.MaxTxRate); err != nil { + return fmt.Errorf("failed to disable rate limiting for vf %d %v", conf.VFID, err) + } + } + + // Restore link state to `auto` + if conf.LinkState != "" { + // Reset only when link_state was explicitly specified, to accommodate for drivers / NICs + // that don't support the netlink command (e.g. igb driver) + if err = s.nLink.LinkSetVfState(pfLink, conf.VFID, conf.OrigVfState.LinkState); err != nil { + return fmt.Errorf("failed to set link state to auto for vf %d: %v", conf.VFID, err) + } + } + + // Restore spoofchk + if conf.SpoofChk != "" { + if err = s.nLink.LinkSetVfSpoofchk(pfLink, conf.VFID, conf.OrigVfState.SpoofChk); err != nil { + return fmt.Errorf("failed to restore spoofchk for vf %d: %v", conf.VFID, err) + } + }*/ + + return nil +} + +// ResetVF resets a netdev VF to its original state +func (s *sriovManager) ResetVF(conf *opitypes.NetConf) error { + // Maybe in this function we need to handle the OriginalVfState.EffectiveMac + // Check ReleaseVF func + + // get VF netdevice from PCI + vfNetdevices, err := sriovnet.GetNetDevicesFromPci(conf.DeviceID) + if err != nil { + return fmt.Errorf("ResetVF(): failed to get VF netdevice from PCI %s : %v", conf.DeviceID, err) + } + + if len(vfNetdevices) == 0 { + // The VF has not been found in the host namespace so no point to continue. + // This is according to the idempotent logic where if something is not found + // then is considered that is not an error. + return nil + } + + curNetVFName := vfNetdevices[0] + + // get VF device + linkObj, err := s.nLink.LinkByName(curNetVFName) + if err != nil { + return fmt.Errorf("ResetVF(): failed to get netlink device with name %s: %q", curNetVFName, err) + } + + // shutdown VF device + if err = s.nLink.LinkSetDown(linkObj); err != nil { + return fmt.Errorf("ResetVF(): failed to set link %s down: %q", curNetVFName, err) + } + + // Delete the altname of the MEV VF. + // If the altname of the original name of the VF is not deleted the renaming will fail + // Note: We need installed on the host bash shell and ip executable for commands to be executed correctly + searchStr := "'altname " + conf.OrigVfState.HostIFName + "'" + showCmd := "ip link show " + curNetVFName + " | grep -o " + searchStr + " | cut -d ' ' -f 2" + altnameByte, err := exec.Command("bash", "-c", showCmd).Output() // #nosec G204 + if err != nil { + return fmt.Errorf("ResetVF(): failed to get the altname: %q", err) + } + + altname := strings.TrimSpace(string(altnameByte)) + if altname == conf.OrigVfState.HostIFName { + delCmd := "ip link property del dev " + curNetVFName + " altname " + conf.OrigVfState.HostIFName + _, err := exec.Command("bash", "-c", delCmd).Output() // #nosec G204 + if err != nil { + return fmt.Errorf("ResetVF(): failed to delete the altname: %q", err) + } + } + + // rename VF device + err = s.nLink.LinkSetName(linkObj, conf.OrigVfState.HostIFName) + if err != nil { + return fmt.Errorf("ResetVF(): failed to rename link %s to host name %s: %q", curNetVFName, conf.OrigVfState.HostIFName, err) + } + + // Bring VF device UP + err = s.nLink.LinkSetUp(linkObj) + if err != nil { + return fmt.Errorf("ResetVF(): failed to set link %s up: %q", curNetVFName, err) + } + + return nil +} diff --git a/pkg/types/types.go b/pkg/types/types.go new file mode 100644 index 0000000..bbcb3a6 --- /dev/null +++ b/pkg/types/types.go @@ -0,0 +1,57 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright (C) 2023 Network Plumping Working Group +// Copyright (C) 2023 Nordix Foundation. + +// Package types holds the main types of the opi-cni +package types + +import ( + "github.com/containernetworking/cni/pkg/types" + "github.com/vishvananda/netlink" +) + +// VfState represents the state of the VF +type VfState struct { + HostIFName string + SpoofChk bool // Not Used + AdminMAC string // Not Used + EffectiveMAC string // Not Used + MinTxRate int // Not Used + MaxTxRate int // Not Used + LinkState uint32 // Not Used +} + +// FillFromVfInfo - Fill attributes according to the provided netlink.VfInfo struct - Not Used +func (vs *VfState) FillFromVfInfo(info *netlink.VfInfo) { + vs.AdminMAC = info.Mac.String() + vs.LinkState = info.LinkState + vs.MaxTxRate = int(info.MaxTxRate) + vs.MinTxRate = int(info.MinTxRate) + vs.SpoofChk = info.Spoofchk +} + +// NetConf extends types.NetConf for opi-cni +type NetConf struct { + types.NetConf + OrigVfState VfState // Stores the original VF state as it was prior to any operations done during cmdAdd flow + DPDKMode bool + Master string + MAC string + LogicalBridge string `json:"logical_bridge,omitempty"` + LogicalBridges []string `json:"logical_bridges,omitempty"` + PortType string + BridgePortName string // Stores the "name" of the created Bridge Port + DeviceID string `json:"deviceID"` // PCI address of a VF in valid sysfs format + VFID int + MinTxRate *int `json:"min_tx_rate"` // Mbps, 0 = disable rate limiting (XPU Not supported) + MaxTxRate *int `json:"max_tx_rate"` // Mbps, 0 = disable rate limiting (XPU Not supported) + SpoofChk string `json:"spoofchk,omitempty"` // on|off (XPU Not supported) + Trust string `json:"trust,omitempty"` // on|off (XPU Not supported) + LinkState string `json:"link_state,omitempty"` // auto|enable|disable (XPU Not supported) + XpuInfraMgrConn string `json:"xpu_infra_mgr_conn"` // the IP and port where the xpu_infra_manager listens. Format "IP:Port" + ConfigurationPath string `json:"configuration_path"` // Configuration path for opi-cni conf files + PciToMacPath string `json:"pci_to_mac_path"` // The Path where we keep the mapping of PCI addresses to MAC addresses for the xPU VFs + RuntimeConfig struct { + Mac string `json:"mac,omitempty"` + } `json:"runtimeConfig,omitempty"` +} diff --git a/pkg/utils/netlink_manager.go b/pkg/utils/netlink_manager.go new file mode 100644 index 0000000..a290f73 --- /dev/null +++ b/pkg/utils/netlink_manager.go @@ -0,0 +1,89 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright (C) 2023 Network Plumping Working Group +// Copyright (C) 2023 Nordix Foundation. + +// Package utils holds utilities for opi-cni +package utils + +import ( + "net" + + "github.com/vishvananda/netlink" +) + +// Mocked netlink interface, this is required for unit tests + +// NetlinkManager is an interface to mock nelink library +type NetlinkManager interface { + LinkByName(string) (netlink.Link, error) + LinkSetVfHardwareAddr(netlink.Link, int, net.HardwareAddr) error + LinkSetHardwareAddr(netlink.Link, net.HardwareAddr) error + LinkSetUp(netlink.Link) error + LinkSetDown(netlink.Link) error + LinkSetNsFd(netlink.Link, int) error + LinkSetName(netlink.Link, string) error + LinkSetVfRate(netlink.Link, int, int, int) error + LinkSetVfSpoofchk(netlink.Link, int, bool) error + LinkSetVfTrust(netlink.Link, int, bool) error + LinkSetVfState(netlink.Link, int, uint32) error +} + +// MyNetlink NetlinkManager +type MyNetlink struct { + NetlinkManager +} + +// LinkByName implements NetlinkManager +func (n *MyNetlink) LinkByName(name string) (netlink.Link, error) { + return netlink.LinkByName(name) +} + +// LinkSetVfHardwareAddr using NetlinkManager +func (n *MyNetlink) LinkSetVfHardwareAddr(link netlink.Link, vf int, hwaddr net.HardwareAddr) error { + return netlink.LinkSetVfHardwareAddr(link, vf, hwaddr) +} + +// LinkSetHardwareAddr using NetlinkManager +func (n *MyNetlink) LinkSetHardwareAddr(link netlink.Link, hwaddr net.HardwareAddr) error { + return netlink.LinkSetHardwareAddr(link, hwaddr) +} + +// LinkSetUp using NetlinkManager +func (n *MyNetlink) LinkSetUp(link netlink.Link) error { + return netlink.LinkSetUp(link) +} + +// LinkSetDown using NetlinkManager +func (n *MyNetlink) LinkSetDown(link netlink.Link) error { + return netlink.LinkSetDown(link) +} + +// LinkSetNsFd using NetlinkManager +func (n *MyNetlink) LinkSetNsFd(link netlink.Link, fd int) error { + return netlink.LinkSetNsFd(link, fd) +} + +// LinkSetName using NetlinkManager +func (n *MyNetlink) LinkSetName(link netlink.Link, name string) error { + return netlink.LinkSetName(link, name) +} + +// LinkSetVfRate using NetlinkManager +func (n *MyNetlink) LinkSetVfRate(link netlink.Link, vf int, minRate int, maxRate int) error { + return netlink.LinkSetVfRate(link, vf, minRate, maxRate) +} + +// LinkSetVfSpoofchk using NetlinkManager +func (n *MyNetlink) LinkSetVfSpoofchk(link netlink.Link, vf int, check bool) error { + return netlink.LinkSetVfSpoofchk(link, vf, check) +} + +// LinkSetVfTrust using NetlinkManager +func (n *MyNetlink) LinkSetVfTrust(link netlink.Link, vf int, state bool) error { + return netlink.LinkSetVfTrust(link, vf, state) +} + +// LinkSetVfState using NetlinkManager +func (n *MyNetlink) LinkSetVfState(link netlink.Link, vf int, state uint32) error { + return netlink.LinkSetVfState(link, vf, state) +} diff --git a/pkg/utils/packet.go b/pkg/utils/packet.go new file mode 100644 index 0000000..8effce2 --- /dev/null +++ b/pkg/utils/packet.go @@ -0,0 +1,208 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright (C) 2023 Network Plumping Working Group +// Copyright (C) 2023 Nordix Foundation. + +// Package utils holds utilities for opi-cni +package utils + +import ( + "bytes" + "encoding/binary" + "fmt" + "net" + "syscall" + + current "github.com/containernetworking/cni/pkg/types/100" + "github.com/vishvananda/netlink" + "golang.org/x/net/icmp" + "golang.org/x/net/ipv6" +) + +var ( + arpPacketName = "ARP" + icmpV6PacketName = "ICMPv6" +) + +// htons converts an uint16 from host to network byte order. +func htons(i uint16) uint16 { + return (i<<8)&0xff00 | i>>8 +} + +// formatPacketFieldWriteError builds an error string for the cases when writing to a field of a packet fails. +func formatPacketFieldWriteError(field string, packetType string, writeErr error) error { + return fmt.Errorf("failed to write the %s field in the %s packet: %v", field, packetType, writeErr) +} + +// SendGratuitousArp sends a gratuitous ARP packet with the provided source IP over the provided interface. +func SendGratuitousArp(srcIP net.IP, linkObj netlink.Link) error { + /* As per RFC 5944 section 4.6, a gratuitous ARP packet can be sent by a node in order to spontaneously cause other nodes to update + * an entry in their ARP cache. In the case of SRIOV-CNI, an address can be reused for different pods. Each pod could likely have a + * different link-layer address in this scenario, which makes the ARP cache entries residing in the other nodes to be an invalid. + * The gratuitous ARP packet should update the link-layer address accordingly for the invalid ARP cache. + */ + + // Construct the ARP packet following RFC 5944 section 4.6. + arpPacket := new(bytes.Buffer) + if writeErr := binary.Write(arpPacket, binary.BigEndian, uint16(1)); writeErr != nil { // Hardware Type: 1 is Ethernet + return formatPacketFieldWriteError("Hardware Type", arpPacketName, writeErr) + } + if writeErr := binary.Write(arpPacket, binary.BigEndian, uint16(syscall.ETH_P_IP)); writeErr != nil { // Protocol Type: 0x0800 is IPv4 + return formatPacketFieldWriteError("Protocol Type", arpPacketName, writeErr) + } + if writeErr := binary.Write(arpPacket, binary.BigEndian, uint8(6)); writeErr != nil { // Hardware address Length: 6 bytes for MAC address + return formatPacketFieldWriteError("Hardware address Length", arpPacketName, writeErr) + } + if writeErr := binary.Write(arpPacket, binary.BigEndian, uint8(4)); writeErr != nil { // Protocol address length: 4 bytes for IPv4 address + return formatPacketFieldWriteError("Protocol address length", arpPacketName, writeErr) + } + if writeErr := binary.Write(arpPacket, binary.BigEndian, uint16(1)); writeErr != nil { // Operation: 1 is request, 2 is response + return formatPacketFieldWriteError("Operation", arpPacketName, writeErr) + } + if _, writeErr := arpPacket.Write(linkObj.Attrs().HardwareAddr); writeErr != nil { // Sender hardware address + return formatPacketFieldWriteError("Sender hardware address", arpPacketName, writeErr) + } + if _, writeErr := arpPacket.Write(srcIP.To4()); writeErr != nil { // Sender protocol address + return formatPacketFieldWriteError("Sender protocol address", arpPacketName, writeErr) + } + if _, writeErr := arpPacket.Write([]byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff}); writeErr != nil { // Target hardware address is the Broadcast MAC. + return formatPacketFieldWriteError("Target hardware address", arpPacketName, writeErr) + } + if _, writeErr := arpPacket.Write(srcIP.To4()); writeErr != nil { // Target protocol address + return formatPacketFieldWriteError("Target protocol address", arpPacketName, writeErr) + } + + sockAddr := syscall.SockaddrLinklayer{ + Protocol: htons(syscall.ETH_P_ARP), // Ethertype of ARP (0x0806) + Ifindex: linkObj.Attrs().Index, // Interface Index + Hatype: 1, // Hardware Type: 1 is Ethernet + Pkttype: 0, // Packet Type. + Halen: 6, // Hardware address Length: 6 bytes for MAC address + Addr: [8]byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, // Address is the broadcast MAC address. + } + + // Create a socket such that the Ethernet header would constructed by the OS. The arpPacket only contains the ARP payload. + soc, err := syscall.Socket(syscall.AF_PACKET, syscall.SOCK_DGRAM, int(htons(syscall.ETH_P_ARP))) + if err != nil { + return fmt.Errorf("failed to create AF_PACKET datagram socket: %v", err) + } + defer func() { + _ = syscall.Close(soc) + }() + + if err := syscall.Sendto(soc, arpPacket.Bytes(), 0, &sockAddr); err != nil { + return fmt.Errorf("failed to send Gratuitous ARP for IPv4 %s on Interface %s: %v", srcIP.String(), linkObj.Attrs().Name, err) + } + + return nil +} + +// SendUnsolicitedNeighborAdvertisement sends an unsolicited neighbor advertisement packet with the provided source IP over the provided interface. +func SendUnsolicitedNeighborAdvertisement(srcIP net.IP, linkObj netlink.Link) error { + /* As per RFC 4861, a link-layer address change can multicast a few unsolicited neighbor advertisements to all nodes to quickly + * update the cached link-layer addresses that have become invalid. In the case of SRIOV-CNI, an address can be reused for + * different pods. Each pod could likely have a different link-layer address in this scenario, which makes the Neighbor Cache + * entries residing in the neighbors to be an invalid. The unsolicited neighbor advertisement should update the link-layer address + * accordingly for the IPv6 entry. + * However if any of these conditions are true: + * - The IPv6 address was not reused for the new pod. + * - No prior established communication with the neighbor. + * Then the neighbor receiving this unsolicited neighbor advertisement would be silently discard. This behavior is described + * in RFC 4861 section 7.2.5. This is acceptable behavior since the purpose of sending an unsolicited neighbor advertisement + * is not to create a new entry but rather update already existing invalid entries. + */ + + // Construct the ICMPv6 Neighbor Advertisement packet following RFC 4861. + payload := new(bytes.Buffer) + // ICMPv6 Flags: As per RFC 4861, the solicited flag must not be set and the override flag should be set (to + // override existing cache entry) for unsolicited advertisements. + if writeErr := binary.Write(payload, binary.BigEndian, uint32(0x20000000)); writeErr != nil { + return formatPacketFieldWriteError("Flags", icmpV6PacketName, writeErr) + } + if _, writeErr := payload.Write(srcIP.To16()); writeErr != nil { // ICMPv6 Target IPv6 Address. + return formatPacketFieldWriteError("Target IPv6 Address", icmpV6PacketName, writeErr) + } + if writeErr := binary.Write(payload, binary.BigEndian, uint8(2)); writeErr != nil { // ICMPv6 Option Type: 2 is target link-layer address. + return formatPacketFieldWriteError("Option Type", icmpV6PacketName, writeErr) + } + if writeErr := binary.Write(payload, binary.BigEndian, uint8(1)); writeErr != nil { // ICMPv6 Option Length. Units of 8 bytes. + return formatPacketFieldWriteError("Option Length", icmpV6PacketName, writeErr) + } + if _, writeErr := payload.Write(linkObj.Attrs().HardwareAddr); writeErr != nil { // ICMPv6 Option Link-layer Address. + return formatPacketFieldWriteError("Option Link-layer Address", icmpV6PacketName, writeErr) + } + + icmpv6Msg := icmp.Message{ + Type: ipv6.ICMPTypeNeighborAdvertisement, // ICMPv6 type is neighbor advertisement. + Code: 0, // ICMPv6 Code: As per RFC 4861 section 7.1.2, the code is always 0. + Checksum: 0, // Checksum is calculated later. + Body: &icmp.RawBody{ + Data: payload.Bytes(), + }, + } + + // Get the byte array of the ICMPv6 Message. + icmpv6Bytes, err := icmpv6Msg.Marshal(nil) + if err != nil { + return fmt.Errorf("failed to Marshal ICMPv6 Message: %v", err) + } + + // Create a socket such that the Ethernet header and IPv6 header would constructed by the OS. + soc, err := syscall.Socket(syscall.AF_INET6, syscall.SOCK_RAW, syscall.IPPROTO_ICMPV6) + if err != nil { + return fmt.Errorf("failed to create AF_INET6 raw socket: %v", err) + } + defer func() { + _ = syscall.Close(soc) + }() + + // As per RFC 4861 section 7.1.2, the IPv6 hop limit is always 255. + if err := syscall.SetsockoptInt(soc, syscall.IPPROTO_IPV6, syscall.IPV6_MULTICAST_HOPS, 255); err != nil { + return fmt.Errorf("failed to set IPv6 multicast hops to 255: %v", err) + } + + // Set the destination IPv6 address to the IPv6 link-local all nodes multicast address (ff02::1). + var r [16]byte + copy(r[:], net.IPv6linklocalallnodes.To16()) + sockAddr := syscall.SockaddrInet6{Addr: r} + if err := syscall.Sendto(soc, icmpv6Bytes, 0, &sockAddr); err != nil { + return fmt.Errorf("failed to send Unsolicited Neighbor Advertisement for IPv6 %s on Interface %s: %v", srcIP.String(), linkObj.Attrs().Name, err) + } + + return nil +} + +// AnnounceIPs sends either a GARP or Unsolicited NA depending on the IP address type (IPv4 vs. IPv6 respectively) configured on the interface. +func AnnounceIPs(ifName string, ipConfigs []*current.IPConfig) error { + myNetLink := MyNetlink{} + + // Retrieve the interface name in the container. + linkObj, err := myNetLink.LinkByName(ifName) + if err != nil { + return fmt.Errorf("failed to get netlink device with name %q: %v", ifName, err) + } + if !IsValidMACAddress(linkObj.Attrs().HardwareAddr) { + return fmt.Errorf("invalid Ethernet MAC address: %q", linkObj.Attrs().HardwareAddr) + } + + // For all the IP addresses assigned by IPAM, we will send either a GARP (IPv4) or Unsolicited NA (IPv6). + for _, ipc := range ipConfigs { + var err error + switch { + case IsIPv6(ipc.Address.IP): + /* As per RFC 4861, sending unsolicited neighbor advertisements should be considered as a performance + * optimization. It does not reliably update caches in all nodes. The Neighbor Unreachability Detection + * algorithm is more reliable although it may take slightly longer to update. + */ + err = SendUnsolicitedNeighborAdvertisement(ipc.Address.IP, linkObj) + case IsIPv4(ipc.Address.IP): + err = SendGratuitousArp(ipc.Address.IP, linkObj) + default: + return fmt.Errorf("the IP %s on interface %q is neither IPv4 or IPv6", ipc.Address.IP.String(), ifName) + } + + if err != nil { + return fmt.Errorf("failed to send GARP/NA message for ip %s on interface %q: %v", ipc.Address.IP.String(), ifName, err) + } + } + return nil +} diff --git a/pkg/utils/pci_allocator.go b/pkg/utils/pci_allocator.go new file mode 100644 index 0000000..8d148e0 --- /dev/null +++ b/pkg/utils/pci_allocator.go @@ -0,0 +1,104 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright (C) 2023 Network Plumping Working Group +// Copyright (C) 2023 Nordix Foundation. + +// Package utils holds utilities for opi-cni +package utils + +import ( + "fmt" + "os" + "path/filepath" + + "github.com/containernetworking/plugins/pkg/ns" +) + +// PCIAllocation holds functions for managing PCI devices +type PCIAllocation interface { + SaveAllocatedPCI(string, string) error + DeleteAllocatedPCI(string) error + IsAllocated(string) error +} + +// PCIAllocator implements PCIAllocation interface +type PCIAllocator struct { + dataDir string +} + +// NewPCIAllocator returns a new PCI allocator +// it will use the /pci folder to store the information about allocated PCI addresses +func NewPCIAllocator(dataDir string) *PCIAllocator { + return &PCIAllocator{dataDir: filepath.Join(dataDir, "pci")} +} + +// SaveAllocatedPCI creates a file with the pci address as a name and the network namespace as the content +// return error if the file was not created +func (p *PCIAllocator) SaveAllocatedPCI(pciAddress, ns string) error { + if err := os.MkdirAll(p.dataDir, 0600); err != nil { + return fmt.Errorf("failed to create the sriov data directory(%q): %v", p.dataDir, err) + } + + path := filepath.Join(p.dataDir, pciAddress) + err := os.WriteFile(path, []byte(ns), 0600) + if err != nil { + return fmt.Errorf("failed to write used PCI address lock file in the path(%q): %v", path, err) + } + + return err +} + +// DeleteAllocatedPCI Remove the allocated PCI file +// return error if the file doesn't exist +func (p *PCIAllocator) DeleteAllocatedPCI(pciAddress string) error { + path := filepath.Join(p.dataDir, pciAddress) + _, err := os.Stat(path) + if err != nil { + if os.IsNotExist(err) { + return nil + } + + return fmt.Errorf("error stating PCI address lock file %s: %v", path, err) + } + + if err := os.Remove(path); err != nil { + return fmt.Errorf("error removing PCI address lock file %s: %v", path, err) + } + return nil +} + +// IsAllocated checks if the PCI address file exist +// if it exists we also check the network namespace still exist if not we delete the allocation +// The function will return an error if the pci is still allocated to a running pod +func (p *PCIAllocator) IsAllocated(pciAddress string) (bool, error) { + path := filepath.Join(p.dataDir, pciAddress) + _, err := os.Stat(path) + if err != nil { + if os.IsNotExist(err) { + return false, nil + } + + return false, fmt.Errorf("failed to check for pci address file for %s: %v", path, err) + } + + dat, err := os.ReadFile(filepath.Clean(path)) + if err != nil { + return false, fmt.Errorf("failed to read for pci address file for %s: %v", path, err) + } + + // To prevent a locking of a PCI address for every pciAddress file we also add the netns path where it's been used + // This way if for some reason the cmdDel command was not called but the pod namespace doesn't exist anymore + // we release the PCI address + networkNamespace, err := ns.GetNS(string(dat)) + if err != nil { + err = p.DeleteAllocatedPCI(pciAddress) + if err != nil { + return false, fmt.Errorf("error deleting the pci allocation for vf pci address %s: %v", pciAddress, err) + } + + return false, nil + } + + // Close the network namespace + _ = networkNamespace.Close() + return true, nil +} diff --git a/pkg/utils/utils.go b/pkg/utils/utils.go new file mode 100644 index 0000000..201e423 --- /dev/null +++ b/pkg/utils/utils.go @@ -0,0 +1,417 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright (C) 2023 Network Plumping Working Group +// Copyright (C) 2023 Nordix Foundation. +// Copyright 2023 NVIDIA CORPORATION & AFFILIATES. + +// Package utils holds utilities for opi-cni +package utils + +import ( + "bytes" + "encoding/json" + "fmt" + "io" + "net" + "os" + "path/filepath" + "strconv" + "strings" + "time" + + utilfs "github.com/k8snetworkplumbingwg/sriovnet/pkg/utils/filesystem" +) + +var ( + sriovConfigured = "/sriov_numvfs" + // NetDirectory sysfs net directory + NetDirectory = "/sys/class/net" + // SysBusPci is sysfs pci device directory for host + SysBusPci = "/sys/bus/pci/devices" + // ContainerSysBusPci is sysfs pci device directory for containers + ContainerSysBusPci = "/root/sys/bus/pci/devices" + // SysV4ArpNotify is the sysfs IPv4 ARP Notify directory + SysV4ArpNotify = "/proc/sys/net/ipv4/conf/" + // SysV6NdiscNotify is the sysfs IPv6 Neighbor Discovery Notify directory + SysV6NdiscNotify = "/proc/sys/net/ipv6/conf/" + // UserspaceDrivers is a list of driver names that don't have netlink representation for their devices + UserspaceDrivers = []string{"vfio-pci", "uio_pci_generic", "igb_uio"} +) + +// EnableArpAndNdiscNotify enables IPv4 arp_notify and IPv6 ndisc_notify for netdev +func EnableArpAndNdiscNotify(ifName string) error { + /* For arp_notify, when a value of "1" is set then a Gratuitous ARP request will be sent + * when the network device is brought up or if the link-layer address changes. + * For ndsic_notify, when a value of "1" is set then a Unsolicited Neighbor Advertisement + * will be sent when the network device is brought up or if the link-layer address changes. + * Both of these being enabled would be useful in the case when an application reenables + * an interface or if the MAC address configuration is changed. The kernel is responsible + * for sending of these packets when the conditions are met. + */ + v4ArpNotifyPath := filepath.Join(SysV4ArpNotify, ifName, "arp_notify") + err := os.WriteFile(v4ArpNotifyPath, []byte("1"), os.ModeAppend) + if err != nil { + return fmt.Errorf("failed to write arp_notify=1 for interface %s: %v", ifName, err) + } + v6NdiscNotifyPath := filepath.Join(SysV6NdiscNotify, ifName, "ndisc_notify") + err = os.WriteFile(v6NdiscNotifyPath, []byte("1"), os.ModeAppend) + if err != nil { + return fmt.Errorf("failed to write ndisc_notify=1 for interface %s: %v", ifName, err) + } + return nil +} + +// GetSriovNumVfs takes in a PF name(ifName) as string and returns number of VF configured as int +func GetSriovNumVfs(ifName string) (int, error) { + var vfTotal int + + sriovFile := filepath.Join(NetDirectory, ifName, "device", sriovConfigured) + if _, err := os.Lstat(sriovFile); err != nil { + return vfTotal, fmt.Errorf("failed to open the sriov_numfs of device %q: %v", ifName, err) + } + + data, err := os.ReadFile(filepath.Clean(sriovFile)) + if err != nil { + return vfTotal, fmt.Errorf("failed to read the sriov_numfs of device %q: %v", ifName, err) + } + + if len(data) == 0 { + return vfTotal, fmt.Errorf("no data in the file %q", sriovFile) + } + + sriovNumfs := strings.TrimSpace(string(data)) + vfTotal, err = strconv.Atoi(sriovNumfs) + if err != nil { + return vfTotal, fmt.Errorf("failed to convert sriov_numfs(byte value) to int of device %q: %v", ifName, err) + } + + return vfTotal, nil +} + +// GetVfid takes in VF's PCI address(addr) and pfName as string and returns VF's ID as int +func GetVfid(addr string, pfName string) (int, error) { + var id int + vfTotal, err := GetSriovNumVfs(pfName) + if err != nil { + return id, err + } + for vf := 0; vf < vfTotal; vf++ { + vfDir := filepath.Join(NetDirectory, pfName, "device", fmt.Sprintf("virtfn%d", vf)) + _, err := os.Lstat(vfDir) + if err != nil { + continue + } + pciinfo, err := os.Readlink(vfDir) + if err != nil { + continue + } + pciaddr := filepath.Base(pciinfo) + if pciaddr == addr { + return vf, nil + } + } + return id, fmt.Errorf("unable to get VF ID with PF: %s and VF pci address %v", pfName, addr) +} + +// GetPfName returns PF net device name of a given VF pci address +func GetPfName(vf string) (string, error) { + pfSymLink := filepath.Join(SysBusPci, vf, "physfn", "net") + _, err := os.Lstat(pfSymLink) + if err != nil { + return "", err + } + + files, err := os.ReadDir(pfSymLink) + if err != nil { + return "", err + } + + if len(files) < 1 { + return "", fmt.Errorf("PF network device not found") + } + + return strings.TrimSpace(files[0].Name()), nil +} + +// GetPciAddress takes in a interface(ifName) and VF id and returns its pci addr as string +func GetPciAddress(ifName string, vf int) (string, error) { + var pciaddr string + vfDir := filepath.Join(NetDirectory, ifName, "device", fmt.Sprintf("virtfn%d", vf)) + dirInfo, err := os.Lstat(vfDir) + if err != nil { + return pciaddr, fmt.Errorf("can't get the symbolic link of virtfn%d dir of the device %q: %v", vf, ifName, err) + } + + if (dirInfo.Mode() & os.ModeSymlink) == 0 { + return pciaddr, fmt.Errorf("no symbolic link for the virtfn%d dir of the device %q", vf, ifName) + } + + pciinfo, err := os.Readlink(vfDir) + if err != nil { + return pciaddr, fmt.Errorf("can't read the symbolic link of virtfn%d dir of the device %q: %v", vf, ifName, err) + } + + pciaddr = filepath.Base(pciinfo) + return pciaddr, nil +} + +// GetSharedPF takes in VF name(ifName) as string and returns the other VF name that shares same PCI address as string +func GetSharedPF(ifName string) (string, error) { + pfName := "" + pfDir := filepath.Join(NetDirectory, ifName) + dirInfo, err := os.Lstat(pfDir) + if err != nil { + return pfName, fmt.Errorf("can't get the symbolic link of the device %q: %v", ifName, err) + } + + if (dirInfo.Mode() & os.ModeSymlink) == 0 { + return pfName, fmt.Errorf("no symbolic link for dir of the device %q", ifName) + } + + fullpath, _ := filepath.EvalSymlinks(pfDir) + parentDir := fullpath[:len(fullpath)-len(ifName)] + dirList, _ := os.ReadDir(parentDir) + + for _, file := range dirList { + if file.Name() != ifName { + pfName = file.Name() + return pfName, nil + } + } + + return pfName, fmt.Errorf("shared PF not found") +} + +// GetVFLinkNames returns VF's network interface name given it's PCI addr +func GetVFLinkNames(pciAddr string) (string, error) { + vfDir := filepath.Join(SysBusPci, pciAddr, "net") + if _, err := os.Lstat(vfDir); err != nil { + return "", err + } + + fInfos, err := os.ReadDir(vfDir) + if err != nil { + return "", fmt.Errorf("failed to read net dir of the device %s: %v", pciAddr, err) + } + + if len(fInfos) == 0 { + return "", fmt.Errorf("VF device %s sysfs path (%s) has no entries", pciAddr, vfDir) + } + + names := make([]string, 0, len(fInfos)) + for _, f := range fInfos { + names = append(names, f.Name()) + } + + return names[0], nil +} + +// GetVFLinkNamesFromVFID returns VF's network interface name given it's PF name as string and VF id as int +func GetVFLinkNamesFromVFID(pfName string, vfID int) ([]string, error) { + vfDir := filepath.Join(NetDirectory, pfName, "device", fmt.Sprintf("virtfn%d", vfID), "net") + if _, err := os.Lstat(vfDir); err != nil { + return nil, err + } + + fInfos, err := os.ReadDir(vfDir) + if err != nil { + return nil, fmt.Errorf("failed to read the virtfn%d dir of the device %q: %v", vfID, pfName, err) + } + + names := make([]string, 0, len(fInfos)) + for _, f := range fInfos { + names = append(names, f.Name()) + } + + return names, nil +} + +// GetContainerNetDevFromPci returns a list of netdevices from PCI address +// that is attached to container +func GetContainerNetDevFromPci(netNSPath, pciAddress string) ([]string, error) { + PidSlice := strings.Split(netNSPath, "/")[1:3] + PidPath := strings.Join(PidSlice, "/") + containerPciNetPath := filepath.Join(PidPath, ContainerSysBusPci, pciAddress, "net") + return getFileNamesFromPath(containerPciNetPath) +} + +// HasDpdkDriver checks if a device is attached to dpdk supported driver +func HasDpdkDriver(pciAddr string) (bool, error) { + driverLink := filepath.Join(SysBusPci, pciAddr, "driver") + driverPath, err := filepath.EvalSymlinks(driverLink) + if err != nil { + return false, err + } + driverStat, err := os.Stat(driverPath) + if err != nil { + return false, err + } + driverName := driverStat.Name() + for _, drv := range UserspaceDrivers { + if driverName == drv { + return true, nil + } + } + return false, nil +} + +// SaveNetConf takes in container ID, data dir and Pod interface name as string and a json encoded struct Conf +// and save this Conf in data dir +func SaveNetConf(cid, dataDir, podIfName string, conf interface{}) error { + netConfBytes, err := json.Marshal(conf) + if err != nil { + return fmt.Errorf("error serializing delegate netconf: %v", err) + } + + s := []string{cid, podIfName} + cRef := strings.Join(s, "-") + + // save the rendered netconf for cmdDel + return saveScratchNetConf(cRef, dataDir, netConfBytes) +} + +func saveScratchNetConf(containerID, dataDir string, netconf []byte) error { + if err := os.MkdirAll(dataDir, 0700); err != nil { + return fmt.Errorf("failed to create the sriov data directory(%q): %v", dataDir, err) + } + + path := filepath.Join(dataDir, containerID) + + err := os.WriteFile(path, netconf, 0600) + if err != nil { + return fmt.Errorf("failed to write container data in the path(%q): %v", path, err) + } + + return err +} + +// ReadScratchNetConf takes in container ID, Pod interface name and data dir as string and returns a pointer to Conf +func ReadScratchNetConf(cRefPath string) ([]byte, error) { + data, err := os.ReadFile(filepath.Clean(cRefPath)) + if err != nil { + return nil, fmt.Errorf("failed to read container data in the path(%q): %v", cRefPath, err) + } + + return data, err +} + +// CleanCachedNetConf removed cached NetConf from disk +func CleanCachedNetConf(cRefPath string) error { + _, err := os.Stat(cRefPath) + if err != nil { + if os.IsNotExist(err) { + return nil + } + + return fmt.Errorf("error stating cached NetConf file %s: %v", cRefPath, err) + } + + if err := os.Remove(cRefPath); err != nil { + return fmt.Errorf("error removing NetConf file %s: %v", cRefPath, err) + } + return nil +} + +// IsValidMACAddress checks if net.HardwareAddr is a valid MAC address. +func IsValidMACAddress(addr net.HardwareAddr) bool { + invalidMACAddresses := [][]byte{ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, + } + valid := false + if len(addr) == 6 { + valid = true + for _, invalidMACAddress := range invalidMACAddresses { + if bytes.Equal(addr, invalidMACAddress) { + valid = false + } + } + } + return valid +} + +// IsIPv4 checks if a net.IP is an IPv4 address. +func IsIPv4(ip net.IP) bool { + return ip.To4() != nil +} + +// IsIPv6 checks if a net.IP is an IPv6 address. +func IsIPv6(ip net.IP) bool { + return ip.To4() == nil && ip.To16() != nil +} + +// Retry retries a given function until no return error; times out after retries*sleep +func Retry(retries int, sleep time.Duration, f func() error) error { + err := error(nil) + for retry := 0; retry < retries; retry++ { + err = f() + if err == nil { + return nil + } + time.Sleep(sleep) + } + return err +} + +// RetrieveMacFromPci gets the Mac address from the PCI address of the VF +// by reading a config file where the mapping is located. +func RetrieveMacFromPci(pciAddr string, pciToMacFile string) (string, error) { + var pciToMacMap = map[string]string{} + + fileExists, err := PathExists(pciToMacFile) + if err != nil { + return "", fmt.Errorf("error checking pciToMac file: error: %v", err) + } + if fileExists { + jsonFile, err := os.Open(filepath.Clean(pciToMacFile)) + if err != nil { + return "", fmt.Errorf("open pciToMac file %s error: %v", pciToMacFile, err) + } + defer func() { + _ = jsonFile.Close() + }() + jsonBytes, err := io.ReadAll(jsonFile) + if err != nil { + return "", fmt.Errorf("load pciToMac file %s: error: %v", pciToMacFile, err) + } + if err := json.Unmarshal(jsonBytes, &pciToMacMap); err != nil { + return "", fmt.Errorf("parse pciToMac file %s: error: %v", pciToMacFile, err) + } + } else { + return "", fmt.Errorf("pciToMac file is not found in the path %s ", pciToMacFile) + } + + if _, ok := pciToMacMap[pciAddr]; !ok { + return "", fmt.Errorf("the pci Address %s is not found in the pciToMac File %s ", pciAddr, pciToMacFile) + } + return pciToMacMap[pciAddr], nil +} + +// PathExists checks if a file exists on a specified path +func PathExists(path string) (bool, error) { + _, err := os.Stat(path) + if err == nil { + return true, nil + } + if os.IsNotExist(err) { + return false, nil + } + return false, err +} + +func getFileNamesFromPath(dir string) ([]string, error) { + _, err := utilfs.Fs.Stat(dir) + if err != nil { + return nil, fmt.Errorf("could not stat the directory %s: %v", dir, err) + } + + files, err := utilfs.Fs.ReadDir(dir) + if err != nil { + return nil, fmt.Errorf("failed to read directory %s: %v", dir, err) + } + + netDevices := make([]string, 0, len(files)) + for _, netDeviceFile := range files { + netDevices = append(netDevices, strings.TrimSpace(netDeviceFile.Name())) + } + return netDevices, nil +} diff --git a/pkg/xpu/xpu.go b/pkg/xpu/xpu.go new file mode 100644 index 0000000..f887128 --- /dev/null +++ b/pkg/xpu/xpu.go @@ -0,0 +1,168 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright (C) 2023 Nordix Foundation. + +// Package xpu handles the configuration of IPU/DPU cards +package xpu + +import ( + "context" + "errors" + "fmt" + "time" + + opitypes "github.com/opiproject/opi-cni/pkg/types" + + xpuMgr "github.com/opiproject/opi-api/network/evpn-gw/v1alpha1/gen/go" + + "google.golang.org/grpc" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/credentials/insecure" + "google.golang.org/grpc/status" +) + +// initConnection initializes a connection to XPU Infra Manager +func initConnection(conf *opitypes.NetConf) (*grpc.ClientConn, error) { + var opts []grpc.DialOption + + if conf.XpuInfraMgrConn == "" { + return nil, errors.New("XpuInfraMgrConn netconf field cannot be empty") + } + + opts = append(opts, grpc.WithTransportCredentials(insecure.NewCredentials())) + conn, err := grpc.Dial(conf.XpuInfraMgrConn, opts...) + if err != nil { + return nil, fmt.Errorf("fail to dial: %q", err) + } + + return conn, nil +} + +// closeConnection closes a grpc connection +func closeConnection(conn *grpc.ClientConn) { + _ = conn.Close() +} + +// getClient gets a BridgePort grpc client +func getClient(conn *grpc.ClientConn) xpuMgr.BridgePortServiceClient { + client := xpuMgr.NewBridgePortServiceClient(conn) + return client +} + +// produceCreateBridgePortRequest produces a CreateBridgePortRequest object +func produceCreateBridgePortRequest(conf *opitypes.NetConf, mac string) *xpuMgr.CreateBridgePortRequest { + var typeOfPort xpuMgr.BridgePortType + var logicalBridges []string + + if conf.LogicalBridge != "" { + typeOfPort = xpuMgr.BridgePortType_ACCESS + logicalBridges = []string{conf.LogicalBridge} + } else { + typeOfPort = xpuMgr.BridgePortType_TRUNK + if len(conf.LogicalBridges) > 0 { + logicalBridges = conf.LogicalBridges + } + } + + bridgePortSpec := &xpuMgr.BridgePortSpec{ + MacAddress: []byte(mac), + Ptype: typeOfPort, + LogicalBridges: logicalBridges, + } + + bridgePort := &xpuMgr.BridgePort{ + Spec: bridgePortSpec, + } + + createBridgePortRequest := &xpuMgr.CreateBridgePortRequest{ + BridgePort: bridgePort, + } + + return createBridgePortRequest +} + +// produceDeleteBridgePortRequest produces a DeleteBridgePortRequest object +func produceDeleteBridgePortRequest(conf *opitypes.NetConf) *xpuMgr.DeleteBridgePortRequest { + deleteBridgePortRequest := &xpuMgr.DeleteBridgePortRequest{ + Name: conf.BridgePortName, + } + + return deleteBridgePortRequest +} + +// CreateBridgePort creates a bridge port +func CreateBridgePort(conf *opitypes.NetConf, mac string) error { + // Init Connection + conn, err := initConnection(conf) + if err != nil { + return fmt.Errorf("CreateBridgePort: Error occurred while init connection: %q", err) + } + + defer closeConnection(conn) + + // Get a Client + client := getClient(conn) + + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) + + defer cancel() + + // produce the createBridgePortRequest object + createBridgePortRequest := produceCreateBridgePortRequest(conf, mac) + + // grpc call to create the bridge port + bridgePort, err := client.CreateBridgePort(ctx, createBridgePortRequest) + if err != nil { + return fmt.Errorf("CreateBridgePort: Error occurred while creating Bridge Port: %q", err) + } + + // storing the name of the created bridge port to the netconf object for caching purposes + conf.BridgePortName = bridgePort.GetName() + + if bridgePort.GetStatus().GetOperStatus() != xpuMgr.BPOperStatus_BP_OPER_STATUS_UP { + return errors.New("CreateBridgePort: The status of created BridgePort is not UP") + } + + return nil +} + +// DeleteBridgePort deletes a bridge port +func DeleteBridgePort(conf *opitypes.NetConf) error { + // Check if the BridgePortName exists in the NetConf object. + // If it doesn't exist then we simply return nil as there is no point to continue + // as we need the BridgePortName for the BridgePort delete process to execute. + // The reason that we do not return error is because we want to give the chance + // to the delete process to continue with the rest of the tasks + // (e.g. ReleaseVFs, ResetVFs, etc...) so there is no leftovers in the system. + if conf.BridgePortName == "" { + return nil + } + + // Init Connection + conn, err := initConnection(conf) + if err != nil { + return fmt.Errorf("DeleteBridgePort: Error occurred while init connection: %q", err) + } + + defer closeConnection(conn) + + // Get a Client + client := getClient(conn) + + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) + + defer cancel() + + // produce the deleteBridgePortRequest object + deleteBridgePortRequest := produceDeleteBridgePortRequest(conf) + + // If error is BridgePort not found then return nil in order to serve idempotence. + _, err = client.DeleteBridgePort(ctx, deleteBridgePortRequest) + if err != nil { + if status.Code(err) == codes.NotFound { + return nil + } + return fmt.Errorf("DeleteBridgePort: Error occurred while Deleting Bridge Port %s : %q", conf.BridgePortName, err) + } + + return nil +}