Skip to content

Commit

Permalink
feat: add distribution API (#92)
Browse files Browse the repository at this point in the history
* feat: add distribution API

Signed-off-by: Justin Alvarez <[email protected]>

* fix non-manifestlist case

Signed-off-by: Justin Alvarez <[email protected]>

---------

Signed-off-by: Justin Alvarez <[email protected]>
  • Loading branch information
pendo324 authored Nov 13, 2024
1 parent 5fd2e3e commit 0e413d7
Show file tree
Hide file tree
Showing 17 changed files with 1,182 additions and 130 deletions.
77 changes: 77 additions & 0 deletions api/handlers/distribution/distribution.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

package distribution

import (
"context"
"fmt"
"net/http"

"github.com/containerd/containerd/namespaces"
"github.com/containerd/nerdctl/pkg/config"
dockertypes "github.com/docker/cli/cli/config/types"
registrytypes "github.com/docker/docker/api/types/registry"
"github.com/gorilla/mux"
"github.com/runfinch/finch-daemon/api/auth"
"github.com/runfinch/finch-daemon/api/response"
"github.com/runfinch/finch-daemon/api/types"
"github.com/runfinch/finch-daemon/pkg/errdefs"
"github.com/runfinch/finch-daemon/pkg/flog"
)

//go:generate mockgen --destination=../../../mocks/mocks_distribution/distributionsvc.go -package=mocks_distribution github.com/runfinch/finch-daemon/api/handlers/distribution Service
type Service interface {
Inspect(ctx context.Context, name string, authCfg *dockertypes.AuthConfig) (*registrytypes.DistributionInspect, error)
}

func RegisterHandlers(r types.VersionedRouter, service Service, conf *config.Config, logger flog.Logger) {
h := newHandler(service, conf, logger)
r.HandleFunc("/distribution/{name}/json", h.inspect, http.MethodGet)
}

func newHandler(service Service, conf *config.Config, logger flog.Logger) *handler {
return &handler{
service: service,
Config: conf,
logger: logger,
}
}

type handler struct {
service Service
Config *config.Config
logger flog.Logger
}

func (h *handler) inspect(w http.ResponseWriter, r *http.Request) {
name := mux.Vars(r)["name"]
// get auth creds from header
authCfg, err := auth.DecodeAuthConfig(r.Header.Get(auth.AuthHeader))
if err != nil {
response.SendErrorResponse(w, http.StatusBadRequest, fmt.Errorf("failed to decode auth header: %s", err))
return
}
ctx := namespaces.WithNamespace(r.Context(), h.Config.Namespace)
inspectRes, err := h.service.Inspect(ctx, name, authCfg)
// map the error into http status code and send response.
if err != nil {
var code int
switch {
case errdefs.IsInvalidFormat(err):
code = http.StatusBadRequest
case errdefs.IsForbiddenError(err):
code = http.StatusForbidden
case errdefs.IsNotFound(err):
code = http.StatusNotFound
default:
code = http.StatusInternalServerError
}
h.logger.Debugf("Inspect Distribution API failed. Status code %d, Message: %s", code, err)
response.SendErrorResponse(w, code, err)
return
}

// return JSON response
response.JSON(w, http.StatusOK, inspectRes)
}
122 changes: 122 additions & 0 deletions api/handlers/distribution/distribution_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

package distribution

import (
"encoding/json"
"fmt"
"net/http"
"net/http/httptest"
"testing"

"github.com/containerd/nerdctl/pkg/config"
registrytypes "github.com/docker/docker/api/types/registry"
"github.com/golang/mock/gomock"
"github.com/gorilla/mux"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
ocispec "github.com/opencontainers/image-spec/specs-go/v1"

"github.com/runfinch/finch-daemon/mocks/mocks_distribution"
"github.com/runfinch/finch-daemon/mocks/mocks_logger"
"github.com/runfinch/finch-daemon/pkg/errdefs"
)

// TestDistributionHandler function is the entry point of distribution handler package's unit test using ginkgo.
func TestDistributionHandler(t *testing.T) {
RegisterFailHandler(Fail)
RunSpecs(t, "UnitTests - Distribution APIs Handler")
}

var _ = Describe("Distribution Inspect API", func() {
var (
mockCtrl *gomock.Controller
logger *mocks_logger.Logger
service *mocks_distribution.MockService
h *handler
rr *httptest.ResponseRecorder
name string
req *http.Request
ociPlatformAmd ocispec.Platform
ociPlatformArm ocispec.Platform
resp registrytypes.DistributionInspect
respJSON []byte
)
BeforeEach(func() {
mockCtrl = gomock.NewController(GinkgoT())
defer mockCtrl.Finish()
logger = mocks_logger.NewLogger(mockCtrl)
service = mocks_distribution.NewMockService(mockCtrl)
c := config.Config{}
h = newHandler(service, &c, logger)
rr = httptest.NewRecorder()
name = "test-image"
var err error
req, err = http.NewRequest(http.MethodGet, fmt.Sprintf("/distribution/%s/json", name), nil)
Expect(err).Should(BeNil())
req = mux.SetURLVars(req, map[string]string{"name": name})
ociPlatformAmd = ocispec.Platform{
Architecture: "amd64",
OS: "linux",
}
ociPlatformArm = ocispec.Platform{
Architecture: "amd64",
OS: "linux",
}
resp = registrytypes.DistributionInspect{
Descriptor: ocispec.Descriptor{
MediaType: ocispec.MediaTypeImageManifest,
Digest: "sha256:9bae60c369e612488c2a089c38737277a4823a3af97ec6866c3b4ad05251bfa5",
Size: 2,
URLs: []string{},
Annotations: map[string]string{},
Data: []byte{},
Platform: &ociPlatformAmd,
},
Platforms: []ocispec.Platform{
ociPlatformAmd,
ociPlatformArm,
},
}
respJSON, err = json.Marshal(resp)
Expect(err).Should(BeNil())
})
Context("handler", func() {
It("should return inspect object and 200 status code upon success", func() {
service.EXPECT().Inspect(gomock.Any(), name, gomock.Any()).Return(&resp, nil)

// handler should return response object with 200 status code
h.inspect(rr, req)
Expect(rr.Body).Should(MatchJSON(respJSON))
Expect(rr).Should(HaveHTTPStatus(http.StatusOK))
})
It("should return 403 status code if image resolution fails due to lack of credentials", func() {
service.EXPECT().Inspect(gomock.Any(), name, gomock.Any()).Return(nil, errdefs.NewForbidden(fmt.Errorf("access denied")))
logger.EXPECT().Debugf(gomock.Any(), gomock.Any())

// handler should return error message with 404 status code
h.inspect(rr, req)
Expect(rr.Body).Should(MatchJSON(`{"message": "access denied"}`))
Expect(rr).Should(HaveHTTPStatus(http.StatusForbidden))
})
It("should return 404 status code if image was not found", func() {
service.EXPECT().Inspect(gomock.Any(), name, gomock.Any()).Return(nil, errdefs.NewNotFound(fmt.Errorf("no such image")))
logger.EXPECT().Debugf(gomock.Any(), gomock.Any())

// handler should return error message with 404 status code
h.inspect(rr, req)
Expect(rr.Body).Should(MatchJSON(`{"message": "no such image"}`))
Expect(rr).Should(HaveHTTPStatus(http.StatusNotFound))
})
It("should return 500 status code if service returns an error message", func() {
service.EXPECT().Inspect(gomock.Any(), name, gomock.Any()).Return(nil, fmt.Errorf("error"))
logger.EXPECT().Debugf(gomock.Any(), gomock.Any())

// handler should return error message
h.inspect(rr, req)
Expect(rr.Body).Should(MatchJSON(`{"message": "error"}`))
Expect(rr).Should(HaveHTTPStatus(http.StatusInternalServerError))
})
})
})
19 changes: 11 additions & 8 deletions api/router/router.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import (

"github.com/runfinch/finch-daemon/api/handlers/builder"
"github.com/runfinch/finch-daemon/api/handlers/container"
"github.com/runfinch/finch-daemon/api/handlers/distribution"
"github.com/runfinch/finch-daemon/api/handlers/exec"
"github.com/runfinch/finch-daemon/api/handlers/image"
"github.com/runfinch/finch-daemon/api/handlers/network"
Expand All @@ -31,14 +32,15 @@ import (

// Options defines the router options to be passed into the handlers.
type Options struct {
Config *config.Config
ContainerService container.Service
ImageService image.Service
NetworkService network.Service
SystemService system.Service
BuilderService builder.Service
VolumeService volume.Service
ExecService exec.Service
Config *config.Config
ContainerService container.Service
ImageService image.Service
NetworkService network.Service
SystemService system.Service
BuilderService builder.Service
VolumeService volume.Service
ExecService exec.Service
DistributionService distribution.Service

// NerdctlWrapper wraps the interactions with nerdctl to build
NerdctlWrapper *backend.NerdctlWrapper
Expand All @@ -59,6 +61,7 @@ func New(opts *Options) http.Handler {
builder.RegisterHandlers(vr, opts.BuilderService, opts.Config, logger, opts.NerdctlWrapper)
volume.RegisterHandlers(vr, opts.VolumeService, opts.Config, logger)
exec.RegisterHandlers(vr, opts.ExecService, opts.Config, logger)
distribution.RegisterHandlers(vr, opts.DistributionService, opts.Config, logger)
return ghandlers.LoggingHandler(os.Stderr, r)
}

Expand Down
20 changes: 11 additions & 9 deletions cmd/finch-daemon/router_utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import (
"github.com/runfinch/finch-daemon/internal/backend"
"github.com/runfinch/finch-daemon/internal/service/builder"
"github.com/runfinch/finch-daemon/internal/service/container"
"github.com/runfinch/finch-daemon/internal/service/distribution"
"github.com/runfinch/finch-daemon/internal/service/exec"
"github.com/runfinch/finch-daemon/internal/service/image"
"github.com/runfinch/finch-daemon/internal/service/network"
Expand Down Expand Up @@ -101,14 +102,15 @@ func createRouterOptions(
tarExtractor := archive.NewTarExtractor(ecc.NewExecCmdCreator(), logger)

return &router.Options{
Config: conf,
ContainerService: container.NewService(clientWrapper, ncWrapper, logger, fs, tarCreator, tarExtractor),
ImageService: image.NewService(clientWrapper, ncWrapper, logger),
NetworkService: network.NewService(clientWrapper, ncWrapper, logger),
SystemService: system.NewService(clientWrapper, ncWrapper, logger),
BuilderService: builder.NewService(clientWrapper, ncWrapper, logger, tarExtractor),
VolumeService: volume.NewService(ncWrapper, logger),
ExecService: exec.NewService(clientWrapper, logger),
NerdctlWrapper: ncWrapper,
Config: conf,
ContainerService: container.NewService(clientWrapper, ncWrapper, logger, fs, tarCreator, tarExtractor),
ImageService: image.NewService(clientWrapper, ncWrapper, logger),
NetworkService: network.NewService(clientWrapper, ncWrapper, logger),
SystemService: system.NewService(clientWrapper, ncWrapper, logger),
BuilderService: builder.NewService(clientWrapper, ncWrapper, logger, tarExtractor),
VolumeService: volume.NewService(ncWrapper, logger),
ExecService: exec.NewService(clientWrapper, logger),
DistributionService: distribution.NewService(clientWrapper, ncWrapper, logger),
NerdctlWrapper: ncWrapper,
}
}
14 changes: 7 additions & 7 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ require (
github.com/gorilla/mux v1.8.1
github.com/moby/moby v26.0.0+incompatible
github.com/onsi/ginkgo/v2 v2.20.2
github.com/onsi/gomega v1.34.2
github.com/onsi/gomega v1.35.1
github.com/opencontainers/go-digest v1.0.0
github.com/opencontainers/image-spec v1.1.0
github.com/opencontainers/runtime-spec v1.2.0
Expand All @@ -40,9 +40,9 @@ require (
github.com/stretchr/testify v1.9.0
github.com/vishvananda/netlink v1.3.0
github.com/vishvananda/netns v0.0.4
golang.org/x/net v0.29.0
golang.org/x/sys v0.25.0
google.golang.org/protobuf v1.34.2
golang.org/x/net v0.30.0
golang.org/x/sys v0.26.0
google.golang.org/protobuf v1.35.1
)

require (
Expand Down Expand Up @@ -143,11 +143,11 @@ require (
go.opentelemetry.io/otel v1.30.0 // indirect
go.opentelemetry.io/otel/metric v1.30.0 // indirect
go.opentelemetry.io/otel/trace v1.30.0 // indirect
golang.org/x/crypto v0.27.0 // indirect
golang.org/x/crypto v0.28.0 // indirect
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 // indirect
golang.org/x/sync v0.8.0 // indirect
golang.org/x/term v0.24.0 // indirect
golang.org/x/text v0.18.0 // indirect
golang.org/x/term v0.25.0 // indirect
golang.org/x/text v0.19.0 // indirect
golang.org/x/time v0.5.0 // indirect
golang.org/x/tools v0.24.0 // indirect
google.golang.org/genproto v0.0.0-20240903143218-8af14fe29dc1 // indirect
Expand Down
28 changes: 14 additions & 14 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -252,8 +252,8 @@ github.com/multiformats/go-varint v0.0.7 h1:sWSGR+f/eu5ABZA2ZpYKBILXTTs9JWpdEM/n
github.com/multiformats/go-varint v0.0.7/go.mod h1:r8PUYw/fD/SjBCiKOoDlGF6QawOELpZAu9eioSos/OU=
github.com/onsi/ginkgo/v2 v2.20.2 h1:7NVCeyIWROIAheY21RLS+3j2bb52W0W82tkberYytp4=
github.com/onsi/ginkgo/v2 v2.20.2/go.mod h1:K9gyxPIlb+aIvnZ8bd9Ak+YP18w3APlR+5coaZoE2ag=
github.com/onsi/gomega v1.34.2 h1:pNCwDkzrsv7MS9kpaQvVb1aVLahQXyJ/Tv5oAZMI3i8=
github.com/onsi/gomega v1.34.2/go.mod h1:v1xfxRgk0KIsG+QOdm7p8UosrOzPYRo60fd3B/1Dukc=
github.com/onsi/gomega v1.35.1 h1:Cwbd75ZBPxFSuZ6T+rN/WCb/gOc6YgFBXLlZLhC7Ds4=
github.com/onsi/gomega v1.35.1/go.mod h1:PvZbdDc8J6XJEpDK4HCuRBm8a6Fzp9/DmhC9C7yFlog=
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug=
Expand Down Expand Up @@ -349,8 +349,8 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A=
golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70=
golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw=
golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0LeHDbnYEryqj5Q1ug8=
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY=
Expand All @@ -376,8 +376,8 @@ golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96b
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
golang.org/x/net v0.29.0 h1:5ORfpBpCs4HzDYoodCDBbwHzdR5UrLBZ3sOnUJmFoHo=
golang.org/x/net v0.29.0/go.mod h1:gLkgy8jTGERgjzMic6DS9+SP0ajcu6Xu3Orq/SpETg0=
golang.org/x/net v0.30.0 h1:AcW1SDZMkb8IpzCdQUaIq2sP4sZ4zw+55h6ynffypl4=
golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
Expand Down Expand Up @@ -409,23 +409,23 @@ golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34=
golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo=
golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
golang.org/x/term v0.24.0 h1:Mh5cbb+Zk2hqqXNO7S1iTjEphVL+jb8ZWaqh/g+JWkM=
golang.org/x/term v0.24.0/go.mod h1:lOBK/LVxemqiMij05LGJ0tzNr8xlmwBRJ81PX6wVLH8=
golang.org/x/term v0.25.0 h1:WtHI/ltw4NvSUig5KARz9h521QvRC8RmF/cuYqifU24=
golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224=
golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM=
golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
Expand Down Expand Up @@ -472,8 +472,8 @@ google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpAD
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg=
google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw=
google.golang.org/protobuf v1.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA=
google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
Expand Down
Loading

0 comments on commit 0e413d7

Please sign in to comment.