diff --git a/.github/release-drafter.yml b/.github/release-drafter.yml new file mode 100644 index 0000000..59bc948 --- /dev/null +++ b/.github/release-drafter.yml @@ -0,0 +1,30 @@ +name-template: 'v$RESOLVED_VERSION' +tag-template: 'v$RESOLVED_VERSION' + +template: | + ## General Changes + + $CHANGES + +categories: +- title: '🚀 Features' + labels: + - 'feature' + - 'enhancement' +- title: '🐛 Bug Fixes' + labels: + - 'fix' + - 'bugfix' + - 'bug' + +version-resolver: + major: + labels: + - 'major' + minor: + labels: + - 'minor' + patch: + labels: + - 'patch' + default: patch diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml new file mode 100644 index 0000000..c78644d --- /dev/null +++ b/.github/workflows/docker.yml @@ -0,0 +1,64 @@ +name: Docker Build Action +on: + pull_request: + branches: + - master + release: + types: + - published + push: + branches: + - master + +env: + REGISTRY: ghcr.io + IMAGE_NAME: ${{ github.repository }} + +jobs: + + build: + name: Build + runs-on: ubuntu-latest + steps: + + - name: Set up Go 1.18 + uses: actions/setup-go@v2 + with: + go-version: 1.18 + id: go + + - name: Check out code into the Go module directory + uses: actions/checkout@v2 + + - name: Lint + uses: golangci/golangci-lint-action@v2 + with: + args: -p bugs -p unused --timeout=3m + + - name: build and test + run: | + make test + make bench + + - name: Publish Codecoverage report + run: bash <(curl -s https://codecov.io/bash) + + - name: Log in to the Container registry + uses: docker/login-action@v1 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Make tag + run: | + [ "${GITHUB_EVENT_NAME}" == 'pull_request' ] && echo "tag=${GITHUB_HEAD_REF##*/}" >> $GITHUB_ENV || true + [ "${GITHUB_EVENT_NAME}" == 'release' ] && echo "tag=${GITHUB_REF##*/}" >> $GITHUB_ENV || true + [ "${GITHUB_EVENT_NAME}" == 'push' ] && echo "tag=latest" >> $GITHUB_ENV || true + + - name: Build and push image + uses: docker/build-push-action@v2 + with: + context: . + push: true + tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ env.tag }} \ No newline at end of file diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml deleted file mode 100644 index b99297a..0000000 --- a/.github/workflows/main.yml +++ /dev/null @@ -1,33 +0,0 @@ -name: build -on: - push: - branches: - - master -jobs: - - build: - name: Build - runs-on: ubuntu-latest - steps: - - - name: Set up Go 1.18 - uses: actions/setup-go@v2 - with: - go-version: 1.18 - id: go - - - name: Check out code into the Go module directory - uses: actions/checkout@v2 - - - name: Lint - uses: golangci/golangci-lint-action@v2 - with: - args: -p bugs -p unused --timeout=3m - - - name: build and test - run: | - make test - make bench - - - name: Publish Codecoverage report - run: bash <(curl -s https://codecov.io/bash) diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml deleted file mode 100644 index ae50468..0000000 --- a/.github/workflows/pr.yml +++ /dev/null @@ -1,33 +0,0 @@ -name: pull request -on: - pull_request: - branches: - - master -jobs: - - build: - name: Build - runs-on: ubuntu-latest - steps: - - - name: Set up Go 1.18 - uses: actions/setup-go@v2 - with: - go-version: 1.18 - id: go - - - name: Check out code into the Go module directory - uses: actions/checkout@v2 - - - name: Lint - uses: golangci/golangci-lint-action@v2 - with: - args: -p bugs -p unused --timeout=3m - - - name: build and test - run: | - make test - make bench - - - name: Publish Codecoverage report - run: bash <(curl -s https://codecov.io/bash) diff --git a/.github/workflows/release-drafter.yaml b/.github/workflows/release-drafter.yaml new file mode 100644 index 0000000..da232f3 --- /dev/null +++ b/.github/workflows/release-drafter.yaml @@ -0,0 +1,15 @@ +--- +name: Release Drafter Action + +on: + push: + branches: + - master + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: release-drafter/release-drafter@v5 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.gitignore b/.gitignore index e437b0f..32d1726 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ .vscode .idea coverage.out +bin \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..2893abf --- /dev/null +++ b/Dockerfile @@ -0,0 +1,18 @@ +FROM bufbuild/buf:1.6.0 as buf +FROM golang:1.18-alpine as builder + +RUN apk add \ + binutils \ + gcc \ + git \ + libc-dev \ + make + +WORKDIR /work +COPY --from=buf /usr/local/bin/buf /usr/local/bin/buf +COPY . . +RUN make server client + +FROM alpine:3.16 +COPY --from=builder /work/bin/* / +ENTRYPOINT [ "/server" ] \ No newline at end of file diff --git a/Makefile b/Makefile index 2e7fb50..b0e472b 100644 --- a/Makefile +++ b/Makefile @@ -1,17 +1,24 @@ .ONESHELL: +SHA := $(shell git rev-parse --short=8 HEAD) +GITVERSION := $(shell git describe --long --all) +BUILDDATE := $(shell date -Iseconds) +VERSION := $(or ${VERSION},devel) + CGO_ENABLED := $(or ${CGO_ENABLED},0) GO := go GO111MODULE := on PG_VERSION := $(or ${PG_VERSION},14-alpine) -COCKROACH_VERSION := $(or ${COCKROACH_VERSION},v22.1.0) +COCKROACH_VERSION := $(or ${COCKROACH_VERSION},latest-v22.1) +LINKMODE := -extldflags '-static -s -w' + .EXPORT_ALL_VARIABLES: -all: test bench +all: proto server client test bench .PHONY: bench bench: - CGO_ENABLED=1 $(GO) test -bench . -run=- -count 5 -benchmem -timeout 20m + CGO_ENABLED=1 $(GO) test -bench ./... -run=- -benchmem -timeout 20m .PHONY: benchstat benchstat: @@ -33,6 +40,30 @@ golangcicheck: lint: golangcicheck golangci-lint run -p bugs -p unused +.PHONY: proto +proto: + $(MAKE) -C proto protoc + +.PHONY: server +server: + go build -tags netgo,osusergo,urfave_cli_no_docs \ + -ldflags "$(LINKMODE) -X 'github.com/metal-stack/v.Version=$(VERSION)' \ + -X 'github.com/metal-stack/v.Revision=$(GITVERSION)' \ + -X 'github.com/metal-stack/v.GitSHA1=$(SHA)' \ + -X 'github.com/metal-stack/v.BuildDate=$(BUILDDATE)'" \ + -o bin/server github.com/metal-stack/go-ipam/cmd/server + strip bin/server + +.PHONY: client +client: + go build -tags netgo,osusergo,urfave_cli_no_docs \ + -ldflags "$(LINKMODE) -X 'github.com/metal-stack/v.Version=$(VERSION)' \ + -X 'github.com/metal-stack/v.Revision=$(GITVERSION)' \ + -X 'github.com/metal-stack/v.GitSHA1=$(SHA)' \ + -X 'github.com/metal-stack/v.BuildDate=$(BUILDDATE)'" \ + -o bin/cli github.com/metal-stack/go-ipam/cmd/client + strip bin/cli + .PHONY: postgres-up postgres-up: postgres-rm docker run -d --name ipamdb -p 5433:5432 -e POSTGRES_PASSWORD="password" postgres:$(PG_VERSION) -c 'max_connections=200' @@ -60,3 +91,11 @@ cockroach-up-cluster: cockroach-rm cockroach-rm: docker rm -f roach1 roach2 roach3 || true docker network rm roachnet || true + +.PHONY: redis-up +redis-up: redis-rm + docker run -d --name ipamredis -p 6379:6379 redis + +.PHONY: redis-rm +redis-rm: + docker rm -f ipamredis || true diff --git a/README.md b/README.md index c9fa1cc..4a02d37 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,8 @@ go-ipam is a module to handle IP address management. It can operate on networks, prefixes and IPs. +It also comes as a ready to go microservice which offers a grpc api. + ## IP Most obvious this library is all about IP management. The main purpose is to acquire and release an IP, or a bunch of @@ -17,7 +19,7 @@ IP's from prefixes. A prefix is a network with IP and mask, typically in the form of *192.168.0.0/24*. To be able to manage IPs you have to create a prefix first. -Example usage: +Library Example usage: ```go @@ -72,36 +74,84 @@ func main() { } ``` +## GRPC Service + +First start the go-ipam container with the database backend of your choice already up and running. For example if you have a postgres database for storing the ipam data, you could run the grpc service like so: + +```bash +docker run -it --rm ghcr.io/metal-stack/go-ipam postgres +``` + +From a client perspective you can now talk to this service via grpc. + +GRPC Example usage: + +```go +package main + +import ( + "http" + + "github.com/bufbuild/connect-go" + v1 "github.com/metal-stack/go-ipam/api/v1" + "github.com/metal-stack/go-ipam/api/v1/apiv1connect" +) +func main() { + + c := apiv1connect.NewIpamServiceClient( + http.DefaultClient, + "http://localhost:9090", + connect.WithGRPC(), + ) + + result, err := c.CreatePrefix(context.Background(), connect.NewRequest(&v1.CreatePrefixRequest{Cidr: "192.168.0.0/16",})) + if err != nil { + panic(err) + } + fmt.Println("Prefix:%q created", result.Msg.Prefix.Cidr) +} +``` + +## GRPC client + +There is also a `cli` provided in the container which can be used to make calls to the grpc endpoint manually: + +```bash +docker run -it --rm --entrypoint /cli ghcr.io/metal-stack/go-ipam +``` + ## Supported Databases & Performance -| Database | Acquire Child Prefix | Acquire IP | New Prefix | Prefix Overlap | Production-Ready | Geo-Redundant | -|:-------------|----------------------:|------------:|-------------:|----------------:|:-----------------|:-----------------------| -| In-Memory | 106,861/sec | 196,687/sec | 330,578/sec | 248/sec | N | N | -| KeyDB | 777/sec | 975/sec | 2,271/sec | | Y | Y | -| Redis | 773/sec | 958/sec | 2,349/sec | | Y | N | -| MongoDB | 415/sec | 682/sec | 772/sec | | Y | Y | -| Etcd | 258/sec | 368/sec | 533/sec | | Y | N | -| Postgres | 203/sec | 331/sec | 472/sec | | Y | N | -| CockroachDB | 40/sec | 37/sec | 46/sec | | Y | Y | +| Database | Acquire Child Prefix | Acquire IP | New Prefix | Prefix Overlap | Production-Ready | Geo-Redundant | +|:------------|---------------------:|------------:|------------:|---------------:|:-----------------|:--------------| +| In-Memory | 106,861/sec | 196,687/sec | 330,578/sec | 248/sec | N | N | +| KeyDB | 777/sec | 975/sec | 2,271/sec | | Y | Y | +| Redis | 773/sec | 958/sec | 2,349/sec | | Y | N | +| MongoDB | 415/sec | 682/sec | 772/sec | | Y | Y | +| Etcd | 258/sec | 368/sec | 533/sec | | Y | N | +| Postgres | 203/sec | 331/sec | 472/sec | | Y | N | +| CockroachDB | 40/sec | 37/sec | 46/sec | | Y | Y | The benchmarks above were performed using: - * cpu: Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz - * postgres:14-alpine - * cockroach:v22.1.0 - * redis:7.0-alpine - * keydb:alpine_x86_64_v6.2.2 - * etcd:v3.5.4 - * mongodb:5.0.9-focal + +* cpu: Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +* postgres:14-alpine +* cockroach:v22.1.0 +* redis:7.0-alpine +* keydb:alpine_x86_64_v6.2.2 +* etcd:v3.5.4 +* mongodb:5.0.9-focal ### Database Version Compatability -| Database | Details | -|-------------|-----------------------------------------------------------------------------------------------| -| KeyDB | | -| Redis | | -| MongoDB | https://www.mongodb.com/docs/drivers/go/current/compatibility/#std-label-golang-compatibility | -| Etcd | | -| Postgres | | -| CockroachDB | | + +| Database | Details | +|-------------|---------------------------------------------------------------------------------------------------------------------------| +| KeyDB | | +| Redis | | +| MongoDB | [mongodb-go compatibility](https://www.mongodb.com/docs/drivers/go/current/compatibility/#std-label-golang-compatibility) | +| Etcd | | +| Postgres | | +| CockroachDB | | ## Testing individual Backends diff --git a/api/v1/apiv1connect/ipam.connect.go b/api/v1/apiv1connect/ipam.connect.go new file mode 100644 index 0000000..41bcc64 --- /dev/null +++ b/api/v1/apiv1connect/ipam.connect.go @@ -0,0 +1,284 @@ +// Code generated by protoc-gen-connect-go. DO NOT EDIT. +// +// Source: api/v1/ipam.proto + +package apiv1connect + +import ( + context "context" + errors "errors" + connect_go "github.com/bufbuild/connect-go" + v1 "github.com/metal-stack/go-ipam/api/v1" + http "net/http" + strings "strings" +) + +// This is a compile-time assertion to ensure that this generated file and the connect package are +// compatible. If you get a compiler error that this constant is not defined, this code was +// generated with a version of connect newer than the one compiled into your binary. You can fix the +// problem by either regenerating this code with an older version of connect or updating the connect +// version compiled into your binary. +const _ = connect_go.IsAtLeastVersion0_1_0 + +const ( + // IpamServiceName is the fully-qualified name of the IpamService service. + IpamServiceName = "api.v1.IpamService" +) + +// IpamServiceClient is a client for the api.v1.IpamService service. +type IpamServiceClient interface { + CreatePrefix(context.Context, *connect_go.Request[v1.CreatePrefixRequest]) (*connect_go.Response[v1.CreatePrefixResponse], error) + DeletePrefix(context.Context, *connect_go.Request[v1.DeletePrefixRequest]) (*connect_go.Response[v1.DeletePrefixResponse], error) + GetPrefix(context.Context, *connect_go.Request[v1.GetPrefixRequest]) (*connect_go.Response[v1.GetPrefixResponse], error) + ListPrefixes(context.Context, *connect_go.Request[v1.ListPrefixesRequest]) (*connect_go.Response[v1.ListPrefixesResponse], error) + AcquireChildPrefix(context.Context, *connect_go.Request[v1.AcquireChildPrefixRequest]) (*connect_go.Response[v1.AcquireChildPrefixResponse], error) + ReleaseChildPrefix(context.Context, *connect_go.Request[v1.ReleaseChildPrefixRequest]) (*connect_go.Response[v1.ReleaseChildPrefixResponse], error) + AcquireIP(context.Context, *connect_go.Request[v1.AcquireIPRequest]) (*connect_go.Response[v1.AcquireIPResponse], error) + ReleaseIP(context.Context, *connect_go.Request[v1.ReleaseIPRequest]) (*connect_go.Response[v1.ReleaseIPResponse], error) + Dump(context.Context, *connect_go.Request[v1.DumpRequest]) (*connect_go.Response[v1.DumpResponse], error) + Load(context.Context, *connect_go.Request[v1.LoadRequest]) (*connect_go.Response[v1.LoadResponse], error) +} + +// NewIpamServiceClient constructs a client for the api.v1.IpamService service. By default, it uses +// the Connect protocol with the binary Protobuf Codec, asks for gzipped responses, and sends +// uncompressed requests. To use the gRPC or gRPC-Web protocols, supply the connect.WithGRPC() or +// connect.WithGRPCWeb() options. +// +// The URL supplied here should be the base URL for the Connect or gRPC server (for example, +// http://api.acme.com or https://acme.com/grpc). +func NewIpamServiceClient(httpClient connect_go.HTTPClient, baseURL string, opts ...connect_go.ClientOption) IpamServiceClient { + baseURL = strings.TrimRight(baseURL, "/") + return &ipamServiceClient{ + createPrefix: connect_go.NewClient[v1.CreatePrefixRequest, v1.CreatePrefixResponse]( + httpClient, + baseURL+"/api.v1.IpamService/CreatePrefix", + opts..., + ), + deletePrefix: connect_go.NewClient[v1.DeletePrefixRequest, v1.DeletePrefixResponse]( + httpClient, + baseURL+"/api.v1.IpamService/DeletePrefix", + opts..., + ), + getPrefix: connect_go.NewClient[v1.GetPrefixRequest, v1.GetPrefixResponse]( + httpClient, + baseURL+"/api.v1.IpamService/GetPrefix", + opts..., + ), + listPrefixes: connect_go.NewClient[v1.ListPrefixesRequest, v1.ListPrefixesResponse]( + httpClient, + baseURL+"/api.v1.IpamService/ListPrefixes", + opts..., + ), + acquireChildPrefix: connect_go.NewClient[v1.AcquireChildPrefixRequest, v1.AcquireChildPrefixResponse]( + httpClient, + baseURL+"/api.v1.IpamService/AcquireChildPrefix", + opts..., + ), + releaseChildPrefix: connect_go.NewClient[v1.ReleaseChildPrefixRequest, v1.ReleaseChildPrefixResponse]( + httpClient, + baseURL+"/api.v1.IpamService/ReleaseChildPrefix", + opts..., + ), + acquireIP: connect_go.NewClient[v1.AcquireIPRequest, v1.AcquireIPResponse]( + httpClient, + baseURL+"/api.v1.IpamService/AcquireIP", + opts..., + ), + releaseIP: connect_go.NewClient[v1.ReleaseIPRequest, v1.ReleaseIPResponse]( + httpClient, + baseURL+"/api.v1.IpamService/ReleaseIP", + opts..., + ), + dump: connect_go.NewClient[v1.DumpRequest, v1.DumpResponse]( + httpClient, + baseURL+"/api.v1.IpamService/Dump", + opts..., + ), + load: connect_go.NewClient[v1.LoadRequest, v1.LoadResponse]( + httpClient, + baseURL+"/api.v1.IpamService/Load", + opts..., + ), + } +} + +// ipamServiceClient implements IpamServiceClient. +type ipamServiceClient struct { + createPrefix *connect_go.Client[v1.CreatePrefixRequest, v1.CreatePrefixResponse] + deletePrefix *connect_go.Client[v1.DeletePrefixRequest, v1.DeletePrefixResponse] + getPrefix *connect_go.Client[v1.GetPrefixRequest, v1.GetPrefixResponse] + listPrefixes *connect_go.Client[v1.ListPrefixesRequest, v1.ListPrefixesResponse] + acquireChildPrefix *connect_go.Client[v1.AcquireChildPrefixRequest, v1.AcquireChildPrefixResponse] + releaseChildPrefix *connect_go.Client[v1.ReleaseChildPrefixRequest, v1.ReleaseChildPrefixResponse] + acquireIP *connect_go.Client[v1.AcquireIPRequest, v1.AcquireIPResponse] + releaseIP *connect_go.Client[v1.ReleaseIPRequest, v1.ReleaseIPResponse] + dump *connect_go.Client[v1.DumpRequest, v1.DumpResponse] + load *connect_go.Client[v1.LoadRequest, v1.LoadResponse] +} + +// CreatePrefix calls api.v1.IpamService.CreatePrefix. +func (c *ipamServiceClient) CreatePrefix(ctx context.Context, req *connect_go.Request[v1.CreatePrefixRequest]) (*connect_go.Response[v1.CreatePrefixResponse], error) { + return c.createPrefix.CallUnary(ctx, req) +} + +// DeletePrefix calls api.v1.IpamService.DeletePrefix. +func (c *ipamServiceClient) DeletePrefix(ctx context.Context, req *connect_go.Request[v1.DeletePrefixRequest]) (*connect_go.Response[v1.DeletePrefixResponse], error) { + return c.deletePrefix.CallUnary(ctx, req) +} + +// GetPrefix calls api.v1.IpamService.GetPrefix. +func (c *ipamServiceClient) GetPrefix(ctx context.Context, req *connect_go.Request[v1.GetPrefixRequest]) (*connect_go.Response[v1.GetPrefixResponse], error) { + return c.getPrefix.CallUnary(ctx, req) +} + +// ListPrefixes calls api.v1.IpamService.ListPrefixes. +func (c *ipamServiceClient) ListPrefixes(ctx context.Context, req *connect_go.Request[v1.ListPrefixesRequest]) (*connect_go.Response[v1.ListPrefixesResponse], error) { + return c.listPrefixes.CallUnary(ctx, req) +} + +// AcquireChildPrefix calls api.v1.IpamService.AcquireChildPrefix. +func (c *ipamServiceClient) AcquireChildPrefix(ctx context.Context, req *connect_go.Request[v1.AcquireChildPrefixRequest]) (*connect_go.Response[v1.AcquireChildPrefixResponse], error) { + return c.acquireChildPrefix.CallUnary(ctx, req) +} + +// ReleaseChildPrefix calls api.v1.IpamService.ReleaseChildPrefix. +func (c *ipamServiceClient) ReleaseChildPrefix(ctx context.Context, req *connect_go.Request[v1.ReleaseChildPrefixRequest]) (*connect_go.Response[v1.ReleaseChildPrefixResponse], error) { + return c.releaseChildPrefix.CallUnary(ctx, req) +} + +// AcquireIP calls api.v1.IpamService.AcquireIP. +func (c *ipamServiceClient) AcquireIP(ctx context.Context, req *connect_go.Request[v1.AcquireIPRequest]) (*connect_go.Response[v1.AcquireIPResponse], error) { + return c.acquireIP.CallUnary(ctx, req) +} + +// ReleaseIP calls api.v1.IpamService.ReleaseIP. +func (c *ipamServiceClient) ReleaseIP(ctx context.Context, req *connect_go.Request[v1.ReleaseIPRequest]) (*connect_go.Response[v1.ReleaseIPResponse], error) { + return c.releaseIP.CallUnary(ctx, req) +} + +// Dump calls api.v1.IpamService.Dump. +func (c *ipamServiceClient) Dump(ctx context.Context, req *connect_go.Request[v1.DumpRequest]) (*connect_go.Response[v1.DumpResponse], error) { + return c.dump.CallUnary(ctx, req) +} + +// Load calls api.v1.IpamService.Load. +func (c *ipamServiceClient) Load(ctx context.Context, req *connect_go.Request[v1.LoadRequest]) (*connect_go.Response[v1.LoadResponse], error) { + return c.load.CallUnary(ctx, req) +} + +// IpamServiceHandler is an implementation of the api.v1.IpamService service. +type IpamServiceHandler interface { + CreatePrefix(context.Context, *connect_go.Request[v1.CreatePrefixRequest]) (*connect_go.Response[v1.CreatePrefixResponse], error) + DeletePrefix(context.Context, *connect_go.Request[v1.DeletePrefixRequest]) (*connect_go.Response[v1.DeletePrefixResponse], error) + GetPrefix(context.Context, *connect_go.Request[v1.GetPrefixRequest]) (*connect_go.Response[v1.GetPrefixResponse], error) + ListPrefixes(context.Context, *connect_go.Request[v1.ListPrefixesRequest]) (*connect_go.Response[v1.ListPrefixesResponse], error) + AcquireChildPrefix(context.Context, *connect_go.Request[v1.AcquireChildPrefixRequest]) (*connect_go.Response[v1.AcquireChildPrefixResponse], error) + ReleaseChildPrefix(context.Context, *connect_go.Request[v1.ReleaseChildPrefixRequest]) (*connect_go.Response[v1.ReleaseChildPrefixResponse], error) + AcquireIP(context.Context, *connect_go.Request[v1.AcquireIPRequest]) (*connect_go.Response[v1.AcquireIPResponse], error) + ReleaseIP(context.Context, *connect_go.Request[v1.ReleaseIPRequest]) (*connect_go.Response[v1.ReleaseIPResponse], error) + Dump(context.Context, *connect_go.Request[v1.DumpRequest]) (*connect_go.Response[v1.DumpResponse], error) + Load(context.Context, *connect_go.Request[v1.LoadRequest]) (*connect_go.Response[v1.LoadResponse], error) +} + +// NewIpamServiceHandler builds an HTTP handler from the service implementation. It returns the path +// on which to mount the handler and the handler itself. +// +// By default, handlers support the Connect, gRPC, and gRPC-Web protocols with the binary Protobuf +// and JSON codecs. They also support gzip compression. +func NewIpamServiceHandler(svc IpamServiceHandler, opts ...connect_go.HandlerOption) (string, http.Handler) { + mux := http.NewServeMux() + mux.Handle("/api.v1.IpamService/CreatePrefix", connect_go.NewUnaryHandler( + "/api.v1.IpamService/CreatePrefix", + svc.CreatePrefix, + opts..., + )) + mux.Handle("/api.v1.IpamService/DeletePrefix", connect_go.NewUnaryHandler( + "/api.v1.IpamService/DeletePrefix", + svc.DeletePrefix, + opts..., + )) + mux.Handle("/api.v1.IpamService/GetPrefix", connect_go.NewUnaryHandler( + "/api.v1.IpamService/GetPrefix", + svc.GetPrefix, + opts..., + )) + mux.Handle("/api.v1.IpamService/ListPrefixes", connect_go.NewUnaryHandler( + "/api.v1.IpamService/ListPrefixes", + svc.ListPrefixes, + opts..., + )) + mux.Handle("/api.v1.IpamService/AcquireChildPrefix", connect_go.NewUnaryHandler( + "/api.v1.IpamService/AcquireChildPrefix", + svc.AcquireChildPrefix, + opts..., + )) + mux.Handle("/api.v1.IpamService/ReleaseChildPrefix", connect_go.NewUnaryHandler( + "/api.v1.IpamService/ReleaseChildPrefix", + svc.ReleaseChildPrefix, + opts..., + )) + mux.Handle("/api.v1.IpamService/AcquireIP", connect_go.NewUnaryHandler( + "/api.v1.IpamService/AcquireIP", + svc.AcquireIP, + opts..., + )) + mux.Handle("/api.v1.IpamService/ReleaseIP", connect_go.NewUnaryHandler( + "/api.v1.IpamService/ReleaseIP", + svc.ReleaseIP, + opts..., + )) + mux.Handle("/api.v1.IpamService/Dump", connect_go.NewUnaryHandler( + "/api.v1.IpamService/Dump", + svc.Dump, + opts..., + )) + mux.Handle("/api.v1.IpamService/Load", connect_go.NewUnaryHandler( + "/api.v1.IpamService/Load", + svc.Load, + opts..., + )) + return "/api.v1.IpamService/", mux +} + +// UnimplementedIpamServiceHandler returns CodeUnimplemented from all methods. +type UnimplementedIpamServiceHandler struct{} + +func (UnimplementedIpamServiceHandler) CreatePrefix(context.Context, *connect_go.Request[v1.CreatePrefixRequest]) (*connect_go.Response[v1.CreatePrefixResponse], error) { + return nil, connect_go.NewError(connect_go.CodeUnimplemented, errors.New("api.v1.IpamService.CreatePrefix is not implemented")) +} + +func (UnimplementedIpamServiceHandler) DeletePrefix(context.Context, *connect_go.Request[v1.DeletePrefixRequest]) (*connect_go.Response[v1.DeletePrefixResponse], error) { + return nil, connect_go.NewError(connect_go.CodeUnimplemented, errors.New("api.v1.IpamService.DeletePrefix is not implemented")) +} + +func (UnimplementedIpamServiceHandler) GetPrefix(context.Context, *connect_go.Request[v1.GetPrefixRequest]) (*connect_go.Response[v1.GetPrefixResponse], error) { + return nil, connect_go.NewError(connect_go.CodeUnimplemented, errors.New("api.v1.IpamService.GetPrefix is not implemented")) +} + +func (UnimplementedIpamServiceHandler) ListPrefixes(context.Context, *connect_go.Request[v1.ListPrefixesRequest]) (*connect_go.Response[v1.ListPrefixesResponse], error) { + return nil, connect_go.NewError(connect_go.CodeUnimplemented, errors.New("api.v1.IpamService.ListPrefixes is not implemented")) +} + +func (UnimplementedIpamServiceHandler) AcquireChildPrefix(context.Context, *connect_go.Request[v1.AcquireChildPrefixRequest]) (*connect_go.Response[v1.AcquireChildPrefixResponse], error) { + return nil, connect_go.NewError(connect_go.CodeUnimplemented, errors.New("api.v1.IpamService.AcquireChildPrefix is not implemented")) +} + +func (UnimplementedIpamServiceHandler) ReleaseChildPrefix(context.Context, *connect_go.Request[v1.ReleaseChildPrefixRequest]) (*connect_go.Response[v1.ReleaseChildPrefixResponse], error) { + return nil, connect_go.NewError(connect_go.CodeUnimplemented, errors.New("api.v1.IpamService.ReleaseChildPrefix is not implemented")) +} + +func (UnimplementedIpamServiceHandler) AcquireIP(context.Context, *connect_go.Request[v1.AcquireIPRequest]) (*connect_go.Response[v1.AcquireIPResponse], error) { + return nil, connect_go.NewError(connect_go.CodeUnimplemented, errors.New("api.v1.IpamService.AcquireIP is not implemented")) +} + +func (UnimplementedIpamServiceHandler) ReleaseIP(context.Context, *connect_go.Request[v1.ReleaseIPRequest]) (*connect_go.Response[v1.ReleaseIPResponse], error) { + return nil, connect_go.NewError(connect_go.CodeUnimplemented, errors.New("api.v1.IpamService.ReleaseIP is not implemented")) +} + +func (UnimplementedIpamServiceHandler) Dump(context.Context, *connect_go.Request[v1.DumpRequest]) (*connect_go.Response[v1.DumpResponse], error) { + return nil, connect_go.NewError(connect_go.CodeUnimplemented, errors.New("api.v1.IpamService.Dump is not implemented")) +} + +func (UnimplementedIpamServiceHandler) Load(context.Context, *connect_go.Request[v1.LoadRequest]) (*connect_go.Response[v1.LoadResponse], error) { + return nil, connect_go.NewError(connect_go.CodeUnimplemented, errors.New("api.v1.IpamService.Load is not implemented")) +} diff --git a/api/v1/ipam.pb.go b/api/v1/ipam.pb.go new file mode 100644 index 0000000..1553aa9 --- /dev/null +++ b/api/v1/ipam.pb.go @@ -0,0 +1,1565 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.27.1 +// protoc (unknown) +// source: api/v1/ipam.proto + +package apiv1 + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type Prefix struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Cidr string `protobuf:"bytes,1,opt,name=cidr,proto3" json:"cidr,omitempty"` + ParentCidr string `protobuf:"bytes,2,opt,name=parent_cidr,json=parentCidr,proto3" json:"parent_cidr,omitempty"` +} + +func (x *Prefix) Reset() { + *x = Prefix{} + if protoimpl.UnsafeEnabled { + mi := &file_api_v1_ipam_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Prefix) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Prefix) ProtoMessage() {} + +func (x *Prefix) ProtoReflect() protoreflect.Message { + mi := &file_api_v1_ipam_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Prefix.ProtoReflect.Descriptor instead. +func (*Prefix) Descriptor() ([]byte, []int) { + return file_api_v1_ipam_proto_rawDescGZIP(), []int{0} +} + +func (x *Prefix) GetCidr() string { + if x != nil { + return x.Cidr + } + return "" +} + +func (x *Prefix) GetParentCidr() string { + if x != nil { + return x.ParentCidr + } + return "" +} + +type CreatePrefixResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Prefix *Prefix `protobuf:"bytes,1,opt,name=prefix,proto3" json:"prefix,omitempty"` +} + +func (x *CreatePrefixResponse) Reset() { + *x = CreatePrefixResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_api_v1_ipam_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *CreatePrefixResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CreatePrefixResponse) ProtoMessage() {} + +func (x *CreatePrefixResponse) ProtoReflect() protoreflect.Message { + mi := &file_api_v1_ipam_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use CreatePrefixResponse.ProtoReflect.Descriptor instead. +func (*CreatePrefixResponse) Descriptor() ([]byte, []int) { + return file_api_v1_ipam_proto_rawDescGZIP(), []int{1} +} + +func (x *CreatePrefixResponse) GetPrefix() *Prefix { + if x != nil { + return x.Prefix + } + return nil +} + +type DeletePrefixResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Prefix *Prefix `protobuf:"bytes,1,opt,name=prefix,proto3" json:"prefix,omitempty"` +} + +func (x *DeletePrefixResponse) Reset() { + *x = DeletePrefixResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_api_v1_ipam_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *DeletePrefixResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DeletePrefixResponse) ProtoMessage() {} + +func (x *DeletePrefixResponse) ProtoReflect() protoreflect.Message { + mi := &file_api_v1_ipam_proto_msgTypes[2] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use DeletePrefixResponse.ProtoReflect.Descriptor instead. +func (*DeletePrefixResponse) Descriptor() ([]byte, []int) { + return file_api_v1_ipam_proto_rawDescGZIP(), []int{2} +} + +func (x *DeletePrefixResponse) GetPrefix() *Prefix { + if x != nil { + return x.Prefix + } + return nil +} + +type GetPrefixResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Prefix *Prefix `protobuf:"bytes,1,opt,name=prefix,proto3" json:"prefix,omitempty"` +} + +func (x *GetPrefixResponse) Reset() { + *x = GetPrefixResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_api_v1_ipam_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetPrefixResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetPrefixResponse) ProtoMessage() {} + +func (x *GetPrefixResponse) ProtoReflect() protoreflect.Message { + mi := &file_api_v1_ipam_proto_msgTypes[3] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetPrefixResponse.ProtoReflect.Descriptor instead. +func (*GetPrefixResponse) Descriptor() ([]byte, []int) { + return file_api_v1_ipam_proto_rawDescGZIP(), []int{3} +} + +func (x *GetPrefixResponse) GetPrefix() *Prefix { + if x != nil { + return x.Prefix + } + return nil +} + +type AcquireChildPrefixResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Prefix *Prefix `protobuf:"bytes,1,opt,name=prefix,proto3" json:"prefix,omitempty"` +} + +func (x *AcquireChildPrefixResponse) Reset() { + *x = AcquireChildPrefixResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_api_v1_ipam_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *AcquireChildPrefixResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AcquireChildPrefixResponse) ProtoMessage() {} + +func (x *AcquireChildPrefixResponse) ProtoReflect() protoreflect.Message { + mi := &file_api_v1_ipam_proto_msgTypes[4] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use AcquireChildPrefixResponse.ProtoReflect.Descriptor instead. +func (*AcquireChildPrefixResponse) Descriptor() ([]byte, []int) { + return file_api_v1_ipam_proto_rawDescGZIP(), []int{4} +} + +func (x *AcquireChildPrefixResponse) GetPrefix() *Prefix { + if x != nil { + return x.Prefix + } + return nil +} + +type ReleaseChildPrefixResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Prefix *Prefix `protobuf:"bytes,1,opt,name=prefix,proto3" json:"prefix,omitempty"` +} + +func (x *ReleaseChildPrefixResponse) Reset() { + *x = ReleaseChildPrefixResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_api_v1_ipam_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ReleaseChildPrefixResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ReleaseChildPrefixResponse) ProtoMessage() {} + +func (x *ReleaseChildPrefixResponse) ProtoReflect() protoreflect.Message { + mi := &file_api_v1_ipam_proto_msgTypes[5] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ReleaseChildPrefixResponse.ProtoReflect.Descriptor instead. +func (*ReleaseChildPrefixResponse) Descriptor() ([]byte, []int) { + return file_api_v1_ipam_proto_rawDescGZIP(), []int{5} +} + +func (x *ReleaseChildPrefixResponse) GetPrefix() *Prefix { + if x != nil { + return x.Prefix + } + return nil +} + +type CreatePrefixRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Cidr string `protobuf:"bytes,1,opt,name=cidr,proto3" json:"cidr,omitempty"` +} + +func (x *CreatePrefixRequest) Reset() { + *x = CreatePrefixRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_api_v1_ipam_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *CreatePrefixRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CreatePrefixRequest) ProtoMessage() {} + +func (x *CreatePrefixRequest) ProtoReflect() protoreflect.Message { + mi := &file_api_v1_ipam_proto_msgTypes[6] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use CreatePrefixRequest.ProtoReflect.Descriptor instead. +func (*CreatePrefixRequest) Descriptor() ([]byte, []int) { + return file_api_v1_ipam_proto_rawDescGZIP(), []int{6} +} + +func (x *CreatePrefixRequest) GetCidr() string { + if x != nil { + return x.Cidr + } + return "" +} + +type DeletePrefixRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Cidr string `protobuf:"bytes,1,opt,name=cidr,proto3" json:"cidr,omitempty"` +} + +func (x *DeletePrefixRequest) Reset() { + *x = DeletePrefixRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_api_v1_ipam_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *DeletePrefixRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DeletePrefixRequest) ProtoMessage() {} + +func (x *DeletePrefixRequest) ProtoReflect() protoreflect.Message { + mi := &file_api_v1_ipam_proto_msgTypes[7] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use DeletePrefixRequest.ProtoReflect.Descriptor instead. +func (*DeletePrefixRequest) Descriptor() ([]byte, []int) { + return file_api_v1_ipam_proto_rawDescGZIP(), []int{7} +} + +func (x *DeletePrefixRequest) GetCidr() string { + if x != nil { + return x.Cidr + } + return "" +} + +type GetPrefixRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Cidr string `protobuf:"bytes,1,opt,name=cidr,proto3" json:"cidr,omitempty"` +} + +func (x *GetPrefixRequest) Reset() { + *x = GetPrefixRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_api_v1_ipam_proto_msgTypes[8] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetPrefixRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetPrefixRequest) ProtoMessage() {} + +func (x *GetPrefixRequest) ProtoReflect() protoreflect.Message { + mi := &file_api_v1_ipam_proto_msgTypes[8] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetPrefixRequest.ProtoReflect.Descriptor instead. +func (*GetPrefixRequest) Descriptor() ([]byte, []int) { + return file_api_v1_ipam_proto_rawDescGZIP(), []int{8} +} + +func (x *GetPrefixRequest) GetCidr() string { + if x != nil { + return x.Cidr + } + return "" +} + +type ListPrefixesRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *ListPrefixesRequest) Reset() { + *x = ListPrefixesRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_api_v1_ipam_proto_msgTypes[9] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ListPrefixesRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListPrefixesRequest) ProtoMessage() {} + +func (x *ListPrefixesRequest) ProtoReflect() protoreflect.Message { + mi := &file_api_v1_ipam_proto_msgTypes[9] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ListPrefixesRequest.ProtoReflect.Descriptor instead. +func (*ListPrefixesRequest) Descriptor() ([]byte, []int) { + return file_api_v1_ipam_proto_rawDescGZIP(), []int{9} +} + +type ListPrefixesResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Prefixes []*Prefix `protobuf:"bytes,1,rep,name=prefixes,proto3" json:"prefixes,omitempty"` +} + +func (x *ListPrefixesResponse) Reset() { + *x = ListPrefixesResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_api_v1_ipam_proto_msgTypes[10] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ListPrefixesResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListPrefixesResponse) ProtoMessage() {} + +func (x *ListPrefixesResponse) ProtoReflect() protoreflect.Message { + mi := &file_api_v1_ipam_proto_msgTypes[10] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ListPrefixesResponse.ProtoReflect.Descriptor instead. +func (*ListPrefixesResponse) Descriptor() ([]byte, []int) { + return file_api_v1_ipam_proto_rawDescGZIP(), []int{10} +} + +func (x *ListPrefixesResponse) GetPrefixes() []*Prefix { + if x != nil { + return x.Prefixes + } + return nil +} + +type AcquireChildPrefixRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Cidr string `protobuf:"bytes,1,opt,name=cidr,proto3" json:"cidr,omitempty"` + Length uint32 `protobuf:"varint,2,opt,name=length,proto3" json:"length,omitempty"` +} + +func (x *AcquireChildPrefixRequest) Reset() { + *x = AcquireChildPrefixRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_api_v1_ipam_proto_msgTypes[11] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *AcquireChildPrefixRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AcquireChildPrefixRequest) ProtoMessage() {} + +func (x *AcquireChildPrefixRequest) ProtoReflect() protoreflect.Message { + mi := &file_api_v1_ipam_proto_msgTypes[11] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use AcquireChildPrefixRequest.ProtoReflect.Descriptor instead. +func (*AcquireChildPrefixRequest) Descriptor() ([]byte, []int) { + return file_api_v1_ipam_proto_rawDescGZIP(), []int{11} +} + +func (x *AcquireChildPrefixRequest) GetCidr() string { + if x != nil { + return x.Cidr + } + return "" +} + +func (x *AcquireChildPrefixRequest) GetLength() uint32 { + if x != nil { + return x.Length + } + return 0 +} + +type ReleaseChildPrefixRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Cidr string `protobuf:"bytes,1,opt,name=cidr,proto3" json:"cidr,omitempty"` +} + +func (x *ReleaseChildPrefixRequest) Reset() { + *x = ReleaseChildPrefixRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_api_v1_ipam_proto_msgTypes[12] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ReleaseChildPrefixRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ReleaseChildPrefixRequest) ProtoMessage() {} + +func (x *ReleaseChildPrefixRequest) ProtoReflect() protoreflect.Message { + mi := &file_api_v1_ipam_proto_msgTypes[12] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ReleaseChildPrefixRequest.ProtoReflect.Descriptor instead. +func (*ReleaseChildPrefixRequest) Descriptor() ([]byte, []int) { + return file_api_v1_ipam_proto_rawDescGZIP(), []int{12} +} + +func (x *ReleaseChildPrefixRequest) GetCidr() string { + if x != nil { + return x.Cidr + } + return "" +} + +type IP struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Ip string `protobuf:"bytes,1,opt,name=ip,proto3" json:"ip,omitempty"` + ParentPrefix string `protobuf:"bytes,2,opt,name=parent_prefix,json=parentPrefix,proto3" json:"parent_prefix,omitempty"` +} + +func (x *IP) Reset() { + *x = IP{} + if protoimpl.UnsafeEnabled { + mi := &file_api_v1_ipam_proto_msgTypes[13] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *IP) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*IP) ProtoMessage() {} + +func (x *IP) ProtoReflect() protoreflect.Message { + mi := &file_api_v1_ipam_proto_msgTypes[13] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use IP.ProtoReflect.Descriptor instead. +func (*IP) Descriptor() ([]byte, []int) { + return file_api_v1_ipam_proto_rawDescGZIP(), []int{13} +} + +func (x *IP) GetIp() string { + if x != nil { + return x.Ip + } + return "" +} + +func (x *IP) GetParentPrefix() string { + if x != nil { + return x.ParentPrefix + } + return "" +} + +type AcquireIPResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Ip *IP `protobuf:"bytes,1,opt,name=ip,proto3" json:"ip,omitempty"` +} + +func (x *AcquireIPResponse) Reset() { + *x = AcquireIPResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_api_v1_ipam_proto_msgTypes[14] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *AcquireIPResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AcquireIPResponse) ProtoMessage() {} + +func (x *AcquireIPResponse) ProtoReflect() protoreflect.Message { + mi := &file_api_v1_ipam_proto_msgTypes[14] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use AcquireIPResponse.ProtoReflect.Descriptor instead. +func (*AcquireIPResponse) Descriptor() ([]byte, []int) { + return file_api_v1_ipam_proto_rawDescGZIP(), []int{14} +} + +func (x *AcquireIPResponse) GetIp() *IP { + if x != nil { + return x.Ip + } + return nil +} + +type ReleaseIPResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Ip *IP `protobuf:"bytes,1,opt,name=ip,proto3" json:"ip,omitempty"` +} + +func (x *ReleaseIPResponse) Reset() { + *x = ReleaseIPResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_api_v1_ipam_proto_msgTypes[15] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ReleaseIPResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ReleaseIPResponse) ProtoMessage() {} + +func (x *ReleaseIPResponse) ProtoReflect() protoreflect.Message { + mi := &file_api_v1_ipam_proto_msgTypes[15] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ReleaseIPResponse.ProtoReflect.Descriptor instead. +func (*ReleaseIPResponse) Descriptor() ([]byte, []int) { + return file_api_v1_ipam_proto_rawDescGZIP(), []int{15} +} + +func (x *ReleaseIPResponse) GetIp() *IP { + if x != nil { + return x.Ip + } + return nil +} + +type AcquireIPRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + PrefixCidr string `protobuf:"bytes,1,opt,name=prefix_cidr,json=prefixCidr,proto3" json:"prefix_cidr,omitempty"` + Ip *string `protobuf:"bytes,2,opt,name=ip,proto3,oneof" json:"ip,omitempty"` +} + +func (x *AcquireIPRequest) Reset() { + *x = AcquireIPRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_api_v1_ipam_proto_msgTypes[16] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *AcquireIPRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AcquireIPRequest) ProtoMessage() {} + +func (x *AcquireIPRequest) ProtoReflect() protoreflect.Message { + mi := &file_api_v1_ipam_proto_msgTypes[16] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use AcquireIPRequest.ProtoReflect.Descriptor instead. +func (*AcquireIPRequest) Descriptor() ([]byte, []int) { + return file_api_v1_ipam_proto_rawDescGZIP(), []int{16} +} + +func (x *AcquireIPRequest) GetPrefixCidr() string { + if x != nil { + return x.PrefixCidr + } + return "" +} + +func (x *AcquireIPRequest) GetIp() string { + if x != nil && x.Ip != nil { + return *x.Ip + } + return "" +} + +type ReleaseIPRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + PrefixCidr string `protobuf:"bytes,1,opt,name=prefix_cidr,json=prefixCidr,proto3" json:"prefix_cidr,omitempty"` + Ip string `protobuf:"bytes,2,opt,name=ip,proto3" json:"ip,omitempty"` +} + +func (x *ReleaseIPRequest) Reset() { + *x = ReleaseIPRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_api_v1_ipam_proto_msgTypes[17] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ReleaseIPRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ReleaseIPRequest) ProtoMessage() {} + +func (x *ReleaseIPRequest) ProtoReflect() protoreflect.Message { + mi := &file_api_v1_ipam_proto_msgTypes[17] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ReleaseIPRequest.ProtoReflect.Descriptor instead. +func (*ReleaseIPRequest) Descriptor() ([]byte, []int) { + return file_api_v1_ipam_proto_rawDescGZIP(), []int{17} +} + +func (x *ReleaseIPRequest) GetPrefixCidr() string { + if x != nil { + return x.PrefixCidr + } + return "" +} + +func (x *ReleaseIPRequest) GetIp() string { + if x != nil { + return x.Ip + } + return "" +} + +type DumpRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *DumpRequest) Reset() { + *x = DumpRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_api_v1_ipam_proto_msgTypes[18] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *DumpRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DumpRequest) ProtoMessage() {} + +func (x *DumpRequest) ProtoReflect() protoreflect.Message { + mi := &file_api_v1_ipam_proto_msgTypes[18] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use DumpRequest.ProtoReflect.Descriptor instead. +func (*DumpRequest) Descriptor() ([]byte, []int) { + return file_api_v1_ipam_proto_rawDescGZIP(), []int{18} +} + +type DumpResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Dump string `protobuf:"bytes,1,opt,name=dump,proto3" json:"dump,omitempty"` +} + +func (x *DumpResponse) Reset() { + *x = DumpResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_api_v1_ipam_proto_msgTypes[19] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *DumpResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DumpResponse) ProtoMessage() {} + +func (x *DumpResponse) ProtoReflect() protoreflect.Message { + mi := &file_api_v1_ipam_proto_msgTypes[19] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use DumpResponse.ProtoReflect.Descriptor instead. +func (*DumpResponse) Descriptor() ([]byte, []int) { + return file_api_v1_ipam_proto_rawDescGZIP(), []int{19} +} + +func (x *DumpResponse) GetDump() string { + if x != nil { + return x.Dump + } + return "" +} + +type LoadRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Dump string `protobuf:"bytes,1,opt,name=dump,proto3" json:"dump,omitempty"` +} + +func (x *LoadRequest) Reset() { + *x = LoadRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_api_v1_ipam_proto_msgTypes[20] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *LoadRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*LoadRequest) ProtoMessage() {} + +func (x *LoadRequest) ProtoReflect() protoreflect.Message { + mi := &file_api_v1_ipam_proto_msgTypes[20] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use LoadRequest.ProtoReflect.Descriptor instead. +func (*LoadRequest) Descriptor() ([]byte, []int) { + return file_api_v1_ipam_proto_rawDescGZIP(), []int{20} +} + +func (x *LoadRequest) GetDump() string { + if x != nil { + return x.Dump + } + return "" +} + +type LoadResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *LoadResponse) Reset() { + *x = LoadResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_api_v1_ipam_proto_msgTypes[21] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *LoadResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*LoadResponse) ProtoMessage() {} + +func (x *LoadResponse) ProtoReflect() protoreflect.Message { + mi := &file_api_v1_ipam_proto_msgTypes[21] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use LoadResponse.ProtoReflect.Descriptor instead. +func (*LoadResponse) Descriptor() ([]byte, []int) { + return file_api_v1_ipam_proto_rawDescGZIP(), []int{21} +} + +var File_api_v1_ipam_proto protoreflect.FileDescriptor + +var file_api_v1_ipam_proto_rawDesc = []byte{ + 0x0a, 0x11, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x69, 0x70, 0x61, 0x6d, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x12, 0x06, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x22, 0x3d, 0x0a, 0x06, 0x50, + 0x72, 0x65, 0x66, 0x69, 0x78, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x69, 0x64, 0x72, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x04, 0x63, 0x69, 0x64, 0x72, 0x12, 0x1f, 0x0a, 0x0b, 0x70, 0x61, 0x72, + 0x65, 0x6e, 0x74, 0x5f, 0x63, 0x69, 0x64, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, + 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x43, 0x69, 0x64, 0x72, 0x22, 0x3e, 0x0a, 0x14, 0x43, 0x72, + 0x65, 0x61, 0x74, 0x65, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x26, 0x0a, 0x06, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x65, 0x66, + 0x69, 0x78, 0x52, 0x06, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x22, 0x3e, 0x0a, 0x14, 0x44, 0x65, + 0x6c, 0x65, 0x74, 0x65, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x26, 0x0a, 0x06, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x65, 0x66, + 0x69, 0x78, 0x52, 0x06, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x22, 0x3b, 0x0a, 0x11, 0x47, 0x65, + 0x74, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x26, 0x0a, 0x06, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x0e, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x52, + 0x06, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x22, 0x44, 0x0a, 0x1a, 0x41, 0x63, 0x71, 0x75, 0x69, + 0x72, 0x65, 0x43, 0x68, 0x69, 0x6c, 0x64, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x26, 0x0a, 0x06, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x50, + 0x72, 0x65, 0x66, 0x69, 0x78, 0x52, 0x06, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x22, 0x44, 0x0a, + 0x1a, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x43, 0x68, 0x69, 0x6c, 0x64, 0x50, 0x72, 0x65, + 0x66, 0x69, 0x78, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x26, 0x0a, 0x06, 0x70, + 0x72, 0x65, 0x66, 0x69, 0x78, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x61, 0x70, + 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x52, 0x06, 0x70, 0x72, 0x65, + 0x66, 0x69, 0x78, 0x22, 0x29, 0x0a, 0x13, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x50, 0x72, 0x65, + 0x66, 0x69, 0x78, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x69, + 0x64, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x63, 0x69, 0x64, 0x72, 0x22, 0x29, + 0x0a, 0x13, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x69, 0x64, 0x72, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x04, 0x63, 0x69, 0x64, 0x72, 0x22, 0x26, 0x0a, 0x10, 0x47, 0x65, 0x74, + 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, + 0x04, 0x63, 0x69, 0x64, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x63, 0x69, 0x64, + 0x72, 0x22, 0x15, 0x0a, 0x13, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x65, + 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x42, 0x0a, 0x14, 0x4c, 0x69, 0x73, 0x74, + 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x2a, 0x0a, 0x08, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x65, 0x66, + 0x69, 0x78, 0x52, 0x08, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x65, 0x73, 0x22, 0x47, 0x0a, 0x19, + 0x41, 0x63, 0x71, 0x75, 0x69, 0x72, 0x65, 0x43, 0x68, 0x69, 0x6c, 0x64, 0x50, 0x72, 0x65, 0x66, + 0x69, 0x78, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x69, 0x64, + 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x63, 0x69, 0x64, 0x72, 0x12, 0x16, 0x0a, + 0x06, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x06, 0x6c, + 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x2f, 0x0a, 0x19, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, + 0x43, 0x68, 0x69, 0x6c, 0x64, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x69, 0x64, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x04, 0x63, 0x69, 0x64, 0x72, 0x22, 0x39, 0x0a, 0x02, 0x49, 0x50, 0x12, 0x0e, 0x0a, 0x02, + 0x69, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x70, 0x12, 0x23, 0x0a, 0x0d, + 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x0c, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x50, 0x72, 0x65, 0x66, 0x69, + 0x78, 0x22, 0x2f, 0x0a, 0x11, 0x41, 0x63, 0x71, 0x75, 0x69, 0x72, 0x65, 0x49, 0x50, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1a, 0x0a, 0x02, 0x69, 0x70, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x0a, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x50, 0x52, 0x02, + 0x69, 0x70, 0x22, 0x2f, 0x0a, 0x11, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x49, 0x50, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1a, 0x0a, 0x02, 0x69, 0x70, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x0a, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x50, 0x52, + 0x02, 0x69, 0x70, 0x22, 0x4f, 0x0a, 0x10, 0x41, 0x63, 0x71, 0x75, 0x69, 0x72, 0x65, 0x49, 0x50, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x70, 0x72, 0x65, 0x66, 0x69, + 0x78, 0x5f, 0x63, 0x69, 0x64, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x70, 0x72, + 0x65, 0x66, 0x69, 0x78, 0x43, 0x69, 0x64, 0x72, 0x12, 0x13, 0x0a, 0x02, 0x69, 0x70, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x02, 0x69, 0x70, 0x88, 0x01, 0x01, 0x42, 0x05, 0x0a, + 0x03, 0x5f, 0x69, 0x70, 0x22, 0x43, 0x0a, 0x10, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x49, + 0x50, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x70, 0x72, 0x65, 0x66, + 0x69, 0x78, 0x5f, 0x63, 0x69, 0x64, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x70, + 0x72, 0x65, 0x66, 0x69, 0x78, 0x43, 0x69, 0x64, 0x72, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x70, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x70, 0x22, 0x0d, 0x0a, 0x0b, 0x44, 0x75, 0x6d, + 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x22, 0x0a, 0x0c, 0x44, 0x75, 0x6d, 0x70, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x75, 0x6d, 0x70, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x64, 0x75, 0x6d, 0x70, 0x22, 0x21, 0x0a, 0x0b, + 0x4c, 0x6f, 0x61, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x64, + 0x75, 0x6d, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x64, 0x75, 0x6d, 0x70, 0x22, + 0x0e, 0x0a, 0x0c, 0x4c, 0x6f, 0x61, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, + 0xd4, 0x05, 0x0a, 0x0b, 0x49, 0x70, 0x61, 0x6d, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, + 0x49, 0x0a, 0x0c, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x12, + 0x1b, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x50, + 0x72, 0x65, 0x66, 0x69, 0x78, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x61, + 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x50, 0x72, 0x65, 0x66, + 0x69, 0x78, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x49, 0x0a, 0x0c, 0x44, 0x65, + 0x6c, 0x65, 0x74, 0x65, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x12, 0x1b, 0x2e, 0x61, 0x70, 0x69, + 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, + 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x40, 0x0a, 0x09, 0x47, 0x65, 0x74, 0x50, 0x72, 0x65, 0x66, + 0x69, 0x78, 0x12, 0x18, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x50, + 0x72, 0x65, 0x66, 0x69, 0x78, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x61, + 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x49, 0x0a, 0x0c, 0x4c, 0x69, 0x73, 0x74, 0x50, + 0x72, 0x65, 0x66, 0x69, 0x78, 0x65, 0x73, 0x12, 0x1b, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, + 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x65, 0x73, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, + 0x73, 0x74, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x5b, 0x0a, 0x12, 0x41, 0x63, 0x71, 0x75, 0x69, 0x72, 0x65, 0x43, 0x68, 0x69, + 0x6c, 0x64, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x12, 0x21, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, + 0x31, 0x2e, 0x41, 0x63, 0x71, 0x75, 0x69, 0x72, 0x65, 0x43, 0x68, 0x69, 0x6c, 0x64, 0x50, 0x72, + 0x65, 0x66, 0x69, 0x78, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x61, 0x70, + 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x63, 0x71, 0x75, 0x69, 0x72, 0x65, 0x43, 0x68, 0x69, 0x6c, + 0x64, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x5b, 0x0a, 0x12, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x43, 0x68, 0x69, 0x6c, 0x64, 0x50, + 0x72, 0x65, 0x66, 0x69, 0x78, 0x12, 0x21, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x52, + 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x43, 0x68, 0x69, 0x6c, 0x64, 0x50, 0x72, 0x65, 0x66, 0x69, + 0x78, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, + 0x31, 0x2e, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x43, 0x68, 0x69, 0x6c, 0x64, 0x50, 0x72, + 0x65, 0x66, 0x69, 0x78, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x40, 0x0a, 0x09, + 0x41, 0x63, 0x71, 0x75, 0x69, 0x72, 0x65, 0x49, 0x50, 0x12, 0x18, 0x2e, 0x61, 0x70, 0x69, 0x2e, + 0x76, 0x31, 0x2e, 0x41, 0x63, 0x71, 0x75, 0x69, 0x72, 0x65, 0x49, 0x50, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x63, 0x71, + 0x75, 0x69, 0x72, 0x65, 0x49, 0x50, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x40, + 0x0a, 0x09, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x49, 0x50, 0x12, 0x18, 0x2e, 0x61, 0x70, + 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x49, 0x50, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x52, + 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x49, 0x50, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x31, 0x0a, 0x04, 0x44, 0x75, 0x6d, 0x70, 0x12, 0x13, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, + 0x31, 0x2e, 0x44, 0x75, 0x6d, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x14, 0x2e, + 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x75, 0x6d, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x31, 0x0a, 0x04, 0x4c, 0x6f, 0x61, 0x64, 0x12, 0x13, 0x2e, 0x61, 0x70, + 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x6f, 0x61, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x14, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x6f, 0x61, 0x64, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x7d, 0x0a, 0x0a, 0x63, 0x6f, 0x6d, 0x2e, 0x61, 0x70, + 0x69, 0x2e, 0x76, 0x31, 0x42, 0x09, 0x49, 0x70, 0x61, 0x6d, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, + 0x01, 0x5a, 0x2b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6d, 0x65, + 0x74, 0x61, 0x6c, 0x2d, 0x73, 0x74, 0x61, 0x63, 0x6b, 0x2f, 0x67, 0x6f, 0x2d, 0x69, 0x70, 0x61, + 0x6d, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x3b, 0x61, 0x70, 0x69, 0x76, 0x31, 0xa2, 0x02, + 0x03, 0x41, 0x58, 0x58, 0xaa, 0x02, 0x06, 0x41, 0x70, 0x69, 0x2e, 0x56, 0x31, 0xca, 0x02, 0x06, + 0x41, 0x70, 0x69, 0x5c, 0x56, 0x31, 0xe2, 0x02, 0x12, 0x41, 0x70, 0x69, 0x5c, 0x56, 0x31, 0x5c, + 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x07, 0x41, 0x70, + 0x69, 0x3a, 0x3a, 0x56, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_api_v1_ipam_proto_rawDescOnce sync.Once + file_api_v1_ipam_proto_rawDescData = file_api_v1_ipam_proto_rawDesc +) + +func file_api_v1_ipam_proto_rawDescGZIP() []byte { + file_api_v1_ipam_proto_rawDescOnce.Do(func() { + file_api_v1_ipam_proto_rawDescData = protoimpl.X.CompressGZIP(file_api_v1_ipam_proto_rawDescData) + }) + return file_api_v1_ipam_proto_rawDescData +} + +var file_api_v1_ipam_proto_msgTypes = make([]protoimpl.MessageInfo, 22) +var file_api_v1_ipam_proto_goTypes = []interface{}{ + (*Prefix)(nil), // 0: api.v1.Prefix + (*CreatePrefixResponse)(nil), // 1: api.v1.CreatePrefixResponse + (*DeletePrefixResponse)(nil), // 2: api.v1.DeletePrefixResponse + (*GetPrefixResponse)(nil), // 3: api.v1.GetPrefixResponse + (*AcquireChildPrefixResponse)(nil), // 4: api.v1.AcquireChildPrefixResponse + (*ReleaseChildPrefixResponse)(nil), // 5: api.v1.ReleaseChildPrefixResponse + (*CreatePrefixRequest)(nil), // 6: api.v1.CreatePrefixRequest + (*DeletePrefixRequest)(nil), // 7: api.v1.DeletePrefixRequest + (*GetPrefixRequest)(nil), // 8: api.v1.GetPrefixRequest + (*ListPrefixesRequest)(nil), // 9: api.v1.ListPrefixesRequest + (*ListPrefixesResponse)(nil), // 10: api.v1.ListPrefixesResponse + (*AcquireChildPrefixRequest)(nil), // 11: api.v1.AcquireChildPrefixRequest + (*ReleaseChildPrefixRequest)(nil), // 12: api.v1.ReleaseChildPrefixRequest + (*IP)(nil), // 13: api.v1.IP + (*AcquireIPResponse)(nil), // 14: api.v1.AcquireIPResponse + (*ReleaseIPResponse)(nil), // 15: api.v1.ReleaseIPResponse + (*AcquireIPRequest)(nil), // 16: api.v1.AcquireIPRequest + (*ReleaseIPRequest)(nil), // 17: api.v1.ReleaseIPRequest + (*DumpRequest)(nil), // 18: api.v1.DumpRequest + (*DumpResponse)(nil), // 19: api.v1.DumpResponse + (*LoadRequest)(nil), // 20: api.v1.LoadRequest + (*LoadResponse)(nil), // 21: api.v1.LoadResponse +} +var file_api_v1_ipam_proto_depIdxs = []int32{ + 0, // 0: api.v1.CreatePrefixResponse.prefix:type_name -> api.v1.Prefix + 0, // 1: api.v1.DeletePrefixResponse.prefix:type_name -> api.v1.Prefix + 0, // 2: api.v1.GetPrefixResponse.prefix:type_name -> api.v1.Prefix + 0, // 3: api.v1.AcquireChildPrefixResponse.prefix:type_name -> api.v1.Prefix + 0, // 4: api.v1.ReleaseChildPrefixResponse.prefix:type_name -> api.v1.Prefix + 0, // 5: api.v1.ListPrefixesResponse.prefixes:type_name -> api.v1.Prefix + 13, // 6: api.v1.AcquireIPResponse.ip:type_name -> api.v1.IP + 13, // 7: api.v1.ReleaseIPResponse.ip:type_name -> api.v1.IP + 6, // 8: api.v1.IpamService.CreatePrefix:input_type -> api.v1.CreatePrefixRequest + 7, // 9: api.v1.IpamService.DeletePrefix:input_type -> api.v1.DeletePrefixRequest + 8, // 10: api.v1.IpamService.GetPrefix:input_type -> api.v1.GetPrefixRequest + 9, // 11: api.v1.IpamService.ListPrefixes:input_type -> api.v1.ListPrefixesRequest + 11, // 12: api.v1.IpamService.AcquireChildPrefix:input_type -> api.v1.AcquireChildPrefixRequest + 12, // 13: api.v1.IpamService.ReleaseChildPrefix:input_type -> api.v1.ReleaseChildPrefixRequest + 16, // 14: api.v1.IpamService.AcquireIP:input_type -> api.v1.AcquireIPRequest + 17, // 15: api.v1.IpamService.ReleaseIP:input_type -> api.v1.ReleaseIPRequest + 18, // 16: api.v1.IpamService.Dump:input_type -> api.v1.DumpRequest + 20, // 17: api.v1.IpamService.Load:input_type -> api.v1.LoadRequest + 1, // 18: api.v1.IpamService.CreatePrefix:output_type -> api.v1.CreatePrefixResponse + 2, // 19: api.v1.IpamService.DeletePrefix:output_type -> api.v1.DeletePrefixResponse + 3, // 20: api.v1.IpamService.GetPrefix:output_type -> api.v1.GetPrefixResponse + 10, // 21: api.v1.IpamService.ListPrefixes:output_type -> api.v1.ListPrefixesResponse + 4, // 22: api.v1.IpamService.AcquireChildPrefix:output_type -> api.v1.AcquireChildPrefixResponse + 5, // 23: api.v1.IpamService.ReleaseChildPrefix:output_type -> api.v1.ReleaseChildPrefixResponse + 14, // 24: api.v1.IpamService.AcquireIP:output_type -> api.v1.AcquireIPResponse + 15, // 25: api.v1.IpamService.ReleaseIP:output_type -> api.v1.ReleaseIPResponse + 19, // 26: api.v1.IpamService.Dump:output_type -> api.v1.DumpResponse + 21, // 27: api.v1.IpamService.Load:output_type -> api.v1.LoadResponse + 18, // [18:28] is the sub-list for method output_type + 8, // [8:18] is the sub-list for method input_type + 8, // [8:8] is the sub-list for extension type_name + 8, // [8:8] is the sub-list for extension extendee + 0, // [0:8] is the sub-list for field type_name +} + +func init() { file_api_v1_ipam_proto_init() } +func file_api_v1_ipam_proto_init() { + if File_api_v1_ipam_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_api_v1_ipam_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Prefix); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_api_v1_ipam_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*CreatePrefixResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_api_v1_ipam_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*DeletePrefixResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_api_v1_ipam_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetPrefixResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_api_v1_ipam_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*AcquireChildPrefixResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_api_v1_ipam_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ReleaseChildPrefixResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_api_v1_ipam_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*CreatePrefixRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_api_v1_ipam_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*DeletePrefixRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_api_v1_ipam_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetPrefixRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_api_v1_ipam_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ListPrefixesRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_api_v1_ipam_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ListPrefixesResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_api_v1_ipam_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*AcquireChildPrefixRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_api_v1_ipam_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ReleaseChildPrefixRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_api_v1_ipam_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*IP); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_api_v1_ipam_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*AcquireIPResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_api_v1_ipam_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ReleaseIPResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_api_v1_ipam_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*AcquireIPRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_api_v1_ipam_proto_msgTypes[17].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ReleaseIPRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_api_v1_ipam_proto_msgTypes[18].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*DumpRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_api_v1_ipam_proto_msgTypes[19].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*DumpResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_api_v1_ipam_proto_msgTypes[20].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*LoadRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_api_v1_ipam_proto_msgTypes[21].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*LoadResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + file_api_v1_ipam_proto_msgTypes[16].OneofWrappers = []interface{}{} + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_api_v1_ipam_proto_rawDesc, + NumEnums: 0, + NumMessages: 22, + NumExtensions: 0, + NumServices: 1, + }, + GoTypes: file_api_v1_ipam_proto_goTypes, + DependencyIndexes: file_api_v1_ipam_proto_depIdxs, + MessageInfos: file_api_v1_ipam_proto_msgTypes, + }.Build() + File_api_v1_ipam_proto = out.File + file_api_v1_ipam_proto_rawDesc = nil + file_api_v1_ipam_proto_goTypes = nil + file_api_v1_ipam_proto_depIdxs = nil +} diff --git a/cmd/client/client.go b/cmd/client/client.go new file mode 100644 index 0000000..e3a4124 --- /dev/null +++ b/cmd/client/client.go @@ -0,0 +1,261 @@ +package main + +import ( + "context" + "fmt" + "net/http" + "os" + + "github.com/bufbuild/connect-go" + compress "github.com/klauspost/connect-compress" + v1 "github.com/metal-stack/go-ipam/api/v1" + "github.com/metal-stack/go-ipam/api/v1/apiv1connect" + "github.com/metal-stack/v" + "github.com/urfave/cli/v2" +) + +func main() { + + app := &cli.App{ + Name: "cli", + Usage: "cli for go-ipam", + Version: v.V.String(), + Flags: []cli.Flag{ + &cli.StringFlag{ + Name: "grpc-server-endpoint", + Value: "http://localhost:9090", + Usage: "gRPC server endpoint", + EnvVars: []string{"GOIPAM_GRPC_SERVER_ENDPOINT"}, + }, + }, + Commands: []*cli.Command{ + { + Name: "prefix", + Aliases: []string{"p"}, + Usage: "prefix manipulation", + Subcommands: []*cli.Command{ + { + Name: "create", + Usage: "create a prefix", + Flags: []cli.Flag{ + &cli.StringFlag{ + Name: "cidr", + }, + }, + Action: func(ctx *cli.Context) error { + c := client(ctx) + result, err := c.CreatePrefix(context.Background(), connect.NewRequest(&v1.CreatePrefixRequest{ + Cidr: ctx.String("cidr"), + })) + + if err != nil { + return err + } + fmt.Printf("prefix:%q created\n", result.Msg.Prefix.Cidr) + return nil + }, + }, + { + Name: "acquire", + Usage: "acquire a child prefix", + Flags: []cli.Flag{ + &cli.StringFlag{ + Name: "parent", + }, + &cli.UintFlag{ + Name: "length", + }, + }, + Action: func(ctx *cli.Context) error { + c := client(ctx) + result, err := c.AcquireChildPrefix(context.Background(), connect.NewRequest(&v1.AcquireChildPrefixRequest{ + Cidr: ctx.String("parent"), + Length: uint32(ctx.Uint("length")), + })) + + if err != nil { + return err + } + fmt.Printf("child prefix:%q from %q created\n", result.Msg.Prefix.Cidr, result.Msg.Prefix.ParentCidr) + return nil + }, + }, + { + Name: "release", + Usage: "release a child prefix", + Flags: []cli.Flag{ + &cli.StringFlag{ + Name: "cidr", + }, + }, + Action: func(ctx *cli.Context) error { + c := client(ctx) + result, err := c.ReleaseChildPrefix(context.Background(), connect.NewRequest(&v1.ReleaseChildPrefixRequest{ + Cidr: ctx.String("cidr"), + })) + + if err != nil { + return err + } + if result.Msg == nil || result.Msg.Prefix == nil { + return fmt.Errorf("result contains no prefix") + } + fmt.Printf("child prefix:%q from %q released\n", result.Msg.Prefix.Cidr, result.Msg.Prefix.ParentCidr) + return nil + }, + }, + { + Name: "list", + Usage: "list all prefixes", + Action: func(ctx *cli.Context) error { + c := client(ctx) + result, err := c.ListPrefixes(context.Background(), connect.NewRequest(&v1.ListPrefixesRequest{})) + + if err != nil { + return err + } + for _, p := range result.Msg.Prefixes { + fmt.Printf("Prefix:%q parent:%q\n", p.Cidr, p.ParentCidr) + } + return nil + }, + }, + { + Name: "delete", + Usage: "delete a prefix", + Flags: []cli.Flag{ + &cli.StringFlag{ + Name: "cidr", + }, + }, + Action: func(ctx *cli.Context) error { + c := client(ctx) + result, err := c.DeletePrefix(context.Background(), connect.NewRequest(&v1.DeletePrefixRequest{ + Cidr: ctx.String("cidr"), + })) + + if err != nil { + return err + } + fmt.Printf("prefix:%q deleted\n", result.Msg.Prefix.Cidr) + return nil + }, + }, + }, + }, + { + Name: "ip", + Aliases: []string{"i"}, + Usage: "ip manipulation", + Subcommands: []*cli.Command{ + { + Name: "acquire", + Usage: "acquire a ip", + Flags: []cli.Flag{ + &cli.StringFlag{ + Name: "prefix", + }, + }, + Action: func(ctx *cli.Context) error { + c := client(ctx) + result, err := c.AcquireIP(context.Background(), connect.NewRequest(&v1.AcquireIPRequest{ + PrefixCidr: ctx.String("prefix"), + })) + + if err != nil { + return err + } + fmt.Printf("ip:%q acquired\n", result.Msg.Ip.Ip) + return nil + }, + }, + { + Name: "release", + Usage: "release a ip", + Flags: []cli.Flag{ + &cli.StringFlag{ + Name: "ip", + }, + &cli.StringFlag{ + Name: "prefix", + }, + }, + Action: func(ctx *cli.Context) error { + c := client(ctx) + result, err := c.ReleaseIP(context.Background(), connect.NewRequest(&v1.ReleaseIPRequest{ + Ip: ctx.String("ip"), + PrefixCidr: ctx.String("prefix"), + })) + + if err != nil { + return err + } + fmt.Printf("ip:%q released\n", result.Msg.Ip.Ip) + return nil + }, + }, + }, + }, + { + Name: "backup", + Usage: "create and restore a backup", + Subcommands: []*cli.Command{ + { + Name: "create", + Usage: "create a json file of the whole ipam db for backup purpose", + Action: func(ctx *cli.Context) error { + c := client(ctx) + result, err := c.Dump(context.Background(), connect.NewRequest(&v1.DumpRequest{})) + if err != nil { + return err + } + fmt.Println(result.Msg.Dump) + return nil + }, + }, + { + Name: "restore", + Usage: "load the whole ipam db from json file, previously created, only works if database is already empty", + Flags: []cli.Flag{ + &cli.StringFlag{ + Name: "file", + }, + }, + Action: func(ctx *cli.Context) error { + c := client(ctx) + json, err := os.ReadFile(ctx.String("file")) + if err != nil { + return err + } + _, err = c.Load(context.Background(), connect.NewRequest(&v1.LoadRequest{ + Dump: string(json), + })) + + if err != nil { + return err + } + fmt.Printf("database restored\n") + return nil + }, + }, + }, + }, + }, + } + err := app.Run(os.Args) + if err != nil { + fmt.Println(err.Error()) + os.Exit(1) + } +} + +func client(ctx *cli.Context) apiv1connect.IpamServiceClient { + clientOpts, _ := compress.All(compress.LevelBalanced) + + return apiv1connect.NewIpamServiceClient( + http.DefaultClient, + ctx.String("grpc-server-endpoint"), + connect.WithGRPC(), + clientOpts, + ) +} diff --git a/cmd/server/main.go b/cmd/server/main.go new file mode 100644 index 0000000..83f4329 --- /dev/null +++ b/cmd/server/main.go @@ -0,0 +1,291 @@ +package main + +import ( + "context" + "fmt" + "log" + "os" + + goipam "github.com/metal-stack/go-ipam" + "github.com/metal-stack/v" + "github.com/urfave/cli/v2" + "go.mongodb.org/mongo-driver/mongo/options" + "go.uber.org/zap" + "go.uber.org/zap/zapcore" +) + +func main() { + + app := &cli.App{ + Name: "go-ipam server", + Usage: "grpc server for go ipam", + Version: v.V.String(), + Flags: []cli.Flag{ + &cli.StringFlag{ + Name: "grpc-server-endpoint", + Value: "localhost:9090", + Usage: "gRPC server endpoint", + EnvVars: []string{"GOIPAM_GRPC_SERVER_ENDPOINT"}, + }, + &cli.StringFlag{ + Name: "log-level", + Value: "info", + Usage: "log-level can be one of error|warn|info|debug", + EnvVars: []string{"GOIPAM_LOG_LEVEL"}, + }, + }, + Commands: []*cli.Command{ + { + Name: "memory", + Aliases: []string{"m"}, + Usage: "start with memory backend", + Action: func(ctx *cli.Context) error { + c := getConfig(ctx) + c.Storage = goipam.NewMemory() + s := newServer(c) + return s.Run() + }, + }, + { + Name: "postgres", + Aliases: []string{"pg"}, + Usage: "start with postgres backend", + Flags: []cli.Flag{ + &cli.StringFlag{ + Name: "host", + Value: "localhost", + Usage: "postgres db hostname", + EnvVars: []string{"GOIPAM_PG_HOST"}, + }, + &cli.StringFlag{ + Name: "port", + Value: "5432", + Usage: "postgres db port", + EnvVars: []string{"GOIPAM_PG_PORT"}, + }, + &cli.StringFlag{ + Name: "user", + Value: "go-ipam", + Usage: "postgres db user", + EnvVars: []string{"GOIPAM_PG_USER"}, + }, + &cli.StringFlag{ + Name: "password", + Value: "secret", + Usage: "postgres db password", + EnvVars: []string{"GOIPAM_PG_PASSWORD"}, + }, + &cli.StringFlag{ + Name: "dbname", + Value: "goipam", + Usage: "postgres db name", + EnvVars: []string{"GOIPAM_PG_DBNAME"}, + }, + &cli.StringFlag{ + Name: "sslmode", + Value: "disable", + Usage: "postgres sslmode, possible values: disable|require|verify-ca|verify-full", + EnvVars: []string{"GOIPAM_PG_SSLMODE"}, + }, + }, + Action: func(ctx *cli.Context) error { + c := getConfig(ctx) + host := ctx.String("host") + port := ctx.String("port") + user := ctx.String("user") + password := ctx.String("password") + dbname := ctx.String("dbname") + sslmode := ctx.String("sslmode") + pgStorage, err := goipam.NewPostgresStorage(host, port, user, password, dbname, goipam.SSLMode(sslmode)) + if err != nil { + return err + } + c.Storage = pgStorage + s := newServer(c) + return s.Run() + }, + }, + { + Name: "redis", + Usage: "start with redis backend", + Flags: []cli.Flag{ + &cli.StringFlag{ + Name: "host", + Value: "localhost", + Usage: "redis db hostname", + EnvVars: []string{"GOIPAM_REDIS_HOST"}, + }, + &cli.StringFlag{ + Name: "port", + Value: "6379", + Usage: "redis db port", + EnvVars: []string{"GOIPAM_REDIS_PORT"}, + }, + }, + Action: func(ctx *cli.Context) error { + c := getConfig(ctx) + host := ctx.String("host") + port := ctx.String("port") + c.Storage = goipam.NewRedis(host, port) + + s := newServer(c) + return s.Run() + }, + }, + { + Name: "etcd", + Usage: "start with etcd backend", + Flags: []cli.Flag{ + &cli.StringFlag{ + Name: "host", + Value: "localhost", + Usage: "etcd db hostname", + EnvVars: []string{"GOIPAM_ETCD_HOST"}, + }, + &cli.StringFlag{ + Name: "port", + Value: "2379", + Usage: "etcd db port", + EnvVars: []string{"GOIPAM_ETCD_PORT"}, + }, + &cli.StringFlag{ + Name: "cert-file", + Value: "cert.pem", + Usage: "etcd cert file", + EnvVars: []string{"GOIPAM_ETCD_CERT_FILE"}, + }, + &cli.StringFlag{ + Name: "key-file", + Value: "key.pem", + Usage: "etcd key file", + EnvVars: []string{"GOIPAM_ETCD_KEY_FILE"}, + }, + &cli.BoolFlag{ + Name: "insecure-skip-verify", + Value: false, + Usage: "skip tls certification verification", + EnvVars: []string{"GOIPAM_ETCD_INSECURE_SKIP_VERIFY"}, + }, + }, + Action: func(ctx *cli.Context) error { + c := getConfig(ctx) + host := ctx.String("host") + port := ctx.String("port") + certFile := ctx.String("cert-file") + keyFile := ctx.String("key-file") + cert, err := os.ReadFile(certFile) + if err != nil { + return err + } + key, err := os.ReadFile(keyFile) + if err != nil { + return err + } + insecureSkip := ctx.Bool("insecure-skip-verify") + + c.Storage = goipam.NewEtcd(host, port, cert, key, insecureSkip) + s := newServer(c) + return s.Run() + }, + }, + { + Name: "mongodb", + Usage: "start with mongodb backend", + Flags: []cli.Flag{ + &cli.StringFlag{ + Name: "host", + Value: "localhost", + Usage: "mongodb db hostname", + EnvVars: []string{"GOIPAM_MONGODB_HOST"}, + }, + &cli.StringFlag{ + Name: "port", + Value: "27017", + Usage: "mongodb db port", + EnvVars: []string{"GOIPAM_MONGODB_PORT"}, + }, + &cli.StringFlag{ + Name: "db-name", + Value: "go-ipam", + Usage: "mongodb db name", + EnvVars: []string{"GOIPAM_MONGODB_DB_NAME"}, + }, + &cli.StringFlag{ + Name: "collection-name", + Value: "prefixes", + Usage: "mongodb db collection name", + EnvVars: []string{"GOIPAM_MONGODB_COLLECTION_NAME"}, + }, + &cli.StringFlag{ + Name: "user", + Value: "mongodb", + Usage: "mongodb db user", + EnvVars: []string{"GOIPAM_MONGODB_USER"}, + }, + &cli.StringFlag{ + Name: "password", + Value: "mongodb", + Usage: "mongodb db password", + EnvVars: []string{"GOIPAM_MONGODB_PASSWORD"}, + }, + }, + Action: func(ctx *cli.Context) error { + c := getConfig(ctx) + host := ctx.String("host") + port := ctx.String("port") + user := ctx.String("user") + password := ctx.String("password") + dbname := ctx.String("db-name") + collectionname := ctx.String("collection-name") + + opts := options.Client() + opts.ApplyURI(fmt.Sprintf(`mongodb://%s:%s`, host, port)) + opts.Auth = &options.Credential{ + AuthMechanism: `SCRAM-SHA-1`, + Username: user, + Password: password, + } + + mongocfg := goipam.MongoConfig{ + DatabaseName: dbname, + CollectionName: collectionname, + MongoClientOptions: opts, + } + db, err := goipam.NewMongo(context.Background(), mongocfg) + if err != nil { + return err + } + c.Storage = db + + s := newServer(c) + return s.Run() + }, + }, + }, + } + + err := app.Run(os.Args) + if err != nil { + log.Fatalf("Error in cli: %v", err) + } + +} + +func getConfig(ctx *cli.Context) config { + cfg := zap.NewProductionConfig() + level, err := zap.ParseAtomicLevel(ctx.String("log-level")) + if err != nil { + panic(err) + } + cfg.Level = level + cfg.EncoderConfig.EncodeTime = zapcore.ISO8601TimeEncoder + zlog, err := cfg.Build() + if err != nil { + panic(err) + } + + return config{ + GrpcServerEndpoint: ctx.String("grpc-server-endpoint"), + Log: zlog.Sugar(), + } +} diff --git a/cmd/server/server.go b/cmd/server/server.go new file mode 100644 index 0000000..eca435c --- /dev/null +++ b/cmd/server/server.go @@ -0,0 +1,65 @@ +package main + +import ( + "net/http" + + compress "github.com/klauspost/connect-compress" + goipam "github.com/metal-stack/go-ipam" + "github.com/metal-stack/go-ipam/api/v1/apiv1connect" + "github.com/metal-stack/go-ipam/pkg/service" + "github.com/metal-stack/v" + + grpchealth "github.com/bufbuild/connect-grpchealth-go" + grpcreflect "github.com/bufbuild/connect-grpcreflect-go" + + "go.uber.org/zap" + "golang.org/x/net/http2" + "golang.org/x/net/http2/h2c" +) + +type config struct { + GrpcServerEndpoint string + Log *zap.SugaredLogger + Storage goipam.Storage +} +type server struct { + c config + ipamer goipam.Ipamer + storage goipam.Storage + log *zap.SugaredLogger +} + +func newServer(c config) *server { + + return &server{ + c: c, + ipamer: goipam.NewWithStorage(c.Storage), + storage: c.Storage, + log: c.Log, + } +} +func (s *server) Run() error { + s.log.Infow("starting go-ipam", "version", v.V, "backend", s.storage.Name()) + mux := http.NewServeMux() + // The generated constructors return a path and a plain net/http + // handler. + mux.Handle(apiv1connect.NewIpamServiceHandler(service.New(s.log, s.ipamer))) + + _, serverOpts := compress.All(compress.LevelBalanced) + mux.Handle(grpchealth.NewHandler( + grpchealth.NewStaticChecker(apiv1connect.IpamServiceName), + serverOpts, + )) + mux.Handle(grpcreflect.NewHandlerV1( + grpcreflect.NewStaticReflector(apiv1connect.IpamServiceName), + serverOpts, + )) + + err := http.ListenAndServe( + s.c.GrpcServerEndpoint, + // For gRPC clients, it's convenient to support HTTP/2 without TLS. You can + // avoid x/net/http2 by using http.ListenAndServeTLS. + h2c.NewHandler(mux, &http2.Server{}), + ) + return err +} diff --git a/etcd.go b/etcd.go index e4ebd3e..e1e98e7 100644 --- a/etcd.go +++ b/etcd.go @@ -21,6 +21,10 @@ func NewEtcd(ip, port string, cert, key []byte, insecureskip bool) Storage { return newEtcd(ip, port, cert, key, insecureskip) } +func (e *etcd) Name() string { + return "etcd" +} + func newEtcd(ip, port string, cert, key []byte, insecureskip bool) *etcd { etcdConfig := clientv3.Config{ Endpoints: []string{fmt.Sprintf("%s:%s", ip, port)}, diff --git a/go.mod b/go.mod index 2813a4f..51744b4 100644 --- a/go.mod +++ b/go.mod @@ -4,27 +4,38 @@ go 1.18 require ( github.com/avast/retry-go/v4 v4.1.0 + github.com/bufbuild/connect-go v0.2.0 + github.com/bufbuild/connect-grpchealth-go v0.1.0 + github.com/bufbuild/connect-grpcreflect-go v0.1.0 github.com/go-redis/redis/v8 v8.11.5 github.com/jmoiron/sqlx v1.3.5 + github.com/klauspost/connect-compress v0.1.1 github.com/lib/pq v1.10.6 + github.com/metal-stack/v v1.0.3 github.com/stretchr/testify v1.8.0 github.com/testcontainers/testcontainers-go v0.13.0 + github.com/urfave/cli/v2 v2.11.1 go.etcd.io/etcd/client/v3 v3.5.4 go.mongodb.org/mongo-driver v1.10.0 - golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f + go.uber.org/zap v1.21.0 + golang.org/x/net v0.0.0-20220725212005-46097bf591d3 + golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4 + google.golang.org/protobuf v1.28.0 inet.af/netaddr v0.0.0-20220617031823-097006376321 ) require ( github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect github.com/Microsoft/go-winio v0.5.2 // indirect - github.com/Microsoft/hcsshim v0.9.3 // indirect + github.com/Microsoft/hcsshim v0.9.4 // indirect + github.com/benbjohnson/clock v1.3.0 // indirect github.com/cenkalti/backoff/v4 v4.1.3 // indirect github.com/cespare/xxhash/v2 v2.1.2 // indirect github.com/containerd/cgroups v1.0.4 // indirect github.com/containerd/containerd v1.6.6 // indirect github.com/coreos/go-semver v0.3.0 // indirect github.com/coreos/go-systemd/v22 v22.3.2 // indirect + github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect github.com/docker/distribution v2.8.1+incompatible // indirect @@ -36,7 +47,7 @@ require ( github.com/golang/protobuf v1.5.2 // indirect github.com/golang/snappy v0.0.4 // indirect github.com/google/uuid v1.3.0 // indirect - github.com/klauspost/compress v1.15.8 // indirect + github.com/klauspost/compress v1.15.9 // indirect github.com/magiconair/properties v1.8.6 // indirect github.com/moby/sys/mount v0.3.3 // indirect github.com/moby/sys/mountinfo v0.6.2 // indirect @@ -48,25 +59,24 @@ require ( github.com/opencontainers/runc v1.1.3 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/sirupsen/logrus v1.9.0 // indirect github.com/xdg-go/pbkdf2 v1.0.0 // indirect github.com/xdg-go/scram v1.1.1 // indirect github.com/xdg-go/stringprep v1.0.3 // indirect + github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a // indirect go.etcd.io/etcd/api/v3 v3.5.4 // indirect go.etcd.io/etcd/client/pkg/v3 v3.5.4 // indirect go.opencensus.io v0.23.0 // indirect go.uber.org/atomic v1.9.0 // indirect go.uber.org/multierr v1.8.0 // indirect - go.uber.org/zap v1.21.0 // indirect go4.org/intern v0.0.0-20220617035311-6925f38cc365 // indirect go4.org/unsafe/assume-no-moving-gc v0.0.0-20220617031537-928513b29760 // indirect - golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d // indirect - golang.org/x/net v0.0.0-20220708220712-1185a9018129 // indirect - golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 // indirect + golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa // indirect + golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f // indirect golang.org/x/text v0.3.7 // indirect - google.golang.org/genproto v0.0.0-20220720214146-176da50484ac // indirect + google.golang.org/genproto v0.0.0-20220725144611-272f38e5d71b // indirect google.golang.org/grpc v1.48.0 // indirect - google.golang.org/protobuf v1.28.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index 8c30d76..a9f8305 100644 --- a/go.sum +++ b/go.sum @@ -58,8 +58,8 @@ github.com/Microsoft/hcsshim v0.8.15/go.mod h1:x38A4YbHbdxJtc0sF6oIz+RG0npwSCAvn github.com/Microsoft/hcsshim v0.8.16/go.mod h1:o5/SZqmR7x9JNKsW3pu+nqHm0MF8vbA+VxGOoXdC600= github.com/Microsoft/hcsshim v0.8.21/go.mod h1:+w2gRZ5ReXQhFOrvSQeNfhrYB/dg3oDwTOcER2fw4I4= github.com/Microsoft/hcsshim v0.8.23/go.mod h1:4zegtUJth7lAvFyc6cH2gGQ5B3OFQim01nnU2M8jKDg= -github.com/Microsoft/hcsshim v0.9.3 h1:k371PzBuRrz2b+ebGuI2nVgVhgsVX60jMfSw80NECxo= -github.com/Microsoft/hcsshim v0.9.3/go.mod h1:7pLA8lDk46WKDWlVsENo92gC0XFa8rbKfyFRBqxEbCc= +github.com/Microsoft/hcsshim v0.9.4 h1:mnUj0ivWy6UzbB1uLFqKR6F+ZyiDc7j4iGgHTpO+5+I= +github.com/Microsoft/hcsshim v0.9.4/go.mod h1:7pLA8lDk46WKDWlVsENo92gC0XFa8rbKfyFRBqxEbCc= github.com/Microsoft/hcsshim/test v0.0.0-20201218223536-d3e5debf77da/go.mod h1:5hlzMzRKMLyo42nCZ9oml8AdTlq/0cvIaBv6tK1RehU= github.com/Microsoft/hcsshim/test v0.0.0-20210227013316-43a75bb4edd3/go.mod h1:mw7qgWloBUl75W/gVH3cQszUg1+gUITj7D6NY7ywVnY= github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= @@ -81,8 +81,9 @@ github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:l github.com/avast/retry-go/v4 v4.1.0 h1:CwudD9anYv6JMVnDuTRlK6kLo4dBamiL+F3U8YDiyfg= github.com/avast/retry-go/v4 v4.1.0/go.mod h1:HqmLvS2VLdStPCGDFjSuZ9pzlTqVRldCI4w2dO4m1Ms= github.com/aws/aws-sdk-go v1.15.11/go.mod h1:mFuSZ37Z9YOHbQEwBWztmVzqXrEkub65tZoCYDt7FT0= -github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= +github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT8A= +github.com/benbjohnson/clock v1.3.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/beorn7/perks v0.0.0-20160804104726-4c0e84591b9a/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= @@ -94,6 +95,12 @@ github.com/blang/semver v3.1.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnweb github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4= github.com/bshuster-repo/logrus-logstash-hook v0.4.1/go.mod h1:zsTqEiSzDgAa/8GZR7E1qaXrhYNDKBYy5/dWPTIflbk= +github.com/bufbuild/connect-go v0.2.0 h1:WuMI/jLiJIhysHWvLWlxRozV67mGjCOUuDSl/lkDVic= +github.com/bufbuild/connect-go v0.2.0/go.mod h1:4efZ2eXFENwd4p7tuLaL9m0qtTsCOzuBvrohvRGevDM= +github.com/bufbuild/connect-grpchealth-go v0.1.0 h1:r3HMBCXkqocR7z1ET98kteRE5K4B84lP9XMCRQXIGmw= +github.com/bufbuild/connect-grpchealth-go v0.1.0/go.mod h1:Vm0Mk9/DurVa0pThTknZTXTzzfNio6EDpU64SP4JONc= +github.com/bufbuild/connect-grpcreflect-go v0.1.0 h1:HBXdqivMVMDaG+CjMogGwhDS8pAY/k5UQMX8TRPB+0A= +github.com/bufbuild/connect-grpcreflect-go v0.1.0/go.mod h1:QJMUStjH/yZvhvaRI0Kn5JfQWAM19l/NbA0wxWkSfp0= github.com/buger/jsonparser v0.0.0-20180808090653-f4dd9f5a6b44/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s= github.com/bugsnag/bugsnag-go v0.0.0-20141110184014-b1d153021fcd/go.mod h1:2oa8nejYd4cQ/b0hMIopN0lCRxU0bueqREvZLWFrtK8= github.com/bugsnag/osext v0.0.0-20130617224835-0dd3f918b21b/go.mod h1:obH5gd0BsqsP2LwDJ9aOkm/6J86V6lyAXCoQWGw3K50= @@ -239,6 +246,8 @@ github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfc github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w= +github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.11 h1:07n33Z8lZxZ2qwegKbObQohDhXDQxiMMz1NOUGYlesw= @@ -400,8 +409,8 @@ github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg= github.com/google/go-containerregistry v0.5.1/go.mod h1:Ct15B4yir3PLOP5jsy0GNeYVaIZs/MK/Jz5any1wFW0= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= @@ -477,8 +486,10 @@ github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+o github.com/klauspost/compress v1.11.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.11.13/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= -github.com/klauspost/compress v1.15.8 h1:JahtItbkWjf2jzm/T+qgMxkP9EMHsqEUA6vCMGmXvhA= -github.com/klauspost/compress v1.15.8/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU= +github.com/klauspost/compress v1.15.9 h1:wKRjX6JRtDdrE9qwa4b/Cip7ACOshUI4smpCQanqjSY= +github.com/klauspost/compress v1.15.9/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU= +github.com/klauspost/connect-compress v0.1.1 h1:w3KSCmu19DvpDhgHFJhF6ipJZlFpgXJJAfFhpXwd0U8= +github.com/klauspost/connect-compress v0.1.1/go.mod h1:tyt/UNZLW/dx6KTkBsoUT4ZQ33ja/68QJUxDXDARJg4= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= @@ -516,6 +527,8 @@ github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= github.com/maxbrunsfeld/counterfeiter/v6 v6.2.2/go.mod h1:eD9eIE7cdwcMi9rYluz88Jz2VyhSmden33/aXg4oVIY= +github.com/metal-stack/v v1.0.3 h1:Sh2oBlnxrCUD+mVpzfC8HiqL045YWkxs0gpTvkjppqs= +github.com/metal-stack/v v1.0.3/go.mod h1:YTahEu7/ishwpYKnp/VaW/7nf8+PInogkfGwLcGPdXg= github.com/miekg/pkcs11 v1.0.3/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs= github.com/mistifyio/go-zfs v2.1.2-0.20190413222219-f784269be439+incompatible/go.mod h1:8AuVvqP/mXw1px98n46wfvcGfQ4ci2FwoAjKYxuo3Z4= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= @@ -653,6 +666,8 @@ github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6So github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/safchain/ethtool v0.0.0-20190326074333-42ed695e3de8/go.mod h1:Z0q5wiBQGYcxhMZ6gUqHn6pYNLypFAvaL3UvgZLR0U4= github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= github.com/sclevine/spec v1.2.0/go.mod h1:W4J29eT/Kzv7/b9IWLB055Z+qvVC9vt0Arko24q7p+U= @@ -717,6 +732,8 @@ github.com/urfave/cli v0.0.0-20171014202726-7bc6a0acffa5/go.mod h1:70zkFmudgCuE/ github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= +github.com/urfave/cli/v2 v2.11.1 h1:UKK6SP7fV3eKOefbS87iT9YHefv7iB/53ih6e+GNAsE= +github.com/urfave/cli/v2 v2.11.1/go.mod h1:f8iq5LtQ/bLxafbdBSLPPNsgaW0l/2fYYEHhAyPlwvo= github.com/vishvananda/netlink v0.0.0-20181108222139-023a6dafdcdf/go.mod h1:+SR5DhBJrl6ZM7CoCKvpw5BKroDKQ+PJqOg65H/2ktk= github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE= github.com/vishvananda/netlink v1.1.1-0.20201029203352-d40f9887b852/go.mod h1:twkDnbuQxJYemMlGd4JFIcuhgX83tXhKS2B/PRMpOho= @@ -736,6 +753,8 @@ github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1: github.com/xeipuuv/gojsonschema v0.0.0-20180618132009-1d523034197f/go.mod h1:5yf86TLmAcydyeJq5YvxkGPE2fm/u4myDekKRoLuqhs= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= +github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU= +github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8= github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA= github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a h1:fZHgsYlfvtyqToslyjUt3VOPF4J7aK/3MPcK7xp3PDk= github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a/go.mod h1:ul22v+Nro/R083muKhosV54bj5niojjWZvU8xrevuH4= @@ -802,8 +821,9 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= -golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d h1:sK3txAijHtOK88l68nt020reeT1ZdKLIYetKl95FzVY= golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa h1:zuSxTR4o9y82ebqCUJYNGJbGPo6sKVl54f/TVDObg1c= +golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -879,8 +899,8 @@ golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qx golang.org/x/net v0.0.0-20210825183410-e898025ed96a/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211108170745-6635138e15ea/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20220708220712-1185a9018129 h1:vucSRfWwTsoXro7P+3Cjlr6flUMtzCwzlvkxEQtHHB0= -golang.org/x/net v0.0.0-20220708220712-1185a9018129/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.0.0-20220725212005-46097bf591d3 h1:2yWTtPWWRcISTw3/o+s/Y4UOMnQL71DWyToOANFusCg= +golang.org/x/net v0.0.0-20220725212005-46097bf591d3/go.mod h1:AaygXjzTFtRAg2ttMY5RMuhpJ3cNnI0XpyFJD1iQRSM= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -897,8 +917,8 @@ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f h1:Ax0t5p6N38Ga0dThY21weqDEyz2oklo4IvDkpigvkD8= -golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4 h1:uVc8UZUe6tr40fFVnUP5Oj+veunVezqYl9z7DYw9xzw= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -980,8 +1000,9 @@ golang.org/x/sys v0.0.0-20211116061358-0a5406a5449c/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 h1:0A+M6Uqn+Eje4kHMK80dtF3JCXC4ykBgQG4Fe06QRhQ= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f h1:v4INt8xihDGvnrfjMDVXGxw9wrfxYyCjk0KbXjhR55s= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -1051,7 +1072,6 @@ golang.org/x/tools v0.1.7/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/api v0.0.0-20160322025152-9bf6e6e569ff/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= @@ -1098,8 +1118,8 @@ google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEY google.golang.org/genproto v0.0.0-20200527145253-8367513e4ece/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= google.golang.org/genproto v0.0.0-20201110150050-8816d57aaa9a/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= -google.golang.org/genproto v0.0.0-20220720214146-176da50484ac h1:EOa+Yrhx1C0O+4pHeXeWrCwdI0tWI6IfUU56Vebs9wQ= -google.golang.org/genproto v0.0.0-20220720214146-176da50484ac/go.mod h1:GkXuJDJ6aQ7lnJcRF+SJVgFdQhypqgl3LB1C9vabdRE= +google.golang.org/genproto v0.0.0-20220725144611-272f38e5d71b h1:SfSkJugek6xm7lWywqth4r2iTrYLpD8lOj1nMIIhMNM= +google.golang.org/genproto v0.0.0-20220725144611-272f38e5d71b/go.mod h1:iHe1svFLAZg9VWz891+QbRMwUv9O/1Ww+/mngYeThbc= google.golang.org/grpc v0.0.0-20160317175043-d3ddb4469d5a/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= diff --git a/memory.go b/memory.go index 90e5b5c..426c7d4 100644 --- a/memory.go +++ b/memory.go @@ -18,7 +18,9 @@ func NewMemory() Storage { lock: sync.RWMutex{}, } } - +func (m *memory) Name() string { + return "memory" +} func (m *memory) CreatePrefix(prefix Prefix) (Prefix, error) { m.lock.Lock() defer m.lock.Unlock() diff --git a/mongodb.go b/mongodb.go index 126c7f3..00b322e 100644 --- a/mongodb.go +++ b/mongodb.go @@ -29,6 +29,10 @@ func NewMongo(ctx context.Context, config MongoConfig) (Storage, error) { return newMongo(ctx, config) } +func (m *mongodb) Name() string { + return "mongodb" +} + func newMongo(ctx context.Context, config MongoConfig) (*mongodb, error) { m, err := mongo.NewClient(config.MongoClientOptions) if err != nil { diff --git a/pkg/service/ipam-service.go b/pkg/service/ipam-service.go new file mode 100644 index 0000000..23b62de --- /dev/null +++ b/pkg/service/ipam-service.go @@ -0,0 +1,204 @@ +package service + +import ( + "context" + "fmt" + + "github.com/bufbuild/connect-go" + goipam "github.com/metal-stack/go-ipam" + v1 "github.com/metal-stack/go-ipam/api/v1" + "go.uber.org/zap" + "inet.af/netaddr" +) + +type IPAMService struct { + log *zap.SugaredLogger + ipamer goipam.Ipamer +} + +func New(log *zap.SugaredLogger, ipamer goipam.Ipamer) *IPAMService { + return &IPAMService{ + log: log, + ipamer: ipamer, + } +} + +func (i *IPAMService) CreatePrefix(_ context.Context, req *connect.Request[v1.CreatePrefixRequest]) (*connect.Response[v1.CreatePrefixResponse], error) { + i.log.Debugw("createprefix", "req", req) + resp, err := i.ipamer.NewPrefix(req.Msg.Cidr) + if err != nil { + i.log.Errorw("createprefix", "error", err) + return nil, connect.NewError(connect.CodeInvalidArgument, err) + } + return &connect.Response[v1.CreatePrefixResponse]{ + Msg: &v1.CreatePrefixResponse{ + Prefix: &v1.Prefix{ + Cidr: resp.Cidr, + ParentCidr: resp.ParentCidr, + }, + }, + }, nil +} +func (i *IPAMService) DeletePrefix(_ context.Context, req *connect.Request[v1.DeletePrefixRequest]) (*connect.Response[v1.DeletePrefixResponse], error) { + i.log.Debugw("deleteprefix", "req", req) + resp, err := i.ipamer.DeletePrefix(req.Msg.Cidr) + if err != nil { + i.log.Errorw("deleteprefix", "error", err) + return nil, connect.NewError(connect.CodeInvalidArgument, err) + } + + return &connect.Response[v1.DeletePrefixResponse]{ + Msg: &v1.DeletePrefixResponse{ + Prefix: &v1.Prefix{ + Cidr: resp.Cidr, + ParentCidr: resp.ParentCidr, + }, + }, + }, nil +} +func (i *IPAMService) GetPrefix(_ context.Context, req *connect.Request[v1.GetPrefixRequest]) (*connect.Response[v1.GetPrefixResponse], error) { + i.log.Debugw("getprefix", "req", req) + + resp := i.ipamer.PrefixFrom(req.Msg.Cidr) + if resp == nil { + return &connect.Response[v1.GetPrefixResponse]{}, connect.NewError(connect.CodeNotFound, fmt.Errorf("prefix:%q not found", req.Msg.Cidr)) + } + + return &connect.Response[v1.GetPrefixResponse]{ + Msg: &v1.GetPrefixResponse{ + Prefix: &v1.Prefix{ + Cidr: resp.Cidr, + ParentCidr: resp.ParentCidr, + }, + }, + }, nil +} +func (i *IPAMService) ListPrefixes(_ context.Context, req *connect.Request[v1.ListPrefixesRequest]) (*connect.Response[v1.ListPrefixesResponse], error) { + i.log.Debugw("listprefixes", "req", req) + + resp, err := i.ipamer.ReadAllPrefixCidrs() + if err != nil { + i.log.Errorw("listprefixes", "error", err) + return nil, connect.NewError(connect.CodeInvalidArgument, err) + } + + var result []*v1.Prefix + for _, cidr := range resp { + p := i.ipamer.PrefixFrom(cidr) + if p == nil { + i.log.Warnw("skipping nil prefix of cidr:%q", cidr) + continue + } + result = append(result, &v1.Prefix{Cidr: cidr, ParentCidr: p.ParentCidr}) + } + return &connect.Response[v1.ListPrefixesResponse]{ + Msg: &v1.ListPrefixesResponse{ + Prefixes: result, + }, + }, nil +} + +func (i *IPAMService) AcquireChildPrefix(_ context.Context, req *connect.Request[v1.AcquireChildPrefixRequest]) (*connect.Response[v1.AcquireChildPrefixResponse], error) { + i.log.Debugw("acquirechildprefix", "req", req) + resp, err := i.ipamer.AcquireChildPrefix(req.Msg.Cidr, uint8(req.Msg.Length)) + if err != nil { + i.log.Errorw("acquirechildprefix", "error", err) + return nil, connect.NewError(connect.CodeInvalidArgument, err) + } + return &connect.Response[v1.AcquireChildPrefixResponse]{ + Msg: &v1.AcquireChildPrefixResponse{ + Prefix: &v1.Prefix{ + Cidr: resp.Cidr, + ParentCidr: resp.ParentCidr, + }, + }, + }, nil +} + +func (i *IPAMService) ReleaseChildPrefix(_ context.Context, req *connect.Request[v1.ReleaseChildPrefixRequest]) (*connect.Response[v1.ReleaseChildPrefixResponse], error) { + i.log.Debugw("releasechildprefix", "req", req) + + prefix := i.ipamer.PrefixFrom(req.Msg.Cidr) + if prefix == nil { + return nil, connect.NewError(connect.CodeNotFound, fmt.Errorf("prefix:%q not found", req.Msg.Cidr)) + } + + err := i.ipamer.ReleaseChildPrefix(prefix) + if err != nil { + i.log.Errorw("releasechildprefix", "error", err) + return nil, connect.NewError(connect.CodeInvalidArgument, err) + } + return &connect.Response[v1.ReleaseChildPrefixResponse]{ + Msg: &v1.ReleaseChildPrefixResponse{ + Prefix: &v1.Prefix{ + Cidr: prefix.Cidr, + ParentCidr: prefix.ParentCidr, + }, + }, + }, nil +} +func (i *IPAMService) AcquireIP(_ context.Context, req *connect.Request[v1.AcquireIPRequest]) (*connect.Response[v1.AcquireIPResponse], error) { + i.log.Debugw("acquireip", "req", req) + + resp, err := i.ipamer.AcquireIP(req.Msg.PrefixCidr) + if err != nil { + i.log.Errorw("acquireip", "error", err) + return nil, connect.NewError(connect.CodeInvalidArgument, err) + } + return &connect.Response[v1.AcquireIPResponse]{ + Msg: &v1.AcquireIPResponse{ + Ip: &v1.IP{ + Ip: resp.IP.String(), + ParentPrefix: resp.ParentPrefix, + }, + }, + }, nil +} +func (i *IPAMService) ReleaseIP(_ context.Context, req *connect.Request[v1.ReleaseIPRequest]) (*connect.Response[v1.ReleaseIPResponse], error) { + i.log.Debugw("releaseip", "req", req) + netip, err := netaddr.ParseIP(req.Msg.Ip) + if err != nil { + i.log.Errorw("releaseip", "error", err) + return nil, connect.NewError(connect.CodeInvalidArgument, err) + } + ip := &goipam.IP{ + IP: netip, + ParentPrefix: req.Msg.PrefixCidr, + } + resp, err := i.ipamer.ReleaseIP(ip) + if err != nil { + i.log.Errorw("releaseip", "error", err) + return nil, connect.NewError(connect.CodeInvalidArgument, err) + } + return &connect.Response[v1.ReleaseIPResponse]{ + Msg: &v1.ReleaseIPResponse{ + Ip: &v1.IP{ + Ip: req.Msg.Ip, + ParentPrefix: resp.ParentCidr, + }, + }, + }, nil +} +func (i *IPAMService) Dump(_ context.Context, req *connect.Request[v1.DumpRequest]) (*connect.Response[v1.DumpResponse], error) { + i.log.Debugw("dump", "req", req) + dump, err := i.ipamer.Dump() + if err != nil { + i.log.Errorw("dump", "error", err) + return nil, connect.NewError(connect.CodeInvalidArgument, err) + } + return &connect.Response[v1.DumpResponse]{ + Msg: &v1.DumpResponse{ + Dump: dump, + }, + }, nil +} + +func (i *IPAMService) Load(_ context.Context, req *connect.Request[v1.LoadRequest]) (*connect.Response[v1.LoadResponse], error) { + i.log.Debugw("load", "req", req) + err := i.ipamer.Load(req.Msg.Dump) + if err != nil { + i.log.Errorw("dump", "error", err) + return nil, connect.NewError(connect.CodeInvalidArgument, err) + } + return &connect.Response[v1.LoadResponse]{}, nil +} diff --git a/pkg/service/ipam-service_test.go b/pkg/service/ipam-service_test.go new file mode 100644 index 0000000..e07c580 --- /dev/null +++ b/pkg/service/ipam-service_test.go @@ -0,0 +1,122 @@ +package service + +import ( + "context" + "fmt" + "net/http" + "net/http/httptest" + "testing" + + "github.com/bufbuild/connect-go" + goipam "github.com/metal-stack/go-ipam" + v1 "github.com/metal-stack/go-ipam/api/v1" + "github.com/metal-stack/go-ipam/api/v1/apiv1connect" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "go.uber.org/zap/zaptest" +) + +func TestIpamService(t *testing.T) { + t.Parallel() + mux := http.NewServeMux() + mux.Handle(apiv1connect.NewIpamServiceHandler( + New(zaptest.NewLogger(t).Sugar(), goipam.New()), + )) + server := httptest.NewUnstartedServer(mux) + server.EnableHTTP2 = true + server.StartTLS() + defer server.Close() + + connectClient := apiv1connect.NewIpamServiceClient( + server.Client(), + server.URL, + ) + grpcClient := apiv1connect.NewIpamServiceClient( + server.Client(), + server.URL, + connect.WithGRPC(), + ) + clients := []apiv1connect.IpamServiceClient{connectClient, grpcClient} + + t.Run("CreateDeleteGetPrefix", func(t *testing.T) { + counter := 0 + for _, client := range clients { + result, err := client.CreatePrefix(context.Background(), connect.NewRequest(&v1.CreatePrefixRequest{ + Cidr: fmt.Sprintf("192.169.%d.0/24", counter), + })) + require.Nil(t, err) + assert.Equal(t, result.Msg.Prefix.Cidr, fmt.Sprintf("192.169.%d.0/24", counter)) + + getresult, err := client.GetPrefix(context.Background(), connect.NewRequest(&v1.GetPrefixRequest{ + Cidr: fmt.Sprintf("192.169.%d.0/24", counter), + })) + require.Nil(t, err) + assert.Equal(t, getresult.Msg.Prefix.Cidr, fmt.Sprintf("192.169.%d.0/24", counter)) + + deleteresult, err := client.DeletePrefix(context.Background(), connect.NewRequest(&v1.DeletePrefixRequest{ + Cidr: fmt.Sprintf("192.169.%d.0/24", counter), + })) + require.Nil(t, err) + assert.Equal(t, deleteresult.Msg.Prefix.Cidr, fmt.Sprintf("192.169.%d.0/24", counter)) + + _, err = client.GetPrefix(context.Background(), connect.NewRequest(&v1.GetPrefixRequest{ + Cidr: fmt.Sprintf("192.169.%d.0/24", counter), + })) + require.Error(t, err, fmt.Errorf("prefix:'192.169.%d.0/24' not found", counter)) + + counter++ + } + }) + + t.Run("AcquireReleaseChildPrefix", func(t *testing.T) { + counter := 0 + for _, client := range clients { + result, err := client.CreatePrefix(context.Background(), connect.NewRequest(&v1.CreatePrefixRequest{ + Cidr: fmt.Sprintf("192.167.%d.0/24", counter), + })) + require.Nil(t, err) + assert.Equal(t, result.Msg.Prefix.Cidr, fmt.Sprintf("192.167.%d.0/24", counter)) + + acquireresult, err := client.AcquireChildPrefix(context.Background(), connect.NewRequest(&v1.AcquireChildPrefixRequest{ + Cidr: fmt.Sprintf("192.167.%d.0/24", counter), + Length: 28, + })) + require.Nil(t, err) + assert.Equal(t, acquireresult.Msg.Prefix.Cidr, fmt.Sprintf("192.167.%d.0/28", counter)) + + releaseresult, err := client.ReleaseChildPrefix(context.Background(), connect.NewRequest(&v1.ReleaseChildPrefixRequest{ + Cidr: acquireresult.Msg.Prefix.Cidr, + })) + require.Nil(t, err) + assert.Equal(t, releaseresult.Msg.Prefix.Cidr, acquireresult.Msg.Prefix.Cidr) + + counter++ + } + }) + + t.Run("AcquireReleaseIP", func(t *testing.T) { + counter := 0 + for _, client := range clients { + result, err := client.CreatePrefix(context.Background(), connect.NewRequest(&v1.CreatePrefixRequest{ + Cidr: fmt.Sprintf("192.166.%d.0/24", counter), + })) + require.Nil(t, err) + assert.Equal(t, result.Msg.Prefix.Cidr, fmt.Sprintf("192.166.%d.0/24", counter)) + + acquireresult, err := client.AcquireIP(context.Background(), connect.NewRequest(&v1.AcquireIPRequest{ + PrefixCidr: fmt.Sprintf("192.166.%d.0/24", counter), + })) + require.Nil(t, err) + assert.Equal(t, acquireresult.Msg.Ip.Ip, fmt.Sprintf("192.166.%d.1", counter)) + + releaseresult, err := client.ReleaseIP(context.Background(), connect.NewRequest(&v1.ReleaseIPRequest{ + PrefixCidr: fmt.Sprintf("192.166.%d.0/24", counter), + Ip: acquireresult.Msg.Ip.Ip, + })) + require.Nil(t, err) + assert.Equal(t, releaseresult.Msg.Ip.Ip, fmt.Sprintf("192.166.%d.1", counter)) + + counter++ + } + }) +} diff --git a/pkg/service/test/ipam-service_benchmark_test.go b/pkg/service/test/ipam-service_benchmark_test.go new file mode 100644 index 0000000..1741339 --- /dev/null +++ b/pkg/service/test/ipam-service_benchmark_test.go @@ -0,0 +1,121 @@ +package test + +import ( + "context" + "net/http" + "net/http/httptest" + "testing" + + "github.com/bufbuild/connect-go" + compress "github.com/klauspost/connect-compress" + goipam "github.com/metal-stack/go-ipam" + v1 "github.com/metal-stack/go-ipam/api/v1" + "github.com/metal-stack/go-ipam/api/v1/apiv1connect" + "github.com/metal-stack/go-ipam/pkg/service" + "go.uber.org/zap/zaptest" +) + +// BenchmarkGrpcImpact located in a separate package to prevent import cycles. +func BenchmarkGrpcImpact(b *testing.B) { + + ipam := goipam.New() + + // Get client and server options for all compressors... + clientOpts, serverOpts := compress.All(compress.LevelBalanced) + + mux := http.NewServeMux() + mux.Handle(apiv1connect.NewIpamServiceHandler( + service.New(zaptest.NewLogger(b).Sugar(), ipam), + serverOpts, + )) + server := httptest.NewUnstartedServer(mux) + server.EnableHTTP2 = true + server.StartTLS() + defer server.Close() + + grpc := apiv1connect.NewIpamServiceClient( + server.Client(), + server.URL, + connect.WithGRPC(), + clientOpts, + ) + httpclient := apiv1connect.NewIpamServiceClient( + server.Client(), + server.URL, + clientOpts, + ) + + benchmarks := []struct { + name string + f func() + }{ + { + name: "library", + f: func() { + p, err := ipam.NewPrefix("192.168.0.0/24") + if err != nil { + panic(err) + } + if p == nil { + panic("Prefix nil") + } + _, err = ipam.DeletePrefix(p.Cidr) + if err != nil { + panic(err) + } + }, + }, + { + name: "grpc", + f: func() { + p, err := grpc.CreatePrefix(context.Background(), connect.NewRequest(&v1.CreatePrefixRequest{ + Cidr: "192.169.0.0/24", + })) + if err != nil { + panic(err) + } + if p == nil { + panic("Prefix nil") + } + _, err = grpc.DeletePrefix(context.Background(), connect.NewRequest(&v1.DeletePrefixRequest{ + Cidr: "192.169.0.0/24", + })) + if err != nil { + panic(err) + } + }, + }, + { + name: "http", + f: func() { + p, err := httpclient.CreatePrefix(context.Background(), connect.NewRequest(&v1.CreatePrefixRequest{ + Cidr: "192.169.0.0/24", + })) + if err != nil { + panic(err) + } + if p == nil { + panic("Prefix nil") + } + _, err = httpclient.DeletePrefix(context.Background(), connect.NewRequest(&v1.DeletePrefixRequest{ + Cidr: "192.169.0.0/24", + })) + if err != nil { + panic(err) + } + }, + }, + } + + for _, bm := range benchmarks { + bm := bm + b.Run(bm.name, func(b *testing.B) { + for i := 0; i < b.N; i++ { + bm.f() + } + }) + } + for n := 0; n < b.N; n++ { + + } +} diff --git a/prefix_benchmark_test.go b/prefix_benchmark_test.go index 9bde8ab..5ba8990 100644 --- a/prefix_benchmark_test.go +++ b/prefix_benchmark_test.go @@ -57,14 +57,8 @@ func BenchmarkAcquireChildPrefix(b *testing.B) { childLength uint8 }{ {name: "8/14", parentLength: 8, childLength: 14}, - {name: "8/16", parentLength: 8, childLength: 16}, - {name: "8/20", parentLength: 8, childLength: 20}, - {name: "8/22", parentLength: 8, childLength: 22}, {name: "8/24", parentLength: 8, childLength: 24}, {name: "16/18", parentLength: 16, childLength: 18}, - {name: "16/20", parentLength: 16, childLength: 20}, - {name: "16/22", parentLength: 16, childLength: 22}, - {name: "16/24", parentLength: 16, childLength: 24}, {name: "16/26", parentLength: 16, childLength: 26}, } for _, bm := range benchmarks { diff --git a/proto/Makefile b/proto/Makefile new file mode 100644 index 0000000..00f71ce --- /dev/null +++ b/proto/Makefile @@ -0,0 +1,8 @@ +.PHONY: protolint +protolint: + buf format -w api/v1 + buf lint -v + +.PHONY: protoc +protoc: protolint + buf generate \ No newline at end of file diff --git a/proto/api/v1/ipam.proto b/proto/api/v1/ipam.proto new file mode 100644 index 0000000..22dca05 --- /dev/null +++ b/proto/api/v1/ipam.proto @@ -0,0 +1,86 @@ +syntax = "proto3"; + +package api.v1; + +option go_package = "v1;v1"; + +service IpamService { + rpc CreatePrefix(CreatePrefixRequest) returns (CreatePrefixResponse); + rpc DeletePrefix(DeletePrefixRequest) returns (DeletePrefixResponse); + rpc GetPrefix(GetPrefixRequest) returns (GetPrefixResponse); + rpc ListPrefixes(ListPrefixesRequest) returns (ListPrefixesResponse); + rpc AcquireChildPrefix(AcquireChildPrefixRequest) returns (AcquireChildPrefixResponse); + rpc ReleaseChildPrefix(ReleaseChildPrefixRequest) returns (ReleaseChildPrefixResponse); + rpc AcquireIP(AcquireIPRequest) returns (AcquireIPResponse); + rpc ReleaseIP(ReleaseIPRequest) returns (ReleaseIPResponse); + rpc Dump(DumpRequest) returns (DumpResponse); + rpc Load(LoadRequest) returns (LoadResponse); +} + +message Prefix { + string cidr = 1; + string parent_cidr = 2; +} +message CreatePrefixResponse { + Prefix prefix = 1; +} +message DeletePrefixResponse { + Prefix prefix = 1; +} +message GetPrefixResponse { + Prefix prefix = 1; +} +message AcquireChildPrefixResponse { + Prefix prefix = 1; +} +message ReleaseChildPrefixResponse { + Prefix prefix = 1; +} +message CreatePrefixRequest { + string cidr = 1; +} +message DeletePrefixRequest { + string cidr = 1; +} +message GetPrefixRequest { + string cidr = 1; +} +message ListPrefixesRequest {} +message ListPrefixesResponse { + repeated Prefix prefixes = 1; +} + +message AcquireChildPrefixRequest { + string cidr = 1; + uint32 length = 2; +} +message ReleaseChildPrefixRequest { + string cidr = 1; +} + +message IP { + string ip = 1; + string parent_prefix = 2; +} +message AcquireIPResponse { + IP ip = 1; +} +message ReleaseIPResponse { + IP ip = 1; +} +message AcquireIPRequest { + string prefix_cidr = 1; + optional string ip = 2; +} +message ReleaseIPRequest { + string prefix_cidr = 1; + string ip = 2; +} +message DumpRequest {} +message DumpResponse { + string dump = 1; +} +message LoadRequest { + string dump = 1; +} +message LoadResponse {} diff --git a/proto/buf.gen.yaml b/proto/buf.gen.yaml new file mode 100644 index 0000000..8d58786 --- /dev/null +++ b/proto/buf.gen.yaml @@ -0,0 +1,14 @@ +version: v1 +managed: + enabled: true + go_package_prefix: + default: github.com/metal-stack/go-ipam +plugins: + # generate go structs for protocol buffer defination + - remote: buf.build/bufbuild/plugins/connect-go:v0.2.0-1 + out: ../ + opt: paths=source_relative + # generate go structs for protocol buffer defination + - remote: buf.build/library/plugins/go:v1.27.1-1 + out: ../ + opt: paths=source_relative diff --git a/proto/buf.yaml b/proto/buf.yaml new file mode 100644 index 0000000..1a51945 --- /dev/null +++ b/proto/buf.yaml @@ -0,0 +1,7 @@ +version: v1 +breaking: + use: + - FILE +lint: + use: + - DEFAULT diff --git a/redis.go b/redis.go index 3376295..824b75d 100644 --- a/redis.go +++ b/redis.go @@ -20,6 +20,9 @@ type redis struct { func NewRedis(ip, port string) Storage { return newRedis(ip, port) } +func (r *redis) Name() string { + return "redis" +} func newRedis(ip, port string) *redis { rdb := redigo.NewClient(&redigo.Options{ diff --git a/sql.go b/sql.go index 9689682..50a3faa 100644 --- a/sql.go +++ b/sql.go @@ -135,3 +135,6 @@ func (s *sql) DeletePrefix(prefix Prefix) (Prefix, error) { } return prefix, tx.Commit() } +func (s *sql) Name() string { + return "postgres" +} diff --git a/storage.go b/storage.go index fe47750..4d6f166 100644 --- a/storage.go +++ b/storage.go @@ -2,6 +2,7 @@ package ipam // Storage is a interface to store ipam objects. type Storage interface { + Name() string CreatePrefix(prefix Prefix) (Prefix, error) ReadPrefix(prefix string) (Prefix, error) DeleteAllPrefixes() error diff --git a/testing_test.go b/testing_test.go index 37f7f7f..6bcbbe7 100644 --- a/testing_test.go +++ b/testing_test.go @@ -43,7 +43,7 @@ func TestMain(m *testing.M) { } cockroachVersion = os.Getenv("COCKROACH_VERSION") if cockroachVersion == "" { - cockroachVersion = "v22.1.0" + cockroachVersion = "latest-v22.1" } redisVersion = os.Getenv("REDIS_VERSION") if redisVersion == "" { @@ -51,7 +51,7 @@ func TestMain(m *testing.M) { } keyDBVersion = os.Getenv("KEYDB_VERSION") if keyDBVersion == "" { - keyDBVersion = "alpine_x86_64_v6.2.2" + keyDBVersion = "alpine_x86_64_v6.3.1" } etcdVersion = os.Getenv("ETCD_VERSION") if etcdVersion == "" {