├── protos ├── BUILD └── faiss_server │ ├── BUILD │ └── service.proto ├── third_party ├── BUILD ├── faiss │ ├── BUILD │ ├── faiss.patch │ └── BUILD.bzl ├── google_cloud_cpp.patch └── zlib.BUILD ├── .clang-format ├── .dockerignore ├── testdata ├── random-index.faiss └── BUILD ├── .bazelrc ├── .github └── workflows │ ├── build.yml │ └── push-github-registry.yml ├── .gitignore ├── faiss ├── wrapper_test.cpp ├── wrapper.h ├── BUILD ├── faiss_test.go ├── faiss.go └── wrapper.cpp ├── main.go ├── go.mod ├── Dockerfile ├── BUILD ├── README.md ├── server.go ├── generate_testdata.cpp ├── server_grpc.go ├── WORKSPACE ├── LICENSE ├── deps.bzl └── go.sum /protos/BUILD: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /third_party/BUILD: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /third_party/faiss/BUILD: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.clang-format: -------------------------------------------------------------------------------- 1 | --- 2 | BasedOnStyle: google 3 | --- 4 | ... 5 | -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | .clang-format 2 | .vscode 3 | Dockerfile 4 | LICENSE 5 | *.md 6 | -------------------------------------------------------------------------------- /testdata/random-index.faiss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jeongukjae/faiss-server/HEAD/testdata/random-index.faiss -------------------------------------------------------------------------------- /testdata/BUILD: -------------------------------------------------------------------------------- 1 | package(default_visibility = ["//visibility:public"]) 2 | 3 | filegroup( 4 | name = "random_index", 5 | srcs = ["random-index.faiss"], 6 | ) 7 | -------------------------------------------------------------------------------- /.bazelrc: -------------------------------------------------------------------------------- 1 | build --enable_platform_specific_config 2 | 3 | # for macOS (local) 4 | build:macos --linkopt=-L/usr/local/opt/llvm/lib 5 | 6 | # for linux build (docker) 7 | build:linux --linkopt=-L/usr/lib/llvm-7/lib/ 8 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: Build 2 | 3 | on: 4 | push: 5 | pull_request: 6 | branches: [ main ] 7 | 8 | jobs: 9 | build: 10 | runs-on: ubuntu-latest 11 | 12 | steps: 13 | - uses: actions/checkout@v2 14 | 15 | - name: Build faiss-server 16 | run: docker build . 17 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Binaries for programs and plugins 2 | *.exe 3 | *.exe~ 4 | *.dll 5 | *.so 6 | *.dylib 7 | 8 | # Test binary, built with `go test -c` 9 | *.test 10 | 11 | # Output of the go coverage tool, specifically when used with LiteIDE 12 | *.out 13 | 14 | # Dependency directories (remove the comment below to include it) 15 | # vendor/ 16 | /bazel-* 17 | /.vscode/settings.json 18 | -------------------------------------------------------------------------------- /faiss/wrapper_test.cpp: -------------------------------------------------------------------------------- 1 | #include "wrapper.h" 2 | 3 | #include "gmock/gmock.h" 4 | #include "gtest/gtest.h" 5 | 6 | TEST(TestWrapper, parseUrl) { 7 | std::string url = "gs://bucket_name/path/to/blob.index"; 8 | std::string bucket, blobPath; 9 | parseUrl(url, bucket, blobPath); 10 | 11 | ASSERT_EQ("bucket_name", bucket); 12 | ASSERT_EQ("path/to/blob.index", blobPath); 13 | } 14 | -------------------------------------------------------------------------------- /third_party/google_cloud_cpp.patch: -------------------------------------------------------------------------------- 1 | diff --git a/bazel/curl.BUILD b/bazel/curl.BUILD 2 | index 95f1ea842..ef9d007d4 100644 3 | --- a/bazel/curl.BUILD 4 | +++ b/bazel/curl.BUILD 5 | @@ -440,7 +440,7 @@ cc_library( 6 | visibility = ["//visibility:public"], 7 | deps = [ 8 | # Use the same version of zlib that gRPC does. 9 | - "//external:madler_zlib", 10 | + "@zlib", 11 | ":define-ca-bundle-location", 12 | ] + select({ 13 | ":windows": [], 14 | -------------------------------------------------------------------------------- /third_party/faiss/faiss.patch: -------------------------------------------------------------------------------- 1 | diff --git a/c_api/CMakeLists.txt b/c_api/CMakeLists.txt 2 | index 747ce50c..3d7f7c19 100644 3 | --- a/c_api/CMakeLists.txt 4 | +++ b/c_api/CMakeLists.txt 5 | @@ -46,6 +46,12 @@ file(GLOB FAISS_C_API_HEADERS 6 | "impl/*.h") 7 | 8 | faiss_install_headers("${FAISS_C_API_HEADERS}" c_api) 9 | +install( 10 | + TARGETS faiss_c 11 | + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} 12 | + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} 13 | + DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/faiss/ 14 | +) 15 | 16 | add_executable(example_c EXCLUDE_FROM_ALL example_c.c) 17 | target_link_libraries(example_c PRIVATE faiss_c) 18 | -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "flag" 5 | 6 | "github.com/golang/glog" 7 | ) 8 | 9 | var ( 10 | // command-line options: 11 | // gRPC server endpoint 12 | grpcServerEndpoint = flag.String("grpc_server_endpoint", "0.0.0.0:8000", "gRPC server endpoint") 13 | // http server endpoint 14 | httpServerEndpoint = flag.String("http_server_endpoint", "0.0.0.0:8001", "http server endpoint") 15 | // faiss index path 16 | faissIndexPath = flag.String("faiss_index", "", "path of prebuilt faiss index") 17 | // with reload method 18 | withReloadMethod = flag.Bool("with_reload_method", false, "enable reload method") 19 | ) 20 | 21 | func main() { 22 | flag.Parse() 23 | defer glog.Flush() 24 | 25 | RunServer(*faissIndexPath, *grpcServerEndpoint, *httpServerEndpoint, *withReloadMethod) 26 | } 27 | -------------------------------------------------------------------------------- /third_party/faiss/BUILD.bzl: -------------------------------------------------------------------------------- 1 | load("@rules_foreign_cc//foreign_cc:defs.bzl", "cmake") 2 | 3 | package(default_visibility = ["//visibility:public"]) 4 | 5 | licenses(["notice"]) # MIT 6 | 7 | exports_files(["LICENSE"]) 8 | 9 | filegroup( 10 | name = "all_srcs", 11 | srcs = glob(["**"]), 12 | ) 13 | 14 | cmake( 15 | name = "faiss_c", 16 | generate_args = [ 17 | "-G Ninja", 18 | "-DFAISS_ENABLE_GPU=OFF", 19 | "-DFAISS_ENABLE_PYTHON=OFF", 20 | "-DFAISS_ENABLE_C_API=ON", 21 | "-DBUILD_TESTING=OFF", 22 | "-DCMAKE_BUILD_TYPE=Release", 23 | "-DFAISS_OPT_LEVEL=general", 24 | ], 25 | lib_source = ":all_srcs", 26 | out_static_libs = [ 27 | "libfaiss_c.a", 28 | "libfaiss.a", 29 | ], 30 | targets = [ 31 | "faiss_c", 32 | "faiss", 33 | ], 34 | ) 35 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/jeongukjae/faiss-server 2 | 3 | go 1.17 4 | 5 | require ( 6 | github.com/golang/glog v1.0.0 7 | github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.1 8 | google.golang.org/grpc v1.42.0 9 | ) 10 | 11 | require ( 12 | github.com/golang/protobuf v1.5.2 // indirect 13 | github.com/stretchr/testify v1.7.0 14 | golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4 // indirect 15 | golang.org/x/text v0.3.5 // indirect 16 | google.golang.org/genproto v0.0.0-20211129164237-f09f9a12af12 // indirect 17 | google.golang.org/protobuf v1.27.1 // indirect 18 | ) 19 | 20 | require ( 21 | github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 22 | github.com/pkg/errors v0.9.1 23 | github.com/pmezard/go-difflib v1.0.0 // indirect 24 | github.com/prometheus/client_golang v1.11.0 25 | gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c // indirect 26 | ) 27 | -------------------------------------------------------------------------------- /third_party/zlib.BUILD: -------------------------------------------------------------------------------- 1 | # From https://github.com/tensorflow/io/blob/master/third_party/zlib.BUILD 2 | package(default_visibility = ["//visibility:public"]) 3 | 4 | licenses(["notice"]) # BSD/MIT-like license (for zlib) 5 | 6 | cc_library( 7 | name = "zlib", 8 | srcs = glob([ 9 | "*.c", 10 | "*.h", 11 | ]) + [ 12 | "contrib/minizip/ioapi.c", 13 | "contrib/minizip/ioapi.h", 14 | "contrib/minizip/unzip.c", 15 | "contrib/minizip/unzip.h", 16 | ], 17 | hdrs = [ 18 | "zlib.h", 19 | ], 20 | copts = select({ 21 | "@bazel_tools//src/conditions:windows": [], 22 | "//conditions:default": [ 23 | "-Wno-shift-negative-value", 24 | "-DZ_HAVE_UNISTD_H", 25 | ], 26 | }), 27 | includes = [ 28 | ".", 29 | "contrib/minizip", 30 | ], 31 | ) 32 | -------------------------------------------------------------------------------- /faiss/wrapper.h: -------------------------------------------------------------------------------- 1 | #ifndef __FAISS_WRAPPER_H__ 2 | #define __FAISS_WRAPPER_H__ 3 | 4 | #ifdef __cplusplus 5 | #include 6 | 7 | extern "C" { 8 | #endif 9 | 10 | #include 11 | 12 | #include "faiss/c_api/Index_c.h" 13 | #include "faiss/c_api/index_io_c.h" 14 | 15 | typedef struct SearchResults { 16 | int64_t* ids; 17 | float* distances; 18 | int isError; 19 | } SearchResults; 20 | 21 | const char* getError(); 22 | 23 | // load index from filepath 24 | FaissIndex* loadIndex(const char*); 25 | 26 | SearchResults searchFaiss(const FaissIndex* index, int numVectors, int topK, 27 | const float* vectors); 28 | 29 | int removeVectors(FaissIndex* index, int numIds, const int64_t* ids); 30 | 31 | #ifdef __cplusplus 32 | } 33 | 34 | // for testing purpose 35 | // below functions are not exposed for cgo binding. 36 | 37 | void parseUrl(const std::string url, std::string& bucket, 38 | std::string& blobPath); 39 | #endif 40 | 41 | #endif // __FAISS_WRAPPER_H__ 42 | -------------------------------------------------------------------------------- /faiss/BUILD: -------------------------------------------------------------------------------- 1 | load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") 2 | 3 | package(default_visibility = ["//visibility:public"]) 4 | 5 | cc_library( 6 | name = "faiss_wrapper", 7 | srcs = [ 8 | "wrapper.cpp", 9 | "wrapper.h", 10 | ], 11 | linkopts = [ 12 | "-lblas", 13 | "-llapack", 14 | "-lomp", 15 | ], 16 | linkstatic = 1, 17 | deps = [ 18 | "@com_github_facebookresearch_faiss//:faiss_c", 19 | "@com_github_googleapis_google_cloud_cpp//:storage", 20 | ], 21 | ) 22 | 23 | cc_test( 24 | name = "faiss_wrapper_test", 25 | srcs = ["wrapper_test.cpp"], 26 | deps = [ 27 | ":faiss_wrapper", 28 | "@com_google_googletest//:gtest_main", 29 | ], 30 | ) 31 | 32 | go_library( 33 | name = "faiss", 34 | srcs = ["faiss.go"], # keep 35 | cdeps = [ 36 | ":faiss_wrapper", 37 | ], 38 | cgo = True, 39 | importpath = "github.com/jeongukjae/faiss-server/faiss", 40 | ) 41 | 42 | go_test( 43 | name = "faiss_test", 44 | srcs = ["faiss_test.go"], 45 | data = ["//testdata:random_index"], 46 | embed = [":faiss"], 47 | deps = ["@com_github_stretchr_testify//assert"], 48 | ) 49 | -------------------------------------------------------------------------------- /protos/faiss_server/BUILD: -------------------------------------------------------------------------------- 1 | load("@rules_proto//proto:defs.bzl", "proto_library") 2 | load("@io_bazel_rules_go//go:def.bzl", "go_library") 3 | load("@io_bazel_rules_go//proto:def.bzl", "go_proto_library") 4 | load("@com_github_grpc_ecosystem_grpc_gateway_v2//protoc-gen-openapiv2:defs.bzl", "protoc_gen_openapiv2") 5 | 6 | package(default_visibility = ["//visibility:public"]) 7 | 8 | proto_library( 9 | name = "service_proto", 10 | srcs = ["service.proto"], 11 | deps = [ 12 | "@go_googleapis//google/api:annotations_proto", 13 | ], 14 | ) 15 | 16 | go_proto_library( 17 | name = "service_go_proto", 18 | compilers = [ 19 | "@io_bazel_rules_go//proto:go_grpc", 20 | "@com_github_grpc_ecosystem_grpc_gateway_v2//protoc-gen-grpc-gateway:go_gen_grpc_gateway", 21 | ], 22 | importpath = "github.com/jeongukjae/faiss-server/protos/faiss/service", 23 | proto = ":service_proto", 24 | deps = [ 25 | "@go_googleapis//google/api:annotations_go_proto", 26 | ], 27 | ) 28 | 29 | go_library( 30 | name = "service", 31 | embed = [":service_go_proto"], 32 | importpath = "github.com/jeongukjae/faiss-server/protos/faiss/service", 33 | ) 34 | 35 | protoc_gen_openapiv2( 36 | name = "openapi", 37 | proto = ":service_proto", 38 | ) 39 | -------------------------------------------------------------------------------- /.github/workflows/push-github-registry.yml: -------------------------------------------------------------------------------- 1 | name: Create and publish a Docker image 2 | 3 | on: 4 | push: 5 | branches: ['main'] 6 | paths-ignore: 7 | - 'README.md' 8 | 9 | env: 10 | REGISTRY: ghcr.io 11 | IMAGE_NAME: ${{ github.repository }} 12 | 13 | jobs: 14 | build-and-push-image: 15 | runs-on: ubuntu-latest 16 | permissions: 17 | contents: read 18 | packages: write 19 | 20 | steps: 21 | - name: Checkout repository 22 | uses: actions/checkout@v2 23 | 24 | - name: Log in to the Container registry 25 | uses: docker/login-action@f054a8b539a109f9f41c372932f1ae047eff08c9 26 | with: 27 | registry: ${{ env.REGISTRY }} 28 | username: ${{ github.actor }} 29 | password: ${{ secrets.GITHUB_TOKEN }} 30 | 31 | - name: Extract metadata (tags, labels) for Docker 32 | id: meta 33 | uses: docker/metadata-action@98669ae865ea3cffbcbaa878cf57c20bbf1c6c38 34 | with: 35 | images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} 36 | tags: | 37 | type=sha 38 | latest 39 | 40 | - name: Build and push Docker image 41 | uses: docker/build-push-action@ad44023a93711e3deb337508980b4b5e9bcdc5dc 42 | with: 43 | context: . 44 | push: true 45 | tags: ${{ steps.meta.outputs.tags }} 46 | labels: ${{ steps.meta.outputs.labels }} 47 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # BUILDER ========== 2 | FROM golang:1.17-buster as BUILDER 3 | 4 | # Install Bazel 5 | RUN apt update && \ 6 | apt install -y apt-transport-https curl gnupg patch && \ 7 | curl -fsSL https://bazel.build/bazel-release.pub.gpg | gpg --dearmor > bazel.gpg && \ 8 | mv bazel.gpg /etc/apt/trusted.gpg.d/ && \ 9 | echo "deb [arch=amd64] https://storage.googleapis.com/bazel-apt stable jdk1.8" \ 10 | | tee /etc/apt/sources.list.d/bazel.list && \ 11 | apt update && apt install -y bazel && \ 12 | bazel version 13 | 14 | WORKDIR /app 15 | COPY . . 16 | 17 | # Build faiss-server 18 | RUN apt install -y libopenblas-dev libomp-7-dev libstdc++6 && \ 19 | bazel build //:faiss-server --nokeep_state_after_build 20 | 21 | # Prepare libraries for distroless image 22 | RUN cd /tmp && \ 23 | apt-get download \ 24 | $(apt-cache depends \ 25 | --recurse --no-recommends --no-suggests --no-conflicts \ 26 | --no-breaks --no-replaces --no-enhances \ 27 | libomp5-7 libopenblas-base libstdc++6 \ 28 | | grep "^\w" | sort -u) && \ 29 | for deb in *.deb; do dpkg --extract $deb /dpkg || exit 10; done && \ 30 | cd /dpkg && mkdir /dpkg-so-files && \ 31 | for so in $(find . -name "*.so*" -not -name "*.py" -not -name "*.conf.d"); do cp $so /dpkg-so-files; done && \ 32 | ls -alh /dpkg-so-files 33 | 34 | # OUTPUT ========== 35 | FROM gcr.io/distroless/base-debian10 36 | 37 | COPY --from=BUILDER /dpkg-so-files /usr/lib 38 | COPY --from=BUILDER /app/bazel-bin/faiss-server_/faiss-server /faiss-server 39 | 40 | EXPOSE 8000 8001 41 | WORKDIR / 42 | ENTRYPOINT ["/faiss-server"] 43 | -------------------------------------------------------------------------------- /BUILD: -------------------------------------------------------------------------------- 1 | load("@bazel_gazelle//:def.bzl", "gazelle") 2 | load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library") 3 | load("@com_github_bazelbuild_buildtools//buildifier:def.bzl", "buildifier") 4 | 5 | # gazelle:prefix github.com/jeongukjae/faiss-server 6 | gazelle( 7 | name = "gazelle", 8 | args = [ 9 | "-go_grpc_compiler=@io_bazel_rules_go//proto:go_grpc", 10 | "-go_grpc_compiler=@com_github_grpc_ecosystem_grpc_gateway_v2//protoc-gen-grpc-gateway:go_gen_grpc_gateway", 11 | ], 12 | command = "update", 13 | ) 14 | 15 | gazelle( 16 | name = "gazelle-update-repos", 17 | args = [ 18 | "-from_file=go.mod", 19 | "-to_macro=deps.bzl%go_dependencies", 20 | "-prune", 21 | ], 22 | command = "update-repos", 23 | ) 24 | 25 | buildifier( 26 | name = "buildifier", 27 | ) 28 | 29 | go_binary( 30 | name = "faiss-server", 31 | embed = [":faiss-server_lib"], 32 | visibility = ["//visibility:public"], 33 | ) 34 | 35 | go_library( 36 | name = "faiss-server_lib", 37 | srcs = [ 38 | "main.go", 39 | "server.go", 40 | "server_grpc.go", 41 | ], 42 | importpath = "github.com/jeongukjae/faiss-server", 43 | visibility = ["//visibility:private"], 44 | deps = [ 45 | "//faiss", 46 | "//protos/faiss_server:service", 47 | "@com_github_golang_glog//:glog", 48 | "@com_github_grpc_ecosystem_go_grpc_prometheus//:go-grpc-prometheus", 49 | "@com_github_grpc_ecosystem_grpc_gateway_v2//runtime", 50 | "@com_github_pkg_errors//:errors", 51 | "@com_github_prometheus_client_golang//prometheus/promhttp", 52 | "@org_golang_google_grpc//:go_default_library", 53 | "@org_golang_google_grpc//codes", 54 | "@org_golang_google_grpc//status", 55 | ], 56 | ) 57 | 58 | cc_binary( 59 | name = "generate_testdata", 60 | testonly = True, 61 | srcs = ["generate_testdata.cpp"], 62 | linkopts = [ 63 | "-lblas", 64 | "-llapack", 65 | "-lomp", 66 | ], 67 | deps = ["@com_github_facebookresearch_faiss//:faiss_c"], 68 | ) 69 | -------------------------------------------------------------------------------- /faiss/faiss_test.go: -------------------------------------------------------------------------------- 1 | package faiss 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/assert" 7 | ) 8 | 9 | func TestLoadIndex(t *testing.T) { 10 | idx, err := LoadIndex("../testdata/random-index.faiss") 11 | assert.Nil(t, err) 12 | assert.NotNil(t, idx) 13 | } 14 | 15 | func TestGetMetadata(t *testing.T) { 16 | idx, err := LoadIndex("../testdata/random-index.faiss") 17 | assert.Nil(t, err) 18 | assert.NotNil(t, idx) 19 | 20 | assert.Equal(t, idx.Dimension, int32(8)) 21 | assert.Equal(t, idx.GetNtotal(), int64(1000)) 22 | assert.Equal(t, idx.MetricType, int32(1)) 23 | } 24 | 25 | func TestSearch(t *testing.T) { 26 | idx, err := LoadIndex("../testdata/random-index.faiss") 27 | assert.Nil(t, err) 28 | assert.NotNil(t, idx) 29 | 30 | queryVectors := []float32{ 31 | 0.497664, 0.817838, 0.612112, 0.77136, 0.86067, 0.150637, 0.198519, 0.815163, 32 | 0.159815, 0.116138, 0.0129075, 0.486833, 0.331015, 0.80264, 0.0982519, 0.0559934, 33 | 0.444663, 0.0221439, 0.290729, 0.246394, 0.738287, 0.889226, 0.987139, 0.117443, 34 | 0.396782, 0.45273, 0.538148, 0.790622, 0.465836, 0.435332, 0.569479, 0.969259, 35 | 0.0445562, 0.54812, 0.462577, 0.376472, 0.327912, 0.813529, 0.646552, 0.0474265, 36 | } 37 | results := idx.Search(5, 4, queryVectors) 38 | 39 | assert.ElementsMatch(t, []int64{ 40 | 0, 372, 74, 425, 41 | 1, 27, 221, 538, 42 | 2, 170, 40, 60, 43 | 3, 39, 79, 627, 44 | 4, 198, 67, 282, 45 | }, results.Ids) 46 | ElementsAllClose(t, []float32{ 47 | 0, 0.220977, 0.23984, 0.298714, 48 | 0, 0.379492, 0.382708, 0.503856, 49 | 0, 0.341152, 0.444937, 0.456188, 50 | 0, 0.108953, 0.302287, 0.304529, 51 | 0, 0.371397, 0.377862, 0.431174, 52 | }, results.Distances, 1e-8, 1e-5) 53 | } 54 | 55 | func ElementsAllClose(t *testing.T, listA, listB []float32, atol float32, rtol float32, msgAndArgs ...interface{}) bool { 56 | if len(listA) != len(listB) { 57 | t.Errorf("ElementsAllClose Failed \nlistA: %s\nlistB: %s\natol: %f\nrtol: %f", listA, listB, atol, rtol) 58 | } 59 | 60 | for i, _ := range listA { 61 | if Abs(listA[i]-listB[i]) > (atol + rtol*Abs(listB[i])) { 62 | t.Errorf("ElementsAllClose Failed at index %d\nlistA: %s\nlistB: %s\natol: %f\nrtol: %f", i, listA, listB, atol, rtol) 63 | } 64 | } 65 | 66 | return true 67 | } 68 | 69 | func Abs(a float32) float32 { 70 | if a < 0 { 71 | return -a 72 | } 73 | return a 74 | } 75 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # faiss-server 2 | 3 | `faiss-server` is a ANN server using [facebookresearch/faiss](https://github.com/facebookresearch/faiss). 4 | 5 | * Supports gRPC/HTTP 6 | * Prometheus handler for monitoring (`/metrics`) 7 | * Deploy with Faiss index stored in GCS 8 | 9 | ## Usage 10 | 11 | * Tag List: 12 | * API Specification: [service proto file (protos/faiss_server/service.proto)](protos/faiss_server/service.proto) 13 | 14 | ```bash 15 | $ docker pull ghcr.io/jeongukjae/faiss-server 16 | $ docker run --rm -it ghcr.io/jeongukjae/faiss-server --help 17 | Usage of /faiss-server: 18 | -alsologtostderr 19 | log to standard error as well as files 20 | -faiss_index string 21 | path of prebuilt faiss index 22 | -grpc_server_endpoint string 23 | gRPC server endpoint (default "0.0.0.0:8000") 24 | -http_server_endpoint string 25 | http server endpoint (default "0.0.0.0:8001") 26 | -log_backtrace_at value 27 | when logging hits line file:N, emit a stack trace 28 | -log_dir string 29 | If non-empty, write log files in this directory 30 | -logtostderr 31 | log to standard error instead of files 32 | -stderrthreshold value 33 | logs at or above this threshold go to stderr 34 | -v value 35 | log level for V logs 36 | -vmodule value 37 | comma-separated list of pattern=N settings for file-filtered logging 38 | -with_reload_method 39 | enable reload method 40 | $ docker run --rm -it \ 41 | -v `pwd`/testdata/random-index.faiss:/random-index.faiss:ro \ 42 | ghcr.io/jeongukjae/faiss-server \ 43 | -faiss_index /random-index.faiss -logtostderr 44 | I1213 02:27:32.106571 1 server.go:108] Loading faiss index from /random-index.faiss 45 | I1213 02:27:32.132563 1 server.go:70] Serve grpc server at 0.0.0.0:8000 46 | I1213 02:27:32.132648 1 server.go:83] Register grpc gateway server at 0.0.0.0:8000 47 | I1213 02:27:32.133806 1 server.go:98] Serve http server at 0.0.0.0:8001 48 | ``` 49 | 50 | ## Build faiss-server 51 | 52 | ### Docker image 53 | 54 | I recommend you to build this repo with docker. 55 | 56 | ```bash 57 | docker build -t faiss-server . 58 | ``` 59 | 60 | ### Binary file 61 | 62 | But you can also build from source. 63 | 64 | ```bash 65 | bazel build //:faiss-server 66 | ``` 67 | 68 | ## Dev notes 69 | 70 | ### Resolve dependencies and run buildifier 71 | 72 | ```bash 73 | # update dependencies and lint 74 | bazel run //:gazelle 75 | bazel run //:gazelle-update-repos 76 | bazel run //:gazelle 77 | bazel run //:buildifier 78 | ``` 79 | 80 | ### TODO 81 | 82 | - [ ] Load from S3 83 | -------------------------------------------------------------------------------- /server.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "log" 6 | "net" 7 | "net/http" 8 | 9 | "github.com/golang/glog" 10 | grpc_prometheus "github.com/grpc-ecosystem/go-grpc-prometheus" 11 | "github.com/pkg/errors" 12 | "github.com/prometheus/client_golang/prometheus/promhttp" 13 | 14 | "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" 15 | "google.golang.org/grpc" 16 | 17 | "github.com/jeongukjae/faiss-server/faiss" 18 | gw "github.com/jeongukjae/faiss-server/protos/faiss/service" 19 | ) 20 | 21 | func runGrpcServer(endpoint string, faissPath string, withReloadMethod bool) error { 22 | lis, err := net.Listen("tcp", endpoint) 23 | if err != nil { 24 | return errors.WithStack(err) 25 | } 26 | 27 | glog.Info("Loading faiss index from ", faissPath) 28 | index, err := faiss.LoadIndex(faissPath) 29 | if err != nil { 30 | return errors.WithStack(err) 31 | } 32 | 33 | s := grpc.NewServer( 34 | grpc.StreamInterceptor(grpc_prometheus.StreamServerInterceptor), 35 | grpc.UnaryInterceptor(grpc_prometheus.UnaryServerInterceptor), 36 | ) 37 | fs := &faissServer{Index: index, WithReloadMethod: withReloadMethod} 38 | gw.RegisterFaissServer(s, fs) 39 | grpc_prometheus.Register(s) 40 | go func() { 41 | defer fs.Index.Free() 42 | log.Fatalln(s.Serve(lis)) 43 | }() 44 | glog.Info("Serve grpc server at ", endpoint) 45 | 46 | return nil 47 | } 48 | 49 | func runGrpcGateway(grpcEndpoint string, httpEndpoint string) error { 50 | ctx := context.Background() 51 | ctx, cancel := context.WithCancel(ctx) 52 | defer cancel() 53 | 54 | // Register gRPC server endpoint 55 | mux := runtime.NewServeMux() 56 | opts := []grpc.DialOption{grpc.WithInsecure()} 57 | glog.Info("Register grpc gateway server at ", grpcEndpoint) 58 | err := gw.RegisterFaissHandlerFromEndpoint(ctx, mux, grpcEndpoint, opts) 59 | if err != nil { 60 | return err 61 | } 62 | 63 | handler := promhttp.Handler() 64 | err = mux.HandlePath("GET", "/metrics", func(w http.ResponseWriter, r *http.Request, _ map[string]string) { 65 | handler.ServeHTTP(w, r) 66 | }) 67 | if err != nil { 68 | return err 69 | } 70 | 71 | // Start HTTP server (and proxy calls to gRPC server endpoint) 72 | glog.Info("Serve http server at ", httpEndpoint) 73 | return http.ListenAndServe(httpEndpoint, mux) 74 | } 75 | 76 | func RunServer(faissPath string, grpcEndpoint string, httpEndpoint string, withReloadMethod bool) { 77 | if faissPath == "" { 78 | glog.Fatal("You should pass faiss index path (-faiss_index option)") 79 | } 80 | 81 | if err := runGrpcServer(grpcEndpoint, faissPath, withReloadMethod); err != nil { 82 | glog.Fatal(err) 83 | } 84 | 85 | if err := runGrpcGateway(grpcEndpoint, httpEndpoint); err != nil { 86 | glog.Fatal(err) 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /protos/faiss_server/service.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | option go_package = "github.com/jeongukjae/faiss-server/protos/faiss/service"; 4 | 5 | package faiss_server.service; 6 | 7 | import "google/api/annotations.proto"; 8 | 9 | message EmptyMessage { 10 | } 11 | 12 | message GetMetadataResponse { 13 | enum MetricType { 14 | METRIC_INNER_PRODUCT = 0; 15 | METRIC_L2 = 1; 16 | METRIC_L1 = 2; 17 | METRIC_Linf = 3; 18 | METRIC_Lp = 4; 19 | 20 | METRIC_Canberra = 20; 21 | METRIC_BrayCurtis = 21; 22 | METRIC_JensenShannon = 22; 23 | } 24 | 25 | string index_name = 1; 26 | int32 dimension = 2; 27 | int64 ntotal = 3; 28 | MetricType metric_type = 4; 29 | } 30 | 31 | message SearchRequest { 32 | int32 num_vectors = 1; 33 | int32 top_k = 2; 34 | repeated float vectors = 3; 35 | } 36 | 37 | message SearchResponse { 38 | repeated int64 ids = 1; 39 | repeated float distances = 2; 40 | } 41 | 42 | message AddVectorsRequest { 43 | int32 num_vectors = 1; 44 | repeated float vectors = 2; 45 | } 46 | 47 | message AddVectorsResponse { 48 | repeated int64 ids = 1; 49 | } 50 | 51 | message AddVectorsWithIdsRequest { 52 | int32 num_vectors = 1; 53 | repeated float vectors = 2; 54 | repeated int64 ids = 3; 55 | } 56 | 57 | message RemoveVectorsRequest { 58 | repeated int64 ids = 1; 59 | } 60 | 61 | message RemoveVectorsResponse { 62 | int32 num_removed = 1; 63 | } 64 | 65 | service Faiss { 66 | rpc GetMetadata(EmptyMessage) returns (GetMetadataResponse) { 67 | option (google.api.http) = { 68 | get: "/v1/metadata" 69 | }; 70 | } 71 | 72 | rpc Search(SearchRequest) returns (SearchResponse) { 73 | option (google.api.http) = { 74 | post: "/v1/search" 75 | body: "*" 76 | }; 77 | } 78 | 79 | rpc AddVectors(AddVectorsRequest) returns (AddVectorsResponse) { 80 | option (google.api.http) = { 81 | post: "/v1/add_vectors" 82 | body: "*" 83 | }; 84 | } 85 | 86 | rpc AddVectorsWithIds(AddVectorsWithIdsRequest) returns (EmptyMessage) { 87 | option (google.api.http) = { 88 | post: "/v1/add_vectors_with_ids" 89 | body: "*" 90 | }; 91 | } 92 | 93 | rpc RemoveVectors(RemoveVectorsRequest) returns (RemoveVectorsResponse) { 94 | option (google.api.http) = { 95 | post: "/v1/remove_vectors" 96 | body: "*" 97 | }; 98 | } 99 | 100 | rpc Reload(EmptyMessage) returns (EmptyMessage) { 101 | option (google.api.http) = { 102 | post: "/v1/reload" 103 | body: "*" 104 | }; 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /faiss/faiss.go: -------------------------------------------------------------------------------- 1 | package faiss 2 | 3 | /* 4 | #include "faiss/wrapper.h" 5 | */ 6 | import "C" 7 | import ( 8 | "errors" 9 | "fmt" 10 | "unsafe" 11 | ) 12 | 13 | type FaissIndex struct { 14 | Index *C.FaissIndex 15 | 16 | Path string 17 | Dimension int32 18 | MetricType int32 19 | } 20 | 21 | type FaissMetadata struct { 22 | Dimension int32 23 | Ntotal int32 24 | MetricType int32 25 | } 26 | 27 | type SearchResult struct { 28 | Ids []int64 29 | Distances []float32 30 | } 31 | 32 | func LoadIndex(path string) (*FaissIndex, error) { 33 | cPath := C.CString(path) 34 | defer C.free(unsafe.Pointer(cPath)) 35 | 36 | index := C.loadIndex(cPath) 37 | if index == nil { 38 | return nil, errors.New(fmt.Sprintf("Cannot create index, %s", C.GoString(C.getError()))) 39 | } 40 | 41 | dimension := int32(C.faiss_Index_d(index)) 42 | metricType := int32(C.faiss_Index_metric_type(index)) 43 | return &FaissIndex{ 44 | Index: index, 45 | Path: path, 46 | Dimension: dimension, 47 | MetricType: metricType, 48 | }, nil 49 | } 50 | 51 | func (index *FaissIndex) Free() { 52 | C.faiss_Index_free(index.Index) 53 | } 54 | 55 | func (index *FaissIndex) GetNtotal() int64 { 56 | Ntotal := int64(C.faiss_Index_ntotal(index.Index)) 57 | return Ntotal 58 | } 59 | 60 | func (index *FaissIndex) Search(numVectors int32, topK int32, vectors []float32) *SearchResult { 61 | cSearchResult := C.searchFaiss(index.Index, C.int(numVectors), C.int(topK), (*C.float)(&vectors[0])) 62 | numResults := topK * numVectors 63 | 64 | cIds := unsafe.Pointer(cSearchResult.ids) 65 | cDistances := unsafe.Pointer(cSearchResult.distances) 66 | 67 | cIdsArray := (*[1 << 30]C.int64_t)(cIds) 68 | cDistancesArray := (*[1 << 30]C.float)(cDistances) 69 | 70 | defer C.free(cIds) 71 | defer C.free(cDistances) 72 | 73 | ids := make([]int64, numResults) 74 | distances := make([]float32, numResults) 75 | 76 | for i := int32(0); i < numResults; i++ { 77 | ids[i] = int64(cIdsArray[i]) 78 | distances[i] = float32(cDistancesArray[i]) 79 | } 80 | 81 | return &SearchResult{ 82 | Ids: ids, 83 | Distances: distances, 84 | } 85 | } 86 | 87 | func (index *FaissIndex) AddVectors(numVectors int32, vectors []float32) ([]int64, error) { 88 | ids := make([]int64, numVectors) 89 | for i := range ids { 90 | ids[i] = index.GetNtotal() + int64(i) 91 | } 92 | code := C.faiss_Index_add(index.Index, C.idx_t(numVectors), (*C.float)(&vectors[0])) 93 | if int(code) != 0 { 94 | return nil, errors.New("Cannot add vectors") 95 | } 96 | return ids, nil 97 | } 98 | 99 | func (index *FaissIndex) AddVectorsWithIds(numVectors int32, vectors []float32, ids []int64) error { 100 | code := C.faiss_Index_add_with_ids(index.Index, C.idx_t(numVectors), (*C.float)(&vectors[0]), (*C.idx_t)(&ids[0])) 101 | if int(code) != 0 { 102 | return errors.New("Cannot add vectors") 103 | } 104 | return nil 105 | } 106 | 107 | func (index *FaissIndex) RemoveVectors(ids []int64) (int32, error) { 108 | numRemovedOrCode := int32(C.removeVectors(index.Index, C.int(len(ids)), (*C.idx_t)(&ids[0]))) 109 | if numRemovedOrCode == -1 { 110 | return -1, errors.New("Cannot remove vectors") 111 | } 112 | return numRemovedOrCode, nil 113 | } 114 | -------------------------------------------------------------------------------- /generate_testdata.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | This file is copied from below link and slightly modified to dump random index. 3 | 4 | https://github.com/facebookresearch/faiss/blob/d68ff421957a02f6137796cb53e292ed24f5a369/tutorial/cpp/1-Flat.cpp 5 | */ 6 | 7 | #include 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #include "faiss/Index.h" 15 | #include "faiss/IndexFlat.h" 16 | #include "faiss/index_io.h" 17 | 18 | // 64-bit int 19 | using idx_t = faiss::Index::idx_t; 20 | 21 | #define INDEX_OUTPUT_FILENAME "testdata/random-index.faiss" 22 | #define RANDOM_SEED 1234 23 | 24 | int main() { 25 | int d = 8; // dimension 26 | int nb = 1000; // database size 27 | int nq = 1000; // nb of queries 28 | 29 | std::mt19937 rng; 30 | rng.seed(RANDOM_SEED); 31 | std::uniform_real_distribution<> distrib; 32 | 33 | float* xb = new float[d * nb]; 34 | float* xq = new float[d * nq]; 35 | 36 | for (int i = 0; i < nb; i++) { 37 | for (int j = 0; j < d; j++) xb[d * i + j] = distrib(rng); 38 | xb[d * i] += i / 1000.; 39 | } 40 | 41 | for (int i = 0; i < nq; i++) { 42 | for (int j = 0; j < d; j++) xq[d * i + j] = distrib(rng); 43 | xq[d * i] += i / 1000.; 44 | } 45 | 46 | faiss::IndexFlatL2 index(d); // call constructor 47 | printf("is_trained = %s\n", index.is_trained ? "true" : "false"); 48 | index.add(nb, xb); // add vectors to the index 49 | printf("ntotal = %lld\n", index.ntotal); 50 | faiss::write_index(reinterpret_cast(&index), 51 | INDEX_OUTPUT_FILENAME); 52 | 53 | { 54 | char buff[FILENAME_MAX]; 55 | getcwd(buff, FILENAME_MAX); 56 | printf("Random Index path: %s/%s\n\n", buff, INDEX_OUTPUT_FILENAME); 57 | } 58 | 59 | int k = 4; 60 | 61 | { // sanity check: search 5 first vectors of xb 62 | idx_t* I = new idx_t[k * 5]; 63 | float* D = new float[k * 5]; 64 | 65 | index.search(5, xb, k, D, I); 66 | printf("query vector=\n"); 67 | for (int i = 0; i < 5; i++) { 68 | for (int j = 0; j < d; j++) { 69 | printf(" %5g", xb[i * d + j]); 70 | } 71 | printf("\n"); 72 | } 73 | 74 | // print results 75 | printf("I=\n"); 76 | for (int i = 0; i < 5; i++) { 77 | for (int j = 0; j < k; j++) printf("%5lld ", I[i * k + j]); 78 | printf("\n"); 79 | } 80 | 81 | printf("D=\n"); 82 | for (int i = 0; i < 5; i++) { 83 | for (int j = 0; j < k; j++) printf("%7g ", D[i * k + j]); 84 | printf("\n"); 85 | } 86 | 87 | delete[] I; 88 | delete[] D; 89 | } 90 | 91 | { // search xq 92 | idx_t* I = new idx_t[k * nq]; 93 | float* D = new float[k * nq]; 94 | 95 | index.search(nq, xq, k, D, I); 96 | 97 | // print results 98 | printf("I (5 first results)=\n"); 99 | for (int i = 0; i < 5; i++) { 100 | for (int j = 0; j < k; j++) printf("%5lld ", I[i * k + j]); 101 | printf("\n"); 102 | } 103 | 104 | printf("I (5 last results)=\n"); 105 | for (int i = nq - 5; i < nq; i++) { 106 | for (int j = 0; j < k; j++) printf("%5lld ", I[i * k + j]); 107 | printf("\n"); 108 | } 109 | 110 | delete[] I; 111 | delete[] D; 112 | } 113 | 114 | delete[] xb; 115 | delete[] xq; 116 | 117 | return 0; 118 | } 119 | -------------------------------------------------------------------------------- /faiss/wrapper.cpp: -------------------------------------------------------------------------------- 1 | #include "wrapper.h" 2 | 3 | #include 4 | #include 5 | 6 | #include "faiss/impl/AuxIndexStructures.h" 7 | #include "faiss/impl/io.h" 8 | #include "faiss/index_io.h" 9 | #include "google/cloud/storage/client.h" 10 | 11 | namespace gcs = ::google::cloud::storage; 12 | 13 | static std::string error; 14 | 15 | const char* getError() { return error.c_str(); } 16 | 17 | struct GCSIOReader : faiss::IOReader { 18 | gcs::Client client; 19 | const std::string bucket; 20 | const std::string blobPath; 21 | size_t offset; 22 | 23 | GCSIOReader(gcs::Client client, const std::string bucket, 24 | const std::string blobPath) 25 | : client(client), bucket(bucket), blobPath(blobPath), offset(0) {} 26 | 27 | size_t operator()(void* ptr, size_t size, size_t nitems) { 28 | size_t bufferSize = size * nitems; 29 | gcs::ObjectReadStream stream = client.ReadObject( 30 | bucket, blobPath, gcs::ReadRange(offset, offset + bufferSize)); 31 | if (!stream) { 32 | std::ostringstream ss; 33 | ss << "Error reading object: " << stream.status(); 34 | error = ss.str(); 35 | return 0; 36 | } 37 | 38 | size_t nReads = bufferSize; 39 | stream.read(static_cast(ptr), bufferSize); 40 | if (!stream) { 41 | nReads = stream.gcount(); 42 | 43 | std::ostringstream ss; 44 | ss << "Cannot read successfully from GCS. offset: " << offset 45 | << ", expected size: " << bufferSize << ", actual: " << nReads; 46 | error = ss.str(); 47 | } 48 | offset += nReads; 49 | stream.Close(); 50 | 51 | return nReads / size; 52 | } 53 | }; 54 | 55 | FaissIndex* loadIndex(const char* cPath) { 56 | std::string path(cPath); 57 | 58 | // Handle GCS 59 | if (path.find("gs://") == 0) { 60 | gcs::Client client = gcs::Client(); 61 | std::string bucket, blobPath; 62 | parseUrl(path, bucket, blobPath); 63 | 64 | if (bucket == "" || blobPath == "") { 65 | error = "Cannot parse GCS url. url: " + path; 66 | return NULL; 67 | } 68 | 69 | GCSIOReader reader(client, bucket, blobPath); 70 | FaissIndex* index = NULL; 71 | try { 72 | index = reinterpret_cast( 73 | faiss::read_index(&reader, FAISS_IO_FLAG_READ_ONLY)); 74 | } catch (std::exception& e) { 75 | error = e.what(); 76 | return NULL; 77 | } 78 | 79 | return index; 80 | } 81 | 82 | // Hadle local fs 83 | FaissIndex* index = NULL; 84 | if (faiss_read_index_fname(cPath, FAISS_IO_FLAG_READ_ONLY, &index)) { 85 | return NULL; 86 | } 87 | return index; 88 | } 89 | 90 | SearchResults searchFaiss(const FaissIndex* index, int numVectors, int topK, 91 | const float* vectors) { 92 | idx_t* ids = (idx_t*)malloc(sizeof(idx_t) * topK * numVectors); 93 | float* distances = (float*)malloc(sizeof(float) * topK * numVectors); 94 | 95 | int result = 96 | faiss_Index_search(index, numVectors, vectors, topK, distances, ids); 97 | 98 | SearchResults searchResult = { 99 | ids, 100 | distances, 101 | result, 102 | }; 103 | return searchResult; 104 | } 105 | 106 | int removeVectors(FaissIndex* index, int numIds, const int64_t* ids) { 107 | faiss::IDSelectorArray selector(numIds, ids); 108 | size_t nRemoved; 109 | int code = faiss_Index_remove_ids( 110 | index, reinterpret_cast(&selector), &nRemoved); 111 | if (code == 0) return (int)nRemoved; 112 | 113 | // errors 114 | return -1; 115 | } 116 | 117 | void parseUrl(const std::string url, std::string& bucket, 118 | std::string& blobPath) { 119 | auto pos = url.find("://"); 120 | if (pos == std::string::npos) return; 121 | auto posOfFirstSlash = url.find("/", pos + 3); 122 | if (posOfFirstSlash == std::string::npos) return; 123 | 124 | bucket = url.substr(pos + 3, posOfFirstSlash - (pos + 3)); 125 | blobPath = url.substr(posOfFirstSlash + 1); 126 | } 127 | -------------------------------------------------------------------------------- /server_grpc.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/golang/glog" 7 | "google.golang.org/grpc/codes" 8 | "google.golang.org/grpc/status" 9 | 10 | "github.com/jeongukjae/faiss-server/faiss" 11 | gw "github.com/jeongukjae/faiss-server/protos/faiss/service" 12 | ) 13 | 14 | type faissServer struct { 15 | gw.UnimplementedFaissServer 16 | 17 | WithReloadMethod bool 18 | Index *faiss.FaissIndex 19 | } 20 | 21 | func (s *faissServer) GetMetadata(ctx context.Context, in *gw.EmptyMessage) (*gw.GetMetadataResponse, error) { 22 | return &gw.GetMetadataResponse{ 23 | IndexName: s.Index.Path, 24 | Dimension: s.Index.Dimension, 25 | MetricType: gw.GetMetadataResponse_MetricType(s.Index.MetricType), 26 | Ntotal: s.Index.GetNtotal(), 27 | }, nil 28 | } 29 | 30 | func (s *faissServer) Search(ctx context.Context, in *gw.SearchRequest) (*gw.SearchResponse, error) { 31 | if err := checkVectorDimension(in.Vectors, in.NumVectors, s.Index.Dimension); err != nil { 32 | return nil, err 33 | } 34 | if in.TopK == 0 { 35 | return nil, status.Errorf(codes.InvalidArgument, "top k argument = 0") 36 | } 37 | 38 | results := s.Index.Search(in.NumVectors, in.TopK, in.Vectors) 39 | return &gw.SearchResponse{ 40 | Ids: results.Ids, 41 | Distances: results.Distances, 42 | }, nil 43 | } 44 | 45 | func (s *faissServer) AddVectors(ctx context.Context, in *gw.AddVectorsRequest) (*gw.AddVectorsResponse, error) { 46 | if err := checkVectorDimension(in.Vectors, in.NumVectors, s.Index.Dimension); err != nil { 47 | return nil, err 48 | } 49 | 50 | ids, err := s.Index.AddVectors(in.NumVectors, in.Vectors) 51 | if err != nil { 52 | return nil, status.Errorf(codes.Internal, err.Error()) 53 | } 54 | return &gw.AddVectorsResponse{Ids: ids}, nil 55 | } 56 | 57 | func (s *faissServer) AddVectorsWithIds(ctx context.Context, in *gw.AddVectorsWithIdsRequest) (*gw.EmptyMessage, error) { 58 | if err := checkVectorDimension(in.Vectors, in.NumVectors, s.Index.Dimension); err != nil { 59 | return nil, err 60 | } 61 | 62 | numElements := int32(len(in.Ids)) 63 | if numElements != in.NumVectors { 64 | return nil, status.Errorf( 65 | codes.InvalidArgument, 66 | "num elements of ids(%d) != num vectors(%d)", 67 | numElements, in.NumVectors, 68 | ) 69 | } 70 | 71 | err := s.Index.AddVectorsWithIds(in.NumVectors, in.Vectors, in.Ids) 72 | if err != nil { 73 | return nil, status.Errorf(codes.Internal, "%s. This method is not supported by all indexes.", err.Error()) 74 | } 75 | return &gw.EmptyMessage{}, nil 76 | } 77 | 78 | func (s *faissServer) RemoveVectors(ctx context.Context, in *gw.RemoveVectorsRequest) (*gw.RemoveVectorsResponse, error) { 79 | if len(in.Ids) == 0 { 80 | return nil, status.Error(codes.InvalidArgument, "num elements of ids = 0") 81 | } 82 | numRemoved, err := s.Index.RemoveVectors(in.Ids) 83 | 84 | if err != nil { 85 | return nil, status.Errorf(codes.Internal, err.Error()) 86 | } 87 | return &gw.RemoveVectorsResponse{NumRemoved: numRemoved}, nil 88 | } 89 | 90 | func (s *faissServer) Reload(ctx context.Context, in *gw.EmptyMessage) (*gw.EmptyMessage, error) { 91 | if !s.WithReloadMethod { 92 | return nil, status.Error(codes.PermissionDenied, "Reload method is disabled.") 93 | } 94 | 95 | indexPath := s.Index.Path 96 | glog.Info("Reload triggered, remove old index...") 97 | s.Index.Free() 98 | 99 | glog.Info("Load new index from ", indexPath, "...") 100 | newIndex, err := faiss.LoadIndex(indexPath) 101 | if err != nil { 102 | glog.Fatal("Cannot load index again!!") 103 | return nil, status.Errorf(codes.Internal, "Cannot reload faiss") 104 | } 105 | s.Index = newIndex 106 | glog.Info("Reloaded index successfully") 107 | return &gw.EmptyMessage{}, nil 108 | } 109 | 110 | func checkVectorDimension(vectors []float32, numVectors int32, dimension int32) error { 111 | numElements := int32(len(vectors)) 112 | if numElements != numVectors*dimension { 113 | return status.Errorf( 114 | codes.InvalidArgument, 115 | "num elements of vector(%d) != num vectors(%d) * dimension(%d)", 116 | numElements, numVectors, dimension, 117 | ) 118 | } 119 | 120 | if numElements == 0 { 121 | return status.Errorf(codes.InvalidArgument, "num elements of vector = 0") 122 | } 123 | 124 | return nil 125 | } 126 | -------------------------------------------------------------------------------- /WORKSPACE: -------------------------------------------------------------------------------- 1 | workspace(name = "faiss-server") 2 | 3 | load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") 4 | 5 | # ==================== 6 | # rules go and gazelle 7 | http_archive( 8 | name = "io_bazel_rules_go", 9 | sha256 = "2b1641428dff9018f9e85c0384f03ec6c10660d935b750e3fa1492a281a53b0f", 10 | urls = [ 11 | "https://mirror.bazel.build/github.com/bazelbuild/rules_go/releases/download/v0.29.0/rules_go-v0.29.0.zip", 12 | "https://github.com/bazelbuild/rules_go/releases/download/v0.29.0/rules_go-v0.29.0.zip", 13 | ], 14 | ) 15 | 16 | load("@io_bazel_rules_go//go:deps.bzl", "go_register_toolchains", "go_rules_dependencies") 17 | 18 | go_rules_dependencies() 19 | 20 | go_register_toolchains(version = "1.17.2") 21 | 22 | # ================ 23 | # Rules foreign cc 24 | http_archive( 25 | name = "rules_foreign_cc", 26 | sha256 = "1df78c7d7eed2dc21b8b325a2853c31933a81e7b780f9a59a5d078be9008b13a", 27 | strip_prefix = "rules_foreign_cc-0.7.0", 28 | url = "https://github.com/bazelbuild/rules_foreign_cc/archive/0.7.0.tar.gz", 29 | ) 30 | 31 | load("@rules_foreign_cc//foreign_cc:repositories.bzl", "rules_foreign_cc_dependencies") 32 | 33 | rules_foreign_cc_dependencies() 34 | 35 | # ============== 36 | # CC dependencies 37 | http_archive( 38 | name = "com_google_googletest", 39 | sha256 = "0eab4e490851b09de09e815954554459606edb1d775c644f4a31ff6b331c524b", 40 | strip_prefix = "googletest-e2f3978937c0244508135f126e2617a7734a68be", 41 | urls = ["https://github.com/google/googletest/archive/e2f3978937c0244508135f126e2617a7734a68be.zip"], 42 | ) 43 | 44 | # ================ 45 | # GCS dependencies 46 | http_archive( 47 | name = "zlib", 48 | build_file = "//third_party:zlib.BUILD", 49 | sha256 = "c3e5e9fdd5004dcb542feda5ee4f0ff0744628baf8ed2dd5d66f8ca1197cb1a1", 50 | strip_prefix = "zlib-1.2.11", 51 | url = "https://zlib.net/zlib-1.2.11.tar.gz", 52 | ) 53 | 54 | http_archive( 55 | name = "com_github_googleapis_google_cloud_cpp", 56 | patch_args = ["-p1"], 57 | patches = ["//third_party:google_cloud_cpp.patch"], 58 | sha256 = "f38ae4ab6f2ed7579a7ceb5d0b32ed04097da07bc898907ed01c8d840c2bdbce", 59 | strip_prefix = "google-cloud-cpp-1.34.1", 60 | url = "https://github.com/googleapis/google-cloud-cpp/archive/v1.34.1.tar.gz", 61 | ) 62 | 63 | load("@com_github_googleapis_google_cloud_cpp//bazel:google_cloud_cpp_deps.bzl", "google_cloud_cpp_deps") 64 | 65 | google_cloud_cpp_deps() 66 | 67 | # =========== 68 | # rules proto 69 | http_archive( 70 | name = "rules_proto", 71 | sha256 = "66bfdf8782796239d3875d37e7de19b1d94301e8972b3cbd2446b332429b4df1", 72 | strip_prefix = "rules_proto-4.0.0", 73 | urls = [ 74 | "https://mirror.bazel.build/github.com/bazelbuild/rules_proto/archive/refs/tags/4.0.0.tar.gz", 75 | "https://github.com/bazelbuild/rules_proto/archive/refs/tags/4.0.0.tar.gz", 76 | ], 77 | ) 78 | 79 | load("@rules_proto//proto:repositories.bzl", "rules_proto_dependencies", "rules_proto_toolchains") 80 | 81 | rules_proto_dependencies() 82 | 83 | rules_proto_toolchains() 84 | 85 | # ====== 86 | # for golang 87 | http_archive( 88 | name = "bazel_gazelle", 89 | sha256 = "de69a09dc70417580aabf20a28619bb3ef60d038470c7cf8442fafcf627c21cb", 90 | urls = [ 91 | "https://mirror.bazel.build/github.com/bazelbuild/bazel-gazelle/releases/download/v0.24.0/bazel-gazelle-v0.24.0.tar.gz", 92 | "https://github.com/bazelbuild/bazel-gazelle/releases/download/v0.24.0/bazel-gazelle-v0.24.0.tar.gz", 93 | ], 94 | ) 95 | 96 | load("@bazel_gazelle//:deps.bzl", "gazelle_dependencies") 97 | load("//:deps.bzl", "go_dependencies") 98 | 99 | # gazelle:repository_macro deps.bzl%go_dependencies 100 | go_dependencies() 101 | 102 | gazelle_dependencies() 103 | 104 | # =========== 105 | # build tools 106 | http_archive( 107 | name = "com_github_bazelbuild_buildtools", 108 | sha256 = "ae34c344514e08c23e90da0e2d6cb700fcd28e80c02e23e4d5715dddcb42f7b3", 109 | strip_prefix = "buildtools-4.2.2", 110 | urls = [ 111 | "https://github.com/bazelbuild/buildtools/archive/refs/tags/4.2.2.tar.gz", 112 | ], 113 | ) 114 | 115 | # =============== 116 | # third party lib 117 | http_archive( 118 | name = "com_github_facebookresearch_faiss", 119 | build_file = "//third_party/faiss:BUILD.bzl", 120 | patch_args = ["-p1"], 121 | patches = ["//third_party/faiss:faiss.patch"], 122 | sha256 = "7e53e763f4081f9fb329634bb51cecaad674b22f5ee56351d09b0fe21bbc4f72", 123 | strip_prefix = "faiss-1.7.1", 124 | url = "https://github.com/facebookresearch/faiss/archive/v1.7.1.zip", 125 | ) 126 | 127 | http_archive( 128 | name = "com_github_grpc_ecosystem_grpc_gateway_v2", 129 | sha256 = "732f8882dffcceb7c14839ffcf492ae0f5b5dcf2e79003c4ca1b83f29892483e", 130 | strip_prefix = "grpc-gateway-2.7.1", 131 | url = "https://github.com/grpc-ecosystem/grpc-gateway/archive/v2.7.1.zip", 132 | ) 133 | 134 | load("@com_github_grpc_ecosystem_grpc_gateway_v2//:repositories.bzl", grpc_gateway_go_repositories = "go_repositories") 135 | 136 | grpc_gateway_go_repositories() 137 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /deps.bzl: -------------------------------------------------------------------------------- 1 | """ 2 | go dependency list 3 | """ 4 | 5 | load("@bazel_gazelle//:deps.bzl", "go_repository") 6 | 7 | def go_dependencies(): 8 | """ 9 | go dependencies for faiss server 10 | """ 11 | go_repository( 12 | name = "co_honnef_go_tools", 13 | importpath = "honnef.co/go/tools", 14 | sum = "h1:/hemPrYIhOhy8zYrNj+069zDB68us2sMGsfkFJO0iZs=", 15 | version = "v0.0.0-20190523083050-ea95bdfd59fc", 16 | ) 17 | go_repository( 18 | name = "com_github_alecthomas_template", 19 | importpath = "github.com/alecthomas/template", 20 | sum = "h1:JYp7IbQjafoB+tBA3gMyHYHrpOtNuDiK/uB5uXxq5wM=", 21 | version = "v0.0.0-20190718012654-fb15b899a751", 22 | ) 23 | go_repository( 24 | name = "com_github_alecthomas_units", 25 | importpath = "github.com/alecthomas/units", 26 | sum = "h1:UQZhZ2O0vMHr2cI+DC1Mbh0TJxzA3RcLoMsFw+aXw7E=", 27 | version = "v0.0.0-20190924025748-f65c72e2690d", 28 | ) 29 | 30 | go_repository( 31 | name = "com_github_antihax_optional", 32 | importpath = "github.com/antihax/optional", 33 | sum = "h1:xK2lYat7ZLaVVcIuj82J8kIro4V6kDe0AUDFboUCwcg=", 34 | version = "v1.0.0", 35 | ) 36 | go_repository( 37 | name = "com_github_beorn7_perks", 38 | importpath = "github.com/beorn7/perks", 39 | sum = "h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=", 40 | version = "v1.0.1", 41 | ) 42 | 43 | go_repository( 44 | name = "com_github_burntsushi_toml", 45 | importpath = "github.com/BurntSushi/toml", 46 | sum = "h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=", 47 | version = "v0.3.1", 48 | ) 49 | go_repository( 50 | name = "com_github_census_instrumentation_opencensus_proto", 51 | importpath = "github.com/census-instrumentation/opencensus-proto", 52 | sum = "h1:glEXhBS5PSLLv4IXzLA5yPRVX4bilULVyxxbrfOtDAk=", 53 | version = "v0.2.1", 54 | ) 55 | go_repository( 56 | name = "com_github_cespare_xxhash", 57 | importpath = "github.com/cespare/xxhash", 58 | sum = "h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=", 59 | version = "v1.1.0", 60 | ) 61 | go_repository( 62 | name = "com_github_cespare_xxhash_v2", 63 | importpath = "github.com/cespare/xxhash/v2", 64 | sum = "h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY=", 65 | version = "v2.1.1", 66 | ) 67 | go_repository( 68 | name = "com_github_client9_misspell", 69 | importpath = "github.com/client9/misspell", 70 | sum = "h1:ta993UF76GwbvJcIo3Y68y/M3WxlpEHPWIGDkJYwzJI=", 71 | version = "v0.3.4", 72 | ) 73 | go_repository( 74 | name = "com_github_cncf_udpa_go", 75 | importpath = "github.com/cncf/udpa/go", 76 | sum = "h1:hzAQntlaYRkVSFEfj9OTWlVV1H155FMD8BTKktLv0QI=", 77 | version = "v0.0.0-20210930031921-04548b0d99d4", 78 | ) 79 | go_repository( 80 | name = "com_github_cncf_xds_go", 81 | importpath = "github.com/cncf/xds/go", 82 | sum = "h1:zH8ljVhhq7yC0MIeUL/IviMtY8hx2mK8cN9wEYb8ggw=", 83 | version = "v0.0.0-20211011173535-cb28da3451f1", 84 | ) 85 | go_repository( 86 | name = "com_github_davecgh_go_spew", 87 | importpath = "github.com/davecgh/go-spew", 88 | sum = "h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=", 89 | version = "v1.1.1", 90 | ) 91 | go_repository( 92 | name = "com_github_envoyproxy_go_control_plane", 93 | importpath = "github.com/envoyproxy/go-control-plane", 94 | sum = "h1:fP+fF0up6oPY49OrjPrhIJ8yQfdIM85NXMLkMg1EXVs=", 95 | version = "v0.9.10-0.20210907150352-cf90f659a021", 96 | ) 97 | go_repository( 98 | name = "com_github_envoyproxy_protoc_gen_validate", 99 | importpath = "github.com/envoyproxy/protoc-gen-validate", 100 | sum = "h1:EQciDnbrYxy13PgWoY8AqoxGiPrpgBZ1R8UNe3ddc+A=", 101 | version = "v0.1.0", 102 | ) 103 | go_repository( 104 | name = "com_github_ghodss_yaml", 105 | importpath = "github.com/ghodss/yaml", 106 | sum = "h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=", 107 | version = "v1.0.0", 108 | ) 109 | go_repository( 110 | name = "com_github_go_kit_kit", 111 | importpath = "github.com/go-kit/kit", 112 | sum = "h1:wDJmvq38kDhkVxi50ni9ykkdUr1PKgqKOoi01fa0Mdk=", 113 | version = "v0.9.0", 114 | ) 115 | go_repository( 116 | name = "com_github_go_kit_log", 117 | importpath = "github.com/go-kit/log", 118 | sum = "h1:DGJh0Sm43HbOeYDNnVZFl8BvcYVvjD5bqYJvp0REbwQ=", 119 | version = "v0.1.0", 120 | ) 121 | go_repository( 122 | name = "com_github_go_logfmt_logfmt", 123 | importpath = "github.com/go-logfmt/logfmt", 124 | sum = "h1:TrB8swr/68K7m9CcGut2g3UOihhbcbiMAYiuTXdEih4=", 125 | version = "v0.5.0", 126 | ) 127 | go_repository( 128 | name = "com_github_go_stack_stack", 129 | importpath = "github.com/go-stack/stack", 130 | sum = "h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk=", 131 | version = "v1.8.0", 132 | ) 133 | go_repository( 134 | name = "com_github_gogo_protobuf", 135 | importpath = "github.com/gogo/protobuf", 136 | sum = "h1:72R+M5VuhED/KujmZVcIquuo8mBgX4oVda//DQb3PXo=", 137 | version = "v1.1.1", 138 | ) 139 | 140 | go_repository( 141 | name = "com_github_golang_glog", 142 | importpath = "github.com/golang/glog", 143 | sum = "h1:nfP3RFugxnNRyKgeWd4oI1nYvXpxrx8ck8ZrcizshdQ=", 144 | version = "v1.0.0", 145 | ) 146 | go_repository( 147 | name = "com_github_golang_mock", 148 | importpath = "github.com/golang/mock", 149 | sum = "h1:G5FRp8JnTd7RQH5kemVNlMeyXQAztQ3mOWV95KxsXH8=", 150 | version = "v1.1.1", 151 | ) 152 | go_repository( 153 | name = "com_github_golang_protobuf", 154 | importpath = "github.com/golang/protobuf", 155 | sum = "h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=", 156 | version = "v1.5.2", 157 | ) 158 | go_repository( 159 | name = "com_github_google_go_cmp", 160 | importpath = "github.com/google/go-cmp", 161 | sum = "h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ=", 162 | version = "v0.5.6", 163 | ) 164 | go_repository( 165 | name = "com_github_google_gofuzz", 166 | importpath = "github.com/google/gofuzz", 167 | sum = "h1:A8PeW59pxE9IoFRqBp37U+mSNaQoZ46F1f0f863XSXw=", 168 | version = "v1.0.0", 169 | ) 170 | 171 | go_repository( 172 | name = "com_github_google_uuid", 173 | importpath = "github.com/google/uuid", 174 | sum = "h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y=", 175 | version = "v1.1.2", 176 | ) 177 | go_repository( 178 | name = "com_github_grpc_ecosystem_go_grpc_prometheus", 179 | importpath = "github.com/grpc-ecosystem/go-grpc-prometheus", 180 | sum = "h1:Ovs26xHkKqVztRpIrF/92BcuyuQ/YW4NSIpoGtfXNho=", 181 | version = "v1.2.0", 182 | ) 183 | 184 | go_repository( 185 | name = "com_github_grpc_ecosystem_grpc_gateway", 186 | importpath = "github.com/grpc-ecosystem/grpc-gateway", 187 | sum = "h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo=", 188 | version = "v1.16.0", 189 | ) 190 | 191 | go_repository( 192 | name = "com_github_grpc_ecosystem_grpc_gateway_v2", 193 | importpath = "github.com/grpc-ecosystem/grpc-gateway/v2", 194 | sum = "h1:p5m7GOEGXyoq6QWl4/RRMsQ6tWbTpbQmAnkxXgWSprY=", 195 | version = "v2.7.1", 196 | ) 197 | go_repository( 198 | name = "com_github_jpillora_backoff", 199 | importpath = "github.com/jpillora/backoff", 200 | sum = "h1:uvFg412JmmHBHw7iwprIxkPMI+sGQ4kzOWsMeHnm2EA=", 201 | version = "v1.0.0", 202 | ) 203 | go_repository( 204 | name = "com_github_json_iterator_go", 205 | importpath = "github.com/json-iterator/go", 206 | sum = "h1:uVUAXhF2To8cbw/3xN3pxj6kk7TYKs98NIrTqPlMWAQ=", 207 | version = "v1.1.11", 208 | ) 209 | go_repository( 210 | name = "com_github_julienschmidt_httprouter", 211 | importpath = "github.com/julienschmidt/httprouter", 212 | sum = "h1:U0609e9tgbseu3rBINet9P48AI/D3oJs4dN7jwJOQ1U=", 213 | version = "v1.3.0", 214 | ) 215 | go_repository( 216 | name = "com_github_konsorten_go_windows_terminal_sequences", 217 | importpath = "github.com/konsorten/go-windows-terminal-sequences", 218 | sum = "h1:CE8S1cTafDpPvMhIxNJKvHsGVBgn1xWYf1NbHQhywc8=", 219 | version = "v1.0.3", 220 | ) 221 | go_repository( 222 | name = "com_github_kr_logfmt", 223 | importpath = "github.com/kr/logfmt", 224 | sum = "h1:T+h1c/A9Gawja4Y9mFVWj2vyii2bbUNDw3kt9VxK2EY=", 225 | version = "v0.0.0-20140226030751-b84e30acd515", 226 | ) 227 | go_repository( 228 | name = "com_github_kr_pretty", 229 | importpath = "github.com/kr/pretty", 230 | sum = "h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=", 231 | version = "v0.1.0", 232 | ) 233 | go_repository( 234 | name = "com_github_kr_pty", 235 | importpath = "github.com/kr/pty", 236 | sum = "h1:VkoXIwSboBpnk99O/KFauAEILuNHv5DVFKZMBN/gUgw=", 237 | version = "v1.1.1", 238 | ) 239 | go_repository( 240 | name = "com_github_kr_text", 241 | importpath = "github.com/kr/text", 242 | sum = "h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=", 243 | version = "v0.1.0", 244 | ) 245 | go_repository( 246 | name = "com_github_matttproud_golang_protobuf_extensions", 247 | importpath = "github.com/matttproud/golang_protobuf_extensions", 248 | sum = "h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=", 249 | version = "v1.0.1", 250 | ) 251 | go_repository( 252 | name = "com_github_modern_go_concurrent", 253 | importpath = "github.com/modern-go/concurrent", 254 | sum = "h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=", 255 | version = "v0.0.0-20180306012644-bacd9c7ef1dd", 256 | ) 257 | go_repository( 258 | name = "com_github_modern_go_reflect2", 259 | importpath = "github.com/modern-go/reflect2", 260 | sum = "h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI=", 261 | version = "v1.0.1", 262 | ) 263 | go_repository( 264 | name = "com_github_mwitkow_go_conntrack", 265 | importpath = "github.com/mwitkow/go-conntrack", 266 | sum = "h1:KUppIJq7/+SVif2QVs3tOP0zanoHgBEVAwHxUSIzRqU=", 267 | version = "v0.0.0-20190716064945-2f068394615f", 268 | ) 269 | 270 | go_repository( 271 | name = "com_github_oneofone_xxhash", 272 | importpath = "github.com/OneOfOne/xxhash", 273 | sum = "h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE=", 274 | version = "v1.2.2", 275 | ) 276 | go_repository( 277 | name = "com_github_pkg_errors", 278 | importpath = "github.com/pkg/errors", 279 | sum = "h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=", 280 | version = "v0.9.1", 281 | ) 282 | 283 | go_repository( 284 | name = "com_github_pmezard_go_difflib", 285 | importpath = "github.com/pmezard/go-difflib", 286 | sum = "h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=", 287 | version = "v1.0.0", 288 | ) 289 | go_repository( 290 | name = "com_github_prometheus_client_golang", 291 | importpath = "github.com/prometheus/client_golang", 292 | sum = "h1:HNkLOAEQMIDv/K+04rukrLx6ch7msSRwf3/SASFAGtQ=", 293 | version = "v1.11.0", 294 | ) 295 | 296 | go_repository( 297 | name = "com_github_prometheus_client_model", 298 | importpath = "github.com/prometheus/client_model", 299 | sum = "h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M=", 300 | version = "v0.2.0", 301 | ) 302 | go_repository( 303 | name = "com_github_prometheus_common", 304 | importpath = "github.com/prometheus/common", 305 | sum = "h1:iMAkS2TDoNWnKM+Kopnx/8tnEStIfpYA0ur0xQzzhMQ=", 306 | version = "v0.26.0", 307 | ) 308 | go_repository( 309 | name = "com_github_prometheus_procfs", 310 | importpath = "github.com/prometheus/procfs", 311 | sum = "h1:mxy4L2jP6qMonqmq+aTtOx1ifVWUgG/TAmntgbh3xv4=", 312 | version = "v0.6.0", 313 | ) 314 | 315 | go_repository( 316 | name = "com_github_rogpeppe_fastuuid", 317 | importpath = "github.com/rogpeppe/fastuuid", 318 | sum = "h1:Ppwyp6VYCF1nvBTXL3trRso7mXMlRrw9ooo375wvi2s=", 319 | version = "v1.2.0", 320 | ) 321 | go_repository( 322 | name = "com_github_sirupsen_logrus", 323 | importpath = "github.com/sirupsen/logrus", 324 | sum = "h1:UBcNElsrwanuuMsnGSlYmtmgbb23qDR5dG+6X6Oo89I=", 325 | version = "v1.6.0", 326 | ) 327 | 328 | go_repository( 329 | name = "com_github_spaolacci_murmur3", 330 | importpath = "github.com/spaolacci/murmur3", 331 | sum = "h1:qLC7fQah7D6K1B0ujays3HV9gkFtllcxhzImRR7ArPQ=", 332 | version = "v0.0.0-20180118202830-f09979ecbc72", 333 | ) 334 | go_repository( 335 | name = "com_github_stretchr_objx", 336 | importpath = "github.com/stretchr/objx", 337 | sum = "h1:2vfRuCMp5sSVIDSqO8oNnWJq7mPa6KVP3iPIwFBuy8A=", 338 | version = "v0.1.1", 339 | ) 340 | go_repository( 341 | name = "com_github_stretchr_testify", 342 | importpath = "github.com/stretchr/testify", 343 | sum = "h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=", 344 | version = "v1.7.0", 345 | ) 346 | go_repository( 347 | name = "com_google_cloud_go", 348 | importpath = "cloud.google.com/go", 349 | sum = "h1:eOI3/cP2VTU6uZLDYAoic+eyzzB9YyGmJ7eIjl8rOPg=", 350 | version = "v0.34.0", 351 | ) 352 | go_repository( 353 | name = "in_gopkg_alecthomas_kingpin_v2", 354 | importpath = "gopkg.in/alecthomas/kingpin.v2", 355 | sum = "h1:jMFz6MfLP0/4fUyZle81rXUoxOBFi19VUFKVDOQfozc=", 356 | version = "v2.2.6", 357 | ) 358 | 359 | go_repository( 360 | name = "in_gopkg_check_v1", 361 | importpath = "gopkg.in/check.v1", 362 | sum = "h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=", 363 | version = "v1.0.0-20190902080502-41f04d3bba15", 364 | ) 365 | go_repository( 366 | name = "in_gopkg_yaml_v2", 367 | importpath = "gopkg.in/yaml.v2", 368 | sum = "h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=", 369 | version = "v2.4.0", 370 | ) 371 | go_repository( 372 | name = "in_gopkg_yaml_v3", 373 | importpath = "gopkg.in/yaml.v3", 374 | sum = "h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=", 375 | version = "v3.0.0-20200313102051-9f266ea9e77c", 376 | ) 377 | go_repository( 378 | name = "io_k8s_sigs_yaml", 379 | importpath = "sigs.k8s.io/yaml", 380 | sum = "h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo=", 381 | version = "v1.3.0", 382 | ) 383 | go_repository( 384 | name = "io_opentelemetry_go_proto_otlp", 385 | importpath = "go.opentelemetry.io/proto/otlp", 386 | sum = "h1:rwOQPCuKAKmwGKq2aVNnYIibI6wnV7EvzgfTCzcdGg8=", 387 | version = "v0.7.0", 388 | ) 389 | go_repository( 390 | name = "org_golang_google_appengine", 391 | importpath = "google.golang.org/appengine", 392 | sum = "h1:lMO5rYAqUxkmaj76jAkRUvt5JZgFymx/+Q5Mzfivuhc=", 393 | version = "v1.6.6", 394 | ) 395 | go_repository( 396 | name = "org_golang_google_genproto", 397 | importpath = "google.golang.org/genproto", 398 | sum = "h1:DN5b3HU13J4sMd/QjDx34U6afpaexKTDdop+26pdjdk=", 399 | version = "v0.0.0-20211129164237-f09f9a12af12", 400 | ) 401 | go_repository( 402 | name = "org_golang_google_grpc", 403 | importpath = "google.golang.org/grpc", 404 | sum = "h1:XT2/MFpuPFsEX2fWh3YQtHkZ+WYZFQRfaUgLZYj/p6A=", 405 | version = "v1.42.0", 406 | ) 407 | go_repository( 408 | name = "org_golang_google_protobuf", 409 | importpath = "google.golang.org/protobuf", 410 | sum = "h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ=", 411 | version = "v1.27.1", 412 | ) 413 | go_repository( 414 | name = "org_golang_x_crypto", 415 | importpath = "golang.org/x/crypto", 416 | sum = "h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI=", 417 | version = "v0.0.0-20200622213623-75b288015ac9", 418 | ) 419 | go_repository( 420 | name = "org_golang_x_exp", 421 | importpath = "golang.org/x/exp", 422 | sum = "h1:c2HOrn5iMezYjSlGPncknSEr/8x5LELb/ilJbXi9DEA=", 423 | version = "v0.0.0-20190121172915-509febef88a4", 424 | ) 425 | go_repository( 426 | name = "org_golang_x_lint", 427 | importpath = "golang.org/x/lint", 428 | sum = "h1:XQyxROzUlZH+WIQwySDgnISgOivlhjIEwaQaJEJrrN0=", 429 | version = "v0.0.0-20190313153728-d0100b6bd8b3", 430 | ) 431 | go_repository( 432 | name = "org_golang_x_net", 433 | importpath = "golang.org/x/net", 434 | sum = "h1:4nGaVu0QrbjT/AK2PRLuQfQuh6DJve+pELhqTdAj3x0=", 435 | version = "v0.0.0-20210405180319-a5a99cb37ef4", 436 | ) 437 | go_repository( 438 | name = "org_golang_x_oauth2", 439 | importpath = "golang.org/x/oauth2", 440 | sum = "h1:RerP+noqYHUQ8CMRcPlC2nvTa4dcBIjegkuWdcUDuqg=", 441 | version = "v0.0.0-20211104180415-d3ed0bb246c8", 442 | ) 443 | go_repository( 444 | name = "org_golang_x_sync", 445 | importpath = "golang.org/x/sync", 446 | sum = "h1:DcqTD9SDLc+1P/r1EmRBwnVsrOwW+kk2vWf9n+1sGhs=", 447 | version = "v0.0.0-20201207232520-09787c993a3a", 448 | ) 449 | go_repository( 450 | name = "org_golang_x_sys", 451 | importpath = "golang.org/x/sys", 452 | sum = "h1:JWgyZ1qgdTaF3N3oxC+MdTV7qvEEgHo3otj+HB5CM7Q=", 453 | version = "v0.0.0-20210603081109-ebe580a85c40", 454 | ) 455 | go_repository( 456 | name = "org_golang_x_term", 457 | importpath = "golang.org/x/term", 458 | sum = "h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E=", 459 | version = "v0.0.0-20201126162022-7de9c90e9dd1", 460 | ) 461 | go_repository( 462 | name = "org_golang_x_text", 463 | importpath = "golang.org/x/text", 464 | sum = "h1:i6eZZ+zk0SOf0xgBpEpPD18qWcJda6q1sxt3S0kzyUQ=", 465 | version = "v0.3.5", 466 | ) 467 | go_repository( 468 | name = "org_golang_x_tools", 469 | importpath = "golang.org/x/tools", 470 | sum = "h1:5Beo0mZN8dRzgrMMkDp0jc8YXQKx9DiJ2k1dkvGsn5A=", 471 | version = "v0.0.0-20190524140312-2c0ae7006135", 472 | ) 473 | go_repository( 474 | name = "org_golang_x_xerrors", 475 | importpath = "golang.org/x/xerrors", 476 | sum = "h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=", 477 | version = "v0.0.0-20200804184101-5ec99f83aff1", 478 | ) 479 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= 2 | cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= 3 | cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= 4 | cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= 5 | cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= 6 | cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= 7 | cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= 8 | cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= 9 | cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= 10 | cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= 11 | cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= 12 | cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= 13 | cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= 14 | cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= 15 | cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= 16 | cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= 17 | cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= 18 | cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= 19 | cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= 20 | cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= 21 | cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= 22 | cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= 23 | cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= 24 | cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= 25 | cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= 26 | cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= 27 | cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= 28 | cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= 29 | cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= 30 | cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= 31 | cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= 32 | cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= 33 | dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= 34 | github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= 35 | github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= 36 | github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= 37 | github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= 38 | github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= 39 | github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= 40 | github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= 41 | github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= 42 | github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= 43 | github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= 44 | github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= 45 | github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= 46 | github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= 47 | github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= 48 | github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= 49 | github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= 50 | github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY= 51 | github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= 52 | github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= 53 | github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= 54 | github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= 55 | github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= 56 | github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= 57 | github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= 58 | github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= 59 | github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= 60 | github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= 61 | github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= 62 | github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= 63 | github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= 64 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 65 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= 66 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 67 | github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= 68 | github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= 69 | github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= 70 | github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= 71 | github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= 72 | github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= 73 | github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= 74 | github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= 75 | github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= 76 | github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= 77 | github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= 78 | github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= 79 | github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= 80 | github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= 81 | github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= 82 | github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= 83 | github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= 84 | github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= 85 | github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= 86 | github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= 87 | github.com/golang/glog v1.0.0 h1:nfP3RFugxnNRyKgeWd4oI1nYvXpxrx8ck8ZrcizshdQ= 88 | github.com/golang/glog v1.0.0/go.mod h1:EWib/APOK0SL3dFbYqvxE3UYd8E6s1ouQ7iEp/0LWV4= 89 | github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= 90 | github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= 91 | github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= 92 | github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= 93 | github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= 94 | github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= 95 | github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= 96 | github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= 97 | github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= 98 | github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= 99 | github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 100 | github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 101 | github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 102 | github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= 103 | github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= 104 | github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= 105 | github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= 106 | github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= 107 | github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= 108 | github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= 109 | github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= 110 | github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= 111 | github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= 112 | github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= 113 | github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= 114 | github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= 115 | github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= 116 | github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= 117 | github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= 118 | github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= 119 | github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= 120 | github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= 121 | github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 122 | github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 123 | github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 124 | github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 125 | github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 126 | github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 127 | github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ= 128 | github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 129 | github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= 130 | github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= 131 | github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= 132 | github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= 133 | github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= 134 | github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= 135 | github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= 136 | github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= 137 | github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= 138 | github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= 139 | github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= 140 | github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= 141 | github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= 142 | github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= 143 | github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 h1:Ovs26xHkKqVztRpIrF/92BcuyuQ/YW4NSIpoGtfXNho= 144 | github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= 145 | github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo= 146 | github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= 147 | github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.1 h1:p5m7GOEGXyoq6QWl4/RRMsQ6tWbTpbQmAnkxXgWSprY= 148 | github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.1/go.mod h1:8ZeZajTed/blCOHBbj8Fss8bPHiFKcmJJzuIbUtFCAo= 149 | github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= 150 | github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= 151 | github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= 152 | github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= 153 | github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= 154 | github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= 155 | github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= 156 | github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= 157 | github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= 158 | github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= 159 | github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= 160 | github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= 161 | github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= 162 | github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= 163 | github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= 164 | github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= 165 | github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= 166 | github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= 167 | github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= 168 | github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= 169 | github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= 170 | github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= 171 | github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= 172 | github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= 173 | github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= 174 | github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= 175 | github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 176 | github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 177 | github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= 178 | github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 179 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 180 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 181 | github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= 182 | github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= 183 | github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= 184 | github.com/prometheus/client_golang v1.11.0 h1:HNkLOAEQMIDv/K+04rukrLx6ch7msSRwf3/SASFAGtQ= 185 | github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= 186 | github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= 187 | github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= 188 | github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= 189 | github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M= 190 | github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= 191 | github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= 192 | github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= 193 | github.com/prometheus/common v0.26.0 h1:iMAkS2TDoNWnKM+Kopnx/8tnEStIfpYA0ur0xQzzhMQ= 194 | github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= 195 | github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= 196 | github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= 197 | github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= 198 | github.com/prometheus/procfs v0.6.0 h1:mxy4L2jP6qMonqmq+aTtOx1ifVWUgG/TAmntgbh3xv4= 199 | github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= 200 | github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= 201 | github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= 202 | github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= 203 | github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= 204 | github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= 205 | github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= 206 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 207 | github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 208 | github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= 209 | github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= 210 | github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= 211 | github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= 212 | github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= 213 | github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 214 | github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= 215 | github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= 216 | github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= 217 | go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= 218 | go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= 219 | go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= 220 | go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= 221 | go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= 222 | go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= 223 | golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= 224 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 225 | golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 226 | golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 227 | golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 228 | golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= 229 | golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= 230 | golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= 231 | golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= 232 | golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= 233 | golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= 234 | golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= 235 | golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= 236 | golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= 237 | golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= 238 | golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= 239 | golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= 240 | golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= 241 | golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= 242 | golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= 243 | golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= 244 | golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= 245 | golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= 246 | golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= 247 | golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= 248 | golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= 249 | golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= 250 | golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= 251 | golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= 252 | golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= 253 | golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= 254 | golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= 255 | golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= 256 | golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= 257 | golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= 258 | golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= 259 | golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 260 | golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 261 | golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 262 | golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 263 | golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 264 | golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 265 | golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 266 | golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 267 | golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 268 | golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= 269 | golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 270 | golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 271 | golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 272 | golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 273 | golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 274 | golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 275 | golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 276 | golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 277 | golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 278 | golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 279 | golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= 280 | golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= 281 | golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= 282 | golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= 283 | golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= 284 | golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= 285 | golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= 286 | golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= 287 | golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4 h1:4nGaVu0QrbjT/AK2PRLuQfQuh6DJve+pELhqTdAj3x0= 288 | golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= 289 | golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= 290 | golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= 291 | golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= 292 | golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= 293 | golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= 294 | golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= 295 | golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 296 | golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 297 | golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 298 | golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 299 | golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 300 | golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 301 | golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 302 | golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 303 | golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 304 | golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 305 | golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 306 | golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 307 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 308 | golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 309 | golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 310 | golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 311 | golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 312 | golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 313 | golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 314 | golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 315 | golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 316 | golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 317 | golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 318 | golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 319 | golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 320 | golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 321 | golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 322 | golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 323 | golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 324 | golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 325 | golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 326 | golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 327 | golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 328 | golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 329 | golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 330 | golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 331 | golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 332 | golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 333 | golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 334 | golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 335 | golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 336 | golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 337 | golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 338 | golang.org/x/sys v0.0.0-20210510120138-977fb7262007 h1:gG67DSER+11cZvqIMb8S8bt0vZtiN6xWYARwirrOSfE= 339 | golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 340 | golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40 h1:JWgyZ1qgdTaF3N3oxC+MdTV7qvEEgHo3otj+HB5CM7Q= 341 | golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 342 | golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= 343 | golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 344 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 345 | golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 346 | golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= 347 | golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 348 | golang.org/x/text v0.3.5 h1:i6eZZ+zk0SOf0xgBpEpPD18qWcJda6q1sxt3S0kzyUQ= 349 | golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 350 | golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= 351 | golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= 352 | golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= 353 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 354 | golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 355 | golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= 356 | golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= 357 | golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= 358 | golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= 359 | golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= 360 | golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= 361 | golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= 362 | golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= 363 | golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= 364 | golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= 365 | golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 366 | golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 367 | golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 368 | golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 369 | golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 370 | golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 371 | golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 372 | golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 373 | golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= 374 | golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= 375 | golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= 376 | golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= 377 | golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= 378 | golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= 379 | golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= 380 | golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= 381 | golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= 382 | golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= 383 | golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= 384 | golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= 385 | golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= 386 | golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= 387 | golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= 388 | golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= 389 | golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= 390 | golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= 391 | golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= 392 | golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= 393 | golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 394 | golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 395 | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 396 | golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= 397 | golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 398 | google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= 399 | google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= 400 | google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= 401 | google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= 402 | google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= 403 | google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= 404 | google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= 405 | google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= 406 | google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= 407 | google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= 408 | google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= 409 | google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= 410 | google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= 411 | google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= 412 | google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= 413 | google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= 414 | google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= 415 | google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= 416 | google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= 417 | google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= 418 | google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= 419 | google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= 420 | google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= 421 | google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= 422 | google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= 423 | google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= 424 | google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= 425 | google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= 426 | google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= 427 | google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= 428 | google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= 429 | google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= 430 | google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= 431 | google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= 432 | google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= 433 | google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= 434 | google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= 435 | google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= 436 | google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= 437 | google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= 438 | google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= 439 | google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= 440 | google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= 441 | google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= 442 | google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= 443 | google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= 444 | google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= 445 | google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= 446 | google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= 447 | google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= 448 | google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= 449 | google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= 450 | google.golang.org/genproto v0.0.0-20211129164237-f09f9a12af12 h1:DN5b3HU13J4sMd/QjDx34U6afpaexKTDdop+26pdjdk= 451 | google.golang.org/genproto v0.0.0-20211129164237-f09f9a12af12/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= 452 | google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= 453 | google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= 454 | google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= 455 | google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= 456 | google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= 457 | google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= 458 | google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= 459 | google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= 460 | google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= 461 | google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= 462 | google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= 463 | google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= 464 | google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= 465 | google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= 466 | google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= 467 | google.golang.org/grpc v1.42.0 h1:XT2/MFpuPFsEX2fWh3YQtHkZ+WYZFQRfaUgLZYj/p6A= 468 | google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= 469 | google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= 470 | google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= 471 | google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= 472 | google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= 473 | google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= 474 | google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= 475 | google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= 476 | google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= 477 | google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= 478 | google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= 479 | google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= 480 | google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= 481 | google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ= 482 | google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= 483 | gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= 484 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= 485 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 486 | gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 487 | gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 488 | gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= 489 | gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 490 | gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 491 | gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 492 | gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 493 | gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 494 | gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 495 | gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= 496 | gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= 497 | gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 498 | honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 499 | honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 500 | honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 501 | honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 502 | honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= 503 | honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= 504 | honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= 505 | rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= 506 | rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= 507 | rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= 508 | sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8= 509 | --------------------------------------------------------------------------------