├── .github └── workflows │ ├── docker.yaml │ ├── go.yaml │ ├── release-docker.yaml │ └── release.yaml ├── .gitignore ├── .goreleaser.yaml ├── Makefile ├── api ├── controlplane.pb.go ├── controlplane_grpc.pb.go ├── dataplane.pb.go ├── dataplane_grpc.pb.go ├── monitoring.pb.go ├── monitoring_grpc.pb.go └── protos │ ├── controlplane.proto │ ├── dataplane.proto │ └── monitoring.proto ├── cmd ├── appagent │ ├── app │ │ └── root.go │ └── appagent.go ├── controlplane │ ├── app │ │ └── root.go │ └── controlplane.go ├── dataplane │ ├── app │ │ └── root.go │ └── dataplane.go ├── monitoring │ ├── app │ │ └── root.go │ └── monitoringserver.go └── srnode-agent │ ├── app │ └── root.go │ ├── config.sample.yaml │ └── srnodeagent.go ├── docker ├── appagent.Dockerfile ├── controlplane.Dockerfile ├── dataplane.Dockerfile ├── monitoring.Dockerfile └── srnode-agent.Dockerfile ├── go.mod ├── go.sum ├── pkg ├── appagent │ ├── appagent.go │ ├── config.go │ └── logging.go ├── controlplane │ ├── api.go │ └── config.go ├── dataplane │ ├── api.go │ └── config.go ├── grpc │ └── grpc.go ├── logging │ ├── logfields │ │ └── logfields.go │ └── logging.go ├── monitoring │ ├── api.go │ └── config.go └── srnode │ ├── config.go │ ├── srnode.go │ └── srnode_test.go └── testdata └── appagent ├── test1.txt └── test2.txt /.github/workflows/docker.yaml: -------------------------------------------------------------------------------- 1 | name: docker 2 | on: 3 | push: 4 | branches: 5 | - main 6 | 7 | jobs: 8 | test: 9 | strategy: 10 | matrix: 11 | platform: [ ubuntu-latest ] 12 | runs-on: ${{ matrix.platform }} 13 | steps: 14 | - name: Checkout code 15 | uses: actions/checkout@v2 16 | 17 | - name: Set up Docker Buildx 18 | uses: docker/setup-buildx-action@v1 19 | 20 | - name: Login to GitHub Container Registry 21 | uses: docker/login-action@v1 22 | with: 23 | registry: ghcr.io 24 | username: ${{ github.repository_owner }} 25 | password: ${{ secrets.GITHUB_TOKEN }} 26 | 27 | - name: Build and push appagent 28 | uses: docker/build-push-action@v2 29 | with: 30 | context: ./ 31 | file: docker/appagent.Dockerfile 32 | push: true 33 | tags: | 34 | ghcr.io/${{ github.repository_owner }}/acar/appagent:latest 35 | 36 | - name: Build and push controlplane 37 | uses: docker/build-push-action@v2 38 | with: 39 | context: ./ 40 | file: docker/controlplane.Dockerfile 41 | push: true 42 | tags: | 43 | ghcr.io/${{ github.repository_owner }}/acar/controlplane:latest 44 | 45 | - name: Build and push dataplane 46 | uses: docker/build-push-action@v2 47 | with: 48 | context: ./ 49 | file: docker/dataplane.Dockerfile 50 | push: true 51 | tags: | 52 | ghcr.io/${{ github.repository_owner }}/acar/dataplane:latest 53 | 54 | - name: Build and push monitoring 55 | uses: docker/build-push-action@v2 56 | with: 57 | context: ./ 58 | file: docker/monitoring.Dockerfile 59 | push: true 60 | tags: | 61 | ghcr.io/${{ github.repository_owner }}/acar/monitoring:latest 62 | 63 | - name: Build and push srnode-agent 64 | uses: docker/build-push-action@v2 65 | with: 66 | context: ./ 67 | file: docker/srnode-agent.Dockerfile 68 | push: true 69 | tags: | 70 | ghcr.io/${{ github.repository_owner }}/acar/srnode-agent:latest -------------------------------------------------------------------------------- /.github/workflows/go.yaml: -------------------------------------------------------------------------------- 1 | name: go_test 2 | on: 3 | push: 4 | branches: 5 | - main 6 | pull_request: 7 | branches: 8 | - main 9 | jobs: 10 | test: 11 | strategy: 12 | matrix: 13 | go-version: [ 1.17.x ] 14 | platform: [ ubuntu-20.04, ubuntu-18.04 ] 15 | protoc-version: [ 3.14.0 ] 16 | runs-on: ${{ matrix.platform }} 17 | steps: 18 | - name: Install Go 19 | uses: actions/setup-go@v2 20 | with: 21 | go-version: ${{ matrix.go-version }} 22 | - name: Install protoc 23 | run: | 24 | PROTOC_ZIP=protoc-${{ matrix.protoc-version }}-linux-x86_64.zip 25 | curl -OL https://github.com/protocolbuffers/protobuf/releases/download/v${{ matrix.protoc-version }}/$PROTOC_ZIP 26 | unzip -o $PROTOC_ZIP -d ./ bin/protoc 27 | unzip -o $PROTOC_ZIP -d ./ 'include/*' 28 | rm -f $PROTOC_ZIP 29 | - name: Checkout code 30 | uses: actions/checkout@v2 31 | - name: using cache 32 | uses: actions/cache@v2 33 | with: 34 | path: ~/go/pkg/mod 35 | key: ${{ runner.os }}-go-${{ matrix.go-version }}-${{ hashFiles('**/go.sum') }} 36 | restore-keys: | 37 | ${{ runner.os }}-go- 38 | - name: go test & vet 39 | run: make sudo-test 40 | - name: Check go.mod and go.sum is up-to-date 41 | run: | 42 | go mod tidy 43 | if [[ $(git diff --name-only | grep -E "go\.(sum|mod)" || echo -n "") != "" ]]; then \ 44 | echo "go.sum or go.mod is not updated."; \ 45 | exit 1; \ 46 | fi 47 | - name: Check .pb.go is up-to-date 48 | run: | 49 | make pb PROTOC=./bin/protoc 50 | if [[ $(git diff --name-only) != "" ]]; then \ 51 | echo "*.pb.go are not updated."; \ 52 | exit 1; \ 53 | fi 54 | -------------------------------------------------------------------------------- /.github/workflows/release-docker.yaml: -------------------------------------------------------------------------------- 1 | name: release-docker 2 | on: 3 | push: 4 | tags: 5 | - '*' 6 | 7 | jobs: 8 | test: 9 | strategy: 10 | matrix: 11 | go-version: [ 1.17.x ] 12 | platform: [ ubuntu-latest ] 13 | runs-on: ${{ matrix.platform }} 14 | steps: 15 | - name: Checkout code 16 | uses: actions/checkout@v2 17 | 18 | - name: Set up Docker Buildx 19 | uses: docker/setup-buildx-action@v1 20 | 21 | - name: Login to GitHub Container Registry 22 | uses: docker/login-action@v1 23 | with: 24 | registry: ghcr.io 25 | username: ${{ github.repository_owner }} 26 | password: ${{ secrets.GITHUB_TOKEN }} 27 | 28 | - name: Prepare for image tag 29 | id: prep 30 | run: | 31 | VERSION=${GITHUB_REF#refs/tags/} 32 | echo ::set-output name=version::${VERSION} 33 | 34 | - name: Build and push appagent 35 | uses: docker/build-push-action@v2 36 | with: 37 | context: ./ 38 | file: docker/appagent.Dockerfile 39 | push: true 40 | tags: | 41 | ghcr.io/${{ github.repository_owner }}/acar/appagent:stable 42 | ghcr.io/${{ github.repository_owner }}/acar/appagent:${{ steps.prep.outputs.version }} 43 | 44 | - name: Build and push controlplane 45 | uses: docker/build-push-action@v2 46 | with: 47 | context: ./ 48 | file: docker/controlplane.Dockerfile 49 | push: true 50 | tags: | 51 | ghcr.io/${{ github.repository_owner }}/acar/controlplane:stable 52 | ghcr.io/${{ github.repository_owner }}/acar/controlplane:${{ steps.prep.outputs.version }} 53 | 54 | - name: Build and push dataplane 55 | uses: docker/build-push-action@v2 56 | with: 57 | context: ./ 58 | file: docker/dataplane.Dockerfile 59 | push: true 60 | tags: | 61 | ghcr.io/${{ github.repository_owner }}/acar/dataplane:stable 62 | ghcr.io/${{ github.repository_owner }}/acar/dataplane:${{ steps.prep.outputs.version }} 63 | 64 | - name: Build and push monitoring 65 | uses: docker/build-push-action@v2 66 | with: 67 | context: ./ 68 | file: docker/monitoring.Dockerfile 69 | push: true 70 | tags: | 71 | ghcr.io/${{ github.repository_owner }}/acar/monitoring:stable 72 | ghcr.io/${{ github.repository_owner }}/acar/monitoring:${{ steps.prep.outputs.version }} 73 | 74 | - name: Build and push srnode-agent 75 | uses: docker/build-push-action@v2 76 | with: 77 | context: ./ 78 | file: docker/srnode-agent.Dockerfile 79 | push: true 80 | tags: | 81 | ghcr.io/${{ github.repository_owner }}/acar/srnode-agent:stable 82 | ghcr.io/${{ github.repository_owner }}/acar/srnode-agent:${{ steps.prep.outputs.version }} 83 | -------------------------------------------------------------------------------- /.github/workflows/release.yaml: -------------------------------------------------------------------------------- 1 | name: release 2 | on: 3 | push: 4 | tags: 5 | - '*' 6 | jobs: 7 | test: 8 | strategy: 9 | matrix: 10 | go-version: [ 1.17.x ] 11 | platform: [ ubuntu-latest ] 12 | runs-on: ${{ matrix.platform }} 13 | steps: 14 | - name: Install Go 15 | uses: actions/setup-go@v2 16 | with: 17 | go-version: ${{ matrix.go-version }} 18 | 19 | - name: Checkout code 20 | uses: actions/checkout@v2 21 | 22 | - name: Run GoReleaser 23 | uses: goreleaser/goreleaser-action@v2 24 | with: 25 | version: latest 26 | args: release --rm-dist 27 | env: 28 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by .ignore support plugin (hsz.mobi) 2 | ### Go template 3 | # Binaries for programs and plugins 4 | *.exe 5 | *.exe~ 6 | *.dll 7 | *.so 8 | *.dylib 9 | 10 | # Test binary, built with `go test -c` 11 | *.test 12 | 13 | # Output of the go coverage tool, specifically when used with LiteIDE 14 | *.out 15 | 16 | # Dependency directories (remove the comment below to include it) 17 | # vendor/ 18 | 19 | .idea 20 | 21 | -------------------------------------------------------------------------------- /.goreleaser.yaml: -------------------------------------------------------------------------------- 1 | builds: 2 | - id: "acar-appagent" 3 | dir: ./cmd/appagent 4 | binary: appagent 5 | goos: 6 | - linux 7 | goarch: 8 | - amd64 9 | - arm 10 | - arm64 11 | env: 12 | - CGO_ENABLED=0 13 | 14 | - id: "acar-controlplane" 15 | dir: ./cmd/controlplane 16 | binary: controlplane 17 | goos: 18 | - linux 19 | goarch: 20 | - amd64 21 | - arm 22 | - arm64 23 | env: 24 | - CGO_ENABLED=0 25 | 26 | - id: "acar-dataplane" 27 | dir: ./cmd/dataplane 28 | binary: dataplane 29 | goos: 30 | - linux 31 | goarch: 32 | - amd64 33 | - arm 34 | - arm64 35 | env: 36 | - CGO_ENABLED=0 37 | 38 | - id: "acar-monitoring" 39 | dir: ./cmd/monitoring 40 | binary: monitoring 41 | goos: 42 | - linux 43 | goarch: 44 | - amd64 45 | - arm 46 | - arm64 47 | env: 48 | - CGO_ENABLED=0 49 | 50 | - id: "acar-srnode-agent" 51 | dir: ./cmd/srnode-agent 52 | binary: srnode-agent 53 | goos: 54 | - linux 55 | goarch: 56 | - amd64 57 | - arm 58 | - arm64 59 | env: 60 | - CGO_ENABLED=0 61 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | SHELL:=/bin/bash 2 | 3 | GO=go 4 | PROTOC=protoc 5 | 6 | GO_VET_OPTS=-v 7 | GO_TEST_OPTS=-v -race 8 | RM_OPTS=-f 9 | 10 | PROTO_SRCS=$(wildcard ./api/protos/*.proto) 11 | PROTO_TYPES_SRCS=$(wildcard ./api/protos/*/*.proto) 12 | GO_PB_DIR=./api/ 13 | GO_TYPES_PB_DIR=./api/types/ 14 | GO_PB_SRCS=$(addprefix $(GO_PB_DIR),$(patsubst %.proto,%.pb.go,$(notdir $(PROTO_SRCS)))) 15 | GO_TYPES_PB_SRCS=$(addprefix $(GO_TYPES_PB_DIR),$(patsubst %.proto,%.pb.go,$(notdir $(PROTO_TYPES_SRCS)))) 16 | 17 | CMD_DIRS:=$(wildcard cmd/*) 18 | CMDS:=$(subst cmd,bin,$(CMD_DIRS)) 19 | 20 | 21 | %.pb.go: $(PROTO_SRCS) $(PROTO_TYPES_SRCS) 22 | @$(PROTOC) \ 23 | --go_out=./api/ \ 24 | --go_opt=module=github.com/chez-shanpu/acar/api \ 25 | --go-grpc_out=./api/ \ 26 | --go-grpc_opt=module=github.com/chez-shanpu/acar/api \ 27 | -I ./api/protos/ \ 28 | $^ 29 | 30 | .SECONDEXPANSION: 31 | #bin/%: $(wildcard cmd/*/*.go) $(wildcard cmd/*/*/*.go) $(wildcard pkg/*/*.go) go.mod bin 32 | bin/%: 33 | $(GO) build $(GO_BUILD_OPT) -o $@ ./cmd/$* 34 | 35 | 36 | .PHONY: build 37 | build: $(CMDS) 38 | 39 | .PHONY: pb 40 | pb: $(GO_PB_SRCS) $(GO_TYPES_PB_SRCS) 41 | 42 | .PHONY: vet 43 | vet: 44 | $(GO) vet $(GO_VET_OPTS) ./... 45 | 46 | .PHONY: test 47 | test: vet 48 | $(GO) test $(GO_TEST_OPTS) ./... 49 | 50 | .PHONY: sudo-test 51 | sudo-test: test 52 | sudo $(GO) test $(GO_TEST_OPTS) ./... 53 | 54 | .PHONY: clean 55 | clean: 56 | -$(GO) clean 57 | -rm $(RM_OPTS) bin/* 58 | 59 | .PHONY: all 60 | all: sudo-test build 61 | 62 | .DEFAULT_GOAL=all 63 | -------------------------------------------------------------------------------- /api/controlplane.pb.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-go. DO NOT EDIT. 2 | // versions: 3 | // protoc-gen-go v1.26.0 4 | // protoc v3.17.3 5 | // source: controlplane.proto 6 | 7 | package api 8 | 9 | import ( 10 | protoreflect "google.golang.org/protobuf/reflect/protoreflect" 11 | protoimpl "google.golang.org/protobuf/runtime/protoimpl" 12 | timestamppb "google.golang.org/protobuf/types/known/timestamppb" 13 | reflect "reflect" 14 | sync "sync" 15 | ) 16 | 17 | const ( 18 | // Verify that this generated code is sufficiently up-to-date. 19 | _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) 20 | // Verify that runtime/protoimpl is sufficiently up-to-date. 21 | _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) 22 | ) 23 | 24 | type RegisterSRPolicyRequest struct { 25 | state protoimpl.MessageState 26 | sizeCache protoimpl.SizeCache 27 | unknownFields protoimpl.UnknownFields 28 | 29 | AppInfo *AppInfo `protobuf:"bytes,1,opt,name=app_info,json=appInfo,proto3" json:"app_info,omitempty"` 30 | } 31 | 32 | func (x *RegisterSRPolicyRequest) Reset() { 33 | *x = RegisterSRPolicyRequest{} 34 | if protoimpl.UnsafeEnabled { 35 | mi := &file_controlplane_proto_msgTypes[0] 36 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 37 | ms.StoreMessageInfo(mi) 38 | } 39 | } 40 | 41 | func (x *RegisterSRPolicyRequest) String() string { 42 | return protoimpl.X.MessageStringOf(x) 43 | } 44 | 45 | func (*RegisterSRPolicyRequest) ProtoMessage() {} 46 | 47 | func (x *RegisterSRPolicyRequest) ProtoReflect() protoreflect.Message { 48 | mi := &file_controlplane_proto_msgTypes[0] 49 | if protoimpl.UnsafeEnabled && x != nil { 50 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 51 | if ms.LoadMessageInfo() == nil { 52 | ms.StoreMessageInfo(mi) 53 | } 54 | return ms 55 | } 56 | return mi.MessageOf(x) 57 | } 58 | 59 | // Deprecated: Use RegisterSRPolicyRequest.ProtoReflect.Descriptor instead. 60 | func (*RegisterSRPolicyRequest) Descriptor() ([]byte, []int) { 61 | return file_controlplane_proto_rawDescGZIP(), []int{0} 62 | } 63 | 64 | func (x *RegisterSRPolicyRequest) GetAppInfo() *AppInfo { 65 | if x != nil { 66 | return x.AppInfo 67 | } 68 | return nil 69 | } 70 | 71 | type RegisterSRPolicyResponse struct { 72 | state protoimpl.MessageState 73 | sizeCache protoimpl.SizeCache 74 | unknownFields protoimpl.UnknownFields 75 | 76 | Time *timestamppb.Timestamp `protobuf:"bytes,1,opt,name=time,proto3" json:"time,omitempty"` 77 | } 78 | 79 | func (x *RegisterSRPolicyResponse) Reset() { 80 | *x = RegisterSRPolicyResponse{} 81 | if protoimpl.UnsafeEnabled { 82 | mi := &file_controlplane_proto_msgTypes[1] 83 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 84 | ms.StoreMessageInfo(mi) 85 | } 86 | } 87 | 88 | func (x *RegisterSRPolicyResponse) String() string { 89 | return protoimpl.X.MessageStringOf(x) 90 | } 91 | 92 | func (*RegisterSRPolicyResponse) ProtoMessage() {} 93 | 94 | func (x *RegisterSRPolicyResponse) ProtoReflect() protoreflect.Message { 95 | mi := &file_controlplane_proto_msgTypes[1] 96 | if protoimpl.UnsafeEnabled && x != nil { 97 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 98 | if ms.LoadMessageInfo() == nil { 99 | ms.StoreMessageInfo(mi) 100 | } 101 | return ms 102 | } 103 | return mi.MessageOf(x) 104 | } 105 | 106 | // Deprecated: Use RegisterSRPolicyResponse.ProtoReflect.Descriptor instead. 107 | func (*RegisterSRPolicyResponse) Descriptor() ([]byte, []int) { 108 | return file_controlplane_proto_rawDescGZIP(), []int{1} 109 | } 110 | 111 | func (x *RegisterSRPolicyResponse) GetTime() *timestamppb.Timestamp { 112 | if x != nil { 113 | return x.Time 114 | } 115 | return nil 116 | } 117 | 118 | type AppInfo struct { 119 | state protoimpl.MessageState 120 | sizeCache protoimpl.SizeCache 121 | unknownFields protoimpl.UnknownFields 122 | 123 | AppName string `protobuf:"bytes,1,opt,name=app_name,json=appName,proto3" json:"app_name,omitempty"` 124 | SrcAddr string `protobuf:"bytes,2,opt,name=src_addr,json=srcAddr,proto3" json:"src_addr,omitempty"` 125 | DstAddr string `protobuf:"bytes,3,opt,name=dst_addr,json=dstAddr,proto3" json:"dst_addr,omitempty"` 126 | SidList []string `protobuf:"bytes,4,rep,name=sid_list,json=sidList,proto3" json:"sid_list,omitempty"` 127 | } 128 | 129 | func (x *AppInfo) Reset() { 130 | *x = AppInfo{} 131 | if protoimpl.UnsafeEnabled { 132 | mi := &file_controlplane_proto_msgTypes[2] 133 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 134 | ms.StoreMessageInfo(mi) 135 | } 136 | } 137 | 138 | func (x *AppInfo) String() string { 139 | return protoimpl.X.MessageStringOf(x) 140 | } 141 | 142 | func (*AppInfo) ProtoMessage() {} 143 | 144 | func (x *AppInfo) ProtoReflect() protoreflect.Message { 145 | mi := &file_controlplane_proto_msgTypes[2] 146 | if protoimpl.UnsafeEnabled && x != nil { 147 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 148 | if ms.LoadMessageInfo() == nil { 149 | ms.StoreMessageInfo(mi) 150 | } 151 | return ms 152 | } 153 | return mi.MessageOf(x) 154 | } 155 | 156 | // Deprecated: Use AppInfo.ProtoReflect.Descriptor instead. 157 | func (*AppInfo) Descriptor() ([]byte, []int) { 158 | return file_controlplane_proto_rawDescGZIP(), []int{2} 159 | } 160 | 161 | func (x *AppInfo) GetAppName() string { 162 | if x != nil { 163 | return x.AppName 164 | } 165 | return "" 166 | } 167 | 168 | func (x *AppInfo) GetSrcAddr() string { 169 | if x != nil { 170 | return x.SrcAddr 171 | } 172 | return "" 173 | } 174 | 175 | func (x *AppInfo) GetDstAddr() string { 176 | if x != nil { 177 | return x.DstAddr 178 | } 179 | return "" 180 | } 181 | 182 | func (x *AppInfo) GetSidList() []string { 183 | if x != nil { 184 | return x.SidList 185 | } 186 | return nil 187 | } 188 | 189 | var File_controlplane_proto protoreflect.FileDescriptor 190 | 191 | var file_controlplane_proto_rawDesc = []byte{ 192 | 0x0a, 0x12, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x70, 193 | 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x04, 0x61, 0x63, 0x61, 0x72, 0x1a, 0x1f, 0x67, 0x6f, 0x6f, 0x67, 194 | 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x74, 0x69, 0x6d, 0x65, 195 | 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x43, 0x0a, 0x17, 0x52, 196 | 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x53, 0x52, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 197 | 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x28, 0x0a, 0x08, 0x61, 0x70, 0x70, 0x5f, 0x69, 0x6e, 198 | 0x66, 0x6f, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x61, 0x63, 0x61, 0x72, 0x2e, 199 | 0x41, 0x70, 0x70, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x07, 0x61, 0x70, 0x70, 0x49, 0x6e, 0x66, 0x6f, 200 | 0x22, 0x4a, 0x0a, 0x18, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x53, 0x52, 0x50, 0x6f, 201 | 0x6c, 0x69, 0x63, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2e, 0x0a, 0x04, 202 | 0x74, 0x69, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 203 | 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 204 | 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x04, 0x74, 0x69, 0x6d, 0x65, 0x22, 0x75, 0x0a, 0x07, 205 | 0x41, 0x70, 0x70, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x19, 0x0a, 0x08, 0x61, 0x70, 0x70, 0x5f, 0x6e, 206 | 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x70, 0x70, 0x4e, 0x61, 207 | 0x6d, 0x65, 0x12, 0x19, 0x0a, 0x08, 0x73, 0x72, 0x63, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x18, 0x02, 208 | 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x73, 0x72, 0x63, 0x41, 0x64, 0x64, 0x72, 0x12, 0x19, 0x0a, 209 | 0x08, 0x64, 0x73, 0x74, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 210 | 0x07, 0x64, 0x73, 0x74, 0x41, 0x64, 0x64, 0x72, 0x12, 0x19, 0x0a, 0x08, 0x73, 0x69, 0x64, 0x5f, 211 | 0x6c, 0x69, 0x73, 0x74, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x73, 0x69, 0x64, 0x4c, 212 | 0x69, 0x73, 0x74, 0x32, 0x61, 0x0a, 0x0c, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x50, 0x6c, 213 | 0x61, 0x6e, 0x65, 0x12, 0x51, 0x0a, 0x10, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x53, 214 | 0x52, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x1d, 0x2e, 0x61, 0x63, 0x61, 0x72, 0x2e, 0x52, 215 | 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x53, 0x52, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 216 | 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x61, 0x63, 0x61, 0x72, 0x2e, 0x52, 0x65, 217 | 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x53, 0x52, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x65, 218 | 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x21, 0x5a, 0x1f, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 219 | 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x68, 0x65, 0x7a, 0x2d, 0x73, 0x68, 0x61, 0x6e, 0x70, 0x75, 220 | 0x2f, 0x61, 0x63, 0x61, 0x72, 0x2f, 0x61, 0x70, 0x69, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 221 | 0x33, 222 | } 223 | 224 | var ( 225 | file_controlplane_proto_rawDescOnce sync.Once 226 | file_controlplane_proto_rawDescData = file_controlplane_proto_rawDesc 227 | ) 228 | 229 | func file_controlplane_proto_rawDescGZIP() []byte { 230 | file_controlplane_proto_rawDescOnce.Do(func() { 231 | file_controlplane_proto_rawDescData = protoimpl.X.CompressGZIP(file_controlplane_proto_rawDescData) 232 | }) 233 | return file_controlplane_proto_rawDescData 234 | } 235 | 236 | var file_controlplane_proto_msgTypes = make([]protoimpl.MessageInfo, 3) 237 | var file_controlplane_proto_goTypes = []interface{}{ 238 | (*RegisterSRPolicyRequest)(nil), // 0: acar.RegisterSRPolicyRequest 239 | (*RegisterSRPolicyResponse)(nil), // 1: acar.RegisterSRPolicyResponse 240 | (*AppInfo)(nil), // 2: acar.AppInfo 241 | (*timestamppb.Timestamp)(nil), // 3: google.protobuf.Timestamp 242 | } 243 | var file_controlplane_proto_depIdxs = []int32{ 244 | 2, // 0: acar.RegisterSRPolicyRequest.app_info:type_name -> acar.AppInfo 245 | 3, // 1: acar.RegisterSRPolicyResponse.time:type_name -> google.protobuf.Timestamp 246 | 0, // 2: acar.ControlPlane.RegisterSRPolicy:input_type -> acar.RegisterSRPolicyRequest 247 | 1, // 3: acar.ControlPlane.RegisterSRPolicy:output_type -> acar.RegisterSRPolicyResponse 248 | 3, // [3:4] is the sub-list for method output_type 249 | 2, // [2:3] is the sub-list for method input_type 250 | 2, // [2:2] is the sub-list for extension type_name 251 | 2, // [2:2] is the sub-list for extension extendee 252 | 0, // [0:2] is the sub-list for field type_name 253 | } 254 | 255 | func init() { file_controlplane_proto_init() } 256 | func file_controlplane_proto_init() { 257 | if File_controlplane_proto != nil { 258 | return 259 | } 260 | if !protoimpl.UnsafeEnabled { 261 | file_controlplane_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { 262 | switch v := v.(*RegisterSRPolicyRequest); i { 263 | case 0: 264 | return &v.state 265 | case 1: 266 | return &v.sizeCache 267 | case 2: 268 | return &v.unknownFields 269 | default: 270 | return nil 271 | } 272 | } 273 | file_controlplane_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { 274 | switch v := v.(*RegisterSRPolicyResponse); i { 275 | case 0: 276 | return &v.state 277 | case 1: 278 | return &v.sizeCache 279 | case 2: 280 | return &v.unknownFields 281 | default: 282 | return nil 283 | } 284 | } 285 | file_controlplane_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { 286 | switch v := v.(*AppInfo); i { 287 | case 0: 288 | return &v.state 289 | case 1: 290 | return &v.sizeCache 291 | case 2: 292 | return &v.unknownFields 293 | default: 294 | return nil 295 | } 296 | } 297 | } 298 | type x struct{} 299 | out := protoimpl.TypeBuilder{ 300 | File: protoimpl.DescBuilder{ 301 | GoPackagePath: reflect.TypeOf(x{}).PkgPath(), 302 | RawDescriptor: file_controlplane_proto_rawDesc, 303 | NumEnums: 0, 304 | NumMessages: 3, 305 | NumExtensions: 0, 306 | NumServices: 1, 307 | }, 308 | GoTypes: file_controlplane_proto_goTypes, 309 | DependencyIndexes: file_controlplane_proto_depIdxs, 310 | MessageInfos: file_controlplane_proto_msgTypes, 311 | }.Build() 312 | File_controlplane_proto = out.File 313 | file_controlplane_proto_rawDesc = nil 314 | file_controlplane_proto_goTypes = nil 315 | file_controlplane_proto_depIdxs = nil 316 | } 317 | -------------------------------------------------------------------------------- /api/controlplane_grpc.pb.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-go-grpc. DO NOT EDIT. 2 | 3 | package api 4 | 5 | import ( 6 | context "context" 7 | grpc "google.golang.org/grpc" 8 | codes "google.golang.org/grpc/codes" 9 | status "google.golang.org/grpc/status" 10 | ) 11 | 12 | // This is a compile-time assertion to ensure that this generated file 13 | // is compatible with the grpc package it is being compiled against. 14 | // Requires gRPC-Go v1.32.0 or later. 15 | const _ = grpc.SupportPackageIsVersion7 16 | 17 | // ControlPlaneClient is the client API for ControlPlane service. 18 | // 19 | // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. 20 | type ControlPlaneClient interface { 21 | RegisterSRPolicy(ctx context.Context, in *RegisterSRPolicyRequest, opts ...grpc.CallOption) (*RegisterSRPolicyResponse, error) 22 | } 23 | 24 | type controlPlaneClient struct { 25 | cc grpc.ClientConnInterface 26 | } 27 | 28 | func NewControlPlaneClient(cc grpc.ClientConnInterface) ControlPlaneClient { 29 | return &controlPlaneClient{cc} 30 | } 31 | 32 | func (c *controlPlaneClient) RegisterSRPolicy(ctx context.Context, in *RegisterSRPolicyRequest, opts ...grpc.CallOption) (*RegisterSRPolicyResponse, error) { 33 | out := new(RegisterSRPolicyResponse) 34 | err := c.cc.Invoke(ctx, "/acar.ControlPlane/RegisterSRPolicy", in, out, opts...) 35 | if err != nil { 36 | return nil, err 37 | } 38 | return out, nil 39 | } 40 | 41 | // ControlPlaneServer is the server API for ControlPlane service. 42 | // All implementations must embed UnimplementedControlPlaneServer 43 | // for forward compatibility 44 | type ControlPlaneServer interface { 45 | RegisterSRPolicy(context.Context, *RegisterSRPolicyRequest) (*RegisterSRPolicyResponse, error) 46 | mustEmbedUnimplementedControlPlaneServer() 47 | } 48 | 49 | // UnimplementedControlPlaneServer must be embedded to have forward compatible implementations. 50 | type UnimplementedControlPlaneServer struct { 51 | } 52 | 53 | func (UnimplementedControlPlaneServer) RegisterSRPolicy(context.Context, *RegisterSRPolicyRequest) (*RegisterSRPolicyResponse, error) { 54 | return nil, status.Errorf(codes.Unimplemented, "method RegisterSRPolicy not implemented") 55 | } 56 | func (UnimplementedControlPlaneServer) mustEmbedUnimplementedControlPlaneServer() {} 57 | 58 | // UnsafeControlPlaneServer may be embedded to opt out of forward compatibility for this service. 59 | // Use of this interface is not recommended, as added methods to ControlPlaneServer will 60 | // result in compilation errors. 61 | type UnsafeControlPlaneServer interface { 62 | mustEmbedUnimplementedControlPlaneServer() 63 | } 64 | 65 | func RegisterControlPlaneServer(s grpc.ServiceRegistrar, srv ControlPlaneServer) { 66 | s.RegisterService(&ControlPlane_ServiceDesc, srv) 67 | } 68 | 69 | func _ControlPlane_RegisterSRPolicy_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { 70 | in := new(RegisterSRPolicyRequest) 71 | if err := dec(in); err != nil { 72 | return nil, err 73 | } 74 | if interceptor == nil { 75 | return srv.(ControlPlaneServer).RegisterSRPolicy(ctx, in) 76 | } 77 | info := &grpc.UnaryServerInfo{ 78 | Server: srv, 79 | FullMethod: "/acar.ControlPlane/RegisterSRPolicy", 80 | } 81 | handler := func(ctx context.Context, req interface{}) (interface{}, error) { 82 | return srv.(ControlPlaneServer).RegisterSRPolicy(ctx, req.(*RegisterSRPolicyRequest)) 83 | } 84 | return interceptor(ctx, in, info, handler) 85 | } 86 | 87 | // ControlPlane_ServiceDesc is the grpc.ServiceDesc for ControlPlane service. 88 | // It's only intended for direct use with grpc.RegisterService, 89 | // and not to be introspected or modified (even as a copy) 90 | var ControlPlane_ServiceDesc = grpc.ServiceDesc{ 91 | ServiceName: "acar.ControlPlane", 92 | HandlerType: (*ControlPlaneServer)(nil), 93 | Methods: []grpc.MethodDesc{ 94 | { 95 | MethodName: "RegisterSRPolicy", 96 | Handler: _ControlPlane_RegisterSRPolicy_Handler, 97 | }, 98 | }, 99 | Streams: []grpc.StreamDesc{}, 100 | Metadata: "controlplane.proto", 101 | } 102 | -------------------------------------------------------------------------------- /api/dataplane.pb.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-go. DO NOT EDIT. 2 | // versions: 3 | // protoc-gen-go v1.26.0 4 | // protoc v3.17.3 5 | // source: dataplane.proto 6 | 7 | package api 8 | 9 | import ( 10 | protoreflect "google.golang.org/protobuf/reflect/protoreflect" 11 | protoimpl "google.golang.org/protobuf/runtime/protoimpl" 12 | timestamppb "google.golang.org/protobuf/types/known/timestamppb" 13 | reflect "reflect" 14 | sync "sync" 15 | ) 16 | 17 | const ( 18 | // Verify that this generated code is sufficiently up-to-date. 19 | _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) 20 | // Verify that runtime/protoimpl is sufficiently up-to-date. 21 | _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) 22 | ) 23 | 24 | type ApplySRPolicyRequest struct { 25 | state protoimpl.MessageState 26 | sizeCache protoimpl.SizeCache 27 | unknownFields protoimpl.UnknownFields 28 | 29 | SrInfo *SRInfo `protobuf:"bytes,1,opt,name=sr_info,json=srInfo,proto3" json:"sr_info,omitempty"` 30 | } 31 | 32 | func (x *ApplySRPolicyRequest) Reset() { 33 | *x = ApplySRPolicyRequest{} 34 | if protoimpl.UnsafeEnabled { 35 | mi := &file_dataplane_proto_msgTypes[0] 36 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 37 | ms.StoreMessageInfo(mi) 38 | } 39 | } 40 | 41 | func (x *ApplySRPolicyRequest) String() string { 42 | return protoimpl.X.MessageStringOf(x) 43 | } 44 | 45 | func (*ApplySRPolicyRequest) ProtoMessage() {} 46 | 47 | func (x *ApplySRPolicyRequest) ProtoReflect() protoreflect.Message { 48 | mi := &file_dataplane_proto_msgTypes[0] 49 | if protoimpl.UnsafeEnabled && x != nil { 50 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 51 | if ms.LoadMessageInfo() == nil { 52 | ms.StoreMessageInfo(mi) 53 | } 54 | return ms 55 | } 56 | return mi.MessageOf(x) 57 | } 58 | 59 | // Deprecated: Use ApplySRPolicyRequest.ProtoReflect.Descriptor instead. 60 | func (*ApplySRPolicyRequest) Descriptor() ([]byte, []int) { 61 | return file_dataplane_proto_rawDescGZIP(), []int{0} 62 | } 63 | 64 | func (x *ApplySRPolicyRequest) GetSrInfo() *SRInfo { 65 | if x != nil { 66 | return x.SrInfo 67 | } 68 | return nil 69 | } 70 | 71 | type ApplySRPolicyResponse struct { 72 | state protoimpl.MessageState 73 | sizeCache protoimpl.SizeCache 74 | unknownFields protoimpl.UnknownFields 75 | 76 | Time *timestamppb.Timestamp `protobuf:"bytes,1,opt,name=time,proto3" json:"time,omitempty"` 77 | } 78 | 79 | func (x *ApplySRPolicyResponse) Reset() { 80 | *x = ApplySRPolicyResponse{} 81 | if protoimpl.UnsafeEnabled { 82 | mi := &file_dataplane_proto_msgTypes[1] 83 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 84 | ms.StoreMessageInfo(mi) 85 | } 86 | } 87 | 88 | func (x *ApplySRPolicyResponse) String() string { 89 | return protoimpl.X.MessageStringOf(x) 90 | } 91 | 92 | func (*ApplySRPolicyResponse) ProtoMessage() {} 93 | 94 | func (x *ApplySRPolicyResponse) ProtoReflect() protoreflect.Message { 95 | mi := &file_dataplane_proto_msgTypes[1] 96 | if protoimpl.UnsafeEnabled && x != nil { 97 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 98 | if ms.LoadMessageInfo() == nil { 99 | ms.StoreMessageInfo(mi) 100 | } 101 | return ms 102 | } 103 | return mi.MessageOf(x) 104 | } 105 | 106 | // Deprecated: Use ApplySRPolicyResponse.ProtoReflect.Descriptor instead. 107 | func (*ApplySRPolicyResponse) Descriptor() ([]byte, []int) { 108 | return file_dataplane_proto_rawDescGZIP(), []int{1} 109 | } 110 | 111 | func (x *ApplySRPolicyResponse) GetTime() *timestamppb.Timestamp { 112 | if x != nil { 113 | return x.Time 114 | } 115 | return nil 116 | } 117 | 118 | type SRInfo struct { 119 | state protoimpl.MessageState 120 | sizeCache protoimpl.SizeCache 121 | unknownFields protoimpl.UnknownFields 122 | 123 | SrcAddr string `protobuf:"bytes,1,opt,name=src_addr,json=srcAddr,proto3" json:"src_addr,omitempty"` 124 | DstAddr string `protobuf:"bytes,2,opt,name=dst_addr,json=dstAddr,proto3" json:"dst_addr,omitempty"` 125 | SidList []string `protobuf:"bytes,3,rep,name=sid_list,json=sidList,proto3" json:"sid_list,omitempty"` 126 | } 127 | 128 | func (x *SRInfo) Reset() { 129 | *x = SRInfo{} 130 | if protoimpl.UnsafeEnabled { 131 | mi := &file_dataplane_proto_msgTypes[2] 132 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 133 | ms.StoreMessageInfo(mi) 134 | } 135 | } 136 | 137 | func (x *SRInfo) String() string { 138 | return protoimpl.X.MessageStringOf(x) 139 | } 140 | 141 | func (*SRInfo) ProtoMessage() {} 142 | 143 | func (x *SRInfo) ProtoReflect() protoreflect.Message { 144 | mi := &file_dataplane_proto_msgTypes[2] 145 | if protoimpl.UnsafeEnabled && x != nil { 146 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 147 | if ms.LoadMessageInfo() == nil { 148 | ms.StoreMessageInfo(mi) 149 | } 150 | return ms 151 | } 152 | return mi.MessageOf(x) 153 | } 154 | 155 | // Deprecated: Use SRInfo.ProtoReflect.Descriptor instead. 156 | func (*SRInfo) Descriptor() ([]byte, []int) { 157 | return file_dataplane_proto_rawDescGZIP(), []int{2} 158 | } 159 | 160 | func (x *SRInfo) GetSrcAddr() string { 161 | if x != nil { 162 | return x.SrcAddr 163 | } 164 | return "" 165 | } 166 | 167 | func (x *SRInfo) GetDstAddr() string { 168 | if x != nil { 169 | return x.DstAddr 170 | } 171 | return "" 172 | } 173 | 174 | func (x *SRInfo) GetSidList() []string { 175 | if x != nil { 176 | return x.SidList 177 | } 178 | return nil 179 | } 180 | 181 | var File_dataplane_proto protoreflect.FileDescriptor 182 | 183 | var file_dataplane_proto_rawDesc = []byte{ 184 | 0x0a, 0x0f, 0x64, 0x61, 0x74, 0x61, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 185 | 0x6f, 0x12, 0x04, 0x61, 0x63, 0x61, 0x72, 0x1a, 0x1f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 186 | 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 187 | 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x3d, 0x0a, 0x14, 0x41, 0x70, 0x70, 0x6c, 188 | 0x79, 0x53, 0x52, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 189 | 0x12, 0x25, 0x0a, 0x07, 0x73, 0x72, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x01, 0x20, 0x01, 0x28, 190 | 0x0b, 0x32, 0x0c, 0x2e, 0x61, 0x63, 0x61, 0x72, 0x2e, 0x53, 0x52, 0x49, 0x6e, 0x66, 0x6f, 0x52, 191 | 0x06, 0x73, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x22, 0x47, 0x0a, 0x15, 0x41, 0x70, 0x70, 0x6c, 0x79, 192 | 0x53, 0x52, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 193 | 0x12, 0x2e, 0x0a, 0x04, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 194 | 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 195 | 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x04, 0x74, 0x69, 0x6d, 0x65, 196 | 0x22, 0x59, 0x0a, 0x06, 0x53, 0x52, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x19, 0x0a, 0x08, 0x73, 0x72, 197 | 0x63, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x73, 0x72, 198 | 0x63, 0x41, 0x64, 0x64, 0x72, 0x12, 0x19, 0x0a, 0x08, 0x64, 0x73, 0x74, 0x5f, 0x61, 0x64, 0x64, 199 | 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x64, 0x73, 0x74, 0x41, 0x64, 0x64, 0x72, 200 | 0x12, 0x19, 0x0a, 0x08, 0x73, 0x69, 0x64, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x18, 0x03, 0x20, 0x03, 201 | 0x28, 0x09, 0x52, 0x07, 0x73, 0x69, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x32, 0x55, 0x0a, 0x09, 0x44, 202 | 0x61, 0x74, 0x61, 0x50, 0x6c, 0x61, 0x6e, 0x65, 0x12, 0x48, 0x0a, 0x0d, 0x41, 0x70, 0x70, 0x6c, 203 | 0x79, 0x53, 0x52, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x1a, 0x2e, 0x61, 0x63, 0x61, 0x72, 204 | 0x2e, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x53, 0x52, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x65, 205 | 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x61, 0x63, 0x61, 0x72, 0x2e, 0x41, 0x70, 0x70, 206 | 0x6c, 0x79, 0x53, 0x52, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 207 | 0x73, 0x65, 0x42, 0x21, 0x5a, 0x1f, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 208 | 0x2f, 0x63, 0x68, 0x65, 0x7a, 0x2d, 0x73, 0x68, 0x61, 0x6e, 0x70, 0x75, 0x2f, 0x61, 0x63, 0x61, 209 | 0x72, 0x2f, 0x61, 0x70, 0x69, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, 210 | } 211 | 212 | var ( 213 | file_dataplane_proto_rawDescOnce sync.Once 214 | file_dataplane_proto_rawDescData = file_dataplane_proto_rawDesc 215 | ) 216 | 217 | func file_dataplane_proto_rawDescGZIP() []byte { 218 | file_dataplane_proto_rawDescOnce.Do(func() { 219 | file_dataplane_proto_rawDescData = protoimpl.X.CompressGZIP(file_dataplane_proto_rawDescData) 220 | }) 221 | return file_dataplane_proto_rawDescData 222 | } 223 | 224 | var file_dataplane_proto_msgTypes = make([]protoimpl.MessageInfo, 3) 225 | var file_dataplane_proto_goTypes = []interface{}{ 226 | (*ApplySRPolicyRequest)(nil), // 0: acar.ApplySRPolicyRequest 227 | (*ApplySRPolicyResponse)(nil), // 1: acar.ApplySRPolicyResponse 228 | (*SRInfo)(nil), // 2: acar.SRInfo 229 | (*timestamppb.Timestamp)(nil), // 3: google.protobuf.Timestamp 230 | } 231 | var file_dataplane_proto_depIdxs = []int32{ 232 | 2, // 0: acar.ApplySRPolicyRequest.sr_info:type_name -> acar.SRInfo 233 | 3, // 1: acar.ApplySRPolicyResponse.time:type_name -> google.protobuf.Timestamp 234 | 0, // 2: acar.DataPlane.ApplySRPolicy:input_type -> acar.ApplySRPolicyRequest 235 | 1, // 3: acar.DataPlane.ApplySRPolicy:output_type -> acar.ApplySRPolicyResponse 236 | 3, // [3:4] is the sub-list for method output_type 237 | 2, // [2:3] is the sub-list for method input_type 238 | 2, // [2:2] is the sub-list for extension type_name 239 | 2, // [2:2] is the sub-list for extension extendee 240 | 0, // [0:2] is the sub-list for field type_name 241 | } 242 | 243 | func init() { file_dataplane_proto_init() } 244 | func file_dataplane_proto_init() { 245 | if File_dataplane_proto != nil { 246 | return 247 | } 248 | if !protoimpl.UnsafeEnabled { 249 | file_dataplane_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { 250 | switch v := v.(*ApplySRPolicyRequest); i { 251 | case 0: 252 | return &v.state 253 | case 1: 254 | return &v.sizeCache 255 | case 2: 256 | return &v.unknownFields 257 | default: 258 | return nil 259 | } 260 | } 261 | file_dataplane_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { 262 | switch v := v.(*ApplySRPolicyResponse); i { 263 | case 0: 264 | return &v.state 265 | case 1: 266 | return &v.sizeCache 267 | case 2: 268 | return &v.unknownFields 269 | default: 270 | return nil 271 | } 272 | } 273 | file_dataplane_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { 274 | switch v := v.(*SRInfo); i { 275 | case 0: 276 | return &v.state 277 | case 1: 278 | return &v.sizeCache 279 | case 2: 280 | return &v.unknownFields 281 | default: 282 | return nil 283 | } 284 | } 285 | } 286 | type x struct{} 287 | out := protoimpl.TypeBuilder{ 288 | File: protoimpl.DescBuilder{ 289 | GoPackagePath: reflect.TypeOf(x{}).PkgPath(), 290 | RawDescriptor: file_dataplane_proto_rawDesc, 291 | NumEnums: 0, 292 | NumMessages: 3, 293 | NumExtensions: 0, 294 | NumServices: 1, 295 | }, 296 | GoTypes: file_dataplane_proto_goTypes, 297 | DependencyIndexes: file_dataplane_proto_depIdxs, 298 | MessageInfos: file_dataplane_proto_msgTypes, 299 | }.Build() 300 | File_dataplane_proto = out.File 301 | file_dataplane_proto_rawDesc = nil 302 | file_dataplane_proto_goTypes = nil 303 | file_dataplane_proto_depIdxs = nil 304 | } 305 | -------------------------------------------------------------------------------- /api/dataplane_grpc.pb.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-go-grpc. DO NOT EDIT. 2 | 3 | package api 4 | 5 | import ( 6 | context "context" 7 | grpc "google.golang.org/grpc" 8 | codes "google.golang.org/grpc/codes" 9 | status "google.golang.org/grpc/status" 10 | ) 11 | 12 | // This is a compile-time assertion to ensure that this generated file 13 | // is compatible with the grpc package it is being compiled against. 14 | // Requires gRPC-Go v1.32.0 or later. 15 | const _ = grpc.SupportPackageIsVersion7 16 | 17 | // DataPlaneClient is the client API for DataPlane service. 18 | // 19 | // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. 20 | type DataPlaneClient interface { 21 | ApplySRPolicy(ctx context.Context, in *ApplySRPolicyRequest, opts ...grpc.CallOption) (*ApplySRPolicyResponse, error) 22 | } 23 | 24 | type dataPlaneClient struct { 25 | cc grpc.ClientConnInterface 26 | } 27 | 28 | func NewDataPlaneClient(cc grpc.ClientConnInterface) DataPlaneClient { 29 | return &dataPlaneClient{cc} 30 | } 31 | 32 | func (c *dataPlaneClient) ApplySRPolicy(ctx context.Context, in *ApplySRPolicyRequest, opts ...grpc.CallOption) (*ApplySRPolicyResponse, error) { 33 | out := new(ApplySRPolicyResponse) 34 | err := c.cc.Invoke(ctx, "/acar.DataPlane/ApplySRPolicy", in, out, opts...) 35 | if err != nil { 36 | return nil, err 37 | } 38 | return out, nil 39 | } 40 | 41 | // DataPlaneServer is the server API for DataPlane service. 42 | // All implementations must embed UnimplementedDataPlaneServer 43 | // for forward compatibility 44 | type DataPlaneServer interface { 45 | ApplySRPolicy(context.Context, *ApplySRPolicyRequest) (*ApplySRPolicyResponse, error) 46 | mustEmbedUnimplementedDataPlaneServer() 47 | } 48 | 49 | // UnimplementedDataPlaneServer must be embedded to have forward compatible implementations. 50 | type UnimplementedDataPlaneServer struct { 51 | } 52 | 53 | func (UnimplementedDataPlaneServer) ApplySRPolicy(context.Context, *ApplySRPolicyRequest) (*ApplySRPolicyResponse, error) { 54 | return nil, status.Errorf(codes.Unimplemented, "method ApplySRPolicy not implemented") 55 | } 56 | func (UnimplementedDataPlaneServer) mustEmbedUnimplementedDataPlaneServer() {} 57 | 58 | // UnsafeDataPlaneServer may be embedded to opt out of forward compatibility for this service. 59 | // Use of this interface is not recommended, as added methods to DataPlaneServer will 60 | // result in compilation errors. 61 | type UnsafeDataPlaneServer interface { 62 | mustEmbedUnimplementedDataPlaneServer() 63 | } 64 | 65 | func RegisterDataPlaneServer(s grpc.ServiceRegistrar, srv DataPlaneServer) { 66 | s.RegisterService(&DataPlane_ServiceDesc, srv) 67 | } 68 | 69 | func _DataPlane_ApplySRPolicy_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { 70 | in := new(ApplySRPolicyRequest) 71 | if err := dec(in); err != nil { 72 | return nil, err 73 | } 74 | if interceptor == nil { 75 | return srv.(DataPlaneServer).ApplySRPolicy(ctx, in) 76 | } 77 | info := &grpc.UnaryServerInfo{ 78 | Server: srv, 79 | FullMethod: "/acar.DataPlane/ApplySRPolicy", 80 | } 81 | handler := func(ctx context.Context, req interface{}) (interface{}, error) { 82 | return srv.(DataPlaneServer).ApplySRPolicy(ctx, req.(*ApplySRPolicyRequest)) 83 | } 84 | return interceptor(ctx, in, info, handler) 85 | } 86 | 87 | // DataPlane_ServiceDesc is the grpc.ServiceDesc for DataPlane service. 88 | // It's only intended for direct use with grpc.RegisterService, 89 | // and not to be introspected or modified (even as a copy) 90 | var DataPlane_ServiceDesc = grpc.ServiceDesc{ 91 | ServiceName: "acar.DataPlane", 92 | HandlerType: (*DataPlaneServer)(nil), 93 | Methods: []grpc.MethodDesc{ 94 | { 95 | MethodName: "ApplySRPolicy", 96 | Handler: _DataPlane_ApplySRPolicy_Handler, 97 | }, 98 | }, 99 | Streams: []grpc.StreamDesc{}, 100 | Metadata: "dataplane.proto", 101 | } 102 | -------------------------------------------------------------------------------- /api/monitoring.pb.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-go. DO NOT EDIT. 2 | // versions: 3 | // protoc-gen-go v1.26.0 4 | // protoc v3.17.3 5 | // source: monitoring.proto 6 | 7 | package api 8 | 9 | import ( 10 | protoreflect "google.golang.org/protobuf/reflect/protoreflect" 11 | protoimpl "google.golang.org/protobuf/runtime/protoimpl" 12 | timestamppb "google.golang.org/protobuf/types/known/timestamppb" 13 | reflect "reflect" 14 | sync "sync" 15 | ) 16 | 17 | const ( 18 | // Verify that this generated code is sufficiently up-to-date. 19 | _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) 20 | // Verify that runtime/protoimpl is sufficiently up-to-date. 21 | _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) 22 | ) 23 | 24 | type GetNodesRequest struct { 25 | state protoimpl.MessageState 26 | sizeCache protoimpl.SizeCache 27 | unknownFields protoimpl.UnknownFields 28 | } 29 | 30 | func (x *GetNodesRequest) Reset() { 31 | *x = GetNodesRequest{} 32 | if protoimpl.UnsafeEnabled { 33 | mi := &file_monitoring_proto_msgTypes[0] 34 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 35 | ms.StoreMessageInfo(mi) 36 | } 37 | } 38 | 39 | func (x *GetNodesRequest) String() string { 40 | return protoimpl.X.MessageStringOf(x) 41 | } 42 | 43 | func (*GetNodesRequest) ProtoMessage() {} 44 | 45 | func (x *GetNodesRequest) ProtoReflect() protoreflect.Message { 46 | mi := &file_monitoring_proto_msgTypes[0] 47 | if protoimpl.UnsafeEnabled && x != nil { 48 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 49 | if ms.LoadMessageInfo() == nil { 50 | ms.StoreMessageInfo(mi) 51 | } 52 | return ms 53 | } 54 | return mi.MessageOf(x) 55 | } 56 | 57 | // Deprecated: Use GetNodesRequest.ProtoReflect.Descriptor instead. 58 | func (*GetNodesRequest) Descriptor() ([]byte, []int) { 59 | return file_monitoring_proto_rawDescGZIP(), []int{0} 60 | } 61 | 62 | type GetNodesResponse struct { 63 | state protoimpl.MessageState 64 | sizeCache protoimpl.SizeCache 65 | unknownFields protoimpl.UnknownFields 66 | 67 | Nodes []*Node `protobuf:"bytes,1,rep,name=nodes,proto3" json:"nodes,omitempty"` 68 | Time *timestamppb.Timestamp `protobuf:"bytes,2,opt,name=time,proto3" json:"time,omitempty"` 69 | } 70 | 71 | func (x *GetNodesResponse) Reset() { 72 | *x = GetNodesResponse{} 73 | if protoimpl.UnsafeEnabled { 74 | mi := &file_monitoring_proto_msgTypes[1] 75 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 76 | ms.StoreMessageInfo(mi) 77 | } 78 | } 79 | 80 | func (x *GetNodesResponse) String() string { 81 | return protoimpl.X.MessageStringOf(x) 82 | } 83 | 84 | func (*GetNodesResponse) ProtoMessage() {} 85 | 86 | func (x *GetNodesResponse) ProtoReflect() protoreflect.Message { 87 | mi := &file_monitoring_proto_msgTypes[1] 88 | if protoimpl.UnsafeEnabled && x != nil { 89 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 90 | if ms.LoadMessageInfo() == nil { 91 | ms.StoreMessageInfo(mi) 92 | } 93 | return ms 94 | } 95 | return mi.MessageOf(x) 96 | } 97 | 98 | // Deprecated: Use GetNodesResponse.ProtoReflect.Descriptor instead. 99 | func (*GetNodesResponse) Descriptor() ([]byte, []int) { 100 | return file_monitoring_proto_rawDescGZIP(), []int{1} 101 | } 102 | 103 | func (x *GetNodesResponse) GetNodes() []*Node { 104 | if x != nil { 105 | return x.Nodes 106 | } 107 | return nil 108 | } 109 | 110 | func (x *GetNodesResponse) GetTime() *timestamppb.Timestamp { 111 | if x != nil { 112 | return x.Time 113 | } 114 | return nil 115 | } 116 | 117 | type RegisterNodesRequest struct { 118 | state protoimpl.MessageState 119 | sizeCache protoimpl.SizeCache 120 | unknownFields protoimpl.UnknownFields 121 | 122 | Nodes []*Node `protobuf:"bytes,1,rep,name=nodes,proto3" json:"nodes,omitempty"` 123 | } 124 | 125 | func (x *RegisterNodesRequest) Reset() { 126 | *x = RegisterNodesRequest{} 127 | if protoimpl.UnsafeEnabled { 128 | mi := &file_monitoring_proto_msgTypes[2] 129 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 130 | ms.StoreMessageInfo(mi) 131 | } 132 | } 133 | 134 | func (x *RegisterNodesRequest) String() string { 135 | return protoimpl.X.MessageStringOf(x) 136 | } 137 | 138 | func (*RegisterNodesRequest) ProtoMessage() {} 139 | 140 | func (x *RegisterNodesRequest) ProtoReflect() protoreflect.Message { 141 | mi := &file_monitoring_proto_msgTypes[2] 142 | if protoimpl.UnsafeEnabled && x != nil { 143 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 144 | if ms.LoadMessageInfo() == nil { 145 | ms.StoreMessageInfo(mi) 146 | } 147 | return ms 148 | } 149 | return mi.MessageOf(x) 150 | } 151 | 152 | // Deprecated: Use RegisterNodesRequest.ProtoReflect.Descriptor instead. 153 | func (*RegisterNodesRequest) Descriptor() ([]byte, []int) { 154 | return file_monitoring_proto_rawDescGZIP(), []int{2} 155 | } 156 | 157 | func (x *RegisterNodesRequest) GetNodes() []*Node { 158 | if x != nil { 159 | return x.Nodes 160 | } 161 | return nil 162 | } 163 | 164 | type RegisterNodesResponse struct { 165 | state protoimpl.MessageState 166 | sizeCache protoimpl.SizeCache 167 | unknownFields protoimpl.UnknownFields 168 | 169 | Time *timestamppb.Timestamp `protobuf:"bytes,2,opt,name=time,proto3" json:"time,omitempty"` 170 | } 171 | 172 | func (x *RegisterNodesResponse) Reset() { 173 | *x = RegisterNodesResponse{} 174 | if protoimpl.UnsafeEnabled { 175 | mi := &file_monitoring_proto_msgTypes[3] 176 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 177 | ms.StoreMessageInfo(mi) 178 | } 179 | } 180 | 181 | func (x *RegisterNodesResponse) String() string { 182 | return protoimpl.X.MessageStringOf(x) 183 | } 184 | 185 | func (*RegisterNodesResponse) ProtoMessage() {} 186 | 187 | func (x *RegisterNodesResponse) ProtoReflect() protoreflect.Message { 188 | mi := &file_monitoring_proto_msgTypes[3] 189 | if protoimpl.UnsafeEnabled && x != nil { 190 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 191 | if ms.LoadMessageInfo() == nil { 192 | ms.StoreMessageInfo(mi) 193 | } 194 | return ms 195 | } 196 | return mi.MessageOf(x) 197 | } 198 | 199 | // Deprecated: Use RegisterNodesResponse.ProtoReflect.Descriptor instead. 200 | func (*RegisterNodesResponse) Descriptor() ([]byte, []int) { 201 | return file_monitoring_proto_rawDescGZIP(), []int{3} 202 | } 203 | 204 | func (x *RegisterNodesResponse) GetTime() *timestamppb.Timestamp { 205 | if x != nil { 206 | return x.Time 207 | } 208 | return nil 209 | } 210 | 211 | type Node struct { 212 | state protoimpl.MessageState 213 | sizeCache protoimpl.SizeCache 214 | unknownFields protoimpl.UnknownFields 215 | 216 | SID string `protobuf:"bytes,1,opt,name=SID,proto3" json:"SID,omitempty"` 217 | NextSids []string `protobuf:"bytes,2,rep,name=nextSids,proto3" json:"nextSids,omitempty"` 218 | LinkCap int64 `protobuf:"varint,3,opt,name=linkCap,proto3" json:"linkCap,omitempty"` 219 | LinkUsageBytes float64 `protobuf:"fixed64,4,opt,name=linkUsageBytes,proto3" json:"linkUsageBytes,omitempty"` 220 | LinkUsageRatio float64 `protobuf:"fixed64,5,opt,name=linkUsageRatio,proto3" json:"linkUsageRatio,omitempty"` 221 | } 222 | 223 | func (x *Node) Reset() { 224 | *x = Node{} 225 | if protoimpl.UnsafeEnabled { 226 | mi := &file_monitoring_proto_msgTypes[4] 227 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 228 | ms.StoreMessageInfo(mi) 229 | } 230 | } 231 | 232 | func (x *Node) String() string { 233 | return protoimpl.X.MessageStringOf(x) 234 | } 235 | 236 | func (*Node) ProtoMessage() {} 237 | 238 | func (x *Node) ProtoReflect() protoreflect.Message { 239 | mi := &file_monitoring_proto_msgTypes[4] 240 | if protoimpl.UnsafeEnabled && x != nil { 241 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 242 | if ms.LoadMessageInfo() == nil { 243 | ms.StoreMessageInfo(mi) 244 | } 245 | return ms 246 | } 247 | return mi.MessageOf(x) 248 | } 249 | 250 | // Deprecated: Use Node.ProtoReflect.Descriptor instead. 251 | func (*Node) Descriptor() ([]byte, []int) { 252 | return file_monitoring_proto_rawDescGZIP(), []int{4} 253 | } 254 | 255 | func (x *Node) GetSID() string { 256 | if x != nil { 257 | return x.SID 258 | } 259 | return "" 260 | } 261 | 262 | func (x *Node) GetNextSids() []string { 263 | if x != nil { 264 | return x.NextSids 265 | } 266 | return nil 267 | } 268 | 269 | func (x *Node) GetLinkCap() int64 { 270 | if x != nil { 271 | return x.LinkCap 272 | } 273 | return 0 274 | } 275 | 276 | func (x *Node) GetLinkUsageBytes() float64 { 277 | if x != nil { 278 | return x.LinkUsageBytes 279 | } 280 | return 0 281 | } 282 | 283 | func (x *Node) GetLinkUsageRatio() float64 { 284 | if x != nil { 285 | return x.LinkUsageRatio 286 | } 287 | return 0 288 | } 289 | 290 | var File_monitoring_proto protoreflect.FileDescriptor 291 | 292 | var file_monitoring_proto_rawDesc = []byte{ 293 | 0x0a, 0x10, 0x6d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x70, 0x72, 0x6f, 294 | 0x74, 0x6f, 0x12, 0x04, 0x61, 0x63, 0x61, 0x72, 0x1a, 0x1f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 295 | 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 296 | 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x11, 0x0a, 0x0f, 0x47, 0x65, 0x74, 297 | 0x4e, 0x6f, 0x64, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x64, 0x0a, 0x10, 298 | 0x47, 0x65, 0x74, 0x4e, 0x6f, 0x64, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 299 | 0x12, 0x20, 0x0a, 0x05, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 300 | 0x0a, 0x2e, 0x61, 0x63, 0x61, 0x72, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x05, 0x6e, 0x6f, 0x64, 301 | 0x65, 0x73, 0x12, 0x2e, 0x0a, 0x04, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 302 | 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 303 | 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x04, 0x74, 0x69, 304 | 0x6d, 0x65, 0x22, 0x38, 0x0a, 0x14, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x4e, 0x6f, 305 | 0x64, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x20, 0x0a, 0x05, 0x6e, 0x6f, 306 | 0x64, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0a, 0x2e, 0x61, 0x63, 0x61, 0x72, 307 | 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x05, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x22, 0x47, 0x0a, 0x15, 308 | 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x4e, 0x6f, 0x64, 0x65, 0x73, 0x52, 0x65, 0x73, 309 | 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2e, 0x0a, 0x04, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x02, 0x20, 310 | 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 311 | 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 312 | 0x04, 0x74, 0x69, 0x6d, 0x65, 0x22, 0x9e, 0x01, 0x0a, 0x04, 0x4e, 0x6f, 0x64, 0x65, 0x12, 0x10, 313 | 0x0a, 0x03, 0x53, 0x49, 0x44, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x53, 0x49, 0x44, 314 | 0x12, 0x1a, 0x0a, 0x08, 0x6e, 0x65, 0x78, 0x74, 0x53, 0x69, 0x64, 0x73, 0x18, 0x02, 0x20, 0x03, 315 | 0x28, 0x09, 0x52, 0x08, 0x6e, 0x65, 0x78, 0x74, 0x53, 0x69, 0x64, 0x73, 0x12, 0x18, 0x0a, 0x07, 316 | 0x6c, 0x69, 0x6e, 0x6b, 0x43, 0x61, 0x70, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, 0x6c, 317 | 0x69, 0x6e, 0x6b, 0x43, 0x61, 0x70, 0x12, 0x26, 0x0a, 0x0e, 0x6c, 0x69, 0x6e, 0x6b, 0x55, 0x73, 318 | 0x61, 0x67, 0x65, 0x42, 0x79, 0x74, 0x65, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x01, 0x52, 0x0e, 319 | 0x6c, 0x69, 0x6e, 0x6b, 0x55, 0x73, 0x61, 0x67, 0x65, 0x42, 0x79, 0x74, 0x65, 0x73, 0x12, 0x26, 320 | 0x0a, 0x0e, 0x6c, 0x69, 0x6e, 0x6b, 0x55, 0x73, 0x61, 0x67, 0x65, 0x52, 0x61, 0x74, 0x69, 0x6f, 321 | 0x18, 0x05, 0x20, 0x01, 0x28, 0x01, 0x52, 0x0e, 0x6c, 0x69, 0x6e, 0x6b, 0x55, 0x73, 0x61, 0x67, 322 | 0x65, 0x52, 0x61, 0x74, 0x69, 0x6f, 0x32, 0x91, 0x01, 0x0a, 0x0a, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 323 | 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x12, 0x39, 0x0a, 0x08, 0x47, 0x65, 0x74, 0x4e, 0x6f, 0x64, 0x65, 324 | 0x73, 0x12, 0x15, 0x2e, 0x61, 0x63, 0x61, 0x72, 0x2e, 0x47, 0x65, 0x74, 0x4e, 0x6f, 0x64, 0x65, 325 | 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x61, 0x63, 0x61, 0x72, 0x2e, 326 | 0x47, 0x65, 0x74, 0x4e, 0x6f, 0x64, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 327 | 0x12, 0x48, 0x0a, 0x0d, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x4e, 0x6f, 0x64, 0x65, 328 | 0x73, 0x12, 0x1a, 0x2e, 0x61, 0x63, 0x61, 0x72, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 329 | 0x72, 0x4e, 0x6f, 0x64, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 330 | 0x61, 0x63, 0x61, 0x72, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x4e, 0x6f, 0x64, 331 | 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x21, 0x5a, 0x1f, 0x67, 0x69, 332 | 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x68, 0x65, 0x7a, 0x2d, 0x73, 0x68, 333 | 0x61, 0x6e, 0x70, 0x75, 0x2f, 0x61, 0x63, 0x61, 0x72, 0x2f, 0x61, 0x70, 0x69, 0x62, 0x06, 0x70, 334 | 0x72, 0x6f, 0x74, 0x6f, 0x33, 335 | } 336 | 337 | var ( 338 | file_monitoring_proto_rawDescOnce sync.Once 339 | file_monitoring_proto_rawDescData = file_monitoring_proto_rawDesc 340 | ) 341 | 342 | func file_monitoring_proto_rawDescGZIP() []byte { 343 | file_monitoring_proto_rawDescOnce.Do(func() { 344 | file_monitoring_proto_rawDescData = protoimpl.X.CompressGZIP(file_monitoring_proto_rawDescData) 345 | }) 346 | return file_monitoring_proto_rawDescData 347 | } 348 | 349 | var file_monitoring_proto_msgTypes = make([]protoimpl.MessageInfo, 5) 350 | var file_monitoring_proto_goTypes = []interface{}{ 351 | (*GetNodesRequest)(nil), // 0: acar.GetNodesRequest 352 | (*GetNodesResponse)(nil), // 1: acar.GetNodesResponse 353 | (*RegisterNodesRequest)(nil), // 2: acar.RegisterNodesRequest 354 | (*RegisterNodesResponse)(nil), // 3: acar.RegisterNodesResponse 355 | (*Node)(nil), // 4: acar.Node 356 | (*timestamppb.Timestamp)(nil), // 5: google.protobuf.Timestamp 357 | } 358 | var file_monitoring_proto_depIdxs = []int32{ 359 | 4, // 0: acar.GetNodesResponse.nodes:type_name -> acar.Node 360 | 5, // 1: acar.GetNodesResponse.time:type_name -> google.protobuf.Timestamp 361 | 4, // 2: acar.RegisterNodesRequest.nodes:type_name -> acar.Node 362 | 5, // 3: acar.RegisterNodesResponse.time:type_name -> google.protobuf.Timestamp 363 | 0, // 4: acar.Monitoring.GetNodes:input_type -> acar.GetNodesRequest 364 | 2, // 5: acar.Monitoring.RegisterNodes:input_type -> acar.RegisterNodesRequest 365 | 1, // 6: acar.Monitoring.GetNodes:output_type -> acar.GetNodesResponse 366 | 3, // 7: acar.Monitoring.RegisterNodes:output_type -> acar.RegisterNodesResponse 367 | 6, // [6:8] is the sub-list for method output_type 368 | 4, // [4:6] is the sub-list for method input_type 369 | 4, // [4:4] is the sub-list for extension type_name 370 | 4, // [4:4] is the sub-list for extension extendee 371 | 0, // [0:4] is the sub-list for field type_name 372 | } 373 | 374 | func init() { file_monitoring_proto_init() } 375 | func file_monitoring_proto_init() { 376 | if File_monitoring_proto != nil { 377 | return 378 | } 379 | if !protoimpl.UnsafeEnabled { 380 | file_monitoring_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { 381 | switch v := v.(*GetNodesRequest); i { 382 | case 0: 383 | return &v.state 384 | case 1: 385 | return &v.sizeCache 386 | case 2: 387 | return &v.unknownFields 388 | default: 389 | return nil 390 | } 391 | } 392 | file_monitoring_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { 393 | switch v := v.(*GetNodesResponse); i { 394 | case 0: 395 | return &v.state 396 | case 1: 397 | return &v.sizeCache 398 | case 2: 399 | return &v.unknownFields 400 | default: 401 | return nil 402 | } 403 | } 404 | file_monitoring_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { 405 | switch v := v.(*RegisterNodesRequest); i { 406 | case 0: 407 | return &v.state 408 | case 1: 409 | return &v.sizeCache 410 | case 2: 411 | return &v.unknownFields 412 | default: 413 | return nil 414 | } 415 | } 416 | file_monitoring_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { 417 | switch v := v.(*RegisterNodesResponse); i { 418 | case 0: 419 | return &v.state 420 | case 1: 421 | return &v.sizeCache 422 | case 2: 423 | return &v.unknownFields 424 | default: 425 | return nil 426 | } 427 | } 428 | file_monitoring_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { 429 | switch v := v.(*Node); i { 430 | case 0: 431 | return &v.state 432 | case 1: 433 | return &v.sizeCache 434 | case 2: 435 | return &v.unknownFields 436 | default: 437 | return nil 438 | } 439 | } 440 | } 441 | type x struct{} 442 | out := protoimpl.TypeBuilder{ 443 | File: protoimpl.DescBuilder{ 444 | GoPackagePath: reflect.TypeOf(x{}).PkgPath(), 445 | RawDescriptor: file_monitoring_proto_rawDesc, 446 | NumEnums: 0, 447 | NumMessages: 5, 448 | NumExtensions: 0, 449 | NumServices: 1, 450 | }, 451 | GoTypes: file_monitoring_proto_goTypes, 452 | DependencyIndexes: file_monitoring_proto_depIdxs, 453 | MessageInfos: file_monitoring_proto_msgTypes, 454 | }.Build() 455 | File_monitoring_proto = out.File 456 | file_monitoring_proto_rawDesc = nil 457 | file_monitoring_proto_goTypes = nil 458 | file_monitoring_proto_depIdxs = nil 459 | } 460 | -------------------------------------------------------------------------------- /api/monitoring_grpc.pb.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-go-grpc. DO NOT EDIT. 2 | 3 | package api 4 | 5 | import ( 6 | context "context" 7 | grpc "google.golang.org/grpc" 8 | codes "google.golang.org/grpc/codes" 9 | status "google.golang.org/grpc/status" 10 | ) 11 | 12 | // This is a compile-time assertion to ensure that this generated file 13 | // is compatible with the grpc package it is being compiled against. 14 | // Requires gRPC-Go v1.32.0 or later. 15 | const _ = grpc.SupportPackageIsVersion7 16 | 17 | // MonitoringClient is the client API for Monitoring service. 18 | // 19 | // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. 20 | type MonitoringClient interface { 21 | GetNodes(ctx context.Context, in *GetNodesRequest, opts ...grpc.CallOption) (*GetNodesResponse, error) 22 | RegisterNodes(ctx context.Context, in *RegisterNodesRequest, opts ...grpc.CallOption) (*RegisterNodesResponse, error) 23 | } 24 | 25 | type monitoringClient struct { 26 | cc grpc.ClientConnInterface 27 | } 28 | 29 | func NewMonitoringClient(cc grpc.ClientConnInterface) MonitoringClient { 30 | return &monitoringClient{cc} 31 | } 32 | 33 | func (c *monitoringClient) GetNodes(ctx context.Context, in *GetNodesRequest, opts ...grpc.CallOption) (*GetNodesResponse, error) { 34 | out := new(GetNodesResponse) 35 | err := c.cc.Invoke(ctx, "/acar.Monitoring/GetNodes", in, out, opts...) 36 | if err != nil { 37 | return nil, err 38 | } 39 | return out, nil 40 | } 41 | 42 | func (c *monitoringClient) RegisterNodes(ctx context.Context, in *RegisterNodesRequest, opts ...grpc.CallOption) (*RegisterNodesResponse, error) { 43 | out := new(RegisterNodesResponse) 44 | err := c.cc.Invoke(ctx, "/acar.Monitoring/RegisterNodes", in, out, opts...) 45 | if err != nil { 46 | return nil, err 47 | } 48 | return out, nil 49 | } 50 | 51 | // MonitoringServer is the server API for Monitoring service. 52 | // All implementations must embed UnimplementedMonitoringServer 53 | // for forward compatibility 54 | type MonitoringServer interface { 55 | GetNodes(context.Context, *GetNodesRequest) (*GetNodesResponse, error) 56 | RegisterNodes(context.Context, *RegisterNodesRequest) (*RegisterNodesResponse, error) 57 | mustEmbedUnimplementedMonitoringServer() 58 | } 59 | 60 | // UnimplementedMonitoringServer must be embedded to have forward compatible implementations. 61 | type UnimplementedMonitoringServer struct { 62 | } 63 | 64 | func (UnimplementedMonitoringServer) GetNodes(context.Context, *GetNodesRequest) (*GetNodesResponse, error) { 65 | return nil, status.Errorf(codes.Unimplemented, "method GetNodes not implemented") 66 | } 67 | func (UnimplementedMonitoringServer) RegisterNodes(context.Context, *RegisterNodesRequest) (*RegisterNodesResponse, error) { 68 | return nil, status.Errorf(codes.Unimplemented, "method RegisterNodes not implemented") 69 | } 70 | func (UnimplementedMonitoringServer) mustEmbedUnimplementedMonitoringServer() {} 71 | 72 | // UnsafeMonitoringServer may be embedded to opt out of forward compatibility for this service. 73 | // Use of this interface is not recommended, as added methods to MonitoringServer will 74 | // result in compilation errors. 75 | type UnsafeMonitoringServer interface { 76 | mustEmbedUnimplementedMonitoringServer() 77 | } 78 | 79 | func RegisterMonitoringServer(s grpc.ServiceRegistrar, srv MonitoringServer) { 80 | s.RegisterService(&Monitoring_ServiceDesc, srv) 81 | } 82 | 83 | func _Monitoring_GetNodes_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { 84 | in := new(GetNodesRequest) 85 | if err := dec(in); err != nil { 86 | return nil, err 87 | } 88 | if interceptor == nil { 89 | return srv.(MonitoringServer).GetNodes(ctx, in) 90 | } 91 | info := &grpc.UnaryServerInfo{ 92 | Server: srv, 93 | FullMethod: "/acar.Monitoring/GetNodes", 94 | } 95 | handler := func(ctx context.Context, req interface{}) (interface{}, error) { 96 | return srv.(MonitoringServer).GetNodes(ctx, req.(*GetNodesRequest)) 97 | } 98 | return interceptor(ctx, in, info, handler) 99 | } 100 | 101 | func _Monitoring_RegisterNodes_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { 102 | in := new(RegisterNodesRequest) 103 | if err := dec(in); err != nil { 104 | return nil, err 105 | } 106 | if interceptor == nil { 107 | return srv.(MonitoringServer).RegisterNodes(ctx, in) 108 | } 109 | info := &grpc.UnaryServerInfo{ 110 | Server: srv, 111 | FullMethod: "/acar.Monitoring/RegisterNodes", 112 | } 113 | handler := func(ctx context.Context, req interface{}) (interface{}, error) { 114 | return srv.(MonitoringServer).RegisterNodes(ctx, req.(*RegisterNodesRequest)) 115 | } 116 | return interceptor(ctx, in, info, handler) 117 | } 118 | 119 | // Monitoring_ServiceDesc is the grpc.ServiceDesc for Monitoring service. 120 | // It's only intended for direct use with grpc.RegisterService, 121 | // and not to be introspected or modified (even as a copy) 122 | var Monitoring_ServiceDesc = grpc.ServiceDesc{ 123 | ServiceName: "acar.Monitoring", 124 | HandlerType: (*MonitoringServer)(nil), 125 | Methods: []grpc.MethodDesc{ 126 | { 127 | MethodName: "GetNodes", 128 | Handler: _Monitoring_GetNodes_Handler, 129 | }, 130 | { 131 | MethodName: "RegisterNodes", 132 | Handler: _Monitoring_RegisterNodes_Handler, 133 | }, 134 | }, 135 | Streams: []grpc.StreamDesc{}, 136 | Metadata: "monitoring.proto", 137 | } 138 | -------------------------------------------------------------------------------- /api/protos/controlplane.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package acar; 4 | 5 | option go_package = "github.com/chez-shanpu/acar/api"; 6 | 7 | import "google/protobuf/timestamp.proto"; 8 | 9 | service ControlPlane{ 10 | rpc RegisterSRPolicy(RegisterSRPolicyRequest) returns (RegisterSRPolicyResponse); 11 | } 12 | 13 | message RegisterSRPolicyRequest { 14 | AppInfo app_info = 1; 15 | } 16 | 17 | message RegisterSRPolicyResponse { 18 | google.protobuf.Timestamp time = 1; 19 | } 20 | 21 | message AppInfo { 22 | string app_name = 1; 23 | string src_addr = 2; 24 | string dst_addr = 3; 25 | repeated string sid_list = 4; 26 | } 27 | 28 | -------------------------------------------------------------------------------- /api/protos/dataplane.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package acar; 4 | 5 | option go_package = "github.com/chez-shanpu/acar/api"; 6 | 7 | import "google/protobuf/timestamp.proto"; 8 | 9 | service DataPlane{ 10 | rpc ApplySRPolicy(ApplySRPolicyRequest) returns (ApplySRPolicyResponse); 11 | } 12 | 13 | message ApplySRPolicyRequest { 14 | SRInfo sr_info = 1; 15 | } 16 | 17 | message ApplySRPolicyResponse { 18 | google.protobuf.Timestamp time = 1; 19 | } 20 | 21 | message SRInfo { 22 | string src_addr = 1; 23 | string dst_addr = 2; 24 | repeated string sid_list = 3; 25 | } 26 | 27 | -------------------------------------------------------------------------------- /api/protos/monitoring.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package acar; 4 | 5 | option go_package = "github.com/chez-shanpu/acar/api"; 6 | 7 | import "google/protobuf/timestamp.proto"; 8 | 9 | service Monitoring{ 10 | rpc GetNodes(GetNodesRequest) returns(GetNodesResponse); 11 | rpc RegisterNodes(RegisterNodesRequest) returns(RegisterNodesResponse); 12 | } 13 | 14 | message GetNodesRequest{} 15 | 16 | message GetNodesResponse{ 17 | repeated Node nodes = 1; 18 | google.protobuf.Timestamp time = 2; 19 | } 20 | 21 | message RegisterNodesRequest{ 22 | repeated Node nodes = 1; 23 | } 24 | 25 | message RegisterNodesResponse{ 26 | google.protobuf.Timestamp time = 2; 27 | } 28 | 29 | message Node { 30 | string SID = 1; 31 | repeated string nextSids = 2; 32 | int64 linkCap = 3; 33 | double linkUsageBytes = 4; 34 | double linkUsageRatio = 5; 35 | } 36 | -------------------------------------------------------------------------------- /cmd/appagent/app/root.go: -------------------------------------------------------------------------------- 1 | package app 2 | 3 | import ( 4 | "crypto/rand" 5 | "fmt" 6 | "log" 7 | "math" 8 | "math/big" 9 | "os" 10 | "os/signal" 11 | "runtime" 12 | "syscall" 13 | "time" 14 | 15 | "github.com/chez-shanpu/acar/pkg/appagent" 16 | 17 | "github.com/spf13/viper" 18 | 19 | "github.com/spf13/cobra" 20 | ) 21 | 22 | var ( 23 | // Version is version number which automatically set on build. `git describe --tags` 24 | Version string 25 | // Revision is git commit hash which automatically set `git rev-parse --short HEAD` on build. 26 | Revision string 27 | 28 | GoVersion = runtime.Version() 29 | Compiler = runtime.Compiler 30 | ) 31 | 32 | func init() { 33 | // flags 34 | flags := rootCmd.Flags() 35 | flags.String(appagent.AppName, "", "application name") 36 | flags.String(appagent.ControlplaneAddr, "localhost", "controlplane server address") 37 | flags.String(appagent.ControlplaneCert, "", "path to controlplane server cert file (this option is enabled when tls flag is true)") 38 | flags.Bool(appagent.ControlplaneTLS, false, "controlplane server tls flag") 39 | flags.StringSlice(appagent.DepSID, []string{}, "the sid of the departure") 40 | flags.String(appagent.DstAddr, "", "destination address") 41 | flags.String(appagent.DstSID, "", "the sid of the destination") 42 | flags.Int(appagent.Interval, 1, "calculation interval (sec)") 43 | flags.Float64(appagent.Lazy, 0, "lazy probability (float 0 to 1)") 44 | flags.StringP(appagent.Metrics, "", "bytes", "what metrics uses for make a graph ('ratio' and 'bytes' is now supported and default is 'bytes')") 45 | flags.String(appagent.MonitoringAddr, "localhost", "monitoring server address") 46 | flags.String(appagent.MonitoringCert, "", "path to monitoring server cert file (this option is enabled when tls flag is true)") 47 | flags.Bool(appagent.MonitoringTLS, false, "monitoring server tls flag") 48 | flags.Float64(appagent.Require, 0, "required metrics value (if 'byte' metrics is choosed, this value means required free bandwidth[bps])") 49 | flags.String(appagent.SrcAddr, "", "segment routing domain ingress interface address") 50 | 51 | _ = viper.BindPFlags(flags) 52 | 53 | // required 54 | _ = rootCmd.MarkFlagRequired(appagent.AppName) 55 | _ = rootCmd.MarkFlagRequired(appagent.ControlplaneAddr) 56 | _ = rootCmd.MarkFlagRequired(appagent.DepSID) 57 | _ = rootCmd.MarkFlagRequired(appagent.DstAddr) 58 | _ = rootCmd.MarkFlagRequired(appagent.DstSID) 59 | _ = rootCmd.MarkFlagRequired(appagent.Interval) 60 | _ = rootCmd.MarkFlagRequired(appagent.MonitoringAddr) 61 | _ = rootCmd.MarkFlagRequired(appagent.Require) 62 | _ = rootCmd.MarkFlagRequired(appagent.SrcAddr) 63 | } 64 | 65 | // rootCmd represents the base command when called without any subcommands 66 | var rootCmd = &cobra.Command{ 67 | Use: "app-agent", 68 | Short: "acar application agent", 69 | Version: fmt.Sprintf("acar application agent Version: %s (Revision: %s / GoVersion: %s / Compiler: %s)\n", 70 | Version, Revision, GoVersion, Compiler), 71 | Run: func(cmd *cobra.Command, args []string) { 72 | appagent.Config.Populate() 73 | 74 | sigs := make(chan os.Signal, 1) 75 | signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM) 76 | defer func() { 77 | signal.Stop(sigs) 78 | }() 79 | 80 | errCh := make(chan error, 1) 81 | ticker := time.NewTicker(time.Duration(appagent.Config.Interval) * time.Second) 82 | go func() { 83 | for { 84 | select { 85 | case <-ticker.C: 86 | if err := run(); err != nil { 87 | errCh <- err 88 | return 89 | } 90 | } 91 | } 92 | }() 93 | 94 | select { 95 | case sig := <-sigs: 96 | fmt.Printf("Finished with the signal: %v", sig) 97 | case err := <-errCh: 98 | fmt.Printf("[ERROR]: %v", err) 99 | } 100 | }, 101 | } 102 | 103 | // Execute adds all child commands to the root command and sets flags appropriately. 104 | // This is called by main.main(). It only needs to happen once to the rootCmd. 105 | func Execute() { 106 | if err := rootCmd.Execute(); err != nil { 107 | fmt.Println(err) 108 | os.Exit(1) 109 | } 110 | } 111 | 112 | func run() error { 113 | if isLazy() { 114 | log.Println("Lazy") 115 | return nil 116 | } 117 | 118 | nodes, err := appagent.GetSRNodesInfo() 119 | if err != nil { 120 | return err 121 | } 122 | 123 | graph, err := appagent.MakeGraph(nodes) 124 | if err != nil { 125 | return err 126 | } 127 | 128 | list, err := appagent.MakeSIDList(graph) 129 | if err != nil { 130 | return err 131 | } 132 | if list == nil { 133 | log.Println("No best path") 134 | return nil 135 | } 136 | 137 | return appagent.SendSRInfoToControlPlane(list) 138 | } 139 | 140 | func isLazy() bool { 141 | if appagent.Config.Lazy > randFloat() { 142 | return true 143 | } else { 144 | return false 145 | } 146 | } 147 | func randFloat() float64 { 148 | a, err := rand.Int(rand.Reader, big.NewInt(math.MaxInt64)) 149 | if err != nil { 150 | panic(err) 151 | } 152 | again: 153 | f := float64(a.Int64()) / (1 << 63) 154 | if f == 1 { 155 | goto again 156 | } 157 | return f 158 | } 159 | -------------------------------------------------------------------------------- /cmd/appagent/appagent.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "github.com/chez-shanpu/acar/cmd/appagent/app" 5 | ) 6 | 7 | func main() { 8 | app.Execute() 9 | } 10 | -------------------------------------------------------------------------------- /cmd/controlplane/app/root.go: -------------------------------------------------------------------------------- 1 | package app 2 | 3 | import ( 4 | "fmt" 5 | "net" 6 | "os" 7 | "runtime" 8 | 9 | "github.com/chez-shanpu/acar/api" 10 | "github.com/chez-shanpu/acar/pkg/controlplane" 11 | "github.com/chez-shanpu/acar/pkg/grpc" 12 | "github.com/spf13/viper" 13 | 14 | "github.com/spf13/cobra" 15 | ) 16 | 17 | var ( 18 | // Version is version number which automatically set on build. `git describe --tags` 19 | Version string 20 | // Revision is git commit hash which automatically set `git rev-parse --short HEAD` on build. 21 | Revision string 22 | 23 | GoVersion = runtime.Version() 24 | Compiler = runtime.Compiler 25 | ) 26 | 27 | func init() { 28 | // flags 29 | flags := rootCmd.Flags() 30 | flags.String(controlplane.DataplaneAddr, "localhost:18080", "dataplane server addr") 31 | flags.String(controlplane.DataplaneCert, "", "path to dataplane server cert file (this option is enabled when dp-tls flag is true)") 32 | flags.Bool(controlplane.DataplaneTLS, false, "dataplane client tls flag") 33 | flags.StringP(controlplane.ServerAddr, "a", "localhost", "server address") 34 | flags.BoolP(controlplane.TLS, "t", false, "tls flag") 35 | flags.String(controlplane.TLSCert, "", "path to cert file (this option is enabled when tls flag is true)") 36 | flags.String(controlplane.TLSKey, "", "path to key file (this option is enabled when tls flag is true)") 37 | 38 | _ = viper.BindPFlags(flags) 39 | 40 | // required 41 | _ = rootCmd.MarkFlagRequired(controlplane.DataplaneAddr) 42 | _ = rootCmd.MarkFlagRequired(controlplane.ServerAddr) 43 | } 44 | 45 | // rootCmd represents the base command when called without any subcommands 46 | var rootCmd = &cobra.Command{ 47 | Use: "controlplane", 48 | Short: "acar controlplane", 49 | Version: fmt.Sprintf("acar controlplane server Version: %s (Revision: %s / GoVersion: %s / Compiler: %s)\n", 50 | Version, Revision, GoVersion, Compiler), 51 | RunE: func(cmd *cobra.Command, args []string) error { 52 | controlplane.Config.Populate() 53 | return runServer() 54 | }, 55 | } 56 | 57 | // Execute adds all child commands to the root command and sets flags appropriately. 58 | // This is called by main.main(). It only needs to happen once to the rootCmd. 59 | func Execute() { 60 | if err := rootCmd.Execute(); err != nil { 61 | fmt.Println(err) 62 | os.Exit(1) 63 | } 64 | } 65 | 66 | func runServer() error { 67 | s, err := grpc.MakeServer(controlplane.Config.TLS, controlplane.Config.TLSCert, controlplane.Config.TLSKey) 68 | if err != nil { 69 | return err 70 | } 71 | api.RegisterControlPlaneServer(s, controlplane.NewServer()) 72 | 73 | lis, err := net.Listen("tcp", controlplane.Config.ServerAddr) 74 | if err != nil { 75 | return err 76 | } 77 | return s.Serve(lis) 78 | } 79 | -------------------------------------------------------------------------------- /cmd/controlplane/controlplane.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "github.com/chez-shanpu/acar/cmd/controlplane/app" 5 | ) 6 | 7 | func main() { 8 | app.Execute() 9 | } 10 | -------------------------------------------------------------------------------- /cmd/dataplane/app/root.go: -------------------------------------------------------------------------------- 1 | package app 2 | 3 | import ( 4 | "fmt" 5 | "net" 6 | "os" 7 | "runtime" 8 | 9 | "github.com/chez-shanpu/acar/api" 10 | "github.com/chez-shanpu/acar/pkg/dataplane" 11 | "github.com/chez-shanpu/acar/pkg/grpc" 12 | "github.com/spf13/cobra" 13 | "github.com/spf13/viper" 14 | ) 15 | 16 | var ( 17 | // Version is version number which automatically set on build. `git describe --tags` 18 | Version string 19 | // Revision is git commit hash which automatically set `git rev-parse --short HEAD` on build. 20 | Revision string 21 | 22 | GoVersion = runtime.Version() 23 | Compiler = runtime.Compiler 24 | ) 25 | 26 | func init() { 27 | // flags 28 | flags := rootCmd.Flags() 29 | flags.StringP(dataplane.ServerAddr, "a", "localhost:18080", "server address") 30 | flags.BoolP(dataplane.TLS, "t", false, "tls flag") 31 | flags.String(dataplane.TLSCert, "", "path to cert file (this option is enabled when tls flag is true)") 32 | flags.String(dataplane.TLSKey, "", "path to key file (this option is enabled when tls flag is true)") 33 | flags.StringP(dataplane.Device, "d", "", "NIC device name") 34 | 35 | _ = viper.BindPFlags(flags) 36 | 37 | // required 38 | _ = rootCmd.MarkFlagRequired(dataplane.Device) 39 | _ = rootCmd.MarkFlagRequired(dataplane.ServerAddr) 40 | } 41 | 42 | // rootCmd represents the base command when called without any subcommands 43 | var rootCmd = &cobra.Command{ 44 | Use: "dataplane", 45 | Short: "acar dataplane server", 46 | Version: fmt.Sprintf("acar dataplane server Version: %s (Revision: %s / GoVersion: %s / Compiler: %s)\n", 47 | Version, Revision, GoVersion, Compiler), 48 | RunE: func(cmd *cobra.Command, args []string) error { 49 | dataplane.Config.Populate() 50 | return runServer() 51 | }, 52 | } 53 | 54 | // Execute adds all child commands to the root command and sets flags appropriately. 55 | // This is called by main.main(). It only needs to happen once to the rootCmd. 56 | func Execute() { 57 | if err := rootCmd.Execute(); err != nil { 58 | fmt.Println(err) 59 | os.Exit(1) 60 | } 61 | } 62 | 63 | func runServer() error { 64 | s, err := grpc.MakeServer(dataplane.Config.TLS, dataplane.Config.TLSCert, dataplane.Config.TLSKey) 65 | if err != nil { 66 | return err 67 | } 68 | api.RegisterDataPlaneServer(s, dataplane.NewServer()) 69 | 70 | lis, err := net.Listen("tcp", dataplane.Config.ServerAddr) 71 | if err != nil { 72 | return err 73 | } 74 | return s.Serve(lis) 75 | } 76 | -------------------------------------------------------------------------------- /cmd/dataplane/dataplane.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "github.com/chez-shanpu/acar/cmd/dataplane/app" 5 | ) 6 | 7 | func main() { 8 | app.Execute() 9 | } 10 | -------------------------------------------------------------------------------- /cmd/monitoring/app/root.go: -------------------------------------------------------------------------------- 1 | package app 2 | 3 | import ( 4 | "fmt" 5 | "net" 6 | "os" 7 | "runtime" 8 | 9 | "github.com/chez-shanpu/acar/api" 10 | "github.com/chez-shanpu/acar/pkg/grpc" 11 | "github.com/chez-shanpu/acar/pkg/monitoring" 12 | "github.com/spf13/cobra" 13 | "github.com/spf13/viper" 14 | ) 15 | 16 | var ( 17 | // set these value as go build -ldflags option 18 | // Version is version number which automatically set on build. `git describe --tags` 19 | Version string 20 | // Revision is git commit hash which automatically set `git rev-parse --short HEAD` on build. 21 | Revision string 22 | 23 | GoVersion = runtime.Version() 24 | Compiler = runtime.Compiler 25 | ) 26 | 27 | func init() { 28 | // flags 29 | flags := rootCmd.Flags() 30 | flags.String(monitoring.RedisAddr, "localhost:6379", "redis server address") 31 | flags.String(monitoring.RedisPass, "password", "redis password") 32 | flags.Int(monitoring.RedisDB, 1, "redis db number") 33 | flags.BoolP(monitoring.TLS, "t", false, "tls flag") 34 | flags.String(monitoring.TLSCert, "", "path to cert file (this option is enabled when tls flag is true)") 35 | flags.String(monitoring.TLSKey, "", "path to key file (this option is enabled when tls flag is true)") 36 | flags.StringP(monitoring.ServerAddr, "a", "localhost", "server address") 37 | 38 | _ = viper.BindPFlags(flags) 39 | 40 | // required 41 | _ = rootCmd.MarkFlagRequired("addr") 42 | } 43 | 44 | // rootCmd represents the base command when called without any subcommands 45 | var rootCmd = &cobra.Command{ 46 | Use: "monitoring", 47 | Short: "acar monitoring server", 48 | Version: fmt.Sprintf("acar monitoring server Version: %s (Revision: %s / GoVersion: %s / Compiler: %s)\n", 49 | Version, Revision, GoVersion, Compiler), 50 | RunE: func(cmd *cobra.Command, args []string) error { 51 | monitoring.Config.Populate() 52 | return runServer() 53 | }, 54 | } 55 | 56 | // Execute adds all child commands to the root command and sets flags appropriately. 57 | // This is called by main.main(). It only needs to happen once to the rootCmd. 58 | func Execute() { 59 | if err := rootCmd.Execute(); err != nil { 60 | fmt.Println(err) 61 | os.Exit(1) 62 | } 63 | } 64 | 65 | func runServer() error { 66 | s, err := grpc.MakeServer(monitoring.Config.TLS, monitoring.Config.TLSCert, monitoring.Config.TLSKey) 67 | if err != nil { 68 | return err 69 | } 70 | api.RegisterMonitoringServer(s, monitoring.NewServer()) 71 | 72 | lis, err := net.Listen("tcp", monitoring.Config.ServerAddr) 73 | if err != nil { 74 | return err 75 | } 76 | return s.Serve(lis) 77 | } 78 | -------------------------------------------------------------------------------- /cmd/monitoring/monitoringserver.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "github.com/chez-shanpu/acar/cmd/monitoring/app" 5 | ) 6 | 7 | func main() { 8 | app.Execute() 9 | } 10 | -------------------------------------------------------------------------------- /cmd/srnode-agent/app/root.go: -------------------------------------------------------------------------------- 1 | package app 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | "os/signal" 7 | "path/filepath" 8 | "runtime" 9 | "syscall" 10 | "time" 11 | 12 | "github.com/chez-shanpu/acar/pkg/srnode" 13 | 14 | "github.com/mitchellh/go-homedir" 15 | "github.com/spf13/viper" 16 | 17 | "github.com/spf13/cobra" 18 | ) 19 | 20 | var ( 21 | cfgFile string 22 | 23 | // Version is version number which automatically set on build. `git describe --tags` 24 | Version string 25 | // Revision is git commit hash which automatically set `git rev-parse --short HEAD` on build. 26 | Revision string 27 | 28 | GoVersion = runtime.Version() 29 | Compiler = runtime.Compiler 30 | ) 31 | 32 | func init() { 33 | rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.acar/srnode-agent.yaml)") 34 | 35 | // flags 36 | flags := rootCmd.Flags() 37 | flags.String(srnode.Addr, "localhost", "SRNode address") 38 | flags.Int(srnode.ConcurrentNum, 1, "number of gathering metrics process") 39 | flags.Float64(srnode.ConcurrentInterval, 1, "seconds between metrics processes") 40 | flags.Int(srnode.Interval, 60, "measurement interval when measuring the interface usage rate (sec)") 41 | flags.String(srnode.MonitoringAddr, "localhost", "monitoring server address") 42 | flags.Uint16(srnode.Port, 161, "SRNode snmp port num") 43 | flags.String(srnode.SNMPAuthPass, "", "snmp authentication password") 44 | flags.String(srnode.SNMPPrivPass, "", "snmp privacy password") 45 | flags.String(srnode.SNMPUser, "", "snmp user name") 46 | flags.BoolP(srnode.TLS, "t", false, "monitoring server tls flag") 47 | flags.String(srnode.TLSCert, "", "path to monitoring server cert file (this option is enabled when tls flag is true)") 48 | 49 | // bind flags 50 | _ = viper.BindPFlags(flags) 51 | 52 | // required 53 | _ = rootCmd.MarkFlagRequired(srnode.Addr) 54 | _ = rootCmd.MarkFlagRequired(srnode.MonitoringAddr) 55 | _ = rootCmd.MarkFlagRequired(srnode.SNMPAuthPass) 56 | _ = rootCmd.MarkFlagRequired(srnode.SNMPPrivPass) 57 | _ = rootCmd.MarkFlagRequired(srnode.SNMPUser) 58 | 59 | cobra.OnInitialize(initConfig) 60 | } 61 | 62 | func initConfig() { 63 | if cfgFile == "" { 64 | home, err := homedir.Dir() 65 | if err != nil { 66 | fmt.Println(err) 67 | os.Exit(1) 68 | } 69 | cfgFile = filepath.Join(home, ".acar/srnode-agent.yaml") 70 | } 71 | viper.SetConfigFile(cfgFile) 72 | 73 | if err := viper.ReadInConfig(); err != nil { 74 | fmt.Println(err) 75 | os.Exit(1) 76 | } 77 | viper.WatchConfig() 78 | } 79 | 80 | // rootCmd represents the base command when called without any subcommands 81 | var rootCmd = &cobra.Command{ 82 | Use: "srnode-agent", 83 | Short: "acar SRNode Agent", 84 | Version: fmt.Sprintf("acar srnode agent Version: %s (Revision: %s / GoVersion: %s / Compiler: %s)\n", 85 | Version, Revision, GoVersion, Compiler), 86 | Run: func(cmd *cobra.Command, args []string) { 87 | srnode.Config.Populate() 88 | 89 | sigs := make(chan os.Signal, 1) 90 | signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM) 91 | defer func() { 92 | signal.Stop(sigs) 93 | }() 94 | 95 | errCh := make(chan error, 1) 96 | for i := 0; i < srnode.Config.ConcurrentNum; i++ { 97 | ticker := time.NewTicker(time.Duration(srnode.Config.Interval) * time.Second) 98 | go func() { 99 | for { 100 | select { 101 | case <-ticker.C: 102 | if err := run(); err != nil { 103 | errCh <- err 104 | return 105 | } 106 | } 107 | } 108 | }() 109 | time.Sleep(time.Duration(srnode.Config.ConcurrentInterval) * time.Second) 110 | } 111 | 112 | select { 113 | case sig := <-sigs: 114 | fmt.Printf("Finished with the signal: %v", sig) 115 | case err := <-errCh: 116 | fmt.Printf("[ERROR]: %v", err) 117 | } 118 | }, 119 | } 120 | 121 | // Execute adds all child commands to the root command and sets flags appropriately. 122 | // This is called by main.main(). It only needs to happen once to the rootCmd. 123 | func Execute() { 124 | if err := rootCmd.Execute(); err != nil { 125 | fmt.Println(err) 126 | os.Exit(1) 127 | } 128 | } 129 | 130 | func run() error { 131 | nodes, err := srnode.GatherMetricsBySNMP() 132 | if err != nil { 133 | return err 134 | } 135 | return srnode.SendToMonitoringServer(nodes) 136 | } 137 | -------------------------------------------------------------------------------- /cmd/srnode-agent/config.sample.yaml: -------------------------------------------------------------------------------- 1 | networkInterfaces: 2 | - sid: "fd00:0:0:1::1" 3 | nextSids: 4 | - "fd00:0:0:2::1" 5 | - "fd00:0:0:3::1" 6 | interfaceName: "ens160" 7 | linkCap: 10000 8 | # linkCap is Mbps -------------------------------------------------------------------------------- /cmd/srnode-agent/srnodeagent.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "github.com/chez-shanpu/acar/cmd/srnode-agent/app" 5 | ) 6 | 7 | func main() { 8 | app.Execute() 9 | } 10 | -------------------------------------------------------------------------------- /docker/appagent.Dockerfile: -------------------------------------------------------------------------------- 1 | FROM golang:1.15-buster AS builder 2 | ENV PROJECT_DIR /go/src/github.com/chez-shanpu/acar 3 | COPY ./ ${PROJECT_DIR}/ 4 | WORKDIR ${PROJECT_DIR}/ 5 | RUN go build -o bin/appagent ./cmd/appagent 6 | 7 | 8 | FROM ubuntu:focal 9 | COPY --from=builder /go/src/github.com/chez-shanpu/acar/bin/appagent / 10 | ENTRYPOINT ["/appagent"] 11 | CMD ["--help"] 12 | -------------------------------------------------------------------------------- /docker/controlplane.Dockerfile: -------------------------------------------------------------------------------- 1 | FROM golang:1.15-buster AS builder 2 | ENV PROJECT_DIR /go/src/github.com/chez-shanpu/acar 3 | COPY ./ ${PROJECT_DIR}/ 4 | WORKDIR ${PROJECT_DIR}/ 5 | RUN go build -o bin/controlplane ./cmd/controlplane 6 | 7 | 8 | FROM ubuntu:focal 9 | COPY --from=builder /go/src/github.com/chez-shanpu/acar/bin/controlplane / 10 | ENTRYPOINT ["/controlplane"] 11 | CMD ["--help"] 12 | -------------------------------------------------------------------------------- /docker/dataplane.Dockerfile: -------------------------------------------------------------------------------- 1 | FROM golang:1.15-buster AS builder 2 | ENV PROJECT_DIR /go/src/github.com/chez-shanpu/acar 3 | COPY ./ ${PROJECT_DIR}/ 4 | WORKDIR ${PROJECT_DIR}/ 5 | RUN go build -o bin/dataplane ./cmd/dataplane 6 | 7 | 8 | FROM ubuntu:focal 9 | COPY --from=builder /go/src/github.com/chez-shanpu/acar/bin/dataplane / 10 | ENTRYPOINT ["/dataplane"] 11 | CMD ["--help"] 12 | -------------------------------------------------------------------------------- /docker/monitoring.Dockerfile: -------------------------------------------------------------------------------- 1 | FROM golang:1.15-buster AS builder 2 | ENV PROJECT_DIR /go/src/github.com/chez-shanpu/acar 3 | COPY ./ ${PROJECT_DIR}/ 4 | WORKDIR ${PROJECT_DIR}/ 5 | RUN go build -o bin/monitoring ./cmd/monitoring 6 | 7 | 8 | FROM ubuntu:focal 9 | COPY --from=builder /go/src/github.com/chez-shanpu/acar/bin/monitoring / 10 | ENTRYPOINT ["/monitoring"] 11 | CMD ["--help"] 12 | -------------------------------------------------------------------------------- /docker/srnode-agent.Dockerfile: -------------------------------------------------------------------------------- 1 | FROM golang:1.15-buster AS builder 2 | ENV PROJECT_DIR /go/src/github.com/chez-shanpu/acar 3 | COPY ./ ${PROJECT_DIR}/ 4 | WORKDIR ${PROJECT_DIR}/ 5 | RUN go build -o bin/srnode-agent ./cmd/srnode-agent 6 | 7 | 8 | FROM ubuntu:focal 9 | COPY --from=builder /go/src/github.com/chez-shanpu/acar/bin/srnode-agent / 10 | ENTRYPOINT ["/srnode-agent"] 11 | CMD ["--help"] 12 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/chez-shanpu/acar 2 | 3 | go 1.15 4 | 5 | require ( 6 | github.com/RyanCarrier/dijkstra v1.1.0 7 | github.com/go-redis/redis/v8 v8.11.4 8 | github.com/gosnmp/gosnmp v1.34.0 9 | github.com/mitchellh/go-homedir v1.1.0 10 | github.com/sirupsen/logrus v1.8.1 11 | github.com/spf13/cobra v1.2.1 12 | github.com/spf13/viper v1.9.0 13 | github.com/vishvananda/netlink v1.1.0 14 | github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74 // indirect 15 | golang.org/x/net v0.0.0-20211123203042-d83791d6bcd9 // indirect 16 | golang.org/x/sync v0.0.0-20210220032951-036812b2e83c 17 | golang.org/x/sys v0.0.0-20211124211545-fe61309f8881 // indirect 18 | golang.org/x/text v0.3.7 // indirect 19 | google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1 // indirect 20 | google.golang.org/grpc v1.42.0 21 | google.golang.org/protobuf v1.27.1 22 | gopkg.in/ini.v1 v1.64.0 // indirect 23 | ) 24 | -------------------------------------------------------------------------------- /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 v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= 17 | cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk= 18 | cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg= 19 | cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8= 20 | cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0= 21 | cloud.google.com/go v0.83.0/go.mod h1:Z7MJUsANfY0pYPdw0lbnivPx4/vhy/e2FEkSkF7vAVY= 22 | cloud.google.com/go v0.84.0/go.mod h1:RazrYuxIK6Kb7YrzzhPoLmCVzl7Sup4NrbKPg8KHSUM= 23 | cloud.google.com/go v0.87.0/go.mod h1:TpDYlFy7vuLzZMMZ+B6iRiELaY7z/gJPaqbMx6mlWcY= 24 | cloud.google.com/go v0.90.0/go.mod h1:kRX0mNRHe0e2rC6oNakvwQqzyDmg57xJ+SZU1eT2aDQ= 25 | cloud.google.com/go v0.93.3/go.mod h1:8utlLll2EF5XMAV15woO4lSbWQlk8rer9aLOfLh7+YI= 26 | cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= 27 | cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= 28 | cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= 29 | cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= 30 | cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= 31 | cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= 32 | cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= 33 | cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= 34 | cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk= 35 | cloud.google.com/go/firestore v1.6.0/go.mod h1:afJwI0vaXwAG54kI7A//lP/lSPDkQORQuMkv56TxEPU= 36 | cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= 37 | cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= 38 | cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= 39 | cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= 40 | cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= 41 | cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= 42 | cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= 43 | cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= 44 | cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= 45 | dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= 46 | github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= 47 | github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= 48 | github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= 49 | github.com/RyanCarrier/dijkstra v1.1.0 h1:/NDihjfJA3CxFaZz8EdzTwdFKFZDvvB881OVLdakRcI= 50 | github.com/RyanCarrier/dijkstra v1.1.0/go.mod h1:5agGUBNEtUAGIANmbw09fuO3a2htPEkc1jNH01qxCWA= 51 | github.com/RyanCarrier/dijkstra-1 v0.0.0-20170512020943-0e5801a26345 h1:fgSpoKViTSqRb4hjDNj10ig5wUvO0CayCzFdLf6fuRM= 52 | github.com/RyanCarrier/dijkstra-1 v0.0.0-20170512020943-0e5801a26345/go.mod h1:OK4EvWJ441LQqGzed5NGB6vKBAE34n3z7iayPcEwr30= 53 | github.com/albertorestifo/dijkstra v0.0.0-20160910063646-aba76f725f72 h1:uGeGZl8PxSq8VZGG4QK5njJTFA4/G/x5CYORvQVXtAE= 54 | github.com/albertorestifo/dijkstra v0.0.0-20160910063646-aba76f725f72/go.mod h1:o+JdB7VetTHjLhU0N57x18B9voDBQe0paApdEAEoEfw= 55 | github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= 56 | github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= 57 | github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= 58 | github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= 59 | github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= 60 | github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= 61 | github.com/bketelsen/crypt v0.0.4/go.mod h1:aI6NrJ0pMGgvZKL1iVgXLnfIFJtfV+bKCoqOes/6LfM= 62 | github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= 63 | github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= 64 | github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= 65 | github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= 66 | github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE= 67 | github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= 68 | github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= 69 | github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= 70 | github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= 71 | github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= 72 | github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= 73 | github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= 74 | github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= 75 | github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= 76 | github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= 77 | github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= 78 | github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= 79 | github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= 80 | github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= 81 | github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= 82 | github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= 83 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 84 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= 85 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 86 | github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= 87 | github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= 88 | github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= 89 | github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= 90 | github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= 91 | github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= 92 | github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= 93 | github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= 94 | github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= 95 | github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= 96 | github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= 97 | github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= 98 | github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= 99 | github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= 100 | github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= 101 | github.com/fsnotify/fsnotify v1.5.1 h1:mZcQUHVQUQWoPXXtuf9yuEXKudkV2sx1E06UadKWpgI= 102 | github.com/fsnotify/fsnotify v1.5.1/go.mod h1:T3375wBYaZdLLcVNkcVbzGHY7f1l/uK5T5Ai1i3InKU= 103 | github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= 104 | github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= 105 | github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= 106 | github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= 107 | github.com/go-redis/redis/v8 v8.11.4 h1:kHoYkfZP6+pe04aFTnhDH6GDROa5yJdHJVNxV3F46Tg= 108 | github.com/go-redis/redis/v8 v8.11.4/go.mod h1:2Z2wHZXdQpCDXEGzqMockDpNyYvi2l4Pxt6RJr792+w= 109 | github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= 110 | github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= 111 | github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= 112 | github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= 113 | github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= 114 | github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= 115 | github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= 116 | github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= 117 | github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= 118 | github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= 119 | github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= 120 | github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= 121 | github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= 122 | github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= 123 | github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8= 124 | github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= 125 | github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 126 | github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 127 | github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 128 | github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= 129 | github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= 130 | github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= 131 | github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= 132 | github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= 133 | github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= 134 | github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= 135 | github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= 136 | github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= 137 | github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= 138 | github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= 139 | github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= 140 | github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM= 141 | github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= 142 | github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= 143 | github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= 144 | github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= 145 | github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= 146 | github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= 147 | github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= 148 | github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= 149 | github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 150 | github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 151 | github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 152 | github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 153 | github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 154 | github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 155 | github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 156 | github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 157 | github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ= 158 | github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 159 | github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= 160 | github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= 161 | github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= 162 | github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= 163 | github.com/google/martian/v3 v3.2.1/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk= 164 | github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= 165 | github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= 166 | github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= 167 | github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= 168 | github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= 169 | github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= 170 | github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= 171 | github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= 172 | github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= 173 | github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= 174 | github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= 175 | github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= 176 | github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= 177 | github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= 178 | github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= 179 | github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= 180 | github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= 181 | github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= 182 | github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0= 183 | github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= 184 | github.com/gosnmp/gosnmp v1.34.0 h1:p96iiNTTdL4ZYspPC3leSKXiHfE1NiIYffMu9100p5E= 185 | github.com/gosnmp/gosnmp v1.34.0/go.mod h1:QWTRprXN9haHFof3P96XTDYc46boCGAh5IXp0DniEx4= 186 | github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= 187 | github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= 188 | github.com/hashicorp/consul/api v1.10.1/go.mod h1:XjsvQN+RJGWI2TWy1/kqaE16HrR2J/FWgkYjdZQsX9M= 189 | github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= 190 | github.com/hashicorp/consul/sdk v0.8.0/go.mod h1:GBvyrGALthsZObzUGsfgHZQDXjg4lOjagTIwIR1vPms= 191 | github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= 192 | github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= 193 | github.com/hashicorp/go-hclog v0.12.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= 194 | github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= 195 | github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= 196 | github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= 197 | github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA= 198 | github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= 199 | github.com/hashicorp/go-rootcerts v1.0.2/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8= 200 | github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= 201 | github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= 202 | github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= 203 | github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= 204 | github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= 205 | github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= 206 | github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= 207 | github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= 208 | github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= 209 | github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= 210 | github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= 211 | github.com/hashicorp/mdns v1.0.1/go.mod h1:4gW7WsVCke5TE7EPeYliwHlRUyBtfCwuFwuMg2DmyNY= 212 | github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= 213 | github.com/hashicorp/memberlist v0.2.2/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOnAH9VT3Sh9MUE= 214 | github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= 215 | github.com/hashicorp/serf v0.9.5/go.mod h1:UWDWwZeL5cuWDJdl0C6wrvrUwEqtQ4ZKBKKENpqIUyk= 216 | github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= 217 | github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= 218 | github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= 219 | github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= 220 | github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= 221 | github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= 222 | github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= 223 | github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= 224 | github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= 225 | github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= 226 | github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= 227 | github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= 228 | github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= 229 | github.com/kr/pretty v0.2.0 h1:s5hAObm+yFO5uHYt5dYjxi2rXrsnmRpJx4OYvIWUaQs= 230 | github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= 231 | github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= 232 | github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= 233 | github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= 234 | github.com/magiconair/properties v1.8.5 h1:b6kJs+EmPFMYGkow9GiUyCyOvIwYetYJ3fSaWak/Gls= 235 | github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= 236 | github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= 237 | github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= 238 | github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= 239 | github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= 240 | github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= 241 | github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84= 242 | github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= 243 | github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= 244 | github.com/mattomatic/dijkstra v0.0.0-20130617153013-6f6d134eb237 h1:acuCHBjzG7MFTugvx3buC4m5rLDLaKC9J8C9jtlraRc= 245 | github.com/mattomatic/dijkstra v0.0.0-20130617153013-6f6d134eb237/go.mod h1:UOnLAUmVG5paym8pD3C4B9BQylUDC2vXFJJpT7JrlEA= 246 | github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= 247 | github.com/miekg/dns v1.1.26/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso= 248 | github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= 249 | github.com/mitchellh/cli v1.1.0/go.mod h1:xcISNoH86gajksDmfB23e/pu+B+GeFRMYmoHXxx3xhI= 250 | github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= 251 | github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= 252 | github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= 253 | github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= 254 | github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= 255 | github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= 256 | github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= 257 | github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= 258 | github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= 259 | github.com/mitchellh/mapstructure v1.4.2 h1:6h7AQ0yhTcIsmFmnAwQls75jp2Gzs4iB8W7pjMO+rqo= 260 | github.com/mitchellh/mapstructure v1.4.2/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= 261 | github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= 262 | github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= 263 | github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= 264 | github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= 265 | github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= 266 | github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= 267 | github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= 268 | github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= 269 | github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc= 270 | github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= 271 | github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= 272 | github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= 273 | github.com/onsi/gomega v1.16.0 h1:6gjqkI8iiRHMvdccRJM8rVKjCWk6ZIm6FTm3ddIe4/c= 274 | github.com/onsi/gomega v1.16.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= 275 | github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= 276 | github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= 277 | github.com/pelletier/go-toml v1.9.4 h1:tjENF6MfZAg8e4ZmZTeWaWiT2vXtsoO6+iuOjFhECwM= 278 | github.com/pelletier/go-toml v1.9.4/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= 279 | github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 280 | github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI= 281 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 282 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 283 | github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= 284 | github.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSgv7Sy7s/s= 285 | github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= 286 | github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= 287 | github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= 288 | github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= 289 | github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= 290 | github.com/sagikazarmark/crypt v0.1.0/go.mod h1:B/mN0msZuINBtQ1zZLEQcegFJJf9vnYIR88KRMEuODE= 291 | github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= 292 | github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= 293 | github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= 294 | github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= 295 | github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= 296 | github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= 297 | github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= 298 | github.com/spf13/afero v1.6.0 h1:xoax2sJ2DT8S8xA2paPFjDCScCNeWsg75VG0DLRreiY= 299 | github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= 300 | github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= 301 | github.com/spf13/cast v1.4.1 h1:s0hze+J0196ZfEMTs80N7UlFt0BDuQ7Q+JDnHiMWKdA= 302 | github.com/spf13/cast v1.4.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= 303 | github.com/spf13/cobra v1.2.1 h1:+KmjbUw1hriSNMF55oPrkZcb27aECyrj8V2ytv7kWDw= 304 | github.com/spf13/cobra v1.2.1/go.mod h1:ExllRjgxM/piMAM+3tAZvg8fsklGAf3tPfi+i8t68Nk= 305 | github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk= 306 | github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= 307 | github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= 308 | github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= 309 | github.com/spf13/viper v1.8.1/go.mod h1:o0Pch8wJ9BVSWGQMbra6iw0oQ5oktSIBaujf1rJH9Ns= 310 | github.com/spf13/viper v1.9.0 h1:yR6EXjTp0y0cLN8OZg1CRZmOBdI88UcGkhgyJhu6nZk= 311 | github.com/spf13/viper v1.9.0/go.mod h1:+i6ajR7OX2XaiBkrcZJFK21htRk7eDeLg7+O6bhUPP4= 312 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 313 | github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= 314 | github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= 315 | github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= 316 | github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= 317 | github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 318 | github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= 319 | github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 320 | github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s= 321 | github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= 322 | github.com/vishvananda/netlink v1.1.0 h1:1iyaYNBLmP6L0220aDnYQpo1QEV4t4hJ+xEEhhJH8j0= 323 | github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE= 324 | github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU= 325 | github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74 h1:gga7acRE695APm9hlsSMoOoE65U4/TcqNj90mc69Rlg= 326 | github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0= 327 | github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= 328 | github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= 329 | github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= 330 | github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= 331 | github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= 332 | go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs= 333 | go.etcd.io/etcd/client/pkg/v3 v3.5.0/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g= 334 | go.etcd.io/etcd/client/v2 v2.305.0/go.mod h1:h9puh54ZTgAKtEbut2oe9P4L/oqKCVB6xsXlzd7alYQ= 335 | go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= 336 | go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= 337 | go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= 338 | go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= 339 | go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= 340 | go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= 341 | go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= 342 | go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= 343 | go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= 344 | go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= 345 | go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= 346 | golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= 347 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 348 | golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 349 | golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 350 | golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 351 | golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY= 352 | golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 353 | golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= 354 | golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= 355 | golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= 356 | golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= 357 | golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= 358 | golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= 359 | golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= 360 | golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= 361 | golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= 362 | golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= 363 | golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= 364 | golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= 365 | golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= 366 | golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= 367 | golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= 368 | golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= 369 | golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= 370 | golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= 371 | golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= 372 | golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= 373 | golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= 374 | golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= 375 | golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= 376 | golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= 377 | golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= 378 | golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= 379 | golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= 380 | golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= 381 | golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= 382 | golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= 383 | golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= 384 | golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= 385 | golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= 386 | golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= 387 | golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= 388 | golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= 389 | golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= 390 | golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 391 | golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 392 | golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 393 | golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 394 | golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 395 | golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 396 | golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 397 | golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 398 | golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 399 | golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 400 | golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 401 | golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= 402 | golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 403 | golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 404 | golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 405 | golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 406 | golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 407 | golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 408 | golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 409 | golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 410 | golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 411 | golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 412 | golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= 413 | golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= 414 | golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= 415 | golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= 416 | golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= 417 | golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= 418 | golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= 419 | golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= 420 | golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= 421 | golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= 422 | golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= 423 | golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= 424 | golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= 425 | golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= 426 | golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= 427 | golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= 428 | golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= 429 | golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= 430 | golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= 431 | golang.org/x/net v0.0.0-20211123203042-d83791d6bcd9 h1:0qxwC5n+ttVOINCBeRHO0nq9X7uy8SDsPoi5OaCdIEI= 432 | golang.org/x/net v0.0.0-20211123203042-d83791d6bcd9/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= 433 | golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= 434 | golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= 435 | golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= 436 | golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= 437 | golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= 438 | golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= 439 | golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= 440 | golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= 441 | golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= 442 | golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= 443 | golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= 444 | golang.org/x/oauth2 v0.0.0-20210402161424-2e8d93401602/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= 445 | golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= 446 | golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= 447 | golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= 448 | golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= 449 | golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 450 | golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 451 | golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 452 | golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 453 | golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 454 | golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 455 | golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 456 | golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 457 | golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 458 | golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 459 | golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ= 460 | golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 461 | golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 462 | golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 463 | golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 464 | golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 465 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 466 | golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 467 | golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 468 | golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 469 | golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 470 | golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 471 | golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 472 | golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 473 | golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 474 | golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 475 | golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 476 | golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 477 | golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 478 | golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 479 | golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 480 | golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 481 | golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 482 | golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 483 | golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 484 | golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 485 | golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 486 | golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 487 | golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 488 | golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 489 | golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 490 | golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 491 | golang.org/x/sys v0.0.0-20200217220822-9197077df867/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 492 | golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 493 | golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 494 | golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 495 | golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 496 | golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 497 | golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 498 | golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 499 | golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 500 | golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 501 | golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 502 | golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 503 | golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 504 | golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 505 | golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 506 | golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 507 | golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 508 | golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 509 | golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 510 | golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 511 | golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 512 | golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 513 | golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 514 | golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 515 | golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 516 | golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 517 | golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 518 | golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 519 | golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 520 | golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 521 | golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 522 | golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 523 | golang.org/x/sys v0.0.0-20211124211545-fe61309f8881 h1:TyHqChC80pFkXWraUUf6RuB5IqFdQieMLwwCJokV2pc= 524 | golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 525 | golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= 526 | golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 527 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 528 | golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 529 | golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= 530 | golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 531 | golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 532 | golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 533 | golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 534 | golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= 535 | golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= 536 | golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= 537 | golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= 538 | golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= 539 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 540 | golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 541 | golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= 542 | golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= 543 | golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= 544 | golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= 545 | golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= 546 | golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= 547 | golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= 548 | golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= 549 | golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= 550 | golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= 551 | golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= 552 | golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 553 | golang.org/x/tools v0.0.0-20190907020128-2ca718005c18/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 554 | golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 555 | golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 556 | golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 557 | golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 558 | golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 559 | golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 560 | golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 561 | golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 562 | golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= 563 | golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= 564 | golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= 565 | golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= 566 | golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= 567 | golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= 568 | golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= 569 | golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= 570 | golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= 571 | golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= 572 | golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= 573 | golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= 574 | golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= 575 | golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= 576 | golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= 577 | golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= 578 | golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= 579 | golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= 580 | golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= 581 | golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= 582 | golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= 583 | golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= 584 | golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= 585 | golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= 586 | golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= 587 | golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= 588 | golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= 589 | golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= 590 | golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= 591 | golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= 592 | golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= 593 | golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= 594 | golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= 595 | golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= 596 | golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 597 | golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 598 | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 599 | golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= 600 | golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 601 | google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= 602 | google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= 603 | google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= 604 | google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= 605 | google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= 606 | google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= 607 | google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= 608 | google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= 609 | google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= 610 | google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= 611 | google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= 612 | google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= 613 | google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= 614 | google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= 615 | google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= 616 | google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= 617 | google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg= 618 | google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE= 619 | google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8= 620 | google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU= 621 | google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94= 622 | google.golang.org/api v0.44.0/go.mod h1:EBOGZqzyhtvMDoxwS97ctnh0zUmYY6CxqXsc1AvkYD8= 623 | google.golang.org/api v0.47.0/go.mod h1:Wbvgpq1HddcWVtzsVLyfLp8lDg6AA241LmgIL59tHXo= 624 | google.golang.org/api v0.48.0/go.mod h1:71Pr1vy+TAZRPkPs/xlCf5SsU8WjuAWv1Pfjbtukyy4= 625 | google.golang.org/api v0.50.0/go.mod h1:4bNT5pAuq5ji4SRZm+5QIkjny9JAyVD/3gaSihNefaw= 626 | google.golang.org/api v0.51.0/go.mod h1:t4HdrdoNgyN5cbEfm7Lum0lcLDLiise1F8qDKX00sOU= 627 | google.golang.org/api v0.54.0/go.mod h1:7C4bFFOvVDGXjfDTAsgGwDgAxRDeQ4X8NvUedIt6z3k= 628 | google.golang.org/api v0.56.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE= 629 | google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= 630 | google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= 631 | google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= 632 | google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= 633 | google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= 634 | google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= 635 | google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= 636 | google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= 637 | google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= 638 | google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= 639 | google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= 640 | google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= 641 | google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= 642 | google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= 643 | google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= 644 | google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= 645 | google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= 646 | google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= 647 | google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= 648 | google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= 649 | google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= 650 | google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= 651 | google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= 652 | google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= 653 | google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= 654 | google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= 655 | google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= 656 | google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= 657 | google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= 658 | google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= 659 | google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= 660 | google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= 661 | google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= 662 | google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= 663 | google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= 664 | google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= 665 | google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= 666 | google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= 667 | google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= 668 | google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= 669 | google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= 670 | google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= 671 | google.golang.org/genproto v0.0.0-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= 672 | google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= 673 | google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= 674 | google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= 675 | google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= 676 | google.golang.org/genproto v0.0.0-20210513213006-bf773b8c8384/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A= 677 | google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= 678 | google.golang.org/genproto v0.0.0-20210604141403-392c879c8b08/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= 679 | google.golang.org/genproto v0.0.0-20210608205507-b6d2f5bf0d7d/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= 680 | google.golang.org/genproto v0.0.0-20210624195500-8bfb893ecb84/go.mod h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24= 681 | google.golang.org/genproto v0.0.0-20210713002101-d411969a0d9a/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k= 682 | google.golang.org/genproto v0.0.0-20210716133855-ce7ef5c701ea/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k= 683 | google.golang.org/genproto v0.0.0-20210728212813-7823e685a01f/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48= 684 | google.golang.org/genproto v0.0.0-20210805201207-89edb61ffb67/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48= 685 | google.golang.org/genproto v0.0.0-20210813162853-db860fec028c/go.mod h1:cFeNkxwySK631ADgubI+/XFU/xp8FD5KIVV4rj8UC5w= 686 | google.golang.org/genproto v0.0.0-20210821163610-241b8fcbd6c8/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= 687 | google.golang.org/genproto v0.0.0-20210828152312-66f60bf46e71/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= 688 | google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1 h1:b9mVrqYfq3P4bCdaLg1qtBnPzUYgglsIdjZkL/fQVOE= 689 | google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= 690 | google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= 691 | google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= 692 | google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= 693 | google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= 694 | google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= 695 | google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= 696 | google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= 697 | google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= 698 | google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= 699 | google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= 700 | google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= 701 | google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= 702 | google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= 703 | google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= 704 | google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= 705 | google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= 706 | google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= 707 | google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= 708 | google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= 709 | google.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= 710 | google.golang.org/grpc v1.37.1/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= 711 | google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= 712 | google.golang.org/grpc v1.39.0/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= 713 | google.golang.org/grpc v1.39.1/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= 714 | google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= 715 | google.golang.org/grpc v1.42.0 h1:XT2/MFpuPFsEX2fWh3YQtHkZ+WYZFQRfaUgLZYj/p6A= 716 | google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= 717 | google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= 718 | google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= 719 | google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= 720 | google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= 721 | google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= 722 | google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= 723 | google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= 724 | google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= 725 | google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= 726 | google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= 727 | google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= 728 | google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= 729 | google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= 730 | google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ= 731 | google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= 732 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 733 | gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 734 | gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= 735 | gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 736 | gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= 737 | gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= 738 | gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= 739 | gopkg.in/ini.v1 v1.63.2/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= 740 | gopkg.in/ini.v1 v1.64.0 h1:Mj2zXEXcNb5joEiSA0zc3HZpTst/iyjNiR4CN8tDzOg= 741 | gopkg.in/ini.v1 v1.64.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= 742 | gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= 743 | gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= 744 | gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 745 | gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 746 | gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 747 | gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 748 | gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 749 | gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= 750 | gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= 751 | gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 752 | gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= 753 | gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 754 | honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 755 | honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 756 | honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 757 | honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 758 | honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= 759 | honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= 760 | honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= 761 | rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= 762 | rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= 763 | rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= 764 | -------------------------------------------------------------------------------- /pkg/appagent/appagent.go: -------------------------------------------------------------------------------- 1 | package appagent 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "time" 7 | 8 | "github.com/sirupsen/logrus" 9 | 10 | "github.com/RyanCarrier/dijkstra" 11 | "github.com/chez-shanpu/acar/api" 12 | "github.com/chez-shanpu/acar/pkg/grpc" 13 | ) 14 | 15 | const ( 16 | startVertexName = "start" 17 | ratioMetricsTypeOption = "ratio" 18 | bytesMetricsTypeOption = "bytes" 19 | infCost = 999999 20 | byteToBit = 8.0 21 | ) 22 | 23 | func GetSRNodesInfo() ([]*api.Node, error) { 24 | conn, err := grpc.MakeConn(Config.MonitoringAddr, Config.MonitoringTLS, Config.MonitoringCert) 25 | if err != nil { 26 | return nil, err 27 | } 28 | defer conn.Close() 29 | 30 | c := api.NewMonitoringClient(conn) 31 | ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) 32 | defer cancel() 33 | 34 | res, err := c.GetNodes(ctx, &api.GetNodesRequest{}) 35 | if err != nil { 36 | return nil, err 37 | } 38 | return res.GetNodes(), nil 39 | } 40 | 41 | func MakeGraph(nodes []*api.Node) (*dijkstra.Graph, error) { 42 | graph := dijkstra.NewGraph() 43 | for _, node := range nodes { 44 | graph.AddMappedVertex(node.SID) 45 | cost, err := makeCost(node) 46 | if err != nil { 47 | return nil, err 48 | } 49 | 50 | for _, ns := range node.NextSids { 51 | if err = graph.AddMappedArc(node.SID, ns, cost); err != nil { 52 | return nil, err 53 | } 54 | } 55 | } 56 | return graph, nil 57 | } 58 | 59 | func MakeSIDList(g *dijkstra.Graph) ([]string, error) { 60 | best, err := calcPath(g, Config.DepSIDs, Config.DstSID) 61 | if err != nil { 62 | return nil, err 63 | } 64 | if best.Distance >= infCost { 65 | return nil, nil 66 | } 67 | 68 | return constructSIDList(g, best), nil 69 | } 70 | 71 | func SendSRInfoToControlPlane(sidList []string) error { 72 | conn, err := grpc.MakeConn(Config.ControlplaneAddr, Config.ControlplaneTLS, Config.ControlplaneCert) 73 | if err != nil { 74 | return err 75 | } 76 | defer conn.Close() 77 | 78 | c := api.NewControlPlaneClient(conn) 79 | ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) 80 | defer cancel() 81 | 82 | ai := &api.AppInfo{ 83 | AppName: Config.AppName, 84 | SrcAddr: Config.SrcAddr, 85 | DstAddr: Config.DstAddr, 86 | SidList: sidList, 87 | } 88 | _, err = c.RegisterSRPolicy(ctx, &api.RegisterSRPolicyRequest{AppInfo: ai}) 89 | return err 90 | } 91 | 92 | func makeCost(node *api.Node) (int64, error) { 93 | cost := int64(0) 94 | 95 | switch Config.MetricsType { 96 | case ratioMetricsTypeOption: 97 | if Config.RequireValue <= (100 - node.LinkUsageRatio) { 98 | cost = 1 99 | } else { 100 | cost = infCost 101 | } 102 | case bytesMetricsTypeOption: 103 | if Config.RequireValue <= float64(node.LinkCap)-node.LinkUsageBytes*byteToBit { 104 | cost = 1 105 | } else { 106 | cost = infCost 107 | } 108 | log.WithFields(logrus.Fields{ 109 | "Node": fmt.Sprintf("%#v", node), 110 | "require": Config.RequireValue, 111 | "cost": cost, 112 | }).Info("node cost is calculated by bytes metrics") 113 | default: 114 | return 0, fmt.Errorf("metrics type is wrong: %s", Config.MetricsType) 115 | } 116 | return cost, nil 117 | } 118 | 119 | func calcPath(g *dijkstra.Graph, deps []string, dst string) (*dijkstra.BestPath, error) { 120 | dstSidIndex, err := g.GetMapping(dst) 121 | if err != nil { 122 | return nil, err 123 | } 124 | startID := g.AddMappedVertex(startVertexName) 125 | for _, dep := range deps { 126 | if err = g.AddMappedArc(startVertexName, dep, 0); err != nil { 127 | return nil, err 128 | } 129 | } 130 | best, err := g.Shortest(startID, dstSidIndex) 131 | return &best, err 132 | } 133 | 134 | func constructSIDList(g *dijkstra.Graph, b *dijkstra.BestPath) []string { 135 | var sids []string 136 | 137 | for _, verIndex := range b.Path { 138 | sid, _ := g.GetMapped(verIndex) 139 | if sid != startVertexName { 140 | sids = append(sids, sid) 141 | } 142 | } 143 | return sids 144 | } 145 | -------------------------------------------------------------------------------- /pkg/appagent/config.go: -------------------------------------------------------------------------------- 1 | package appagent 2 | 3 | import "github.com/spf13/viper" 4 | 5 | const ( 6 | AppName = "app" 7 | ControlplaneAddr = "cp-addr" 8 | ControlplaneCert = "cp-cert" 9 | ControlplaneTLS = "cp-tls" 10 | DepSID = "dep-sid" 11 | DstAddr = "dst-addr" 12 | DstSID = "dst-sid" 13 | Interval = "interval" 14 | Lazy = "lazy" 15 | Metrics = "metrics" 16 | MonitoringAddr = "mnt-addr" 17 | MonitoringCert = "mnt-cert" 18 | MonitoringTLS = "mnt-tls" 19 | Require = "require" 20 | SrcAddr = "src-addr" 21 | ) 22 | 23 | type DaemonConfig struct { 24 | AppName string 25 | ControlplaneAddr string 26 | ControlplaneCert string 27 | ControlplaneTLS bool 28 | DepSIDs []string 29 | DstAddr string 30 | DstSID string 31 | Interval int 32 | Lazy float64 33 | MetricsType string 34 | MonitoringAddr string 35 | MonitoringCert string 36 | MonitoringTLS bool 37 | RequireValue float64 38 | SrcAddr string 39 | } 40 | 41 | var Config = &DaemonConfig{} 42 | 43 | func (c *DaemonConfig) Populate() { 44 | c.AppName = viper.GetString(AppName) 45 | c.ControlplaneAddr = viper.GetString(ControlplaneAddr) 46 | c.ControlplaneCert = viper.GetString(ControlplaneCert) 47 | c.ControlplaneTLS = viper.GetBool(ControlplaneTLS) 48 | c.DepSIDs = viper.GetStringSlice(DepSID) 49 | c.DstAddr = viper.GetString(DstAddr) 50 | c.DstSID = viper.GetString(DstSID) 51 | c.Interval = viper.GetInt(Interval) 52 | c.Lazy = viper.GetFloat64(Lazy) 53 | c.MetricsType = viper.GetString(Metrics) 54 | c.MonitoringAddr = viper.GetString(MonitoringAddr) 55 | c.MonitoringCert = viper.GetString(MonitoringCert) 56 | c.MonitoringTLS = viper.GetBool(MonitoringTLS) 57 | c.RequireValue = viper.GetFloat64(Require) 58 | c.SrcAddr = viper.GetString(SrcAddr) 59 | } 60 | -------------------------------------------------------------------------------- /pkg/appagent/logging.go: -------------------------------------------------------------------------------- 1 | package appagent 2 | 3 | import "github.com/chez-shanpu/acar/pkg/logging" 4 | 5 | var ( 6 | log = logging.DefaultLogger 7 | ) 8 | -------------------------------------------------------------------------------- /pkg/controlplane/api.go: -------------------------------------------------------------------------------- 1 | package controlplane 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "time" 7 | 8 | "google.golang.org/protobuf/types/known/timestamppb" 9 | 10 | "github.com/chez-shanpu/acar/api" 11 | "github.com/chez-shanpu/acar/pkg/grpc" 12 | "github.com/chez-shanpu/acar/pkg/logging" 13 | "github.com/chez-shanpu/acar/pkg/logging/logfields" 14 | "github.com/sirupsen/logrus" 15 | ) 16 | 17 | const ( 18 | pkg = "controlplane" 19 | ) 20 | 21 | var log = logging.DefaultLogger.WithField(logfields.Package, pkg) 22 | 23 | type Server struct { 24 | api.UnimplementedControlPlaneServer 25 | } 26 | 27 | func NewServer() *Server { 28 | return &Server{} 29 | } 30 | 31 | func (s *Server) RegisterSRPolicy(ctx context.Context, r *api.RegisterSRPolicyRequest) (*api.RegisterSRPolicyResponse, error) { 32 | if err := registerSRPolicy(r.GetAppInfo()); err != nil { 33 | log.WithFields(logrus.Fields{ 34 | "AppInfo": fmt.Sprintf("%#v", r.GetAppInfo()), 35 | }).Error(err) 36 | return nil, err 37 | } 38 | return &api.RegisterSRPolicyResponse{Time: timestamppb.Now()}, nil 39 | } 40 | 41 | func registerSRPolicy(ai *api.AppInfo) error { 42 | conn, err := grpc.MakeConn(Config.DataplaneAddr, Config.DataplaneTLS, Config.DataplaneCert) 43 | if err != nil { 44 | return err 45 | } 46 | defer conn.Close() 47 | 48 | c := api.NewDataPlaneClient(conn) 49 | dctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) 50 | defer cancel() 51 | 52 | sri := &api.SRInfo{ 53 | SrcAddr: ai.SrcAddr, 54 | DstAddr: ai.DstAddr, 55 | SidList: ai.SidList, 56 | } 57 | _, err = c.ApplySRPolicy(dctx, &api.ApplySRPolicyRequest{SrInfo: sri}) 58 | return err 59 | } 60 | -------------------------------------------------------------------------------- /pkg/controlplane/config.go: -------------------------------------------------------------------------------- 1 | package controlplane 2 | 3 | import "github.com/spf13/viper" 4 | 5 | const ( 6 | DataplaneAddr = "dp-addr" 7 | DataplaneCert = "dp-cert" 8 | DataplaneTLS = "dp-tls" 9 | ServerAddr = "addr" 10 | TLS = "tls" 11 | TLSCert = "cert" 12 | TLSKey = "key" 13 | ) 14 | 15 | type DaemonConfig struct { 16 | DataplaneAddr string 17 | DataplaneCert string 18 | DataplaneTLS bool 19 | ServerAddr string 20 | TLS bool 21 | TLSCert string 22 | TLSKey string 23 | } 24 | 25 | var Config = &DaemonConfig{} 26 | 27 | func (c *DaemonConfig) Populate() { 28 | c.DataplaneAddr = viper.GetString(DataplaneAddr) 29 | c.DataplaneCert = viper.GetString(DataplaneCert) 30 | c.DataplaneTLS = viper.GetBool(DataplaneTLS) 31 | c.ServerAddr = viper.GetString(ServerAddr) 32 | c.TLS = viper.GetBool(TLS) 33 | c.TLSCert = viper.GetString(TLSCert) 34 | c.TLSKey = viper.GetString(TLSKey) 35 | } 36 | -------------------------------------------------------------------------------- /pkg/dataplane/api.go: -------------------------------------------------------------------------------- 1 | package dataplane 2 | 3 | import ( 4 | "context" 5 | "errors" 6 | "fmt" 7 | "net" 8 | 9 | "github.com/sirupsen/logrus" 10 | "google.golang.org/protobuf/types/known/timestamppb" 11 | 12 | "github.com/chez-shanpu/acar/pkg/logging" 13 | "github.com/chez-shanpu/acar/pkg/logging/logfields" 14 | 15 | "github.com/chez-shanpu/acar/api" 16 | "github.com/vishvananda/netlink" 17 | "github.com/vishvananda/netlink/nl" 18 | ) 19 | 20 | const ( 21 | pkg = "dataplane" 22 | ) 23 | 24 | var log = logging.DefaultLogger.WithField(logfields.Package, pkg) 25 | 26 | type Server struct { 27 | api.UnimplementedDataPlaneServer 28 | } 29 | 30 | func NewServer() *Server { 31 | return &Server{} 32 | } 33 | 34 | func (s *Server) ApplySRPolicy(ctx context.Context, r *api.ApplySRPolicyRequest) (*api.ApplySRPolicyResponse, error) { 35 | if err := applySRPolicy(r.GetSrInfo()); err != nil { 36 | log.WithFields(logrus.Fields{ 37 | "SRInfo": fmt.Sprintf("%#v", r.GetSrInfo()), 38 | }).Error(err) 39 | return nil, err 40 | } 41 | return &api.ApplySRPolicyResponse{Time: timestamppb.Now()}, nil 42 | } 43 | 44 | func applySRPolicy(si *api.SRInfo) error { 45 | if err := validateSRInfo(si); err != nil { 46 | return err 47 | } 48 | 49 | li, err := netlink.LinkByName(Config.Device) 50 | if err != nil { 51 | return err 52 | } 53 | 54 | dstIP, dstIPnet, err := net.ParseCIDR(si.DstAddr) 55 | if err != nil { 56 | return err 57 | } 58 | 59 | route := netlink.Route{ 60 | LinkIndex: li.Attrs().Index, 61 | Dst: &net.IPNet{ 62 | IP: dstIP, 63 | Mask: dstIPnet.Mask, 64 | }, 65 | Encap: constructEncapRule(si), 66 | } 67 | _ = netlink.RouteDel(&route) 68 | return netlink.RouteAdd(&route) 69 | } 70 | 71 | func constructEncapRule(si *api.SRInfo) *netlink.SEG6Encap { 72 | var sidList []net.IP 73 | 74 | for _, sid := range si.SidList { 75 | sidList = append([]net.IP{net.ParseIP(sid)}, sidList...) 76 | } 77 | encap := &netlink.SEG6Encap{Mode: nl.SEG6_IPTUN_MODE_ENCAP} 78 | encap.Segments = sidList 79 | return encap 80 | } 81 | 82 | func validateSRInfo(si *api.SRInfo) error { 83 | srcIPv6Flag, err := isIPV6(si.SrcAddr) 84 | if err != nil { 85 | return errors.New("src address is wrong format") 86 | } 87 | 88 | dstIPv6Flag, err := isIPV6(si.DstAddr) 89 | if err != nil { 90 | return errors.New("dst address is wrong format") 91 | } 92 | 93 | if srcIPv6Flag != dstIPv6Flag { 94 | return errors.New("src address and dst address are different format") 95 | } 96 | return nil 97 | } 98 | 99 | func isIPV6(addr string) (bool, error) { 100 | for i := 0; i < len(addr); i++ { 101 | switch addr[i] { 102 | case '.': 103 | return false, nil 104 | case ':': 105 | return true, nil 106 | } 107 | } 108 | return false, errors.New("not ip addr") 109 | } 110 | -------------------------------------------------------------------------------- /pkg/dataplane/config.go: -------------------------------------------------------------------------------- 1 | package dataplane 2 | 3 | import "github.com/spf13/viper" 4 | 5 | const ( 6 | Device = "device" 7 | ServerAddr = "addr" 8 | TLS = "tls" 9 | TLSCert = "cert" 10 | TLSKey = "key" 11 | ) 12 | 13 | type DaemonConfig struct { 14 | Device string 15 | ServerAddr string 16 | TLS bool 17 | TLSCert string 18 | TLSKey string 19 | } 20 | 21 | var Config = &DaemonConfig{} 22 | 23 | func (c *DaemonConfig) Populate() { 24 | c.Device = viper.GetString(Device) 25 | c.ServerAddr = viper.GetString(ServerAddr) 26 | c.TLS = viper.GetBool(TLS) 27 | c.TLSCert = viper.GetString(TLSCert) 28 | c.TLSKey = viper.GetString(TLSKey) 29 | } 30 | -------------------------------------------------------------------------------- /pkg/grpc/grpc.go: -------------------------------------------------------------------------------- 1 | package grpc 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | 7 | "google.golang.org/grpc" 8 | "google.golang.org/grpc/credentials" 9 | ) 10 | 11 | func MakeConn(addr string, tls bool, cert string) (*grpc.ClientConn, error) { 12 | opts, err := MakeClientOpts(tls, cert) 13 | if err != nil { 14 | return nil, err 15 | } 16 | return grpc.Dial(addr, opts...) 17 | } 18 | 19 | func MakeClientOpts(tls bool, cert string) ([]grpc.DialOption, error) { 20 | var opts []grpc.DialOption 21 | 22 | if tls { 23 | if cert == "" { 24 | return nil, fmt.Errorf("certificate file path is undefined") 25 | } 26 | creds, err := credentials.NewClientTLSFromFile(cert, "") 27 | if err != nil { 28 | return nil, fmt.Errorf("failed to create TLS credentials: %v", err) 29 | } 30 | opts = append(opts, grpc.WithTransportCredentials(creds)) 31 | } else { 32 | opts = append(opts, grpc.WithInsecure()) 33 | } 34 | opts = append(opts, grpc.WithBlock()) 35 | return opts, nil 36 | } 37 | 38 | func MakeServer(tls bool, cert, key string) (*grpc.Server, error) { 39 | var opts []grpc.ServerOption 40 | 41 | if tls { 42 | if cert == "" || key == "" { 43 | return nil, errors.New("cert file path or key file path is empty") 44 | } 45 | creds, err := credentials.NewServerTLSFromFile(cert, key) 46 | if err != nil { 47 | return nil, err 48 | } 49 | opts = []grpc.ServerOption{grpc.Creds(creds)} 50 | } 51 | 52 | return grpc.NewServer(opts...), nil 53 | } 54 | -------------------------------------------------------------------------------- /pkg/logging/logfields/logfields.go: -------------------------------------------------------------------------------- 1 | package logfields 2 | 3 | const ( 4 | Command = "cmd" 5 | Package = "pkg" 6 | ) 7 | -------------------------------------------------------------------------------- /pkg/logging/logging.go: -------------------------------------------------------------------------------- 1 | package logging 2 | 3 | import "github.com/sirupsen/logrus" 4 | 5 | type LogFormat string 6 | 7 | const ( 8 | LogFormatText LogFormat = "text" 9 | LogFormatJSON LogFormat = "json" 10 | 11 | DefaultLogFormat = LogFormatText 12 | DefaultLogLevel = logrus.InfoLevel 13 | ) 14 | 15 | var DefaultLogger = InitializeDefaultLogger() 16 | 17 | func InitializeDefaultLogger() (logger *logrus.Logger) { 18 | logger = logrus.New() 19 | logger.SetFormatter(GetFormatter(DefaultLogFormat)) 20 | logger.SetLevel(DefaultLogLevel) 21 | return 22 | } 23 | 24 | func GetFormatter(format LogFormat) logrus.Formatter { 25 | switch format { 26 | case LogFormatText: 27 | return &logrus.TextFormatter{ 28 | DisableTimestamp: true, 29 | //DisableColors: true, 30 | } 31 | case LogFormatJSON: 32 | return &logrus.JSONFormatter{ 33 | //DisableTimestamp: true, 34 | } 35 | } 36 | 37 | return nil 38 | } 39 | -------------------------------------------------------------------------------- /pkg/monitoring/api.go: -------------------------------------------------------------------------------- 1 | package monitoring 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "strconv" 7 | "strings" 8 | 9 | "github.com/chez-shanpu/acar/pkg/logging" 10 | "github.com/chez-shanpu/acar/pkg/logging/logfields" 11 | "google.golang.org/protobuf/types/known/timestamppb" 12 | 13 | "github.com/go-redis/redis/v8" 14 | 15 | "github.com/chez-shanpu/acar/api" 16 | ) 17 | 18 | const ( 19 | pkg = "dataplane" 20 | nodeinfoRedisPrefix = "sids/" 21 | nextSidsKey = "NextSids" 22 | linkCapKey = "linkcap" 23 | usageRatioKey = "ratio" 24 | usageBytesKey = "bytes" 25 | ) 26 | 27 | var log = logging.DefaultLogger.WithField(logfields.Package, pkg) 28 | 29 | type Server struct { 30 | api.UnimplementedMonitoringServer 31 | } 32 | 33 | func NewServer() *Server { 34 | s := &Server{} 35 | return s 36 | } 37 | 38 | func (s *Server) GetNodes(ctx context.Context, r *api.GetNodesRequest) (*api.GetNodesResponse, error) { 39 | ns, err := getNodes(ctx) 40 | if err != nil { 41 | log.Error(err) 42 | return nil, err 43 | } 44 | return &api.GetNodesResponse{Nodes: ns, Time: timestamppb.Now()}, nil 45 | } 46 | 47 | func (s *Server) RegisterNodes(ctx context.Context, r *api.RegisterNodesRequest) (*api.RegisterNodesResponse, error) { 48 | if err := registerNodes(ctx, r.GetNodes()); err != nil { 49 | log.WithField("Nodes", fmt.Sprintf("%#v", r.GetNodes())).Error(err) 50 | return nil, err 51 | } 52 | return &api.RegisterNodesResponse{Time: timestamppb.Now()}, nil 53 | } 54 | 55 | func getNodes(ctx context.Context) ([]*api.Node, error) { 56 | var ns []*api.Node 57 | 58 | rdb := newRedisClient(Config.RedisAddr, Config.RedisPass, Config.RedisDB) 59 | res := rdb.Keys(ctx, nodeinfoRedisPrefix+"*") 60 | keys, err := res.Result() 61 | if err != nil { 62 | return nil, err 63 | } 64 | 65 | for _, key := range keys { 66 | sid := strings.Split(key, "/")[1] 67 | n := api.Node{SID: sid} 68 | res := rdb.HGetAll(ctx, key) 69 | ifInfo, err := res.Result() 70 | if err != nil { 71 | return nil, err 72 | } 73 | n.NextSids = strings.Split(ifInfo[nextSidsKey], ",") 74 | n.LinkCap, err = strconv.ParseInt(ifInfo[linkCapKey], 10, 64) 75 | if err != nil { 76 | return nil, err 77 | } 78 | n.LinkUsageRatio, err = strconv.ParseFloat(ifInfo[usageRatioKey], 64) 79 | if err != nil { 80 | return nil, err 81 | } 82 | n.LinkUsageBytes, err = strconv.ParseFloat(ifInfo[usageBytesKey], 64) 83 | if err != nil { 84 | return nil, err 85 | } 86 | ns = append(ns, &n) 87 | } 88 | return ns, nil 89 | } 90 | 91 | func registerNodes(ctx context.Context, ns []*api.Node) error { 92 | rdb := newRedisClient(Config.RedisAddr, Config.RedisPass, Config.RedisDB) 93 | 94 | for _, n := range ns { 95 | nextSidsStr := strings.Join(n.NextSids, ",") 96 | res := rdb.HSet(ctx, nodeinfoRedisPrefix+n.SID, nextSidsKey, nextSidsStr) 97 | if _, err := res.Result(); err != nil { 98 | return err 99 | } 100 | 101 | res = rdb.HSet(ctx, nodeinfoRedisPrefix+n.SID, linkCapKey, n.LinkCap) 102 | if _, err := res.Result(); err != nil { 103 | return err 104 | } 105 | 106 | res = rdb.HSet(ctx, nodeinfoRedisPrefix+n.SID, usageRatioKey, n.LinkUsageRatio) 107 | if _, err := res.Result(); err != nil { 108 | return err 109 | } 110 | 111 | res = rdb.HSet(ctx, nodeinfoRedisPrefix+n.SID, usageBytesKey, n.LinkUsageBytes) 112 | if _, err := res.Result(); err != nil { 113 | return err 114 | } 115 | } 116 | return nil 117 | } 118 | 119 | func newRedisClient(addr, pass string, db int) *redis.Client { 120 | return redis.NewClient(&redis.Options{ 121 | Addr: addr, 122 | Password: pass, 123 | DB: db, // use default DB 124 | }) 125 | } 126 | -------------------------------------------------------------------------------- /pkg/monitoring/config.go: -------------------------------------------------------------------------------- 1 | package monitoring 2 | 3 | import "github.com/spf13/viper" 4 | 5 | const ( 6 | RedisAddr = "redis-addr" 7 | RedisDB = "redis-db" 8 | RedisPass = "redis-pass" 9 | ServerAddr = "addr" 10 | TLS = "tls" 11 | TLSCert = "cert" 12 | TLSKey = "key" 13 | ) 14 | 15 | var Config = &DaemonConfig{} 16 | 17 | type DaemonConfig struct { 18 | RedisAddr string 19 | RedisDB int 20 | RedisPass string 21 | ServerAddr string 22 | TLS bool 23 | TLSCert string 24 | TLSKey string 25 | } 26 | 27 | func (c *DaemonConfig) Populate() { 28 | c.RedisAddr = viper.GetString(RedisAddr) 29 | c.RedisDB = viper.GetInt(RedisDB) 30 | c.RedisPass = viper.GetString(RedisPass) 31 | c.ServerAddr = viper.GetString(ServerAddr) 32 | c.TLS = viper.GetBool(TLS) 33 | c.TLSCert = viper.GetString(TLSCert) 34 | c.TLSKey = viper.GetString(TLSKey) 35 | } 36 | -------------------------------------------------------------------------------- /pkg/srnode/config.go: -------------------------------------------------------------------------------- 1 | package srnode 2 | 3 | import "github.com/spf13/viper" 4 | 5 | const ( 6 | Addr = "addr" 7 | ConcurrentNum = "concurrent" 8 | ConcurrentInterval = "concurrent-interval" 9 | Interval = "interval" 10 | MonitoringAddr = "mnt-addr" 11 | Port = "port" 12 | SNMPAuthPass = "auth-pass" 13 | SNMPPrivPass = "priv-pass" 14 | SNMPUser = "snmp-user" 15 | TLS = "tls" 16 | TLSCert = "cert" 17 | ) 18 | 19 | type DaemonConfig struct { 20 | Addr string 21 | ConcurrentNum int 22 | ConcurrentInterval float64 23 | Interval int 24 | MonitoringAddr string 25 | Port int 26 | SNMPAuthPass string 27 | SNMPPrivPass string 28 | SNMPUser string 29 | TLS bool 30 | TLSCert string 31 | NetworkInterfaces []*NetworkInterface 32 | } 33 | 34 | var Config = &DaemonConfig{} 35 | 36 | func (c *DaemonConfig) Populate() { 37 | c.Addr = viper.GetString(Addr) 38 | c.ConcurrentNum = viper.GetInt(ConcurrentNum) 39 | c.ConcurrentInterval = viper.GetFloat64(ConcurrentInterval) 40 | c.Interval = viper.GetInt(Interval) 41 | c.MonitoringAddr = viper.GetString(MonitoringAddr) 42 | c.Port = viper.GetInt(Port) 43 | c.SNMPAuthPass = viper.GetString(SNMPAuthPass) 44 | c.SNMPPrivPass = viper.GetString(SNMPPrivPass) 45 | c.SNMPUser = viper.GetString(SNMPUser) 46 | c.TLS = viper.GetBool(TLS) 47 | c.TLSCert = viper.GetString(TLSCert) 48 | _ = viper.Unmarshal(c) 49 | } 50 | -------------------------------------------------------------------------------- /pkg/srnode/srnode.go: -------------------------------------------------------------------------------- 1 | package srnode 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "log" 7 | "math/big" 8 | "sync" 9 | "time" 10 | 11 | "github.com/chez-shanpu/acar/pkg/grpc" 12 | 13 | "github.com/chez-shanpu/acar/api" 14 | "github.com/gosnmp/gosnmp" 15 | "golang.org/x/sync/errgroup" 16 | ) 17 | 18 | const BytesToBits = 8.0 19 | const MegaBitsToBits = 1000000 20 | const ifHighSpeedOID = "1.3.6.1.2.1.31.1.1.1.15" 21 | const ifHCOutOctetsOID = "1.3.6.1.2.1.31.1.1.1.10" 22 | const ifIndexOID = "1.3.6.1.2.1.2.2.1.1" 23 | const ifDescrOID = "1.3.6.1.2.1.2.2.1.2" 24 | 25 | type NetworkInterface struct { 26 | Sid string 27 | NextSids []string 28 | InterfaceName string 29 | LinkCap int64 30 | } 31 | 32 | func GatherMetricsBySNMP() ([]*api.Node, error) { 33 | var eg errgroup.Group 34 | var nodes []*api.Node 35 | 36 | mutex := &sync.Mutex{} 37 | for _, ni := range Config.NetworkInterfaces { 38 | ni := ni 39 | eg.Go(func() error { 40 | return func(ni *NetworkInterface) error { 41 | sc := newSNMPClient(Config.Addr, Config.Port, Config.SNMPUser, Config.SNMPAuthPass, Config.SNMPPrivPass) 42 | ifIndex, err := getInterfaceIndexByName(sc, ni.InterfaceName) 43 | if err != nil { 44 | return err 45 | } 46 | 47 | usageRatio, usageBytes, err := getInterfaceUsageBySNMP(sc, ifIndex, Config.Interval, ni.LinkCap) 48 | if err != nil { 49 | return err 50 | } 51 | 52 | node := &api.Node{ 53 | SID: ni.Sid, 54 | NextSids: ni.NextSids, 55 | LinkCap: ni.LinkCap, 56 | LinkUsageRatio: usageRatio, 57 | LinkUsageBytes: usageBytes, 58 | } 59 | mutex.Lock() 60 | nodes = append(nodes, node) 61 | mutex.Unlock() 62 | return nil 63 | }(ni) 64 | }) 65 | } 66 | if err := eg.Wait(); err != nil { 67 | return nil, err 68 | } 69 | return nodes, nil 70 | } 71 | 72 | func SendToMonitoringServer(ns []*api.Node) error { 73 | conn, err := grpc.MakeConn(Config.MonitoringAddr, Config.TLS, Config.TLSCert) 74 | if err != nil { 75 | return err 76 | } 77 | defer conn.Close() 78 | 79 | c := api.NewMonitoringClient(conn) 80 | ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) 81 | defer cancel() 82 | 83 | _, err = c.RegisterNodes(ctx, &api.RegisterNodesRequest{Nodes: ns}) 84 | return err 85 | } 86 | 87 | func newSNMPClient(addr string, port int, user, authPass, privPass string) *gosnmp.GoSNMP { 88 | return &gosnmp.GoSNMP{ 89 | Target: addr, 90 | Port: uint16(port), 91 | Version: gosnmp.Version3, 92 | SecurityModel: gosnmp.UserSecurityModel, 93 | MsgFlags: gosnmp.AuthPriv, 94 | SecurityParameters: &gosnmp.UsmSecurityParameters{ 95 | UserName: user, 96 | AuthenticationProtocol: gosnmp.MD5, 97 | AuthenticationPassphrase: authPass, 98 | PrivacyProtocol: gosnmp.DES, 99 | PrivacyPassphrase: privPass, 100 | }, 101 | Timeout: 10 * time.Second, 102 | } 103 | } 104 | 105 | func getInterfaceIndexByName(snmp *gosnmp.GoSNMP, ifName string) (int, error) { 106 | err := snmp.Connect() 107 | if err != nil { 108 | log.Fatalf("Connect() err: %v", err) 109 | } 110 | defer snmp.Conn.Close() 111 | 112 | res, err := snmp.WalkAll(ifIndexOID) 113 | if err != nil { 114 | return 0, fmt.Errorf("failed get interface number from snmp agent: %v", err) 115 | } 116 | 117 | var indexSlice []int 118 | for _, v := range res { 119 | if v.Type != gosnmp.Integer { 120 | return 0, fmt.Errorf("variable type is wrong correct %v, got %v", gosnmp.Integer, v.Type) 121 | } 122 | indexSlice = append(indexSlice, int(gosnmp.ToBigInt(v.Value).Int64())) 123 | } 124 | 125 | for _, i := range indexSlice { 126 | oids := []string{fmt.Sprintf("%s.%d", ifDescrOID, i)} 127 | res, err := snmp.Get(oids) 128 | if err != nil { 129 | return 0, fmt.Errorf("failed to get interface name from snmp agent: %v", err) 130 | } 131 | 132 | for _, variable := range res.Variables { 133 | if variable.Value == nil { 134 | continue 135 | } 136 | 137 | if variable.Type == gosnmp.OctetString || variable.Type == gosnmp.NoSuchInstance { 138 | if string(variable.Value.([]uint8)) == ifName { 139 | return i, nil 140 | } 141 | } else { 142 | return 0, fmt.Errorf("variable type is wrong correct %v, got %v", gosnmp.OctetString, variable.Type) 143 | } 144 | } 145 | } 146 | return 0, fmt.Errorf("no interface named %s", ifName) 147 | } 148 | 149 | func getInterfaceCapacity(snmp *gosnmp.GoSNMP, ifIndex int) (int64, error) { 150 | err := snmp.Connect() 151 | if err != nil { 152 | log.Fatalf("Connect() err: %v", err) 153 | } 154 | defer snmp.Conn.Close() 155 | 156 | oids := []string{fmt.Sprintf("%s.%d", ifHighSpeedOID, ifIndex)} 157 | res, err := snmp.Get(oids) 158 | if err != nil { 159 | return -1, fmt.Errorf("failed get metrics from snmp agent: %v", err) 160 | } 161 | 162 | var linkCapBits int64 163 | for _, variable := range res.Variables { 164 | if variable.Type != gosnmp.Gauge32 { 165 | return -1, fmt.Errorf("variable type is wrong correct %v, got %v", gosnmp.Gauge32, variable.Type) 166 | } 167 | linkCapBits = gosnmp.ToBigInt(variable.Value).Int64() 168 | } 169 | return linkCapBits, nil 170 | } 171 | 172 | func getInterfaceUsageBySNMP(snmp *gosnmp.GoSNMP, ifIndex, secInterval int, linkCap int64) (float64, float64, error) { 173 | if linkCap <= 0 { 174 | var err error 175 | linkCap, err = getInterfaceCapacity(snmp, ifIndex) 176 | if err != nil { 177 | return 0, 0, err 178 | } 179 | } 180 | // first 181 | firstUsageBytesMetric, err := getInterfaceUsageBytes(snmp, ifIndex) 182 | if err != nil { 183 | return 0, 0, err 184 | } 185 | firstGetTime := time.Now() 186 | 187 | // wait 188 | time.Sleep(time.Duration(secInterval) * time.Second) 189 | 190 | // second 191 | secondUsageBytesMetric, err := getInterfaceUsageBytes(snmp, ifIndex) 192 | if err != nil { 193 | return 0, 0, err 194 | } 195 | secondGetTime := time.Now() 196 | 197 | // calcurate 198 | dur := secondGetTime.Sub(firstGetTime).Seconds() 199 | ifUsageRatio, ifUsageBytes := calcInterfaceUsage(firstUsageBytesMetric, secondUsageBytesMetric, dur, linkCap) 200 | 201 | return ifUsageRatio, ifUsageBytes, nil 202 | } 203 | 204 | func getInterfaceUsageBytes(snmp *gosnmp.GoSNMP, ifIndex int) (int64, error) { 205 | err := snmp.Connect() 206 | if err != nil { 207 | return 0, err 208 | } 209 | defer snmp.Conn.Close() 210 | 211 | oids := []string{fmt.Sprintf("%s.%d", ifHCOutOctetsOID, ifIndex)} 212 | res, err := snmp.Get(oids) 213 | if err != nil { 214 | return 0, fmt.Errorf("failed get metrics from snmp agent: %v", err) 215 | } 216 | 217 | totalBytes := big.NewInt(0) 218 | for _, variable := range res.Variables { 219 | if variable.Type != gosnmp.Counter64 { 220 | return 0, fmt.Errorf("variable type is wrong correct %v, got %v", gosnmp.Counter64, variable.Type) 221 | } 222 | totalBytes.Add(totalBytes, gosnmp.ToBigInt(variable.Value)) 223 | } 224 | return totalBytes.Int64(), nil 225 | } 226 | 227 | func calcInterfaceUsage(firstBytes, secondBytes int64, duration float64, linkCapBits int64) (float64, float64) { 228 | traficBytesDiff := secondBytes - firstBytes 229 | 230 | ifUsageRatio := float64(traficBytesDiff*BytesToBits*100.0) / (duration * float64(linkCapBits)) 231 | if ifUsageRatio < 0 { 232 | ifUsageRatio = 0 233 | } 234 | 235 | ifUsageBytes := float64(traficBytesDiff) / duration 236 | if ifUsageBytes < 0 { 237 | ifUsageBytes = 0 238 | } 239 | 240 | return ifUsageRatio, ifUsageBytes 241 | } 242 | -------------------------------------------------------------------------------- /pkg/srnode/srnode_test.go: -------------------------------------------------------------------------------- 1 | package srnode 2 | 3 | import "testing" 4 | 5 | func Test_calcInterfaceUsagePercent(t *testing.T) { 6 | type args struct { 7 | firstBytes int64 8 | secondBytes int64 9 | duration float64 10 | linkCapBits int64 11 | } 12 | tests := []struct { 13 | name string 14 | args args 15 | want1 float64 16 | want2 float64 17 | }{ 18 | { 19 | name: "correct case", 20 | args: args{ 21 | firstBytes: 800, 22 | secondBytes: 1600, 23 | duration: 10, 24 | linkCapBits: 10000, 25 | }, 26 | want1: 6.4, 27 | want2: 80, 28 | }, 29 | } 30 | for _, tt := range tests { 31 | t.Run(tt.name, func(t *testing.T) { 32 | got1, got2 := calcInterfaceUsage(tt.args.firstBytes, tt.args.secondBytes, tt.args.duration, tt.args.linkCapBits) 33 | if got1 != tt.want1 { 34 | t.Errorf("calcInterfaceUsage() got = %v, want %v", got1, tt.want1) 35 | } 36 | if got2 != tt.want2 { 37 | t.Errorf("calcInterfaceUsage() got1 = %v, want %v", got2, tt.want2) 38 | } 39 | }) 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /testdata/appagent/test1.txt: -------------------------------------------------------------------------------- 1 | fd00:0:0:1::1 fd00:0:0:2::1,4 fd00:0:0:3::1,2 2 | fd00:0:0:2::1 fd00:0:0:4::1,2 fd00:0:0:3::1,3 fd00:0:0:5::1,3 3 | fd00:0:0:3::1 fd00:0:0:2::1,1 fd00:0:0:4::1,4 fd00:0:0:5::1,5 4 | fd00:0:0:4::1 5 | fd00:0:0:5::1 fd00:0:0:5::1,1 -------------------------------------------------------------------------------- /testdata/appagent/test2.txt: -------------------------------------------------------------------------------- 1 | fd00:0:0:1::1 fd00:0:0:2::1,400000 fd00:0:0:3::1,400000 2 | fd00:0:0:2::1 fd00:0:0:4::1,400000 3 | fd00:0:0:3::1 fd00:0:0:5::1,100000 4 | fd00:0:0:4::1 fd00:0:0:5::2,300000 fd00:0:0:6::1,300000 5 | fd00:0:0:5::1 fd00:0:0:4::2,200000 fd00:0:0:6::1,200000 6 | fd00:0:0:6::1 --------------------------------------------------------------------------------