Skip to content

Commit 0e413d7

Browse files
authored
feat: add distribution API (#92)
* 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]>
1 parent 5fd2e3e commit 0e413d7

File tree

17 files changed

+1182
-130
lines changed

17 files changed

+1182
-130
lines changed
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
package distribution
5+
6+
import (
7+
"context"
8+
"fmt"
9+
"net/http"
10+
11+
"github.com/containerd/containerd/namespaces"
12+
"github.com/containerd/nerdctl/pkg/config"
13+
dockertypes "github.com/docker/cli/cli/config/types"
14+
registrytypes "github.com/docker/docker/api/types/registry"
15+
"github.com/gorilla/mux"
16+
"github.com/runfinch/finch-daemon/api/auth"
17+
"github.com/runfinch/finch-daemon/api/response"
18+
"github.com/runfinch/finch-daemon/api/types"
19+
"github.com/runfinch/finch-daemon/pkg/errdefs"
20+
"github.com/runfinch/finch-daemon/pkg/flog"
21+
)
22+
23+
//go:generate mockgen --destination=../../../mocks/mocks_distribution/distributionsvc.go -package=mocks_distribution github.com/runfinch/finch-daemon/api/handlers/distribution Service
24+
type Service interface {
25+
Inspect(ctx context.Context, name string, authCfg *dockertypes.AuthConfig) (*registrytypes.DistributionInspect, error)
26+
}
27+
28+
func RegisterHandlers(r types.VersionedRouter, service Service, conf *config.Config, logger flog.Logger) {
29+
h := newHandler(service, conf, logger)
30+
r.HandleFunc("/distribution/{name}/json", h.inspect, http.MethodGet)
31+
}
32+
33+
func newHandler(service Service, conf *config.Config, logger flog.Logger) *handler {
34+
return &handler{
35+
service: service,
36+
Config: conf,
37+
logger: logger,
38+
}
39+
}
40+
41+
type handler struct {
42+
service Service
43+
Config *config.Config
44+
logger flog.Logger
45+
}
46+
47+
func (h *handler) inspect(w http.ResponseWriter, r *http.Request) {
48+
name := mux.Vars(r)["name"]
49+
// get auth creds from header
50+
authCfg, err := auth.DecodeAuthConfig(r.Header.Get(auth.AuthHeader))
51+
if err != nil {
52+
response.SendErrorResponse(w, http.StatusBadRequest, fmt.Errorf("failed to decode auth header: %s", err))
53+
return
54+
}
55+
ctx := namespaces.WithNamespace(r.Context(), h.Config.Namespace)
56+
inspectRes, err := h.service.Inspect(ctx, name, authCfg)
57+
// map the error into http status code and send response.
58+
if err != nil {
59+
var code int
60+
switch {
61+
case errdefs.IsInvalidFormat(err):
62+
code = http.StatusBadRequest
63+
case errdefs.IsForbiddenError(err):
64+
code = http.StatusForbidden
65+
case errdefs.IsNotFound(err):
66+
code = http.StatusNotFound
67+
default:
68+
code = http.StatusInternalServerError
69+
}
70+
h.logger.Debugf("Inspect Distribution API failed. Status code %d, Message: %s", code, err)
71+
response.SendErrorResponse(w, code, err)
72+
return
73+
}
74+
75+
// return JSON response
76+
response.JSON(w, http.StatusOK, inspectRes)
77+
}
Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
package distribution
5+
6+
import (
7+
"encoding/json"
8+
"fmt"
9+
"net/http"
10+
"net/http/httptest"
11+
"testing"
12+
13+
"github.com/containerd/nerdctl/pkg/config"
14+
registrytypes "github.com/docker/docker/api/types/registry"
15+
"github.com/golang/mock/gomock"
16+
"github.com/gorilla/mux"
17+
. "github.com/onsi/ginkgo/v2"
18+
. "github.com/onsi/gomega"
19+
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
20+
21+
"github.com/runfinch/finch-daemon/mocks/mocks_distribution"
22+
"github.com/runfinch/finch-daemon/mocks/mocks_logger"
23+
"github.com/runfinch/finch-daemon/pkg/errdefs"
24+
)
25+
26+
// TestDistributionHandler function is the entry point of distribution handler package's unit test using ginkgo.
27+
func TestDistributionHandler(t *testing.T) {
28+
RegisterFailHandler(Fail)
29+
RunSpecs(t, "UnitTests - Distribution APIs Handler")
30+
}
31+
32+
var _ = Describe("Distribution Inspect API", func() {
33+
var (
34+
mockCtrl *gomock.Controller
35+
logger *mocks_logger.Logger
36+
service *mocks_distribution.MockService
37+
h *handler
38+
rr *httptest.ResponseRecorder
39+
name string
40+
req *http.Request
41+
ociPlatformAmd ocispec.Platform
42+
ociPlatformArm ocispec.Platform
43+
resp registrytypes.DistributionInspect
44+
respJSON []byte
45+
)
46+
BeforeEach(func() {
47+
mockCtrl = gomock.NewController(GinkgoT())
48+
defer mockCtrl.Finish()
49+
logger = mocks_logger.NewLogger(mockCtrl)
50+
service = mocks_distribution.NewMockService(mockCtrl)
51+
c := config.Config{}
52+
h = newHandler(service, &c, logger)
53+
rr = httptest.NewRecorder()
54+
name = "test-image"
55+
var err error
56+
req, err = http.NewRequest(http.MethodGet, fmt.Sprintf("/distribution/%s/json", name), nil)
57+
Expect(err).Should(BeNil())
58+
req = mux.SetURLVars(req, map[string]string{"name": name})
59+
ociPlatformAmd = ocispec.Platform{
60+
Architecture: "amd64",
61+
OS: "linux",
62+
}
63+
ociPlatformArm = ocispec.Platform{
64+
Architecture: "amd64",
65+
OS: "linux",
66+
}
67+
resp = registrytypes.DistributionInspect{
68+
Descriptor: ocispec.Descriptor{
69+
MediaType: ocispec.MediaTypeImageManifest,
70+
Digest: "sha256:9bae60c369e612488c2a089c38737277a4823a3af97ec6866c3b4ad05251bfa5",
71+
Size: 2,
72+
URLs: []string{},
73+
Annotations: map[string]string{},
74+
Data: []byte{},
75+
Platform: &ociPlatformAmd,
76+
},
77+
Platforms: []ocispec.Platform{
78+
ociPlatformAmd,
79+
ociPlatformArm,
80+
},
81+
}
82+
respJSON, err = json.Marshal(resp)
83+
Expect(err).Should(BeNil())
84+
})
85+
Context("handler", func() {
86+
It("should return inspect object and 200 status code upon success", func() {
87+
service.EXPECT().Inspect(gomock.Any(), name, gomock.Any()).Return(&resp, nil)
88+
89+
// handler should return response object with 200 status code
90+
h.inspect(rr, req)
91+
Expect(rr.Body).Should(MatchJSON(respJSON))
92+
Expect(rr).Should(HaveHTTPStatus(http.StatusOK))
93+
})
94+
It("should return 403 status code if image resolution fails due to lack of credentials", func() {
95+
service.EXPECT().Inspect(gomock.Any(), name, gomock.Any()).Return(nil, errdefs.NewForbidden(fmt.Errorf("access denied")))
96+
logger.EXPECT().Debugf(gomock.Any(), gomock.Any())
97+
98+
// handler should return error message with 404 status code
99+
h.inspect(rr, req)
100+
Expect(rr.Body).Should(MatchJSON(`{"message": "access denied"}`))
101+
Expect(rr).Should(HaveHTTPStatus(http.StatusForbidden))
102+
})
103+
It("should return 404 status code if image was not found", func() {
104+
service.EXPECT().Inspect(gomock.Any(), name, gomock.Any()).Return(nil, errdefs.NewNotFound(fmt.Errorf("no such image")))
105+
logger.EXPECT().Debugf(gomock.Any(), gomock.Any())
106+
107+
// handler should return error message with 404 status code
108+
h.inspect(rr, req)
109+
Expect(rr.Body).Should(MatchJSON(`{"message": "no such image"}`))
110+
Expect(rr).Should(HaveHTTPStatus(http.StatusNotFound))
111+
})
112+
It("should return 500 status code if service returns an error message", func() {
113+
service.EXPECT().Inspect(gomock.Any(), name, gomock.Any()).Return(nil, fmt.Errorf("error"))
114+
logger.EXPECT().Debugf(gomock.Any(), gomock.Any())
115+
116+
// handler should return error message
117+
h.inspect(rr, req)
118+
Expect(rr.Body).Should(MatchJSON(`{"message": "error"}`))
119+
Expect(rr).Should(HaveHTTPStatus(http.StatusInternalServerError))
120+
})
121+
})
122+
})

api/router/router.go

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import (
1717

1818
"github.com/runfinch/finch-daemon/api/handlers/builder"
1919
"github.com/runfinch/finch-daemon/api/handlers/container"
20+
"github.com/runfinch/finch-daemon/api/handlers/distribution"
2021
"github.com/runfinch/finch-daemon/api/handlers/exec"
2122
"github.com/runfinch/finch-daemon/api/handlers/image"
2223
"github.com/runfinch/finch-daemon/api/handlers/network"
@@ -31,14 +32,15 @@ import (
3132

3233
// Options defines the router options to be passed into the handlers.
3334
type Options struct {
34-
Config *config.Config
35-
ContainerService container.Service
36-
ImageService image.Service
37-
NetworkService network.Service
38-
SystemService system.Service
39-
BuilderService builder.Service
40-
VolumeService volume.Service
41-
ExecService exec.Service
35+
Config *config.Config
36+
ContainerService container.Service
37+
ImageService image.Service
38+
NetworkService network.Service
39+
SystemService system.Service
40+
BuilderService builder.Service
41+
VolumeService volume.Service
42+
ExecService exec.Service
43+
DistributionService distribution.Service
4244

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

cmd/finch-daemon/router_utils.go

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import (
1717
"github.com/runfinch/finch-daemon/internal/backend"
1818
"github.com/runfinch/finch-daemon/internal/service/builder"
1919
"github.com/runfinch/finch-daemon/internal/service/container"
20+
"github.com/runfinch/finch-daemon/internal/service/distribution"
2021
"github.com/runfinch/finch-daemon/internal/service/exec"
2122
"github.com/runfinch/finch-daemon/internal/service/image"
2223
"github.com/runfinch/finch-daemon/internal/service/network"
@@ -101,14 +102,15 @@ func createRouterOptions(
101102
tarExtractor := archive.NewTarExtractor(ecc.NewExecCmdCreator(), logger)
102103

103104
return &router.Options{
104-
Config: conf,
105-
ContainerService: container.NewService(clientWrapper, ncWrapper, logger, fs, tarCreator, tarExtractor),
106-
ImageService: image.NewService(clientWrapper, ncWrapper, logger),
107-
NetworkService: network.NewService(clientWrapper, ncWrapper, logger),
108-
SystemService: system.NewService(clientWrapper, ncWrapper, logger),
109-
BuilderService: builder.NewService(clientWrapper, ncWrapper, logger, tarExtractor),
110-
VolumeService: volume.NewService(ncWrapper, logger),
111-
ExecService: exec.NewService(clientWrapper, logger),
112-
NerdctlWrapper: ncWrapper,
105+
Config: conf,
106+
ContainerService: container.NewService(clientWrapper, ncWrapper, logger, fs, tarCreator, tarExtractor),
107+
ImageService: image.NewService(clientWrapper, ncWrapper, logger),
108+
NetworkService: network.NewService(clientWrapper, ncWrapper, logger),
109+
SystemService: system.NewService(clientWrapper, ncWrapper, logger),
110+
BuilderService: builder.NewService(clientWrapper, ncWrapper, logger, tarExtractor),
111+
VolumeService: volume.NewService(ncWrapper, logger),
112+
ExecService: exec.NewService(clientWrapper, logger),
113+
DistributionService: distribution.NewService(clientWrapper, ncWrapper, logger),
114+
NerdctlWrapper: ncWrapper,
113115
}
114116
}

go.mod

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ require (
2727
github.com/gorilla/mux v1.8.1
2828
github.com/moby/moby v26.0.0+incompatible
2929
github.com/onsi/ginkgo/v2 v2.20.2
30-
github.com/onsi/gomega v1.34.2
30+
github.com/onsi/gomega v1.35.1
3131
github.com/opencontainers/go-digest v1.0.0
3232
github.com/opencontainers/image-spec v1.1.0
3333
github.com/opencontainers/runtime-spec v1.2.0
@@ -40,9 +40,9 @@ require (
4040
github.com/stretchr/testify v1.9.0
4141
github.com/vishvananda/netlink v1.3.0
4242
github.com/vishvananda/netns v0.0.4
43-
golang.org/x/net v0.29.0
44-
golang.org/x/sys v0.25.0
45-
google.golang.org/protobuf v1.34.2
43+
golang.org/x/net v0.30.0
44+
golang.org/x/sys v0.26.0
45+
google.golang.org/protobuf v1.35.1
4646
)
4747

4848
require (
@@ -143,11 +143,11 @@ require (
143143
go.opentelemetry.io/otel v1.30.0 // indirect
144144
go.opentelemetry.io/otel/metric v1.30.0 // indirect
145145
go.opentelemetry.io/otel/trace v1.30.0 // indirect
146-
golang.org/x/crypto v0.27.0 // indirect
146+
golang.org/x/crypto v0.28.0 // indirect
147147
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 // indirect
148148
golang.org/x/sync v0.8.0 // indirect
149-
golang.org/x/term v0.24.0 // indirect
150-
golang.org/x/text v0.18.0 // indirect
149+
golang.org/x/term v0.25.0 // indirect
150+
golang.org/x/text v0.19.0 // indirect
151151
golang.org/x/time v0.5.0 // indirect
152152
golang.org/x/tools v0.24.0 // indirect
153153
google.golang.org/genproto v0.0.0-20240903143218-8af14fe29dc1 // indirect

go.sum

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -252,8 +252,8 @@ github.com/multiformats/go-varint v0.0.7 h1:sWSGR+f/eu5ABZA2ZpYKBILXTTs9JWpdEM/n
252252
github.com/multiformats/go-varint v0.0.7/go.mod h1:r8PUYw/fD/SjBCiKOoDlGF6QawOELpZAu9eioSos/OU=
253253
github.com/onsi/ginkgo/v2 v2.20.2 h1:7NVCeyIWROIAheY21RLS+3j2bb52W0W82tkberYytp4=
254254
github.com/onsi/ginkgo/v2 v2.20.2/go.mod h1:K9gyxPIlb+aIvnZ8bd9Ak+YP18w3APlR+5coaZoE2ag=
255-
github.com/onsi/gomega v1.34.2 h1:pNCwDkzrsv7MS9kpaQvVb1aVLahQXyJ/Tv5oAZMI3i8=
256-
github.com/onsi/gomega v1.34.2/go.mod h1:v1xfxRgk0KIsG+QOdm7p8UosrOzPYRo60fd3B/1Dukc=
255+
github.com/onsi/gomega v1.35.1 h1:Cwbd75ZBPxFSuZ6T+rN/WCb/gOc6YgFBXLlZLhC7Ds4=
256+
github.com/onsi/gomega v1.35.1/go.mod h1:PvZbdDc8J6XJEpDK4HCuRBm8a6Fzp9/DmhC9C7yFlog=
257257
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
258258
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
259259
github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug=
@@ -349,8 +349,8 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U
349349
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
350350
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
351351
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
352-
golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A=
353-
golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70=
352+
golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw=
353+
golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U=
354354
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
355355
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0LeHDbnYEryqj5Q1ug8=
356356
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY=
@@ -376,8 +376,8 @@ golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96b
376376
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
377377
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
378378
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
379-
golang.org/x/net v0.29.0 h1:5ORfpBpCs4HzDYoodCDBbwHzdR5UrLBZ3sOnUJmFoHo=
380-
golang.org/x/net v0.29.0/go.mod h1:gLkgy8jTGERgjzMic6DS9+SP0ajcu6Xu3Orq/SpETg0=
379+
golang.org/x/net v0.30.0 h1:AcW1SDZMkb8IpzCdQUaIq2sP4sZ4zw+55h6ynffypl4=
380+
golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU=
381381
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
382382
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
383383
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -409,23 +409,23 @@ golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
409409
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
410410
golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
411411
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
412-
golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34=
413-
golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
412+
golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo=
413+
golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
414414
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
415415
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
416416
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
417417
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
418418
golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
419-
golang.org/x/term v0.24.0 h1:Mh5cbb+Zk2hqqXNO7S1iTjEphVL+jb8ZWaqh/g+JWkM=
420-
golang.org/x/term v0.24.0/go.mod h1:lOBK/LVxemqiMij05LGJ0tzNr8xlmwBRJ81PX6wVLH8=
419+
golang.org/x/term v0.25.0 h1:WtHI/ltw4NvSUig5KARz9h521QvRC8RmF/cuYqifU24=
420+
golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M=
421421
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
422422
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
423423
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
424424
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
425425
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
426426
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
427-
golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224=
428-
golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
427+
golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM=
428+
golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
429429
golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
430430
golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
431431
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
@@ -472,8 +472,8 @@ google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpAD
472472
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
473473
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
474474
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
475-
google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg=
476-
google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw=
475+
google.golang.org/protobuf v1.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA=
476+
google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
477477
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
478478
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
479479
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=

0 commit comments

Comments
 (0)