mirror of
https://gitea.com/Lydanne/buildx.git
synced 2025-07-09 21:17:09 +08:00
vendor: update buildkit
Signed-off-by: CrazyMax <crazy-max@users.noreply.github.com>
This commit is contained in:
6627
vendor/github.com/containerd/containerd/api/services/content/v1/content.pb.go
generated
vendored
6627
vendor/github.com/containerd/containerd/api/services/content/v1/content.pb.go
generated
vendored
File diff suppressed because it is too large
Load Diff
48
vendor/github.com/containerd/containerd/api/services/content/v1/content.proto
generated
vendored
48
vendor/github.com/containerd/containerd/api/services/content/v1/content.proto
generated
vendored
@ -18,7 +18,6 @@ syntax = "proto3";
|
||||
|
||||
package containerd.services.content.v1;
|
||||
|
||||
import weak "gogoproto/gogo.proto";
|
||||
import "google/protobuf/field_mask.proto";
|
||||
import "google/protobuf/timestamp.proto";
|
||||
import "google/protobuf/empty.proto";
|
||||
@ -92,16 +91,16 @@ service Content {
|
||||
|
||||
message Info {
|
||||
// Digest is the hash identity of the blob.
|
||||
string digest = 1 [(gogoproto.customtype) = "github.com/opencontainers/go-digest.Digest", (gogoproto.nullable) = false];
|
||||
string digest = 1;
|
||||
|
||||
// Size is the total number of bytes in the blob.
|
||||
int64 size = 2;
|
||||
|
||||
// CreatedAt provides the time at which the blob was committed.
|
||||
google.protobuf.Timestamp created_at = 3 [(gogoproto.stdtime) = true, (gogoproto.nullable) = false];
|
||||
google.protobuf.Timestamp created_at = 3;
|
||||
|
||||
// UpdatedAt provides the time the info was last updated.
|
||||
google.protobuf.Timestamp updated_at = 4 [(gogoproto.stdtime) = true, (gogoproto.nullable) = false];
|
||||
google.protobuf.Timestamp updated_at = 4;
|
||||
|
||||
// Labels are arbitrary data on snapshots.
|
||||
//
|
||||
@ -110,15 +109,15 @@ message Info {
|
||||
}
|
||||
|
||||
message InfoRequest {
|
||||
string digest = 1 [(gogoproto.customtype) = "github.com/opencontainers/go-digest.Digest", (gogoproto.nullable) = false];
|
||||
string digest = 1;
|
||||
}
|
||||
|
||||
message InfoResponse {
|
||||
Info info = 1 [(gogoproto.nullable) = false];
|
||||
Info info = 1;
|
||||
}
|
||||
|
||||
message UpdateRequest {
|
||||
Info info = 1 [(gogoproto.nullable) = false];
|
||||
Info info = 1;
|
||||
|
||||
// UpdateMask specifies which fields to perform the update on. If empty,
|
||||
// the operation applies to all fields.
|
||||
@ -130,7 +129,7 @@ message UpdateRequest {
|
||||
}
|
||||
|
||||
message UpdateResponse {
|
||||
Info info = 1 [(gogoproto.nullable) = false];
|
||||
Info info = 1;
|
||||
}
|
||||
|
||||
message ListContentRequest {
|
||||
@ -141,26 +140,26 @@ message ListContentRequest {
|
||||
// filters. Expanded, containers that match the following will be
|
||||
// returned:
|
||||
//
|
||||
// filters[0] or filters[1] or ... or filters[n-1] or filters[n]
|
||||
// filters[0] or filters[1] or ... or filters[n-1] or filters[n]
|
||||
//
|
||||
// If filters is zero-length or nil, all items will be returned.
|
||||
repeated string filters = 1;
|
||||
}
|
||||
|
||||
message ListContentResponse {
|
||||
repeated Info info = 1 [(gogoproto.nullable) = false];
|
||||
repeated Info info = 1;
|
||||
}
|
||||
|
||||
message DeleteContentRequest {
|
||||
// Digest specifies which content to delete.
|
||||
string digest = 1 [(gogoproto.customtype) = "github.com/opencontainers/go-digest.Digest", (gogoproto.nullable) = false];
|
||||
string digest = 1;
|
||||
}
|
||||
|
||||
// ReadContentRequest defines the fields that make up a request to read a portion of
|
||||
// data from a stored object.
|
||||
message ReadContentRequest {
|
||||
// Digest is the hash identity to read.
|
||||
string digest = 1 [(gogoproto.customtype) = "github.com/opencontainers/go-digest.Digest", (gogoproto.nullable) = false];
|
||||
string digest = 1;
|
||||
|
||||
// Offset specifies the number of bytes from the start at which to begin
|
||||
// the read. If zero or less, the read will be from the start. This uses
|
||||
@ -179,12 +178,12 @@ message ReadContentResponse {
|
||||
}
|
||||
|
||||
message Status {
|
||||
google.protobuf.Timestamp started_at = 1 [(gogoproto.stdtime) = true, (gogoproto.nullable) = false];
|
||||
google.protobuf.Timestamp updated_at = 2 [(gogoproto.stdtime) = true, (gogoproto.nullable) = false];
|
||||
google.protobuf.Timestamp started_at = 1;
|
||||
google.protobuf.Timestamp updated_at = 2;
|
||||
string ref = 3;
|
||||
int64 offset = 4;
|
||||
int64 total = 5;
|
||||
string expected = 6 [(gogoproto.customtype) = "github.com/opencontainers/go-digest.Digest", (gogoproto.nullable) = false];
|
||||
string expected = 6;
|
||||
}
|
||||
|
||||
|
||||
@ -201,17 +200,14 @@ message ListStatusesRequest {
|
||||
}
|
||||
|
||||
message ListStatusesResponse {
|
||||
repeated Status statuses = 1 [(gogoproto.nullable) = false];
|
||||
repeated Status statuses = 1;
|
||||
}
|
||||
|
||||
// WriteAction defines the behavior of a WriteRequest.
|
||||
enum WriteAction {
|
||||
option (gogoproto.goproto_enum_prefix) = false;
|
||||
option (gogoproto.enum_customname) = "WriteAction";
|
||||
|
||||
// WriteActionStat instructs the writer to return the current status while
|
||||
// holding the lock on the write.
|
||||
STAT = 0 [(gogoproto.enumvalue_customname) = "WriteActionStat"];
|
||||
STAT = 0;
|
||||
|
||||
// WriteActionWrite sets the action for the write request to write data.
|
||||
//
|
||||
@ -219,7 +215,7 @@ enum WriteAction {
|
||||
// transaction will be left open for further writes.
|
||||
//
|
||||
// This is the default.
|
||||
WRITE = 1 [(gogoproto.enumvalue_customname) = "WriteActionWrite"];
|
||||
WRITE = 1;
|
||||
|
||||
// WriteActionCommit will write any outstanding data in the message and
|
||||
// commit the write, storing it under the digest.
|
||||
@ -228,7 +224,7 @@ enum WriteAction {
|
||||
// commit it.
|
||||
//
|
||||
// This action will always terminate the write.
|
||||
COMMIT = 2 [(gogoproto.enumvalue_customname) = "WriteActionCommit"];
|
||||
COMMIT = 2;
|
||||
}
|
||||
|
||||
// WriteContentRequest writes data to the request ref at offset.
|
||||
@ -269,7 +265,7 @@ message WriteContentRequest {
|
||||
// Only the latest version will be used to check the content against the
|
||||
// digest. It is only required to include it on a single message, before or
|
||||
// with the commit action message.
|
||||
string expected = 4 [(gogoproto.customtype) = "github.com/opencontainers/go-digest.Digest", (gogoproto.nullable) = false];
|
||||
string expected = 4;
|
||||
|
||||
// Offset specifies the number of bytes from the start at which to begin
|
||||
// the write. For most implementations, this means from the start of the
|
||||
@ -304,13 +300,13 @@ message WriteContentResponse {
|
||||
//
|
||||
// This must be set for stat and commit write actions. All other write
|
||||
// actions may omit this.
|
||||
google.protobuf.Timestamp started_at = 2 [(gogoproto.stdtime) = true, (gogoproto.nullable) = false];
|
||||
google.protobuf.Timestamp started_at = 2;
|
||||
|
||||
// UpdatedAt provides the last time of a successful write.
|
||||
//
|
||||
// This must be set for stat and commit write actions. All other write
|
||||
// actions may omit this.
|
||||
google.protobuf.Timestamp updated_at = 3 [(gogoproto.stdtime) = true, (gogoproto.nullable) = false];
|
||||
google.protobuf.Timestamp updated_at = 3;
|
||||
|
||||
// Offset is the current committed size for the write.
|
||||
int64 offset = 4;
|
||||
@ -326,7 +322,7 @@ message WriteContentResponse {
|
||||
// Digest, if present, includes the digest up to the currently committed
|
||||
// bytes. If action is commit, this field will be set. It is implementation
|
||||
// defined if this is set for other actions.
|
||||
string digest = 6 [(gogoproto.customtype) = "github.com/opencontainers/go-digest.Digest", (gogoproto.nullable) = false];
|
||||
string digest = 6;
|
||||
}
|
||||
|
||||
message AbortRequest {
|
||||
|
569
vendor/github.com/containerd/containerd/api/services/content/v1/content_grpc.pb.go
generated
vendored
Normal file
569
vendor/github.com/containerd/containerd/api/services/content/v1/content_grpc.pb.go
generated
vendored
Normal file
@ -0,0 +1,569 @@
|
||||
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
|
||||
// versions:
|
||||
// - protoc-gen-go-grpc v1.2.0
|
||||
// - protoc v3.20.1
|
||||
// source: github.com/containerd/containerd/api/services/content/v1/content.proto
|
||||
|
||||
package content
|
||||
|
||||
import (
|
||||
context "context"
|
||||
grpc "google.golang.org/grpc"
|
||||
codes "google.golang.org/grpc/codes"
|
||||
status "google.golang.org/grpc/status"
|
||||
emptypb "google.golang.org/protobuf/types/known/emptypb"
|
||||
)
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the grpc package it is being compiled against.
|
||||
// Requires gRPC-Go v1.32.0 or later.
|
||||
const _ = grpc.SupportPackageIsVersion7
|
||||
|
||||
// ContentClient is the client API for Content service.
|
||||
//
|
||||
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
|
||||
type ContentClient interface {
|
||||
// Info returns information about a committed object.
|
||||
//
|
||||
// This call can be used for getting the size of content and checking for
|
||||
// existence.
|
||||
Info(ctx context.Context, in *InfoRequest, opts ...grpc.CallOption) (*InfoResponse, error)
|
||||
// Update updates content metadata.
|
||||
//
|
||||
// This call can be used to manage the mutable content labels. The
|
||||
// immutable metadata such as digest, size, and committed at cannot
|
||||
// be updated.
|
||||
Update(ctx context.Context, in *UpdateRequest, opts ...grpc.CallOption) (*UpdateResponse, error)
|
||||
// List streams the entire set of content as Info objects and closes the
|
||||
// stream.
|
||||
//
|
||||
// Typically, this will yield a large response, chunked into messages.
|
||||
// Clients should make provisions to ensure they can handle the entire data
|
||||
// set.
|
||||
List(ctx context.Context, in *ListContentRequest, opts ...grpc.CallOption) (Content_ListClient, error)
|
||||
// Delete will delete the referenced object.
|
||||
Delete(ctx context.Context, in *DeleteContentRequest, opts ...grpc.CallOption) (*emptypb.Empty, error)
|
||||
// Read allows one to read an object based on the offset into the content.
|
||||
//
|
||||
// The requested data may be returned in one or more messages.
|
||||
Read(ctx context.Context, in *ReadContentRequest, opts ...grpc.CallOption) (Content_ReadClient, error)
|
||||
// Status returns the status for a single reference.
|
||||
Status(ctx context.Context, in *StatusRequest, opts ...grpc.CallOption) (*StatusResponse, error)
|
||||
// ListStatuses returns the status of ongoing object ingestions, started via
|
||||
// Write.
|
||||
//
|
||||
// Only those matching the regular expression will be provided in the
|
||||
// response. If the provided regular expression is empty, all ingestions
|
||||
// will be provided.
|
||||
ListStatuses(ctx context.Context, in *ListStatusesRequest, opts ...grpc.CallOption) (*ListStatusesResponse, error)
|
||||
// Write begins or resumes writes to a resource identified by a unique ref.
|
||||
// Only one active stream may exist at a time for each ref.
|
||||
//
|
||||
// Once a write stream has started, it may only write to a single ref, thus
|
||||
// once a stream is started, the ref may be omitted on subsequent writes.
|
||||
//
|
||||
// For any write transaction represented by a ref, only a single write may
|
||||
// be made to a given offset. If overlapping writes occur, it is an error.
|
||||
// Writes should be sequential and implementations may throw an error if
|
||||
// this is required.
|
||||
//
|
||||
// If expected_digest is set and already part of the content store, the
|
||||
// write will fail.
|
||||
//
|
||||
// When completed, the commit flag should be set to true. If expected size
|
||||
// or digest is set, the content will be validated against those values.
|
||||
Write(ctx context.Context, opts ...grpc.CallOption) (Content_WriteClient, error)
|
||||
// Abort cancels the ongoing write named in the request. Any resources
|
||||
// associated with the write will be collected.
|
||||
Abort(ctx context.Context, in *AbortRequest, opts ...grpc.CallOption) (*emptypb.Empty, error)
|
||||
}
|
||||
|
||||
type contentClient struct {
|
||||
cc grpc.ClientConnInterface
|
||||
}
|
||||
|
||||
func NewContentClient(cc grpc.ClientConnInterface) ContentClient {
|
||||
return &contentClient{cc}
|
||||
}
|
||||
|
||||
func (c *contentClient) Info(ctx context.Context, in *InfoRequest, opts ...grpc.CallOption) (*InfoResponse, error) {
|
||||
out := new(InfoResponse)
|
||||
err := c.cc.Invoke(ctx, "/containerd.services.content.v1.Content/Info", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *contentClient) Update(ctx context.Context, in *UpdateRequest, opts ...grpc.CallOption) (*UpdateResponse, error) {
|
||||
out := new(UpdateResponse)
|
||||
err := c.cc.Invoke(ctx, "/containerd.services.content.v1.Content/Update", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *contentClient) List(ctx context.Context, in *ListContentRequest, opts ...grpc.CallOption) (Content_ListClient, error) {
|
||||
stream, err := c.cc.NewStream(ctx, &Content_ServiceDesc.Streams[0], "/containerd.services.content.v1.Content/List", opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
x := &contentListClient{stream}
|
||||
if err := x.ClientStream.SendMsg(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := x.ClientStream.CloseSend(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return x, nil
|
||||
}
|
||||
|
||||
type Content_ListClient interface {
|
||||
Recv() (*ListContentResponse, error)
|
||||
grpc.ClientStream
|
||||
}
|
||||
|
||||
type contentListClient struct {
|
||||
grpc.ClientStream
|
||||
}
|
||||
|
||||
func (x *contentListClient) Recv() (*ListContentResponse, error) {
|
||||
m := new(ListContentResponse)
|
||||
if err := x.ClientStream.RecvMsg(m); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
||||
func (c *contentClient) Delete(ctx context.Context, in *DeleteContentRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) {
|
||||
out := new(emptypb.Empty)
|
||||
err := c.cc.Invoke(ctx, "/containerd.services.content.v1.Content/Delete", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *contentClient) Read(ctx context.Context, in *ReadContentRequest, opts ...grpc.CallOption) (Content_ReadClient, error) {
|
||||
stream, err := c.cc.NewStream(ctx, &Content_ServiceDesc.Streams[1], "/containerd.services.content.v1.Content/Read", opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
x := &contentReadClient{stream}
|
||||
if err := x.ClientStream.SendMsg(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := x.ClientStream.CloseSend(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return x, nil
|
||||
}
|
||||
|
||||
type Content_ReadClient interface {
|
||||
Recv() (*ReadContentResponse, error)
|
||||
grpc.ClientStream
|
||||
}
|
||||
|
||||
type contentReadClient struct {
|
||||
grpc.ClientStream
|
||||
}
|
||||
|
||||
func (x *contentReadClient) Recv() (*ReadContentResponse, error) {
|
||||
m := new(ReadContentResponse)
|
||||
if err := x.ClientStream.RecvMsg(m); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
||||
func (c *contentClient) Status(ctx context.Context, in *StatusRequest, opts ...grpc.CallOption) (*StatusResponse, error) {
|
||||
out := new(StatusResponse)
|
||||
err := c.cc.Invoke(ctx, "/containerd.services.content.v1.Content/Status", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *contentClient) ListStatuses(ctx context.Context, in *ListStatusesRequest, opts ...grpc.CallOption) (*ListStatusesResponse, error) {
|
||||
out := new(ListStatusesResponse)
|
||||
err := c.cc.Invoke(ctx, "/containerd.services.content.v1.Content/ListStatuses", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *contentClient) Write(ctx context.Context, opts ...grpc.CallOption) (Content_WriteClient, error) {
|
||||
stream, err := c.cc.NewStream(ctx, &Content_ServiceDesc.Streams[2], "/containerd.services.content.v1.Content/Write", opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
x := &contentWriteClient{stream}
|
||||
return x, nil
|
||||
}
|
||||
|
||||
type Content_WriteClient interface {
|
||||
Send(*WriteContentRequest) error
|
||||
Recv() (*WriteContentResponse, error)
|
||||
grpc.ClientStream
|
||||
}
|
||||
|
||||
type contentWriteClient struct {
|
||||
grpc.ClientStream
|
||||
}
|
||||
|
||||
func (x *contentWriteClient) Send(m *WriteContentRequest) error {
|
||||
return x.ClientStream.SendMsg(m)
|
||||
}
|
||||
|
||||
func (x *contentWriteClient) Recv() (*WriteContentResponse, error) {
|
||||
m := new(WriteContentResponse)
|
||||
if err := x.ClientStream.RecvMsg(m); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
||||
func (c *contentClient) Abort(ctx context.Context, in *AbortRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) {
|
||||
out := new(emptypb.Empty)
|
||||
err := c.cc.Invoke(ctx, "/containerd.services.content.v1.Content/Abort", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// ContentServer is the server API for Content service.
|
||||
// All implementations must embed UnimplementedContentServer
|
||||
// for forward compatibility
|
||||
type ContentServer interface {
|
||||
// Info returns information about a committed object.
|
||||
//
|
||||
// This call can be used for getting the size of content and checking for
|
||||
// existence.
|
||||
Info(context.Context, *InfoRequest) (*InfoResponse, error)
|
||||
// Update updates content metadata.
|
||||
//
|
||||
// This call can be used to manage the mutable content labels. The
|
||||
// immutable metadata such as digest, size, and committed at cannot
|
||||
// be updated.
|
||||
Update(context.Context, *UpdateRequest) (*UpdateResponse, error)
|
||||
// List streams the entire set of content as Info objects and closes the
|
||||
// stream.
|
||||
//
|
||||
// Typically, this will yield a large response, chunked into messages.
|
||||
// Clients should make provisions to ensure they can handle the entire data
|
||||
// set.
|
||||
List(*ListContentRequest, Content_ListServer) error
|
||||
// Delete will delete the referenced object.
|
||||
Delete(context.Context, *DeleteContentRequest) (*emptypb.Empty, error)
|
||||
// Read allows one to read an object based on the offset into the content.
|
||||
//
|
||||
// The requested data may be returned in one or more messages.
|
||||
Read(*ReadContentRequest, Content_ReadServer) error
|
||||
// Status returns the status for a single reference.
|
||||
Status(context.Context, *StatusRequest) (*StatusResponse, error)
|
||||
// ListStatuses returns the status of ongoing object ingestions, started via
|
||||
// Write.
|
||||
//
|
||||
// Only those matching the regular expression will be provided in the
|
||||
// response. If the provided regular expression is empty, all ingestions
|
||||
// will be provided.
|
||||
ListStatuses(context.Context, *ListStatusesRequest) (*ListStatusesResponse, error)
|
||||
// Write begins or resumes writes to a resource identified by a unique ref.
|
||||
// Only one active stream may exist at a time for each ref.
|
||||
//
|
||||
// Once a write stream has started, it may only write to a single ref, thus
|
||||
// once a stream is started, the ref may be omitted on subsequent writes.
|
||||
//
|
||||
// For any write transaction represented by a ref, only a single write may
|
||||
// be made to a given offset. If overlapping writes occur, it is an error.
|
||||
// Writes should be sequential and implementations may throw an error if
|
||||
// this is required.
|
||||
//
|
||||
// If expected_digest is set and already part of the content store, the
|
||||
// write will fail.
|
||||
//
|
||||
// When completed, the commit flag should be set to true. If expected size
|
||||
// or digest is set, the content will be validated against those values.
|
||||
Write(Content_WriteServer) error
|
||||
// Abort cancels the ongoing write named in the request. Any resources
|
||||
// associated with the write will be collected.
|
||||
Abort(context.Context, *AbortRequest) (*emptypb.Empty, error)
|
||||
mustEmbedUnimplementedContentServer()
|
||||
}
|
||||
|
||||
// UnimplementedContentServer must be embedded to have forward compatible implementations.
|
||||
type UnimplementedContentServer struct {
|
||||
}
|
||||
|
||||
func (UnimplementedContentServer) Info(context.Context, *InfoRequest) (*InfoResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method Info not implemented")
|
||||
}
|
||||
func (UnimplementedContentServer) Update(context.Context, *UpdateRequest) (*UpdateResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method Update not implemented")
|
||||
}
|
||||
func (UnimplementedContentServer) List(*ListContentRequest, Content_ListServer) error {
|
||||
return status.Errorf(codes.Unimplemented, "method List not implemented")
|
||||
}
|
||||
func (UnimplementedContentServer) Delete(context.Context, *DeleteContentRequest) (*emptypb.Empty, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method Delete not implemented")
|
||||
}
|
||||
func (UnimplementedContentServer) Read(*ReadContentRequest, Content_ReadServer) error {
|
||||
return status.Errorf(codes.Unimplemented, "method Read not implemented")
|
||||
}
|
||||
func (UnimplementedContentServer) Status(context.Context, *StatusRequest) (*StatusResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method Status not implemented")
|
||||
}
|
||||
func (UnimplementedContentServer) ListStatuses(context.Context, *ListStatusesRequest) (*ListStatusesResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ListStatuses not implemented")
|
||||
}
|
||||
func (UnimplementedContentServer) Write(Content_WriteServer) error {
|
||||
return status.Errorf(codes.Unimplemented, "method Write not implemented")
|
||||
}
|
||||
func (UnimplementedContentServer) Abort(context.Context, *AbortRequest) (*emptypb.Empty, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method Abort not implemented")
|
||||
}
|
||||
func (UnimplementedContentServer) mustEmbedUnimplementedContentServer() {}
|
||||
|
||||
// UnsafeContentServer may be embedded to opt out of forward compatibility for this service.
|
||||
// Use of this interface is not recommended, as added methods to ContentServer will
|
||||
// result in compilation errors.
|
||||
type UnsafeContentServer interface {
|
||||
mustEmbedUnimplementedContentServer()
|
||||
}
|
||||
|
||||
func RegisterContentServer(s grpc.ServiceRegistrar, srv ContentServer) {
|
||||
s.RegisterService(&Content_ServiceDesc, srv)
|
||||
}
|
||||
|
||||
func _Content_Info_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(InfoRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(ContentServer).Info(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/containerd.services.content.v1.Content/Info",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(ContentServer).Info(ctx, req.(*InfoRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _Content_Update_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(UpdateRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(ContentServer).Update(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/containerd.services.content.v1.Content/Update",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(ContentServer).Update(ctx, req.(*UpdateRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _Content_List_Handler(srv interface{}, stream grpc.ServerStream) error {
|
||||
m := new(ListContentRequest)
|
||||
if err := stream.RecvMsg(m); err != nil {
|
||||
return err
|
||||
}
|
||||
return srv.(ContentServer).List(m, &contentListServer{stream})
|
||||
}
|
||||
|
||||
type Content_ListServer interface {
|
||||
Send(*ListContentResponse) error
|
||||
grpc.ServerStream
|
||||
}
|
||||
|
||||
type contentListServer struct {
|
||||
grpc.ServerStream
|
||||
}
|
||||
|
||||
func (x *contentListServer) Send(m *ListContentResponse) error {
|
||||
return x.ServerStream.SendMsg(m)
|
||||
}
|
||||
|
||||
func _Content_Delete_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(DeleteContentRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(ContentServer).Delete(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/containerd.services.content.v1.Content/Delete",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(ContentServer).Delete(ctx, req.(*DeleteContentRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _Content_Read_Handler(srv interface{}, stream grpc.ServerStream) error {
|
||||
m := new(ReadContentRequest)
|
||||
if err := stream.RecvMsg(m); err != nil {
|
||||
return err
|
||||
}
|
||||
return srv.(ContentServer).Read(m, &contentReadServer{stream})
|
||||
}
|
||||
|
||||
type Content_ReadServer interface {
|
||||
Send(*ReadContentResponse) error
|
||||
grpc.ServerStream
|
||||
}
|
||||
|
||||
type contentReadServer struct {
|
||||
grpc.ServerStream
|
||||
}
|
||||
|
||||
func (x *contentReadServer) Send(m *ReadContentResponse) error {
|
||||
return x.ServerStream.SendMsg(m)
|
||||
}
|
||||
|
||||
func _Content_Status_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(StatusRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(ContentServer).Status(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/containerd.services.content.v1.Content/Status",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(ContentServer).Status(ctx, req.(*StatusRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _Content_ListStatuses_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(ListStatusesRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(ContentServer).ListStatuses(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/containerd.services.content.v1.Content/ListStatuses",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(ContentServer).ListStatuses(ctx, req.(*ListStatusesRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _Content_Write_Handler(srv interface{}, stream grpc.ServerStream) error {
|
||||
return srv.(ContentServer).Write(&contentWriteServer{stream})
|
||||
}
|
||||
|
||||
type Content_WriteServer interface {
|
||||
Send(*WriteContentResponse) error
|
||||
Recv() (*WriteContentRequest, error)
|
||||
grpc.ServerStream
|
||||
}
|
||||
|
||||
type contentWriteServer struct {
|
||||
grpc.ServerStream
|
||||
}
|
||||
|
||||
func (x *contentWriteServer) Send(m *WriteContentResponse) error {
|
||||
return x.ServerStream.SendMsg(m)
|
||||
}
|
||||
|
||||
func (x *contentWriteServer) Recv() (*WriteContentRequest, error) {
|
||||
m := new(WriteContentRequest)
|
||||
if err := x.ServerStream.RecvMsg(m); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
||||
func _Content_Abort_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(AbortRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(ContentServer).Abort(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/containerd.services.content.v1.Content/Abort",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(ContentServer).Abort(ctx, req.(*AbortRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
// Content_ServiceDesc is the grpc.ServiceDesc for Content service.
|
||||
// It's only intended for direct use with grpc.RegisterService,
|
||||
// and not to be introspected or modified (even as a copy)
|
||||
var Content_ServiceDesc = grpc.ServiceDesc{
|
||||
ServiceName: "containerd.services.content.v1.Content",
|
||||
HandlerType: (*ContentServer)(nil),
|
||||
Methods: []grpc.MethodDesc{
|
||||
{
|
||||
MethodName: "Info",
|
||||
Handler: _Content_Info_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "Update",
|
||||
Handler: _Content_Update_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "Delete",
|
||||
Handler: _Content_Delete_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "Status",
|
||||
Handler: _Content_Status_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "ListStatuses",
|
||||
Handler: _Content_ListStatuses_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "Abort",
|
||||
Handler: _Content_Abort_Handler,
|
||||
},
|
||||
},
|
||||
Streams: []grpc.StreamDesc{
|
||||
{
|
||||
StreamName: "List",
|
||||
Handler: _Content_List_Handler,
|
||||
ServerStreams: true,
|
||||
},
|
||||
{
|
||||
StreamName: "Read",
|
||||
Handler: _Content_Read_Handler,
|
||||
ServerStreams: true,
|
||||
},
|
||||
{
|
||||
StreamName: "Write",
|
||||
Handler: _Content_Write_Handler,
|
||||
ServerStreams: true,
|
||||
ClientStreams: true,
|
||||
},
|
||||
},
|
||||
Metadata: "github.com/containerd/containerd/api/services/content/v1/content.proto",
|
||||
}
|
28
vendor/github.com/containerd/containerd/archive/compression/compression_fuzzer.go
generated
vendored
Normal file
28
vendor/github.com/containerd/containerd/archive/compression/compression_fuzzer.go
generated
vendored
Normal file
@ -0,0 +1,28 @@
|
||||
//go:build gofuzz
|
||||
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package compression
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
)
|
||||
|
||||
func FuzzDecompressStream(data []byte) int {
|
||||
_, _ = DecompressStream(bytes.NewReader(data))
|
||||
return 1
|
||||
}
|
69
vendor/github.com/containerd/containerd/content/content.go
generated
vendored
69
vendor/github.com/containerd/containerd/content/content.go
generated
vendored
@ -25,6 +25,26 @@ import (
|
||||
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
)
|
||||
|
||||
// Store combines the methods of content-oriented interfaces into a set that
|
||||
// are commonly provided by complete implementations.
|
||||
//
|
||||
// Overall content lifecycle:
|
||||
// - Ingester is used to initiate a write operation (aka ingestion)
|
||||
// - IngestManager is used to manage (e.g. list, abort) active ingestions
|
||||
// - Once an ingestion is complete (see Writer.Commit), Provider is used to
|
||||
// query a single piece of content by its digest
|
||||
// - Manager is used to manage (e.g. list, delete) previously committed content
|
||||
//
|
||||
// Note that until ingestion is complete, its content is not visible through
|
||||
// Provider or Manager. Once ingestion is complete, it is no longer exposed
|
||||
// through IngestManager.
|
||||
type Store interface {
|
||||
Manager
|
||||
Provider
|
||||
IngestManager
|
||||
Ingester
|
||||
}
|
||||
|
||||
// ReaderAt extends the standard io.ReaderAt interface with reporting of Size and io.Closer
|
||||
type ReaderAt interface {
|
||||
io.ReaderAt
|
||||
@ -42,10 +62,30 @@ type Provider interface {
|
||||
|
||||
// Ingester writes content
|
||||
type Ingester interface {
|
||||
// Some implementations require WithRef to be included in opts.
|
||||
// Writer initiates a writing operation (aka ingestion). A single ingestion
|
||||
// is uniquely identified by its ref, provided using a WithRef option.
|
||||
// Writer can be called multiple times with the same ref to access the same
|
||||
// ingestion.
|
||||
// Once all the data is written, use Writer.Commit to complete the ingestion.
|
||||
Writer(ctx context.Context, opts ...WriterOpt) (Writer, error)
|
||||
}
|
||||
|
||||
// IngestManager provides methods for managing ingestions. An ingestion is a
|
||||
// not-yet-complete writing operation initiated using Ingester and identified
|
||||
// by a ref string.
|
||||
type IngestManager interface {
|
||||
// Status returns the status of the provided ref.
|
||||
Status(ctx context.Context, ref string) (Status, error)
|
||||
|
||||
// ListStatuses returns the status of any active ingestions whose ref match
|
||||
// the provided regular expression. If empty, all active ingestions will be
|
||||
// returned.
|
||||
ListStatuses(ctx context.Context, filters ...string) ([]Status, error)
|
||||
|
||||
// Abort completely cancels the ingest operation targeted by ref.
|
||||
Abort(ctx context.Context, ref string) error
|
||||
}
|
||||
|
||||
// Info holds content specific information
|
||||
//
|
||||
// TODO(stevvooe): Consider a very different name for this struct. Info is way
|
||||
@ -58,7 +98,7 @@ type Info struct {
|
||||
Labels map[string]string
|
||||
}
|
||||
|
||||
// Status of a content operation
|
||||
// Status of a content operation (i.e. an ingestion)
|
||||
type Status struct {
|
||||
Ref string
|
||||
Offset int64
|
||||
@ -94,21 +134,7 @@ type Manager interface {
|
||||
Delete(ctx context.Context, dgst digest.Digest) error
|
||||
}
|
||||
|
||||
// IngestManager provides methods for managing ingests.
|
||||
type IngestManager interface {
|
||||
// Status returns the status of the provided ref.
|
||||
Status(ctx context.Context, ref string) (Status, error)
|
||||
|
||||
// ListStatuses returns the status of any active ingestions whose ref match the
|
||||
// provided regular expression. If empty, all active ingestions will be
|
||||
// returned.
|
||||
ListStatuses(ctx context.Context, filters ...string) ([]Status, error)
|
||||
|
||||
// Abort completely cancels the ingest operation targeted by ref.
|
||||
Abort(ctx context.Context, ref string) error
|
||||
}
|
||||
|
||||
// Writer handles the write of content into a content store
|
||||
// Writer handles writing of content into a content store
|
||||
type Writer interface {
|
||||
// Close closes the writer, if the writer has not been
|
||||
// committed this allows resuming or aborting.
|
||||
@ -131,15 +157,6 @@ type Writer interface {
|
||||
Truncate(size int64) error
|
||||
}
|
||||
|
||||
// Store combines the methods of content-oriented interfaces into a set that
|
||||
// are commonly provided by complete implementations.
|
||||
type Store interface {
|
||||
Manager
|
||||
Provider
|
||||
IngestManager
|
||||
Ingester
|
||||
}
|
||||
|
||||
// Opt is used to alter the mutable properties of content
|
||||
type Opt func(*Info) error
|
||||
|
||||
|
10
vendor/github.com/containerd/containerd/content/helpers.go
generated
vendored
10
vendor/github.com/containerd/containerd/content/helpers.go
generated
vendored
@ -43,10 +43,16 @@ var bufPool = sync.Pool{
|
||||
},
|
||||
}
|
||||
|
||||
type reader interface {
|
||||
Reader() io.Reader
|
||||
}
|
||||
|
||||
// NewReader returns a io.Reader from a ReaderAt
|
||||
func NewReader(ra ReaderAt) io.Reader {
|
||||
rd := io.NewSectionReader(ra, 0, ra.Size())
|
||||
return rd
|
||||
if rd, ok := ra.(reader); ok {
|
||||
return rd.Reader()
|
||||
}
|
||||
return io.NewSectionReader(ra, 0, ra.Size())
|
||||
}
|
||||
|
||||
// ReadBlob retrieves the entire contents of the blob from the provider.
|
||||
|
76
vendor/github.com/containerd/containerd/content/local/content_local_fuzzer.go
generated
vendored
Normal file
76
vendor/github.com/containerd/containerd/content/local/content_local_fuzzer.go
generated
vendored
Normal file
@ -0,0 +1,76 @@
|
||||
//go:build gofuzz
|
||||
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package local
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"context"
|
||||
_ "crypto/sha256"
|
||||
"io"
|
||||
"testing"
|
||||
|
||||
"github.com/opencontainers/go-digest"
|
||||
|
||||
"github.com/containerd/containerd/content"
|
||||
)
|
||||
|
||||
func FuzzContentStoreWriter(data []byte) int {
|
||||
t := &testing.T{}
|
||||
ctx := context.Background()
|
||||
ctx, _, cs, cleanup := contentStoreEnv(t)
|
||||
defer cleanup()
|
||||
|
||||
cw, err := cs.Writer(ctx, content.WithRef("myref"))
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
if err := cw.Close(); err != nil {
|
||||
return 0
|
||||
}
|
||||
|
||||
// reopen, so we can test things
|
||||
cw, err = cs.Writer(ctx, content.WithRef("myref"))
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
|
||||
err = checkCopyFuzz(int64(len(data)), cw, bufio.NewReader(io.NopCloser(bytes.NewReader(data))))
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
expected := digest.FromBytes(data)
|
||||
|
||||
if err = cw.Commit(ctx, int64(len(data)), expected); err != nil {
|
||||
return 0
|
||||
}
|
||||
return 1
|
||||
}
|
||||
|
||||
func checkCopyFuzz(size int64, dst io.Writer, src io.Reader) error {
|
||||
nn, err := io.Copy(dst, src)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if nn != size {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
5
vendor/github.com/containerd/containerd/content/local/readerat.go
generated
vendored
5
vendor/github.com/containerd/containerd/content/local/readerat.go
generated
vendored
@ -18,6 +18,7 @@ package local
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
|
||||
"github.com/containerd/containerd/content"
|
||||
@ -65,3 +66,7 @@ func (ra sizeReaderAt) Size() int64 {
|
||||
func (ra sizeReaderAt) Close() error {
|
||||
return ra.fp.Close()
|
||||
}
|
||||
|
||||
func (ra sizeReaderAt) Reader() io.Reader {
|
||||
return io.LimitReader(ra.fp, ra.size)
|
||||
}
|
||||
|
9
vendor/github.com/containerd/containerd/content/local/store.go
generated
vendored
9
vendor/github.com/containerd/containerd/content/local/store.go
generated
vendored
@ -34,7 +34,7 @@ import (
|
||||
"github.com/containerd/containerd/log"
|
||||
"github.com/sirupsen/logrus"
|
||||
|
||||
digest "github.com/opencontainers/go-digest"
|
||||
"github.com/opencontainers/go-digest"
|
||||
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
)
|
||||
|
||||
@ -262,7 +262,7 @@ func (s *store) Walk(ctx context.Context, fn content.WalkFunc, fs ...string) err
|
||||
return nil
|
||||
}
|
||||
|
||||
dgst := digest.NewDigestFromHex(alg.String(), filepath.Base(path))
|
||||
dgst := digest.NewDigestFromEncoded(alg, filepath.Base(path))
|
||||
if err := dgst.Validate(); err != nil {
|
||||
// log error but don't report
|
||||
log.L.WithError(err).WithField("path", path).Error("invalid digest for blob path")
|
||||
@ -505,6 +505,7 @@ func (s *store) resumeStatus(ref string, total int64, digester digest.Digester)
|
||||
return status, fmt.Errorf("provided total differs from status: %v != %v", total, status.Total)
|
||||
}
|
||||
|
||||
//nolint:dupword
|
||||
// TODO(stevvooe): slow slow slow!!, send to goroutine or use resumable hashes
|
||||
fp, err := os.Open(data)
|
||||
if err != nil {
|
||||
@ -628,14 +629,14 @@ func (s *store) blobPath(dgst digest.Digest) (string, error) {
|
||||
return "", fmt.Errorf("cannot calculate blob path from invalid digest: %v: %w", err, errdefs.ErrInvalidArgument)
|
||||
}
|
||||
|
||||
return filepath.Join(s.root, "blobs", dgst.Algorithm().String(), dgst.Hex()), nil
|
||||
return filepath.Join(s.root, "blobs", dgst.Algorithm().String(), dgst.Encoded()), nil
|
||||
}
|
||||
|
||||
func (s *store) ingestRoot(ref string) string {
|
||||
// we take a digest of the ref to keep the ingest paths constant length.
|
||||
// Note that this is not the current or potential digest of incoming content.
|
||||
dgst := digest.FromString(ref)
|
||||
return filepath.Join(s.root, "ingest", dgst.Hex())
|
||||
return filepath.Join(s.root, "ingest", dgst.Encoded())
|
||||
}
|
||||
|
||||
// ingestPaths are returned. The paths are the following:
|
||||
|
1
vendor/github.com/containerd/containerd/content/local/store_bsd.go
generated
vendored
1
vendor/github.com/containerd/containerd/content/local/store_bsd.go
generated
vendored
@ -1,5 +1,4 @@
|
||||
//go:build darwin || freebsd || netbsd
|
||||
// +build darwin freebsd netbsd
|
||||
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
1
vendor/github.com/containerd/containerd/content/local/store_openbsd.go
generated
vendored
1
vendor/github.com/containerd/containerd/content/local/store_openbsd.go
generated
vendored
@ -1,5 +1,4 @@
|
||||
//go:build openbsd
|
||||
// +build openbsd
|
||||
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
1
vendor/github.com/containerd/containerd/content/local/store_unix.go
generated
vendored
1
vendor/github.com/containerd/containerd/content/local/store_unix.go
generated
vendored
@ -1,5 +1,4 @@
|
||||
//go:build linux || solaris
|
||||
// +build linux solaris
|
||||
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
38
vendor/github.com/containerd/containerd/content/local/test_helper.go
generated
vendored
Normal file
38
vendor/github.com/containerd/containerd/content/local/test_helper.go
generated
vendored
Normal file
@ -0,0 +1,38 @@
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package local
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/containerd/containerd/content"
|
||||
)
|
||||
|
||||
func contentStoreEnv(t testing.TB) (context.Context, string, content.Store, func()) {
|
||||
tmpdir := t.TempDir()
|
||||
|
||||
cs, err := NewStore(tmpdir)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
return ctx, tmpdir, cs, func() {
|
||||
cancel()
|
||||
}
|
||||
}
|
4
vendor/github.com/containerd/containerd/content/proxy/content_reader.go
generated
vendored
4
vendor/github.com/containerd/containerd/content/proxy/content_reader.go
generated
vendored
@ -36,9 +36,9 @@ func (ra *remoteReaderAt) Size() int64 {
|
||||
|
||||
func (ra *remoteReaderAt) ReadAt(p []byte, off int64) (n int, err error) {
|
||||
rr := &contentapi.ReadContentRequest{
|
||||
Digest: ra.digest,
|
||||
Digest: ra.digest.String(),
|
||||
Offset: off,
|
||||
Size_: int64(len(p)),
|
||||
Size: int64(len(p)),
|
||||
}
|
||||
// we need a child context with cancel, or the eventually called
|
||||
// grpc.NewStream will leak the goroutine until the whole thing is cleared.
|
||||
|
47
vendor/github.com/containerd/containerd/content/proxy/content_store.go
generated
vendored
47
vendor/github.com/containerd/containerd/content/proxy/content_store.go
generated
vendored
@ -23,7 +23,8 @@ import (
|
||||
contentapi "github.com/containerd/containerd/api/services/content/v1"
|
||||
"github.com/containerd/containerd/content"
|
||||
"github.com/containerd/containerd/errdefs"
|
||||
protobuftypes "github.com/gogo/protobuf/types"
|
||||
"github.com/containerd/containerd/protobuf"
|
||||
protobuftypes "github.com/containerd/containerd/protobuf/types"
|
||||
digest "github.com/opencontainers/go-digest"
|
||||
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
)
|
||||
@ -42,7 +43,7 @@ func NewContentStore(client contentapi.ContentClient) content.Store {
|
||||
|
||||
func (pcs *proxyContentStore) Info(ctx context.Context, dgst digest.Digest) (content.Info, error) {
|
||||
resp, err := pcs.client.Info(ctx, &contentapi.InfoRequest{
|
||||
Digest: dgst,
|
||||
Digest: dgst.String(),
|
||||
})
|
||||
if err != nil {
|
||||
return content.Info{}, errdefs.FromGRPC(err)
|
||||
@ -81,7 +82,7 @@ func (pcs *proxyContentStore) Walk(ctx context.Context, fn content.WalkFunc, fil
|
||||
|
||||
func (pcs *proxyContentStore) Delete(ctx context.Context, dgst digest.Digest) error {
|
||||
if _, err := pcs.client.Delete(ctx, &contentapi.DeleteContentRequest{
|
||||
Digest: dgst,
|
||||
Digest: dgst.String(),
|
||||
}); err != nil {
|
||||
return errdefs.FromGRPC(err)
|
||||
}
|
||||
@ -115,17 +116,17 @@ func (pcs *proxyContentStore) Status(ctx context.Context, ref string) (content.S
|
||||
status := resp.Status
|
||||
return content.Status{
|
||||
Ref: status.Ref,
|
||||
StartedAt: status.StartedAt,
|
||||
UpdatedAt: status.UpdatedAt,
|
||||
StartedAt: protobuf.FromTimestamp(status.StartedAt),
|
||||
UpdatedAt: protobuf.FromTimestamp(status.UpdatedAt),
|
||||
Offset: status.Offset,
|
||||
Total: status.Total,
|
||||
Expected: status.Expected,
|
||||
Expected: digest.Digest(status.Expected),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (pcs *proxyContentStore) Update(ctx context.Context, info content.Info, fieldpaths ...string) (content.Info, error) {
|
||||
resp, err := pcs.client.Update(ctx, &contentapi.UpdateRequest{
|
||||
Info: infoToGRPC(info),
|
||||
Info: infoToGRPC(&info),
|
||||
UpdateMask: &protobuftypes.FieldMask{
|
||||
Paths: fieldpaths,
|
||||
},
|
||||
@ -148,11 +149,11 @@ func (pcs *proxyContentStore) ListStatuses(ctx context.Context, filters ...strin
|
||||
for _, status := range resp.Statuses {
|
||||
statuses = append(statuses, content.Status{
|
||||
Ref: status.Ref,
|
||||
StartedAt: status.StartedAt,
|
||||
UpdatedAt: status.UpdatedAt,
|
||||
StartedAt: protobuf.FromTimestamp(status.StartedAt),
|
||||
UpdatedAt: protobuf.FromTimestamp(status.UpdatedAt),
|
||||
Offset: status.Offset,
|
||||
Total: status.Total,
|
||||
Expected: status.Expected,
|
||||
Expected: digest.Digest(status.Expected),
|
||||
})
|
||||
}
|
||||
|
||||
@ -197,10 +198,10 @@ func (pcs *proxyContentStore) negotiate(ctx context.Context, ref string, size in
|
||||
}
|
||||
|
||||
if err := wrclient.Send(&contentapi.WriteContentRequest{
|
||||
Action: contentapi.WriteActionStat,
|
||||
Action: contentapi.WriteAction_STAT,
|
||||
Ref: ref,
|
||||
Total: size,
|
||||
Expected: expected,
|
||||
Expected: expected.String(),
|
||||
}); err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
@ -213,22 +214,22 @@ func (pcs *proxyContentStore) negotiate(ctx context.Context, ref string, size in
|
||||
return wrclient, resp.Offset, nil
|
||||
}
|
||||
|
||||
func infoToGRPC(info content.Info) contentapi.Info {
|
||||
return contentapi.Info{
|
||||
Digest: info.Digest,
|
||||
Size_: info.Size,
|
||||
CreatedAt: info.CreatedAt,
|
||||
UpdatedAt: info.UpdatedAt,
|
||||
func infoToGRPC(info *content.Info) *contentapi.Info {
|
||||
return &contentapi.Info{
|
||||
Digest: info.Digest.String(),
|
||||
Size: info.Size,
|
||||
CreatedAt: protobuf.ToTimestamp(info.CreatedAt),
|
||||
UpdatedAt: protobuf.ToTimestamp(info.UpdatedAt),
|
||||
Labels: info.Labels,
|
||||
}
|
||||
}
|
||||
|
||||
func infoFromGRPC(info contentapi.Info) content.Info {
|
||||
func infoFromGRPC(info *contentapi.Info) content.Info {
|
||||
return content.Info{
|
||||
Digest: info.Digest,
|
||||
Size: info.Size_,
|
||||
CreatedAt: info.CreatedAt,
|
||||
UpdatedAt: info.UpdatedAt,
|
||||
Digest: digest.Digest(info.Digest),
|
||||
Size: info.Size,
|
||||
CreatedAt: protobuf.FromTimestamp(info.CreatedAt),
|
||||
UpdatedAt: protobuf.FromTimestamp(info.UpdatedAt),
|
||||
Labels: info.Labels,
|
||||
}
|
||||
}
|
||||
|
22
vendor/github.com/containerd/containerd/content/proxy/content_writer.go
generated
vendored
22
vendor/github.com/containerd/containerd/content/proxy/content_writer.go
generated
vendored
@ -24,6 +24,7 @@ import (
|
||||
contentapi "github.com/containerd/containerd/api/services/content/v1"
|
||||
"github.com/containerd/containerd/content"
|
||||
"github.com/containerd/containerd/errdefs"
|
||||
"github.com/containerd/containerd/protobuf"
|
||||
digest "github.com/opencontainers/go-digest"
|
||||
)
|
||||
|
||||
@ -45,7 +46,7 @@ func (rw *remoteWriter) send(req *contentapi.WriteContentRequest) (*contentapi.W
|
||||
if err == nil {
|
||||
// try to keep these in sync
|
||||
if resp.Digest != "" {
|
||||
rw.digest = resp.Digest
|
||||
rw.digest = digest.Digest(resp.Digest)
|
||||
}
|
||||
}
|
||||
|
||||
@ -54,7 +55,7 @@ func (rw *remoteWriter) send(req *contentapi.WriteContentRequest) (*contentapi.W
|
||||
|
||||
func (rw *remoteWriter) Status() (content.Status, error) {
|
||||
resp, err := rw.send(&contentapi.WriteContentRequest{
|
||||
Action: contentapi.WriteActionStat,
|
||||
Action: contentapi.WriteAction_STAT,
|
||||
})
|
||||
if err != nil {
|
||||
return content.Status{}, fmt.Errorf("error getting writer status: %w", errdefs.FromGRPC(err))
|
||||
@ -64,8 +65,8 @@ func (rw *remoteWriter) Status() (content.Status, error) {
|
||||
Ref: rw.ref,
|
||||
Offset: resp.Offset,
|
||||
Total: resp.Total,
|
||||
StartedAt: resp.StartedAt,
|
||||
UpdatedAt: resp.UpdatedAt,
|
||||
StartedAt: protobuf.FromTimestamp(resp.StartedAt),
|
||||
UpdatedAt: protobuf.FromTimestamp(resp.UpdatedAt),
|
||||
}, nil
|
||||
}
|
||||
|
||||
@ -77,7 +78,7 @@ func (rw *remoteWriter) Write(p []byte) (n int, err error) {
|
||||
offset := rw.offset
|
||||
|
||||
resp, err := rw.send(&contentapi.WriteContentRequest{
|
||||
Action: contentapi.WriteActionWrite,
|
||||
Action: contentapi.WriteAction_WRITE,
|
||||
Offset: offset,
|
||||
Data: p,
|
||||
})
|
||||
@ -92,7 +93,7 @@ func (rw *remoteWriter) Write(p []byte) (n int, err error) {
|
||||
|
||||
rw.offset += int64(n)
|
||||
if resp.Digest != "" {
|
||||
rw.digest = resp.Digest
|
||||
rw.digest = digest.Digest(resp.Digest)
|
||||
}
|
||||
return
|
||||
}
|
||||
@ -112,10 +113,10 @@ func (rw *remoteWriter) Commit(ctx context.Context, size int64, expected digest.
|
||||
}
|
||||
}
|
||||
resp, err := rw.send(&contentapi.WriteContentRequest{
|
||||
Action: contentapi.WriteActionCommit,
|
||||
Action: contentapi.WriteAction_COMMIT,
|
||||
Total: size,
|
||||
Offset: rw.offset,
|
||||
Expected: expected,
|
||||
Expected: expected.String(),
|
||||
Labels: base.Labels,
|
||||
})
|
||||
if err != nil {
|
||||
@ -126,11 +127,12 @@ func (rw *remoteWriter) Commit(ctx context.Context, size int64, expected digest.
|
||||
return fmt.Errorf("unexpected size: %v != %v", resp.Offset, size)
|
||||
}
|
||||
|
||||
if expected != "" && resp.Digest != expected {
|
||||
actual := digest.Digest(resp.Digest)
|
||||
if expected != "" && actual != expected {
|
||||
return fmt.Errorf("unexpected digest: %v != %v", resp.Digest, expected)
|
||||
}
|
||||
|
||||
rw.digest = resp.Digest
|
||||
rw.digest = actual
|
||||
rw.offset = resp.Offset
|
||||
return nil
|
||||
}
|
||||
|
1
vendor/github.com/containerd/containerd/defaults/defaults_unix.go
generated
vendored
1
vendor/github.com/containerd/containerd/defaults/defaults_unix.go
generated
vendored
@ -1,5 +1,4 @@
|
||||
//go:build !windows && !darwin
|
||||
// +build !windows,!darwin
|
||||
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
4
vendor/github.com/containerd/containerd/images/image.go
generated
vendored
4
vendor/github.com/containerd/containerd/images/image.go
generated
vendored
@ -138,7 +138,7 @@ type platformManifest struct {
|
||||
// TODO(stevvooe): This violates the current platform agnostic approach to this
|
||||
// package by returning a specific manifest type. We'll need to refactor this
|
||||
// to return a manifest descriptor or decide that we want to bring the API in
|
||||
// this direction because this abstraction is not needed.`
|
||||
// this direction because this abstraction is not needed.
|
||||
func Manifest(ctx context.Context, provider content.Provider, image ocispec.Descriptor, platform platforms.MatchComparer) (ocispec.Manifest, error) {
|
||||
var (
|
||||
limit = 1
|
||||
@ -311,7 +311,7 @@ func Check(ctx context.Context, provider content.Provider, image ocispec.Descrip
|
||||
return false, nil, nil, nil, fmt.Errorf("failed to check image %v: %w", image.Digest, err)
|
||||
}
|
||||
|
||||
// TODO(stevvooe): It is possible that referenced conponents could have
|
||||
// TODO(stevvooe): It is possible that referenced components could have
|
||||
// children, but this is rare. For now, we ignore this and only verify
|
||||
// that manifest components are present.
|
||||
required = append([]ocispec.Descriptor{mfst.Config}, mfst.Layers...)
|
||||
|
31
vendor/github.com/containerd/containerd/images/mediatypes.go
generated
vendored
31
vendor/github.com/containerd/containerd/images/mediatypes.go
generated
vendored
@ -38,7 +38,9 @@ const (
|
||||
MediaTypeDockerSchema2Config = "application/vnd.docker.container.image.v1+json"
|
||||
MediaTypeDockerSchema2Manifest = "application/vnd.docker.distribution.manifest.v2+json"
|
||||
MediaTypeDockerSchema2ManifestList = "application/vnd.docker.distribution.manifest.list.v2+json"
|
||||
|
||||
// Checkpoint/Restore Media Types
|
||||
|
||||
MediaTypeContainerd1Checkpoint = "application/vnd.containerd.container.criu.checkpoint.criu.tar"
|
||||
MediaTypeContainerd1CheckpointPreDump = "application/vnd.containerd.container.criu.checkpoint.predump.tar"
|
||||
MediaTypeContainerd1Resource = "application/vnd.containerd.container.resource.tar"
|
||||
@ -47,9 +49,12 @@ const (
|
||||
MediaTypeContainerd1CheckpointOptions = "application/vnd.containerd.container.checkpoint.options.v1+proto"
|
||||
MediaTypeContainerd1CheckpointRuntimeName = "application/vnd.containerd.container.checkpoint.runtime.name"
|
||||
MediaTypeContainerd1CheckpointRuntimeOptions = "application/vnd.containerd.container.checkpoint.runtime.options+proto"
|
||||
// Legacy Docker schema1 manifest
|
||||
|
||||
// MediaTypeDockerSchema1Manifest is the legacy Docker schema1 manifest
|
||||
MediaTypeDockerSchema1Manifest = "application/vnd.docker.distribution.manifest.v1+prettyjws"
|
||||
// Encypted media types
|
||||
|
||||
// Encrypted media types
|
||||
|
||||
MediaTypeImageLayerEncrypted = ocispec.MediaTypeImageLayer + "+encrypted"
|
||||
MediaTypeImageLayerGzipEncrypted = ocispec.MediaTypeImageLayerGzip + "+encrypted"
|
||||
)
|
||||
@ -93,16 +98,23 @@ func DiffCompression(ctx context.Context, mediaType string) (string, error) {
|
||||
|
||||
// parseMediaTypes splits the media type into the base type and
|
||||
// an array of sorted extensions
|
||||
func parseMediaTypes(mt string) (string, []string) {
|
||||
func parseMediaTypes(mt string) (mediaType string, suffixes []string) {
|
||||
if mt == "" {
|
||||
return "", []string{}
|
||||
}
|
||||
mediaType, ext, ok := strings.Cut(mt, "+")
|
||||
if !ok {
|
||||
return mediaType, []string{}
|
||||
}
|
||||
|
||||
s := strings.Split(mt, "+")
|
||||
ext := s[1:]
|
||||
sort.Strings(ext)
|
||||
|
||||
return s[0], ext
|
||||
// Splitting the extensions following the mediatype "(+)gzip+encrypted".
|
||||
// We expect this to be a limited list, so add an arbitrary limit (50).
|
||||
//
|
||||
// Note that DiffCompression is only using the last element, so perhaps we
|
||||
// should split on the last "+" only.
|
||||
suffixes = strings.SplitN(ext, "+", 50)
|
||||
sort.Strings(suffixes)
|
||||
return mediaType, suffixes
|
||||
}
|
||||
|
||||
// IsNonDistributable returns true if the media type is non-distributable.
|
||||
@ -118,8 +130,7 @@ func IsLayerType(mt string) bool {
|
||||
}
|
||||
|
||||
// Parse Docker media types, strip off any + suffixes first
|
||||
base, _ := parseMediaTypes(mt)
|
||||
switch base {
|
||||
switch base, _ := parseMediaTypes(mt); base {
|
||||
case MediaTypeDockerSchema2Layer, MediaTypeDockerSchema2LayerGzip,
|
||||
MediaTypeDockerSchema2LayerForeign, MediaTypeDockerSchema2LayerForeignGzip:
|
||||
return true
|
||||
|
4
vendor/github.com/containerd/containerd/labels/labels.go
generated
vendored
4
vendor/github.com/containerd/containerd/labels/labels.go
generated
vendored
@ -19,3 +19,7 @@ package labels
|
||||
// LabelUncompressed is added to compressed layer contents.
|
||||
// The value is digest of the uncompressed content.
|
||||
const LabelUncompressed = "containerd.io/uncompressed"
|
||||
|
||||
// LabelSharedNamespace is added to a namespace to allow that namespaces
|
||||
// contents to be shared.
|
||||
const LabelSharedNamespace = "containerd.io/namespace.shareable"
|
||||
|
11
vendor/github.com/containerd/containerd/labels/validate.go
generated
vendored
11
vendor/github.com/containerd/containerd/labels/validate.go
generated
vendored
@ -24,15 +24,18 @@ import (
|
||||
|
||||
const (
|
||||
maxSize = 4096
|
||||
// maximum length of key portion of error message if len of key + len of value > maxSize
|
||||
keyMaxLen = 64
|
||||
)
|
||||
|
||||
// Validate a label's key and value are under 4096 bytes
|
||||
func Validate(k, v string) error {
|
||||
if (len(k) + len(v)) > maxSize {
|
||||
if len(k) > 10 {
|
||||
k = k[:10]
|
||||
total := len(k) + len(v)
|
||||
if total > maxSize {
|
||||
if len(k) > keyMaxLen {
|
||||
k = k[:keyMaxLen]
|
||||
}
|
||||
return fmt.Errorf("label key and value greater than maximum size (%d bytes), key: %s: %w", maxSize, k, errdefs.ErrInvalidArgument)
|
||||
return fmt.Errorf("label key and value length (%d bytes) greater than maximum size (%d bytes), key: %s: %w", total, maxSize, k, errdefs.ErrInvalidArgument)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
1
vendor/github.com/containerd/containerd/pkg/dialer/dialer_unix.go
generated
vendored
1
vendor/github.com/containerd/containerd/pkg/dialer/dialer_unix.go
generated
vendored
@ -1,5 +1,4 @@
|
||||
//go:build !windows
|
||||
// +build !windows
|
||||
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
1
vendor/github.com/containerd/containerd/pkg/seed/seed_other.go
generated
vendored
1
vendor/github.com/containerd/containerd/pkg/seed/seed_other.go
generated
vendored
@ -1,5 +1,4 @@
|
||||
//go:build !linux
|
||||
// +build !linux
|
||||
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
1
vendor/github.com/containerd/containerd/pkg/userns/userns_unsupported.go
generated
vendored
1
vendor/github.com/containerd/containerd/pkg/userns/userns_unsupported.go
generated
vendored
@ -1,5 +1,4 @@
|
||||
//go:build !linux
|
||||
// +build !linux
|
||||
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
98
vendor/github.com/containerd/containerd/platforms/cpuinfo.go
generated
vendored
98
vendor/github.com/containerd/containerd/platforms/cpuinfo.go
generated
vendored
@ -17,14 +17,9 @@
|
||||
package platforms
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"os"
|
||||
"runtime"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/containerd/containerd/errdefs"
|
||||
"github.com/containerd/containerd/log"
|
||||
)
|
||||
|
||||
@ -37,95 +32,12 @@ var cpuVariantOnce sync.Once
|
||||
func cpuVariant() string {
|
||||
cpuVariantOnce.Do(func() {
|
||||
if isArmArch(runtime.GOARCH) {
|
||||
cpuVariantValue = getCPUVariant()
|
||||
var err error
|
||||
cpuVariantValue, err = getCPUVariant()
|
||||
if err != nil {
|
||||
log.L.Errorf("Error getCPUVariant for OS %s: %v", runtime.GOOS, err)
|
||||
}
|
||||
}
|
||||
})
|
||||
return cpuVariantValue
|
||||
}
|
||||
|
||||
// For Linux, the kernel has already detected the ABI, ISA and Features.
|
||||
// So we don't need to access the ARM registers to detect platform information
|
||||
// by ourselves. We can just parse these information from /proc/cpuinfo
|
||||
func getCPUInfo(pattern string) (info string, err error) {
|
||||
if !isLinuxOS(runtime.GOOS) {
|
||||
return "", fmt.Errorf("getCPUInfo for OS %s: %w", runtime.GOOS, errdefs.ErrNotImplemented)
|
||||
}
|
||||
|
||||
cpuinfo, err := os.Open("/proc/cpuinfo")
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer cpuinfo.Close()
|
||||
|
||||
// Start to Parse the Cpuinfo line by line. For SMP SoC, we parse
|
||||
// the first core is enough.
|
||||
scanner := bufio.NewScanner(cpuinfo)
|
||||
for scanner.Scan() {
|
||||
newline := scanner.Text()
|
||||
list := strings.Split(newline, ":")
|
||||
|
||||
if len(list) > 1 && strings.EqualFold(strings.TrimSpace(list[0]), pattern) {
|
||||
return strings.TrimSpace(list[1]), nil
|
||||
}
|
||||
}
|
||||
|
||||
// Check whether the scanner encountered errors
|
||||
err = scanner.Err()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return "", fmt.Errorf("getCPUInfo for pattern: %s: %w", pattern, errdefs.ErrNotFound)
|
||||
}
|
||||
|
||||
func getCPUVariant() string {
|
||||
if runtime.GOOS == "windows" || runtime.GOOS == "darwin" {
|
||||
// Windows/Darwin only supports v7 for ARM32 and v8 for ARM64 and so we can use
|
||||
// runtime.GOARCH to determine the variants
|
||||
var variant string
|
||||
switch runtime.GOARCH {
|
||||
case "arm64":
|
||||
variant = "v8"
|
||||
case "arm":
|
||||
variant = "v7"
|
||||
default:
|
||||
variant = "unknown"
|
||||
}
|
||||
|
||||
return variant
|
||||
}
|
||||
|
||||
variant, err := getCPUInfo("Cpu architecture")
|
||||
if err != nil {
|
||||
log.L.WithError(err).Error("failure getting variant")
|
||||
return ""
|
||||
}
|
||||
|
||||
// handle edge case for Raspberry Pi ARMv6 devices (which due to a kernel quirk, report "CPU architecture: 7")
|
||||
// https://www.raspberrypi.org/forums/viewtopic.php?t=12614
|
||||
if runtime.GOARCH == "arm" && variant == "7" {
|
||||
model, err := getCPUInfo("model name")
|
||||
if err == nil && strings.HasPrefix(strings.ToLower(model), "armv6-compatible") {
|
||||
variant = "6"
|
||||
}
|
||||
}
|
||||
|
||||
switch strings.ToLower(variant) {
|
||||
case "8", "aarch64":
|
||||
variant = "v8"
|
||||
case "7", "7m", "?(12)", "?(13)", "?(14)", "?(15)", "?(16)", "?(17)":
|
||||
variant = "v7"
|
||||
case "6", "6tej":
|
||||
variant = "v6"
|
||||
case "5", "5t", "5te", "5tej":
|
||||
variant = "v5"
|
||||
case "4", "4t":
|
||||
variant = "v4"
|
||||
case "3":
|
||||
variant = "v3"
|
||||
default:
|
||||
variant = "unknown"
|
||||
}
|
||||
|
||||
return variant
|
||||
}
|
||||
|
161
vendor/github.com/containerd/containerd/platforms/cpuinfo_linux.go
generated
vendored
Normal file
161
vendor/github.com/containerd/containerd/platforms/cpuinfo_linux.go
generated
vendored
Normal file
@ -0,0 +1,161 @@
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package platforms
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"fmt"
|
||||
"os"
|
||||
"runtime"
|
||||
"strings"
|
||||
|
||||
"github.com/containerd/containerd/errdefs"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
// getMachineArch retrieves the machine architecture through system call
|
||||
func getMachineArch() (string, error) {
|
||||
var uname unix.Utsname
|
||||
err := unix.Uname(&uname)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
arch := string(uname.Machine[:bytes.IndexByte(uname.Machine[:], 0)])
|
||||
|
||||
return arch, nil
|
||||
}
|
||||
|
||||
// For Linux, the kernel has already detected the ABI, ISA and Features.
|
||||
// So we don't need to access the ARM registers to detect platform information
|
||||
// by ourselves. We can just parse these information from /proc/cpuinfo
|
||||
func getCPUInfo(pattern string) (info string, err error) {
|
||||
|
||||
cpuinfo, err := os.Open("/proc/cpuinfo")
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer cpuinfo.Close()
|
||||
|
||||
// Start to Parse the Cpuinfo line by line. For SMP SoC, we parse
|
||||
// the first core is enough.
|
||||
scanner := bufio.NewScanner(cpuinfo)
|
||||
for scanner.Scan() {
|
||||
newline := scanner.Text()
|
||||
list := strings.Split(newline, ":")
|
||||
|
||||
if len(list) > 1 && strings.EqualFold(strings.TrimSpace(list[0]), pattern) {
|
||||
return strings.TrimSpace(list[1]), nil
|
||||
}
|
||||
}
|
||||
|
||||
// Check whether the scanner encountered errors
|
||||
err = scanner.Err()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return "", fmt.Errorf("getCPUInfo for pattern %s: %w", pattern, errdefs.ErrNotFound)
|
||||
}
|
||||
|
||||
// getCPUVariantFromArch get CPU variant from arch through a system call
|
||||
func getCPUVariantFromArch(arch string) (string, error) {
|
||||
|
||||
var variant string
|
||||
|
||||
arch = strings.ToLower(arch)
|
||||
|
||||
if arch == "aarch64" {
|
||||
variant = "8"
|
||||
} else if arch[0:4] == "armv" && len(arch) >= 5 {
|
||||
//Valid arch format is in form of armvXx
|
||||
switch arch[3:5] {
|
||||
case "v8":
|
||||
variant = "8"
|
||||
case "v7":
|
||||
variant = "7"
|
||||
case "v6":
|
||||
variant = "6"
|
||||
case "v5":
|
||||
variant = "5"
|
||||
case "v4":
|
||||
variant = "4"
|
||||
case "v3":
|
||||
variant = "3"
|
||||
default:
|
||||
variant = "unknown"
|
||||
}
|
||||
} else {
|
||||
return "", fmt.Errorf("getCPUVariantFromArch invalid arch: %s, %w", arch, errdefs.ErrInvalidArgument)
|
||||
}
|
||||
return variant, nil
|
||||
}
|
||||
|
||||
// getCPUVariant returns cpu variant for ARM
|
||||
// We first try reading "Cpu architecture" field from /proc/cpuinfo
|
||||
// If we can't find it, then fall back using a system call
|
||||
// This is to cover running ARM in emulated environment on x86 host as this field in /proc/cpuinfo
|
||||
// was not present.
|
||||
func getCPUVariant() (string, error) {
|
||||
|
||||
variant, err := getCPUInfo("Cpu architecture")
|
||||
if err != nil {
|
||||
if errdefs.IsNotFound(err) {
|
||||
//Let's try getting CPU variant from machine architecture
|
||||
arch, err := getMachineArch()
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failure getting machine architecture: %v", err)
|
||||
}
|
||||
|
||||
variant, err = getCPUVariantFromArch(arch)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failure getting CPU variant from machine architecture: %v", err)
|
||||
}
|
||||
} else {
|
||||
return "", fmt.Errorf("failure getting CPU variant: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// handle edge case for Raspberry Pi ARMv6 devices (which due to a kernel quirk, report "CPU architecture: 7")
|
||||
// https://www.raspberrypi.org/forums/viewtopic.php?t=12614
|
||||
if runtime.GOARCH == "arm" && variant == "7" {
|
||||
model, err := getCPUInfo("model name")
|
||||
if err == nil && strings.HasPrefix(strings.ToLower(model), "armv6-compatible") {
|
||||
variant = "6"
|
||||
}
|
||||
}
|
||||
|
||||
switch strings.ToLower(variant) {
|
||||
case "8", "aarch64":
|
||||
variant = "v8"
|
||||
case "7", "7m", "?(12)", "?(13)", "?(14)", "?(15)", "?(16)", "?(17)":
|
||||
variant = "v7"
|
||||
case "6", "6tej":
|
||||
variant = "v6"
|
||||
case "5", "5t", "5te", "5tej":
|
||||
variant = "v5"
|
||||
case "4", "4t":
|
||||
variant = "v4"
|
||||
case "3":
|
||||
variant = "v3"
|
||||
default:
|
||||
variant = "unknown"
|
||||
}
|
||||
|
||||
return variant, nil
|
||||
}
|
59
vendor/github.com/containerd/containerd/platforms/cpuinfo_other.go
generated
vendored
Normal file
59
vendor/github.com/containerd/containerd/platforms/cpuinfo_other.go
generated
vendored
Normal file
@ -0,0 +1,59 @@
|
||||
//go:build !linux
|
||||
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package platforms
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"runtime"
|
||||
|
||||
"github.com/containerd/containerd/errdefs"
|
||||
)
|
||||
|
||||
func getCPUVariant() (string, error) {
|
||||
|
||||
var variant string
|
||||
|
||||
if runtime.GOOS == "windows" || runtime.GOOS == "darwin" {
|
||||
// Windows/Darwin only supports v7 for ARM32 and v8 for ARM64 and so we can use
|
||||
// runtime.GOARCH to determine the variants
|
||||
switch runtime.GOARCH {
|
||||
case "arm64":
|
||||
variant = "v8"
|
||||
case "arm":
|
||||
variant = "v7"
|
||||
default:
|
||||
variant = "unknown"
|
||||
}
|
||||
} else if runtime.GOOS == "freebsd" {
|
||||
// FreeBSD supports ARMv6 and ARMv7 as well as ARMv4 and ARMv5 (though deprecated)
|
||||
// detecting those variants is currently unimplemented
|
||||
switch runtime.GOARCH {
|
||||
case "arm64":
|
||||
variant = "v8"
|
||||
default:
|
||||
variant = "unknown"
|
||||
}
|
||||
|
||||
} else {
|
||||
return "", fmt.Errorf("getCPUVariant for OS %s: %v", runtime.GOOS, errdefs.ErrNotImplemented)
|
||||
|
||||
}
|
||||
|
||||
return variant, nil
|
||||
}
|
7
vendor/github.com/containerd/containerd/platforms/database.go
generated
vendored
7
vendor/github.com/containerd/containerd/platforms/database.go
generated
vendored
@ -21,13 +21,6 @@ import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
// isLinuxOS returns true if the operating system is Linux.
|
||||
//
|
||||
// The OS value should be normalized before calling this function.
|
||||
func isLinuxOS(os string) bool {
|
||||
return os == "linux"
|
||||
}
|
||||
|
||||
// These function are generated from https://golang.org/src/go/build/syslist.go.
|
||||
//
|
||||
// We use switch statements because they are slightly faster than map lookups
|
||||
|
1
vendor/github.com/containerd/containerd/platforms/defaults_darwin.go
generated
vendored
1
vendor/github.com/containerd/containerd/platforms/defaults_darwin.go
generated
vendored
@ -1,5 +1,4 @@
|
||||
//go:build darwin
|
||||
// +build darwin
|
||||
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
43
vendor/github.com/containerd/containerd/platforms/defaults_freebsd.go
generated
vendored
Normal file
43
vendor/github.com/containerd/containerd/platforms/defaults_freebsd.go
generated
vendored
Normal file
@ -0,0 +1,43 @@
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package platforms
|
||||
|
||||
import (
|
||||
"runtime"
|
||||
|
||||
specs "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
)
|
||||
|
||||
// DefaultSpec returns the current platform's default platform specification.
|
||||
func DefaultSpec() specs.Platform {
|
||||
return specs.Platform{
|
||||
OS: runtime.GOOS,
|
||||
Architecture: runtime.GOARCH,
|
||||
// The Variant field will be empty if arch != ARM.
|
||||
Variant: cpuVariant(),
|
||||
}
|
||||
}
|
||||
|
||||
// Default returns the default matcher for the platform.
|
||||
func Default() MatchComparer {
|
||||
return Ordered(DefaultSpec(), specs.Platform{
|
||||
OS: "linux",
|
||||
Architecture: runtime.GOARCH,
|
||||
// The Variant field will be empty if arch != ARM.
|
||||
Variant: cpuVariant(),
|
||||
})
|
||||
}
|
3
vendor/github.com/containerd/containerd/platforms/defaults_unix.go
generated
vendored
3
vendor/github.com/containerd/containerd/platforms/defaults_unix.go
generated
vendored
@ -1,5 +1,4 @@
|
||||
//go:build !windows && !darwin
|
||||
// +build !windows,!darwin
|
||||
//go:build !windows && !darwin && !freebsd
|
||||
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
37
vendor/github.com/containerd/containerd/platforms/defaults_windows.go
generated
vendored
37
vendor/github.com/containerd/containerd/platforms/defaults_windows.go
generated
vendored
@ -22,7 +22,6 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
imagespec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
specs "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
@ -39,25 +38,28 @@ func DefaultSpec() specs.Platform {
|
||||
}
|
||||
}
|
||||
|
||||
type matchComparer struct {
|
||||
defaults Matcher
|
||||
type windowsmatcher struct {
|
||||
specs.Platform
|
||||
osVersionPrefix string
|
||||
defaultMatcher Matcher
|
||||
}
|
||||
|
||||
// Match matches platform with the same windows major, minor
|
||||
// and build version.
|
||||
func (m matchComparer) Match(p imagespec.Platform) bool {
|
||||
if m.defaults.Match(p) {
|
||||
// TODO(windows): Figure out whether OSVersion is deprecated.
|
||||
return strings.HasPrefix(p.OSVersion, m.osVersionPrefix)
|
||||
func (m windowsmatcher) Match(p specs.Platform) bool {
|
||||
match := m.defaultMatcher.Match(p)
|
||||
|
||||
if match && m.OS == "windows" {
|
||||
return strings.HasPrefix(p.OSVersion, m.osVersionPrefix) && m.defaultMatcher.Match(p)
|
||||
}
|
||||
return false
|
||||
|
||||
return match
|
||||
}
|
||||
|
||||
// Less sorts matched platforms in front of other platforms.
|
||||
// For matched platforms, it puts platforms with larger revision
|
||||
// number in front.
|
||||
func (m matchComparer) Less(p1, p2 imagespec.Platform) bool {
|
||||
func (m windowsmatcher) Less(p1, p2 specs.Platform) bool {
|
||||
m1, m2 := m.Match(p1), m.Match(p2)
|
||||
if m1 && m2 {
|
||||
r1, r2 := revision(p1.OSVersion), revision(p2.OSVersion)
|
||||
@ -78,14 +80,15 @@ func revision(v string) int {
|
||||
return r
|
||||
}
|
||||
|
||||
func prefix(v string) string {
|
||||
parts := strings.Split(v, ".")
|
||||
if len(parts) < 4 {
|
||||
return v
|
||||
}
|
||||
return strings.Join(parts[0:3], ".")
|
||||
}
|
||||
|
||||
// Default returns the current platform's default platform specification.
|
||||
func Default() MatchComparer {
|
||||
major, minor, build := windows.RtlGetNtVersionNumbers()
|
||||
return matchComparer{
|
||||
defaults: Ordered(DefaultSpec(), specs.Platform{
|
||||
OS: "linux",
|
||||
Architecture: runtime.GOARCH,
|
||||
}),
|
||||
osVersionPrefix: fmt.Sprintf("%d.%d.%d", major, minor, build),
|
||||
}
|
||||
return Only(DefaultSpec())
|
||||
}
|
||||
|
11
vendor/github.com/containerd/containerd/platforms/platforms.go
generated
vendored
11
vendor/github.com/containerd/containerd/platforms/platforms.go
generated
vendored
@ -114,14 +114,18 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/containerd/containerd/errdefs"
|
||||
specs "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
|
||||
"github.com/containerd/containerd/errdefs"
|
||||
)
|
||||
|
||||
var (
|
||||
specifierRe = regexp.MustCompile(`^[A-Za-z0-9_-]+$`)
|
||||
)
|
||||
|
||||
// Platform is a type alias for convenience, so there is no need to import image-spec package everywhere.
|
||||
type Platform = specs.Platform
|
||||
|
||||
// Matcher matches platforms specifications, provided by an image or runtime.
|
||||
type Matcher interface {
|
||||
Match(platform specs.Platform) bool
|
||||
@ -136,9 +140,7 @@ type Matcher interface {
|
||||
//
|
||||
// Applications should opt to use `Match` over directly parsing specifiers.
|
||||
func NewMatcher(platform specs.Platform) Matcher {
|
||||
return &matcher{
|
||||
Platform: Normalize(platform),
|
||||
}
|
||||
return newDefaultMatcher(platform)
|
||||
}
|
||||
|
||||
type matcher struct {
|
||||
@ -257,5 +259,6 @@ func Format(platform specs.Platform) string {
|
||||
func Normalize(platform specs.Platform) specs.Platform {
|
||||
platform.OS = normalizeOS(platform.OS)
|
||||
platform.Architecture, platform.Variant = normalizeArch(platform.Architecture, platform.Variant)
|
||||
|
||||
return platform
|
||||
}
|
||||
|
30
vendor/github.com/containerd/containerd/platforms/platforms_other.go
generated
vendored
Normal file
30
vendor/github.com/containerd/containerd/platforms/platforms_other.go
generated
vendored
Normal file
@ -0,0 +1,30 @@
|
||||
//go:build !windows
|
||||
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package platforms
|
||||
|
||||
import (
|
||||
specs "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
)
|
||||
|
||||
// NewMatcher returns the default Matcher for containerd
|
||||
func newDefaultMatcher(platform specs.Platform) Matcher {
|
||||
return &matcher{
|
||||
Platform: Normalize(platform),
|
||||
}
|
||||
}
|
34
vendor/github.com/containerd/containerd/platforms/platforms_windows.go
generated
vendored
Normal file
34
vendor/github.com/containerd/containerd/platforms/platforms_windows.go
generated
vendored
Normal file
@ -0,0 +1,34 @@
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package platforms
|
||||
|
||||
import (
|
||||
specs "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
)
|
||||
|
||||
// NewMatcher returns a Windows matcher that will match on osVersionPrefix if
|
||||
// the platform is Windows otherwise use the default matcher
|
||||
func newDefaultMatcher(platform specs.Platform) Matcher {
|
||||
prefix := prefix(platform.OSVersion)
|
||||
return windowsmatcher{
|
||||
Platform: platform,
|
||||
osVersionPrefix: prefix,
|
||||
defaultMatcher: &matcher{
|
||||
Platform: Normalize(platform),
|
||||
},
|
||||
}
|
||||
}
|
47
vendor/github.com/containerd/containerd/protobuf/any.go
generated
vendored
Normal file
47
vendor/github.com/containerd/containerd/protobuf/any.go
generated
vendored
Normal file
@ -0,0 +1,47 @@
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package protobuf
|
||||
|
||||
import (
|
||||
"github.com/containerd/typeurl"
|
||||
"google.golang.org/protobuf/types/known/anypb"
|
||||
)
|
||||
|
||||
// FromAny converts typeurl.Any to github.com/containerd/containerd/protobuf/types.Any.
|
||||
func FromAny(from typeurl.Any) *anypb.Any {
|
||||
if from == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
if pbany, ok := from.(*anypb.Any); ok {
|
||||
return pbany
|
||||
}
|
||||
|
||||
return &anypb.Any{
|
||||
TypeUrl: from.GetTypeUrl(),
|
||||
Value: from.GetValue(),
|
||||
}
|
||||
}
|
||||
|
||||
// FromAny converts an arbitrary interface to github.com/containerd/containerd/protobuf/types.Any.
|
||||
func MarshalAnyToProto(from interface{}) (*anypb.Any, error) {
|
||||
any, err := typeurl.MarshalAny(from)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return FromAny(any), nil
|
||||
}
|
41
vendor/github.com/containerd/containerd/protobuf/compare.go
generated
vendored
Normal file
41
vendor/github.com/containerd/containerd/protobuf/compare.go
generated
vendored
Normal file
@ -0,0 +1,41 @@
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package protobuf
|
||||
|
||||
import (
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
var Compare = cmp.FilterValues(
|
||||
func(x, y interface{}) bool {
|
||||
_, xok := x.(proto.Message)
|
||||
_, yok := y.(proto.Message)
|
||||
return xok && yok
|
||||
},
|
||||
cmp.Comparer(func(x, y interface{}) bool {
|
||||
vx, ok := x.(proto.Message)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
vy, ok := y.(proto.Message)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
return proto.Equal(vx, vy)
|
||||
}),
|
||||
)
|
36
vendor/github.com/containerd/containerd/protobuf/timestamp.go
generated
vendored
Normal file
36
vendor/github.com/containerd/containerd/protobuf/timestamp.go
generated
vendored
Normal file
@ -0,0 +1,36 @@
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package protobuf
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"google.golang.org/protobuf/types/known/timestamppb"
|
||||
)
|
||||
|
||||
// Once we migrate off from gogo/protobuf, we can use the function below, which don't return any errors.
|
||||
// https://github.com/protocolbuffers/protobuf-go/blob/v1.28.0/types/known/timestamppb/timestamp.pb.go#L200-L208
|
||||
|
||||
// ToTimestamp creates protobuf's Timestamp from time.Time.
|
||||
func ToTimestamp(from time.Time) *timestamppb.Timestamp {
|
||||
return timestamppb.New(from)
|
||||
}
|
||||
|
||||
// FromTimestamp creates time.Time from protobuf's Timestamp.
|
||||
func FromTimestamp(from *timestamppb.Timestamp) time.Time {
|
||||
return from.AsTime()
|
||||
}
|
28
vendor/github.com/containerd/containerd/protobuf/types/types.go
generated
vendored
Normal file
28
vendor/github.com/containerd/containerd/protobuf/types/types.go
generated
vendored
Normal file
@ -0,0 +1,28 @@
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// Package types provides convinient aliases that make google.golang.org/protobuf migration easier.
|
||||
package types
|
||||
|
||||
import (
|
||||
"google.golang.org/genproto/protobuf/field_mask"
|
||||
"google.golang.org/protobuf/types/known/anypb"
|
||||
"google.golang.org/protobuf/types/known/emptypb"
|
||||
)
|
||||
|
||||
type Empty = emptypb.Empty
|
||||
type Any = anypb.Any
|
||||
type FieldMask = field_mask.FieldMask
|
58
vendor/github.com/containerd/containerd/reference/docker/helpers.go
generated
vendored
Normal file
58
vendor/github.com/containerd/containerd/reference/docker/helpers.go
generated
vendored
Normal file
@ -0,0 +1,58 @@
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package docker
|
||||
|
||||
import "path"
|
||||
|
||||
// IsNameOnly returns true if reference only contains a repo name.
|
||||
func IsNameOnly(ref Named) bool {
|
||||
if _, ok := ref.(NamedTagged); ok {
|
||||
return false
|
||||
}
|
||||
if _, ok := ref.(Canonical); ok {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// FamiliarName returns the familiar name string
|
||||
// for the given named, familiarizing if needed.
|
||||
func FamiliarName(ref Named) string {
|
||||
if nn, ok := ref.(normalizedNamed); ok {
|
||||
return nn.Familiar().Name()
|
||||
}
|
||||
return ref.Name()
|
||||
}
|
||||
|
||||
// FamiliarString returns the familiar string representation
|
||||
// for the given reference, familiarizing if needed.
|
||||
func FamiliarString(ref Reference) string {
|
||||
if nn, ok := ref.(normalizedNamed); ok {
|
||||
return nn.Familiar().String()
|
||||
}
|
||||
return ref.String()
|
||||
}
|
||||
|
||||
// FamiliarMatch reports whether ref matches the specified pattern.
|
||||
// See https://godoc.org/path#Match for supported patterns.
|
||||
func FamiliarMatch(pattern string, ref Reference) (bool, error) {
|
||||
matched, err := path.Match(pattern, FamiliarString(ref))
|
||||
if namedRef, isNamed := ref.(Named); isNamed && !matched {
|
||||
matched, _ = path.Match(pattern, FamiliarName(namedRef))
|
||||
}
|
||||
return matched, err
|
||||
}
|
196
vendor/github.com/containerd/containerd/reference/docker/normalize.go
generated
vendored
Normal file
196
vendor/github.com/containerd/containerd/reference/docker/normalize.go
generated
vendored
Normal file
@ -0,0 +1,196 @@
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package docker
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/opencontainers/go-digest"
|
||||
)
|
||||
|
||||
var (
|
||||
legacyDefaultDomain = "index.docker.io"
|
||||
defaultDomain = "docker.io"
|
||||
officialRepoName = "library"
|
||||
defaultTag = "latest"
|
||||
)
|
||||
|
||||
// normalizedNamed represents a name which has been
|
||||
// normalized and has a familiar form. A familiar name
|
||||
// is what is used in Docker UI. An example normalized
|
||||
// name is "docker.io/library/ubuntu" and corresponding
|
||||
// familiar name of "ubuntu".
|
||||
type normalizedNamed interface {
|
||||
Named
|
||||
Familiar() Named
|
||||
}
|
||||
|
||||
// ParseNormalizedNamed parses a string into a named reference
|
||||
// transforming a familiar name from Docker UI to a fully
|
||||
// qualified reference. If the value may be an identifier
|
||||
// use ParseAnyReference.
|
||||
func ParseNormalizedNamed(s string) (Named, error) {
|
||||
if ok := anchoredIdentifierRegexp.MatchString(s); ok {
|
||||
return nil, fmt.Errorf("invalid repository name (%s), cannot specify 64-byte hexadecimal strings", s)
|
||||
}
|
||||
domain, remainder := splitDockerDomain(s)
|
||||
var remoteName string
|
||||
if tagSep := strings.IndexRune(remainder, ':'); tagSep > -1 {
|
||||
remoteName = remainder[:tagSep]
|
||||
} else {
|
||||
remoteName = remainder
|
||||
}
|
||||
if strings.ToLower(remoteName) != remoteName {
|
||||
return nil, fmt.Errorf("invalid reference format: repository name (%s) must be lowercase", remoteName)
|
||||
}
|
||||
|
||||
ref, err := Parse(domain + "/" + remainder)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
named, isNamed := ref.(Named)
|
||||
if !isNamed {
|
||||
return nil, fmt.Errorf("reference %s has no name", ref.String())
|
||||
}
|
||||
return named, nil
|
||||
}
|
||||
|
||||
// ParseDockerRef normalizes the image reference following the docker convention. This is added
|
||||
// mainly for backward compatibility.
|
||||
// The reference returned can only be either tagged or digested. For reference contains both tag
|
||||
// and digest, the function returns digested reference, e.g. docker.io/library/busybox:latest@
|
||||
// sha256:7cc4b5aefd1d0cadf8d97d4350462ba51c694ebca145b08d7d41b41acc8db5aa will be returned as
|
||||
// docker.io/library/busybox@sha256:7cc4b5aefd1d0cadf8d97d4350462ba51c694ebca145b08d7d41b41acc8db5aa.
|
||||
func ParseDockerRef(ref string) (Named, error) {
|
||||
named, err := ParseNormalizedNamed(ref)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if _, ok := named.(NamedTagged); ok {
|
||||
if canonical, ok := named.(Canonical); ok {
|
||||
// The reference is both tagged and digested, only
|
||||
// return digested.
|
||||
newNamed, err := WithName(canonical.Name())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
newCanonical, err := WithDigest(newNamed, canonical.Digest())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return newCanonical, nil
|
||||
}
|
||||
}
|
||||
return TagNameOnly(named), nil
|
||||
}
|
||||
|
||||
// splitDockerDomain splits a repository name to domain and remotename string.
|
||||
// If no valid domain is found, the default domain is used. Repository name
|
||||
// needs to be already validated before.
|
||||
func splitDockerDomain(name string) (domain, remainder string) {
|
||||
i := strings.IndexRune(name, '/')
|
||||
if i == -1 || (!strings.ContainsAny(name[:i], ".:") && name[:i] != "localhost" && strings.ToLower(name[:i]) == name[:i]) {
|
||||
domain, remainder = defaultDomain, name
|
||||
} else {
|
||||
domain, remainder = name[:i], name[i+1:]
|
||||
}
|
||||
if domain == legacyDefaultDomain {
|
||||
domain = defaultDomain
|
||||
}
|
||||
if domain == defaultDomain && !strings.ContainsRune(remainder, '/') {
|
||||
remainder = officialRepoName + "/" + remainder
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// familiarizeName returns a shortened version of the name familiar
|
||||
// to the Docker UI. Familiar names have the default domain
|
||||
// "docker.io" and "library/" repository prefix removed.
|
||||
// For example, "docker.io/library/redis" will have the familiar
|
||||
// name "redis" and "docker.io/dmcgowan/myapp" will be "dmcgowan/myapp".
|
||||
// Returns a familiarized named only reference.
|
||||
func familiarizeName(named namedRepository) repository {
|
||||
repo := repository{
|
||||
domain: named.Domain(),
|
||||
path: named.Path(),
|
||||
}
|
||||
|
||||
if repo.domain == defaultDomain {
|
||||
repo.domain = ""
|
||||
// Handle official repositories which have the pattern "library/<official repo name>"
|
||||
if split := strings.Split(repo.path, "/"); len(split) == 2 && split[0] == officialRepoName {
|
||||
repo.path = split[1]
|
||||
}
|
||||
}
|
||||
return repo
|
||||
}
|
||||
|
||||
func (r reference) Familiar() Named {
|
||||
return reference{
|
||||
namedRepository: familiarizeName(r.namedRepository),
|
||||
tag: r.tag,
|
||||
digest: r.digest,
|
||||
}
|
||||
}
|
||||
|
||||
func (r repository) Familiar() Named {
|
||||
return familiarizeName(r)
|
||||
}
|
||||
|
||||
func (t taggedReference) Familiar() Named {
|
||||
return taggedReference{
|
||||
namedRepository: familiarizeName(t.namedRepository),
|
||||
tag: t.tag,
|
||||
}
|
||||
}
|
||||
|
||||
func (c canonicalReference) Familiar() Named {
|
||||
return canonicalReference{
|
||||
namedRepository: familiarizeName(c.namedRepository),
|
||||
digest: c.digest,
|
||||
}
|
||||
}
|
||||
|
||||
// TagNameOnly adds the default tag "latest" to a reference if it only has
|
||||
// a repo name.
|
||||
func TagNameOnly(ref Named) Named {
|
||||
if IsNameOnly(ref) {
|
||||
namedTagged, err := WithTag(ref, defaultTag)
|
||||
if err != nil {
|
||||
// Default tag must be valid, to create a NamedTagged
|
||||
// type with non-validated input the WithTag function
|
||||
// should be used instead
|
||||
panic(err)
|
||||
}
|
||||
return namedTagged
|
||||
}
|
||||
return ref
|
||||
}
|
||||
|
||||
// ParseAnyReference parses a reference string as a possible identifier,
|
||||
// full digest, or familiar name.
|
||||
func ParseAnyReference(ref string) (Reference, error) {
|
||||
if ok := anchoredIdentifierRegexp.MatchString(ref); ok {
|
||||
return digestReference("sha256:" + ref), nil
|
||||
}
|
||||
if dgst, err := digest.Parse(ref); err == nil {
|
||||
return digestReference(dgst), nil
|
||||
}
|
||||
|
||||
return ParseNormalizedNamed(ref)
|
||||
}
|
453
vendor/github.com/containerd/containerd/reference/docker/reference.go
generated
vendored
Normal file
453
vendor/github.com/containerd/containerd/reference/docker/reference.go
generated
vendored
Normal file
@ -0,0 +1,453 @@
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// Package docker provides a general type to represent any way of referencing images within the registry.
|
||||
// Its main purpose is to abstract tags and digests (content-addressable hash).
|
||||
//
|
||||
// Grammar
|
||||
//
|
||||
// reference := name [ ":" tag ] [ "@" digest ]
|
||||
// name := [domain '/'] path-component ['/' path-component]*
|
||||
// domain := host [':' port-number]
|
||||
// host := domain-name | IPv4address | \[ IPv6address \] ; rfc3986 appendix-A
|
||||
// domain-name := domain-component ['.' domain-component]*
|
||||
// domain-component := /([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9])/
|
||||
// port-number := /[0-9]+/
|
||||
// path-component := alpha-numeric [separator alpha-numeric]*
|
||||
// alpha-numeric := /[a-z0-9]+/
|
||||
// separator := /[_.]|__|[-]*/
|
||||
//
|
||||
// tag := /[\w][\w.-]{0,127}/
|
||||
//
|
||||
// digest := digest-algorithm ":" digest-hex
|
||||
// digest-algorithm := digest-algorithm-component [ digest-algorithm-separator digest-algorithm-component ]*
|
||||
// digest-algorithm-separator := /[+.-_]/
|
||||
// digest-algorithm-component := /[A-Za-z][A-Za-z0-9]*/
|
||||
// digest-hex := /[0-9a-fA-F]{32,}/ ; At least 128 bit digest value
|
||||
//
|
||||
// identifier := /[a-f0-9]{64}/
|
||||
// short-identifier := /[a-f0-9]{6,64}/
|
||||
package docker
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/opencontainers/go-digest"
|
||||
)
|
||||
|
||||
const (
|
||||
// NameTotalLengthMax is the maximum total number of characters in a repository name.
|
||||
NameTotalLengthMax = 255
|
||||
)
|
||||
|
||||
var (
|
||||
// ErrReferenceInvalidFormat represents an error while trying to parse a string as a reference.
|
||||
ErrReferenceInvalidFormat = errors.New("invalid reference format")
|
||||
|
||||
// ErrTagInvalidFormat represents an error while trying to parse a string as a tag.
|
||||
ErrTagInvalidFormat = errors.New("invalid tag format")
|
||||
|
||||
// ErrDigestInvalidFormat represents an error while trying to parse a string as a tag.
|
||||
ErrDigestInvalidFormat = errors.New("invalid digest format")
|
||||
|
||||
// ErrNameContainsUppercase is returned for invalid repository names that contain uppercase characters.
|
||||
ErrNameContainsUppercase = errors.New("repository name must be lowercase")
|
||||
|
||||
// ErrNameEmpty is returned for empty, invalid repository names.
|
||||
ErrNameEmpty = errors.New("repository name must have at least one component")
|
||||
|
||||
// ErrNameTooLong is returned when a repository name is longer than NameTotalLengthMax.
|
||||
ErrNameTooLong = fmt.Errorf("repository name must not be more than %v characters", NameTotalLengthMax)
|
||||
|
||||
// ErrNameNotCanonical is returned when a name is not canonical.
|
||||
ErrNameNotCanonical = errors.New("repository name must be canonical")
|
||||
)
|
||||
|
||||
// Reference is an opaque object reference identifier that may include
|
||||
// modifiers such as a hostname, name, tag, and digest.
|
||||
type Reference interface {
|
||||
// String returns the full reference
|
||||
String() string
|
||||
}
|
||||
|
||||
// Field provides a wrapper type for resolving correct reference types when
|
||||
// working with encoding.
|
||||
type Field struct {
|
||||
reference Reference
|
||||
}
|
||||
|
||||
// AsField wraps a reference in a Field for encoding.
|
||||
func AsField(reference Reference) Field {
|
||||
return Field{reference}
|
||||
}
|
||||
|
||||
// Reference unwraps the reference type from the field to
|
||||
// return the Reference object. This object should be
|
||||
// of the appropriate type to further check for different
|
||||
// reference types.
|
||||
func (f Field) Reference() Reference {
|
||||
return f.reference
|
||||
}
|
||||
|
||||
// MarshalText serializes the field to byte text which
|
||||
// is the string of the reference.
|
||||
func (f Field) MarshalText() (p []byte, err error) {
|
||||
return []byte(f.reference.String()), nil
|
||||
}
|
||||
|
||||
// UnmarshalText parses text bytes by invoking the
|
||||
// reference parser to ensure the appropriately
|
||||
// typed reference object is wrapped by field.
|
||||
func (f *Field) UnmarshalText(p []byte) error {
|
||||
r, err := Parse(string(p))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
f.reference = r
|
||||
return nil
|
||||
}
|
||||
|
||||
// Named is an object with a full name
|
||||
type Named interface {
|
||||
Reference
|
||||
Name() string
|
||||
}
|
||||
|
||||
// Tagged is an object which has a tag
|
||||
type Tagged interface {
|
||||
Reference
|
||||
Tag() string
|
||||
}
|
||||
|
||||
// NamedTagged is an object including a name and tag.
|
||||
type NamedTagged interface {
|
||||
Named
|
||||
Tag() string
|
||||
}
|
||||
|
||||
// Digested is an object which has a digest
|
||||
// in which it can be referenced by
|
||||
type Digested interface {
|
||||
Reference
|
||||
Digest() digest.Digest
|
||||
}
|
||||
|
||||
// Canonical reference is an object with a fully unique
|
||||
// name including a name with domain and digest
|
||||
type Canonical interface {
|
||||
Named
|
||||
Digest() digest.Digest
|
||||
}
|
||||
|
||||
// namedRepository is a reference to a repository with a name.
|
||||
// A namedRepository has both domain and path components.
|
||||
type namedRepository interface {
|
||||
Named
|
||||
Domain() string
|
||||
Path() string
|
||||
}
|
||||
|
||||
// Domain returns the domain part of the Named reference
|
||||
func Domain(named Named) string {
|
||||
if r, ok := named.(namedRepository); ok {
|
||||
return r.Domain()
|
||||
}
|
||||
domain, _ := splitDomain(named.Name())
|
||||
return domain
|
||||
}
|
||||
|
||||
// Path returns the name without the domain part of the Named reference
|
||||
func Path(named Named) (name string) {
|
||||
if r, ok := named.(namedRepository); ok {
|
||||
return r.Path()
|
||||
}
|
||||
_, path := splitDomain(named.Name())
|
||||
return path
|
||||
}
|
||||
|
||||
func splitDomain(name string) (string, string) {
|
||||
match := anchoredNameRegexp.FindStringSubmatch(name)
|
||||
if len(match) != 3 {
|
||||
return "", name
|
||||
}
|
||||
return match[1], match[2]
|
||||
}
|
||||
|
||||
// SplitHostname splits a named reference into a
|
||||
// hostname and name string. If no valid hostname is
|
||||
// found, the hostname is empty and the full value
|
||||
// is returned as name
|
||||
// DEPRECATED: Use Domain or Path
|
||||
func SplitHostname(named Named) (string, string) {
|
||||
if r, ok := named.(namedRepository); ok {
|
||||
return r.Domain(), r.Path()
|
||||
}
|
||||
return splitDomain(named.Name())
|
||||
}
|
||||
|
||||
// Parse parses s and returns a syntactically valid Reference.
|
||||
// If an error was encountered it is returned, along with a nil Reference.
|
||||
// NOTE: Parse will not handle short digests.
|
||||
func Parse(s string) (Reference, error) {
|
||||
matches := ReferenceRegexp.FindStringSubmatch(s)
|
||||
if matches == nil {
|
||||
if s == "" {
|
||||
return nil, ErrNameEmpty
|
||||
}
|
||||
if ReferenceRegexp.FindStringSubmatch(strings.ToLower(s)) != nil {
|
||||
return nil, ErrNameContainsUppercase
|
||||
}
|
||||
return nil, ErrReferenceInvalidFormat
|
||||
}
|
||||
|
||||
if len(matches[1]) > NameTotalLengthMax {
|
||||
return nil, ErrNameTooLong
|
||||
}
|
||||
|
||||
var repo repository
|
||||
|
||||
nameMatch := anchoredNameRegexp.FindStringSubmatch(matches[1])
|
||||
if len(nameMatch) == 3 {
|
||||
repo.domain = nameMatch[1]
|
||||
repo.path = nameMatch[2]
|
||||
} else {
|
||||
repo.domain = ""
|
||||
repo.path = matches[1]
|
||||
}
|
||||
|
||||
ref := reference{
|
||||
namedRepository: repo,
|
||||
tag: matches[2],
|
||||
}
|
||||
if matches[3] != "" {
|
||||
var err error
|
||||
ref.digest, err = digest.Parse(matches[3])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
r := getBestReferenceType(ref)
|
||||
if r == nil {
|
||||
return nil, ErrNameEmpty
|
||||
}
|
||||
|
||||
return r, nil
|
||||
}
|
||||
|
||||
// ParseNamed parses s and returns a syntactically valid reference implementing
|
||||
// the Named interface. The reference must have a name and be in the canonical
|
||||
// form, otherwise an error is returned.
|
||||
// If an error was encountered it is returned, along with a nil Reference.
|
||||
// NOTE: ParseNamed will not handle short digests.
|
||||
func ParseNamed(s string) (Named, error) {
|
||||
named, err := ParseNormalizedNamed(s)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if named.String() != s {
|
||||
return nil, ErrNameNotCanonical
|
||||
}
|
||||
return named, nil
|
||||
}
|
||||
|
||||
// WithName returns a named object representing the given string. If the input
|
||||
// is invalid ErrReferenceInvalidFormat will be returned.
|
||||
func WithName(name string) (Named, error) {
|
||||
if len(name) > NameTotalLengthMax {
|
||||
return nil, ErrNameTooLong
|
||||
}
|
||||
|
||||
match := anchoredNameRegexp.FindStringSubmatch(name)
|
||||
if match == nil || len(match) != 3 {
|
||||
return nil, ErrReferenceInvalidFormat
|
||||
}
|
||||
return repository{
|
||||
domain: match[1],
|
||||
path: match[2],
|
||||
}, nil
|
||||
}
|
||||
|
||||
// WithTag combines the name from "name" and the tag from "tag" to form a
|
||||
// reference incorporating both the name and the tag.
|
||||
func WithTag(name Named, tag string) (NamedTagged, error) {
|
||||
if !anchoredTagRegexp.MatchString(tag) {
|
||||
return nil, ErrTagInvalidFormat
|
||||
}
|
||||
var repo repository
|
||||
if r, ok := name.(namedRepository); ok {
|
||||
repo.domain = r.Domain()
|
||||
repo.path = r.Path()
|
||||
} else {
|
||||
repo.path = name.Name()
|
||||
}
|
||||
if canonical, ok := name.(Canonical); ok {
|
||||
return reference{
|
||||
namedRepository: repo,
|
||||
tag: tag,
|
||||
digest: canonical.Digest(),
|
||||
}, nil
|
||||
}
|
||||
return taggedReference{
|
||||
namedRepository: repo,
|
||||
tag: tag,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// WithDigest combines the name from "name" and the digest from "digest" to form
|
||||
// a reference incorporating both the name and the digest.
|
||||
func WithDigest(name Named, digest digest.Digest) (Canonical, error) {
|
||||
if !anchoredDigestRegexp.MatchString(digest.String()) {
|
||||
return nil, ErrDigestInvalidFormat
|
||||
}
|
||||
var repo repository
|
||||
if r, ok := name.(namedRepository); ok {
|
||||
repo.domain = r.Domain()
|
||||
repo.path = r.Path()
|
||||
} else {
|
||||
repo.path = name.Name()
|
||||
}
|
||||
if tagged, ok := name.(Tagged); ok {
|
||||
return reference{
|
||||
namedRepository: repo,
|
||||
tag: tagged.Tag(),
|
||||
digest: digest,
|
||||
}, nil
|
||||
}
|
||||
return canonicalReference{
|
||||
namedRepository: repo,
|
||||
digest: digest,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// TrimNamed removes any tag or digest from the named reference.
|
||||
func TrimNamed(ref Named) Named {
|
||||
repo := repository{}
|
||||
if r, ok := ref.(namedRepository); ok {
|
||||
repo.domain, repo.path = r.Domain(), r.Path()
|
||||
} else {
|
||||
repo.domain, repo.path = splitDomain(ref.Name())
|
||||
}
|
||||
return repo
|
||||
}
|
||||
|
||||
func getBestReferenceType(ref reference) Reference {
|
||||
if ref.Name() == "" {
|
||||
// Allow digest only references
|
||||
if ref.digest != "" {
|
||||
return digestReference(ref.digest)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
if ref.tag == "" {
|
||||
if ref.digest != "" {
|
||||
return canonicalReference{
|
||||
namedRepository: ref.namedRepository,
|
||||
digest: ref.digest,
|
||||
}
|
||||
}
|
||||
return ref.namedRepository
|
||||
}
|
||||
if ref.digest == "" {
|
||||
return taggedReference{
|
||||
namedRepository: ref.namedRepository,
|
||||
tag: ref.tag,
|
||||
}
|
||||
}
|
||||
|
||||
return ref
|
||||
}
|
||||
|
||||
type reference struct {
|
||||
namedRepository
|
||||
tag string
|
||||
digest digest.Digest
|
||||
}
|
||||
|
||||
func (r reference) String() string {
|
||||
return r.Name() + ":" + r.tag + "@" + r.digest.String()
|
||||
}
|
||||
|
||||
func (r reference) Tag() string {
|
||||
return r.tag
|
||||
}
|
||||
|
||||
func (r reference) Digest() digest.Digest {
|
||||
return r.digest
|
||||
}
|
||||
|
||||
type repository struct {
|
||||
domain string
|
||||
path string
|
||||
}
|
||||
|
||||
func (r repository) String() string {
|
||||
return r.Name()
|
||||
}
|
||||
|
||||
func (r repository) Name() string {
|
||||
if r.domain == "" {
|
||||
return r.path
|
||||
}
|
||||
return r.domain + "/" + r.path
|
||||
}
|
||||
|
||||
func (r repository) Domain() string {
|
||||
return r.domain
|
||||
}
|
||||
|
||||
func (r repository) Path() string {
|
||||
return r.path
|
||||
}
|
||||
|
||||
type digestReference digest.Digest
|
||||
|
||||
func (d digestReference) String() string {
|
||||
return digest.Digest(d).String()
|
||||
}
|
||||
|
||||
func (d digestReference) Digest() digest.Digest {
|
||||
return digest.Digest(d)
|
||||
}
|
||||
|
||||
type taggedReference struct {
|
||||
namedRepository
|
||||
tag string
|
||||
}
|
||||
|
||||
func (t taggedReference) String() string {
|
||||
return t.Name() + ":" + t.tag
|
||||
}
|
||||
|
||||
func (t taggedReference) Tag() string {
|
||||
return t.tag
|
||||
}
|
||||
|
||||
type canonicalReference struct {
|
||||
namedRepository
|
||||
digest digest.Digest
|
||||
}
|
||||
|
||||
func (c canonicalReference) String() string {
|
||||
return c.Name() + "@" + c.digest.String()
|
||||
}
|
||||
|
||||
func (c canonicalReference) Digest() digest.Digest {
|
||||
return c.digest
|
||||
}
|
191
vendor/github.com/containerd/containerd/reference/docker/regexp.go
generated
vendored
Normal file
191
vendor/github.com/containerd/containerd/reference/docker/regexp.go
generated
vendored
Normal file
@ -0,0 +1,191 @@
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package docker
|
||||
|
||||
import "regexp"
|
||||
|
||||
var (
|
||||
// alphaNumeric defines the alpha numeric atom, typically a
|
||||
// component of names. This only allows lower case characters and digits.
|
||||
alphaNumeric = `[a-z0-9]+`
|
||||
|
||||
// separator defines the separators allowed to be embedded in name
|
||||
// components. This allow one period, one or two underscore and multiple
|
||||
// dashes. Repeated dashes and underscores are intentionally treated
|
||||
// differently. In order to support valid hostnames as name components,
|
||||
// supporting repeated dash was added. Additionally double underscore is
|
||||
// now allowed as a separator to loosen the restriction for previously
|
||||
// supported names.
|
||||
separator = `(?:[._]|__|[-]*)`
|
||||
|
||||
// nameComponent restricts registry path component names to start
|
||||
// with at least one letter or number, with following parts able to be
|
||||
// separated by one period, one or two underscore and multiple dashes.
|
||||
nameComponent = expression(
|
||||
alphaNumeric,
|
||||
optional(repeated(separator, alphaNumeric)))
|
||||
|
||||
// domainNameComponent restricts the registry domain component of a
|
||||
// repository name to start with a component as defined by DomainRegexp.
|
||||
domainNameComponent = `(?:[a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9])`
|
||||
|
||||
// ipv6address are enclosed between square brackets and may be represented
|
||||
// in many ways, see rfc5952. Only IPv6 in compressed or uncompressed format
|
||||
// are allowed, IPv6 zone identifiers (rfc6874) or Special addresses such as
|
||||
// IPv4-Mapped are deliberately excluded.
|
||||
ipv6address = expression(
|
||||
literal(`[`), `(?:[a-fA-F0-9:]+)`, literal(`]`),
|
||||
)
|
||||
|
||||
// domainName defines the structure of potential domain components
|
||||
// that may be part of image names. This is purposely a subset of what is
|
||||
// allowed by DNS to ensure backwards compatibility with Docker image
|
||||
// names. This includes IPv4 addresses on decimal format.
|
||||
domainName = expression(
|
||||
domainNameComponent,
|
||||
optional(repeated(literal(`.`), domainNameComponent)),
|
||||
)
|
||||
|
||||
// host defines the structure of potential domains based on the URI
|
||||
// Host subcomponent on rfc3986. It may be a subset of DNS domain name,
|
||||
// or an IPv4 address in decimal format, or an IPv6 address between square
|
||||
// brackets (excluding zone identifiers as defined by rfc6874 or special
|
||||
// addresses such as IPv4-Mapped).
|
||||
host = `(?:` + domainName + `|` + ipv6address + `)`
|
||||
|
||||
// allowed by the URI Host subcomponent on rfc3986 to ensure backwards
|
||||
// compatibility with Docker image names.
|
||||
domain = expression(
|
||||
host,
|
||||
optional(literal(`:`), `[0-9]+`))
|
||||
|
||||
// DomainRegexp defines the structure of potential domain components
|
||||
// that may be part of image names. This is purposely a subset of what is
|
||||
// allowed by DNS to ensure backwards compatibility with Docker image
|
||||
// names.
|
||||
DomainRegexp = regexp.MustCompile(domain)
|
||||
|
||||
tag = `[\w][\w.-]{0,127}`
|
||||
// TagRegexp matches valid tag names. From docker/docker:graph/tags.go.
|
||||
TagRegexp = regexp.MustCompile(tag)
|
||||
|
||||
anchoredTag = anchored(tag)
|
||||
// anchoredTagRegexp matches valid tag names, anchored at the start and
|
||||
// end of the matched string.
|
||||
anchoredTagRegexp = regexp.MustCompile(anchoredTag)
|
||||
|
||||
digestPat = `[A-Za-z][A-Za-z0-9]*(?:[-_+.][A-Za-z][A-Za-z0-9]*)*[:][[:xdigit:]]{32,}`
|
||||
// DigestRegexp matches valid digests.
|
||||
DigestRegexp = regexp.MustCompile(digestPat)
|
||||
|
||||
anchoredDigest = anchored(digestPat)
|
||||
// anchoredDigestRegexp matches valid digests, anchored at the start and
|
||||
// end of the matched string.
|
||||
anchoredDigestRegexp = regexp.MustCompile(anchoredDigest)
|
||||
|
||||
namePat = expression(
|
||||
optional(domain, literal(`/`)),
|
||||
nameComponent,
|
||||
optional(repeated(literal(`/`), nameComponent)))
|
||||
// NameRegexp is the format for the name component of references. The
|
||||
// regexp has capturing groups for the domain and name part omitting
|
||||
// the separating forward slash from either.
|
||||
NameRegexp = regexp.MustCompile(namePat)
|
||||
|
||||
anchoredName = anchored(
|
||||
optional(capture(domain), literal(`/`)),
|
||||
capture(nameComponent,
|
||||
optional(repeated(literal(`/`), nameComponent))))
|
||||
// anchoredNameRegexp is used to parse a name value, capturing the
|
||||
// domain and trailing components.
|
||||
anchoredNameRegexp = regexp.MustCompile(anchoredName)
|
||||
|
||||
referencePat = anchored(capture(namePat),
|
||||
optional(literal(":"), capture(tag)),
|
||||
optional(literal("@"), capture(digestPat)))
|
||||
// ReferenceRegexp is the full supported format of a reference. The regexp
|
||||
// is anchored and has capturing groups for name, tag, and digest
|
||||
// components.
|
||||
ReferenceRegexp = regexp.MustCompile(referencePat)
|
||||
|
||||
identifier = `([a-f0-9]{64})`
|
||||
// IdentifierRegexp is the format for string identifier used as a
|
||||
// content addressable identifier using sha256. These identifiers
|
||||
// are like digests without the algorithm, since sha256 is used.
|
||||
IdentifierRegexp = regexp.MustCompile(identifier)
|
||||
|
||||
shortIdentifier = `([a-f0-9]{6,64})`
|
||||
// ShortIdentifierRegexp is the format used to represent a prefix
|
||||
// of an identifier. A prefix may be used to match a sha256 identifier
|
||||
// within a list of trusted identifiers.
|
||||
ShortIdentifierRegexp = regexp.MustCompile(shortIdentifier)
|
||||
|
||||
anchoredIdentifier = anchored(identifier)
|
||||
// anchoredIdentifierRegexp is used to check or match an
|
||||
// identifier value, anchored at start and end of string.
|
||||
anchoredIdentifierRegexp = regexp.MustCompile(anchoredIdentifier)
|
||||
)
|
||||
|
||||
// literal compiles s into a literal regular expression, escaping any regexp
|
||||
// reserved characters.
|
||||
func literal(s string) string {
|
||||
re := regexp.MustCompile(regexp.QuoteMeta(s))
|
||||
|
||||
if _, complete := re.LiteralPrefix(); !complete {
|
||||
panic("must be a literal")
|
||||
}
|
||||
|
||||
return re.String()
|
||||
}
|
||||
|
||||
// expression defines a full expression, where each regular expression must
|
||||
// follow the previous.
|
||||
func expression(res ...string) string {
|
||||
var s string
|
||||
for _, re := range res {
|
||||
s += re
|
||||
}
|
||||
|
||||
return s
|
||||
}
|
||||
|
||||
// optional wraps the expression in a non-capturing group and makes the
|
||||
// production optional.
|
||||
func optional(res ...string) string {
|
||||
return group(expression(res...)) + `?`
|
||||
}
|
||||
|
||||
// repeated wraps the regexp in a non-capturing group to get one or more
|
||||
// matches.
|
||||
func repeated(res ...string) string {
|
||||
return group(expression(res...)) + `+`
|
||||
}
|
||||
|
||||
// group wraps the regexp in a non-capturing group.
|
||||
func group(res ...string) string {
|
||||
return `(?:` + expression(res...) + `)`
|
||||
}
|
||||
|
||||
// capture wraps the expression in a capturing group.
|
||||
func capture(res ...string) string {
|
||||
return `(` + expression(res...) + `)`
|
||||
}
|
||||
|
||||
// anchored anchors the regular expression by adding start and end delimiters.
|
||||
func anchored(res ...string) string {
|
||||
return `^` + expression(res...) + `$`
|
||||
}
|
73
vendor/github.com/containerd/containerd/reference/docker/sort.go
generated
vendored
Normal file
73
vendor/github.com/containerd/containerd/reference/docker/sort.go
generated
vendored
Normal file
@ -0,0 +1,73 @@
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package docker
|
||||
|
||||
import (
|
||||
"sort"
|
||||
)
|
||||
|
||||
// Sort sorts string references preferring higher information references
|
||||
// The precedence is as follows:
|
||||
// 1. Name + Tag + Digest
|
||||
// 2. Name + Tag
|
||||
// 3. Name + Digest
|
||||
// 4. Name
|
||||
// 5. Digest
|
||||
// 6. Parse error
|
||||
func Sort(references []string) []string {
|
||||
var prefs []Reference
|
||||
var bad []string
|
||||
|
||||
for _, ref := range references {
|
||||
pref, err := ParseAnyReference(ref)
|
||||
if err != nil {
|
||||
bad = append(bad, ref)
|
||||
} else {
|
||||
prefs = append(prefs, pref)
|
||||
}
|
||||
}
|
||||
sort.Slice(prefs, func(a, b int) bool {
|
||||
ar := refRank(prefs[a])
|
||||
br := refRank(prefs[b])
|
||||
if ar == br {
|
||||
return prefs[a].String() < prefs[b].String()
|
||||
}
|
||||
return ar < br
|
||||
})
|
||||
sort.Strings(bad)
|
||||
var refs []string
|
||||
for _, pref := range prefs {
|
||||
refs = append(refs, pref.String())
|
||||
}
|
||||
return append(refs, bad...)
|
||||
}
|
||||
|
||||
func refRank(ref Reference) uint8 {
|
||||
if _, ok := ref.(Named); ok {
|
||||
if _, ok = ref.(Tagged); ok {
|
||||
if _, ok = ref.(Digested); ok {
|
||||
return 1
|
||||
}
|
||||
return 2
|
||||
}
|
||||
if _, ok = ref.(Digested); ok {
|
||||
return 3
|
||||
}
|
||||
return 4
|
||||
}
|
||||
return 5
|
||||
}
|
9
vendor/github.com/containerd/containerd/remotes/docker/auth/fetch.go
generated
vendored
9
vendor/github.com/containerd/containerd/remotes/docker/auth/fetch.go
generated
vendored
@ -29,7 +29,6 @@ import (
|
||||
"github.com/containerd/containerd/log"
|
||||
remoteserrors "github.com/containerd/containerd/remotes/errors"
|
||||
"github.com/containerd/containerd/version"
|
||||
"golang.org/x/net/context/ctxhttp"
|
||||
)
|
||||
|
||||
var (
|
||||
@ -115,7 +114,7 @@ func FetchTokenWithOAuth(ctx context.Context, client *http.Client, headers http.
|
||||
form.Set("access_type", "offline")
|
||||
}
|
||||
|
||||
req, err := http.NewRequest("POST", to.Realm, strings.NewReader(form.Encode()))
|
||||
req, err := http.NewRequestWithContext(ctx, "POST", to.Realm, strings.NewReader(form.Encode()))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -127,7 +126,7 @@ func FetchTokenWithOAuth(ctx context.Context, client *http.Client, headers http.
|
||||
req.Header.Set("User-Agent", "containerd/"+version.Version)
|
||||
}
|
||||
|
||||
resp, err := ctxhttp.Do(ctx, client, req)
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -162,7 +161,7 @@ type FetchTokenResponse struct {
|
||||
|
||||
// FetchToken fetches a token using a GET request
|
||||
func FetchToken(ctx context.Context, client *http.Client, headers http.Header, to TokenOptions) (*FetchTokenResponse, error) {
|
||||
req, err := http.NewRequest("GET", to.Realm, nil)
|
||||
req, err := http.NewRequestWithContext(ctx, "GET", to.Realm, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -194,7 +193,7 @@ func FetchToken(ctx context.Context, client *http.Client, headers http.Header, t
|
||||
|
||||
req.URL.RawQuery = reqParams.Encode()
|
||||
|
||||
resp, err := ctxhttp.Do(ctx, client, req)
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
7
vendor/github.com/containerd/containerd/remotes/docker/authorizer.go
generated
vendored
7
vendor/github.com/containerd/containerd/remotes/docker/authorizer.go
generated
vendored
@ -45,13 +45,6 @@ type dockerAuthorizer struct {
|
||||
onFetchRefreshToken OnFetchRefreshToken
|
||||
}
|
||||
|
||||
// NewAuthorizer creates a Docker authorizer using the provided function to
|
||||
// get credentials for the token server or basic auth.
|
||||
// Deprecated: Use NewDockerAuthorizer
|
||||
func NewAuthorizer(client *http.Client, f func(string) (string, string, error)) Authorizer {
|
||||
return NewDockerAuthorizer(WithAuthClient(client), WithAuthCreds(f))
|
||||
}
|
||||
|
||||
type authorizerConfig struct {
|
||||
credentials func(string) (string, string, error)
|
||||
client *http.Client
|
||||
|
55
vendor/github.com/containerd/containerd/remotes/docker/converter_fuzz.go
generated
vendored
Normal file
55
vendor/github.com/containerd/containerd/remotes/docker/converter_fuzz.go
generated
vendored
Normal file
@ -0,0 +1,55 @@
|
||||
//go:build gofuzz
|
||||
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package docker
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
|
||||
fuzz "github.com/AdaLogics/go-fuzz-headers"
|
||||
"github.com/containerd/containerd/content/local"
|
||||
"github.com/containerd/containerd/log"
|
||||
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
func FuzzConvertManifest(data []byte) int {
|
||||
ctx := context.Background()
|
||||
|
||||
// Do not log the message below
|
||||
// level=warning msg="do nothing for media type: ..."
|
||||
log.G(ctx).Logger.SetLevel(logrus.PanicLevel)
|
||||
|
||||
f := fuzz.NewConsumer(data)
|
||||
desc := ocispec.Descriptor{}
|
||||
err := f.GenerateStruct(&desc)
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
tmpdir, err := os.MkdirTemp("", "fuzzing-")
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
cs, err := local.NewStore(tmpdir)
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
_, _ = ConvertManifest(ctx, cs, desc)
|
||||
return 1
|
||||
}
|
108
vendor/github.com/containerd/containerd/remotes/docker/fetcher.go
generated
vendored
108
vendor/github.com/containerd/containerd/remotes/docker/fetcher.go
generated
vendored
@ -29,6 +29,7 @@ import (
|
||||
"github.com/containerd/containerd/errdefs"
|
||||
"github.com/containerd/containerd/images"
|
||||
"github.com/containerd/containerd/log"
|
||||
digest "github.com/opencontainers/go-digest"
|
||||
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
)
|
||||
|
||||
@ -52,18 +53,17 @@ func (r dockerFetcher) Fetch(ctx context.Context, desc ocispec.Descriptor) (io.R
|
||||
return newHTTPReadSeeker(desc.Size, func(offset int64) (io.ReadCloser, error) {
|
||||
// firstly try fetch via external urls
|
||||
for _, us := range desc.URLs {
|
||||
ctx = log.WithLogger(ctx, log.G(ctx).WithField("url", us))
|
||||
|
||||
u, err := url.Parse(us)
|
||||
if err != nil {
|
||||
log.G(ctx).WithError(err).Debug("failed to parse")
|
||||
log.G(ctx).WithError(err).Debugf("failed to parse %q", us)
|
||||
continue
|
||||
}
|
||||
if u.Scheme != "http" && u.Scheme != "https" {
|
||||
log.G(ctx).Debug("non-http(s) alternative url is unsupported")
|
||||
continue
|
||||
}
|
||||
log.G(ctx).Debug("trying alternative url")
|
||||
ctx = log.WithLogger(ctx, log.G(ctx).WithField("url", u))
|
||||
log.G(ctx).Info("request")
|
||||
|
||||
// Try this first, parse it
|
||||
host := RegistryHost{
|
||||
@ -151,8 +151,106 @@ func (r dockerFetcher) Fetch(ctx context.Context, desc ocispec.Descriptor) (io.R
|
||||
})
|
||||
}
|
||||
|
||||
func (r dockerFetcher) createGetReq(ctx context.Context, host RegistryHost, ps ...string) (*request, int64, error) {
|
||||
headReq := r.request(host, http.MethodHead, ps...)
|
||||
if err := headReq.addNamespace(r.refspec.Hostname()); err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
headResp, err := headReq.doWithRetries(ctx, nil)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
if headResp.Body != nil {
|
||||
headResp.Body.Close()
|
||||
}
|
||||
if headResp.StatusCode > 299 {
|
||||
return nil, 0, fmt.Errorf("unexpected HEAD status code %v: %s", headReq.String(), headResp.Status)
|
||||
}
|
||||
|
||||
getReq := r.request(host, http.MethodGet, ps...)
|
||||
if err := getReq.addNamespace(r.refspec.Hostname()); err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
return getReq, headResp.ContentLength, nil
|
||||
}
|
||||
|
||||
func (r dockerFetcher) FetchByDigest(ctx context.Context, dgst digest.Digest) (io.ReadCloser, ocispec.Descriptor, error) {
|
||||
var desc ocispec.Descriptor
|
||||
ctx = log.WithLogger(ctx, log.G(ctx).WithField("digest", dgst))
|
||||
|
||||
hosts := r.filterHosts(HostCapabilityPull)
|
||||
if len(hosts) == 0 {
|
||||
return nil, desc, fmt.Errorf("no pull hosts: %w", errdefs.ErrNotFound)
|
||||
}
|
||||
|
||||
ctx, err := ContextWithRepositoryScope(ctx, r.refspec, false)
|
||||
if err != nil {
|
||||
return nil, desc, err
|
||||
}
|
||||
|
||||
var (
|
||||
getReq *request
|
||||
sz int64
|
||||
firstErr error
|
||||
)
|
||||
|
||||
for _, host := range r.hosts {
|
||||
getReq, sz, err = r.createGetReq(ctx, host, "blobs", dgst.String())
|
||||
if err == nil {
|
||||
break
|
||||
}
|
||||
// Store the error for referencing later
|
||||
if firstErr == nil {
|
||||
firstErr = err
|
||||
}
|
||||
}
|
||||
|
||||
if getReq == nil {
|
||||
// Fall back to the "manifests" endpoint
|
||||
for _, host := range r.hosts {
|
||||
getReq, sz, err = r.createGetReq(ctx, host, "manifests", dgst.String())
|
||||
if err == nil {
|
||||
break
|
||||
}
|
||||
// Store the error for referencing later
|
||||
if firstErr == nil {
|
||||
firstErr = err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if getReq == nil {
|
||||
if errdefs.IsNotFound(firstErr) {
|
||||
firstErr = fmt.Errorf("could not fetch content %v from remote: %w", dgst, errdefs.ErrNotFound)
|
||||
}
|
||||
if firstErr == nil {
|
||||
firstErr = fmt.Errorf("could not fetch content %v from remote: (unknown)", dgst)
|
||||
}
|
||||
return nil, desc, firstErr
|
||||
}
|
||||
|
||||
seeker, err := newHTTPReadSeeker(sz, func(offset int64) (io.ReadCloser, error) {
|
||||
return r.open(ctx, getReq, "", offset)
|
||||
})
|
||||
if err != nil {
|
||||
return nil, desc, err
|
||||
}
|
||||
|
||||
desc = ocispec.Descriptor{
|
||||
MediaType: "application/octet-stream",
|
||||
Digest: dgst,
|
||||
Size: sz,
|
||||
}
|
||||
return seeker, desc, nil
|
||||
}
|
||||
|
||||
func (r dockerFetcher) open(ctx context.Context, req *request, mediatype string, offset int64) (_ io.ReadCloser, retErr error) {
|
||||
req.header.Set("Accept", strings.Join([]string{mediatype, `*/*`}, ", "))
|
||||
if mediatype == "" {
|
||||
req.header.Set("Accept", "*/*")
|
||||
} else {
|
||||
req.header.Set("Accept", strings.Join([]string{mediatype, `*/*`}, ", "))
|
||||
}
|
||||
|
||||
if offset > 0 {
|
||||
// Note: "Accept-Ranges: bytes" cannot be trusted as some endpoints
|
||||
|
81
vendor/github.com/containerd/containerd/remotes/docker/fetcher_fuzz.go
generated
vendored
Normal file
81
vendor/github.com/containerd/containerd/remotes/docker/fetcher_fuzz.go
generated
vendored
Normal file
@ -0,0 +1,81 @@
|
||||
//go:build gofuzz
|
||||
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package docker
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"net/url"
|
||||
|
||||
refDocker "github.com/containerd/containerd/reference/docker"
|
||||
)
|
||||
|
||||
func FuzzFetcher(data []byte) int {
|
||||
dataLen := len(data)
|
||||
if dataLen == 0 {
|
||||
return -1
|
||||
}
|
||||
|
||||
s := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
|
||||
rw.Header().Set("content-range", fmt.Sprintf("bytes %d-%d/%d", 0, dataLen-1, dataLen))
|
||||
rw.Header().Set("content-length", fmt.Sprintf("%d", dataLen))
|
||||
rw.Write(data)
|
||||
}))
|
||||
defer s.Close()
|
||||
|
||||
u, err := url.Parse(s.URL)
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
|
||||
f := dockerFetcher{&dockerBase{
|
||||
repository: "nonempty",
|
||||
}}
|
||||
host := RegistryHost{
|
||||
Client: s.Client(),
|
||||
Host: u.Host,
|
||||
Scheme: u.Scheme,
|
||||
Path: u.Path,
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
req := f.request(host, http.MethodGet)
|
||||
rc, err := f.open(ctx, req, "", 0)
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
b, err := io.ReadAll(rc)
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
|
||||
expected := data
|
||||
if len(b) != len(expected) {
|
||||
panic("len of request is not equal to len of expected but should be")
|
||||
}
|
||||
return 1
|
||||
}
|
||||
|
||||
func FuzzParseDockerRef(data []byte) int {
|
||||
_, _ = refDocker.ParseDockerRef(string(data))
|
||||
return 1
|
||||
}
|
3
vendor/github.com/containerd/containerd/remotes/docker/pusher.go
generated
vendored
3
vendor/github.com/containerd/containerd/remotes/docker/pusher.go
generated
vendored
@ -191,6 +191,9 @@ func (p dockerPusher) push(ctx context.Context, desc ocispec.Descriptor, ref str
|
||||
if resp == nil {
|
||||
resp, err = req.doWithRetries(ctx, nil)
|
||||
if err != nil {
|
||||
if errors.Is(err, ErrInvalidAuthorization) {
|
||||
return nil, fmt.Errorf("push access denied, repository does not exist or may require authorization: %w", err)
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
55
vendor/github.com/containerd/containerd/remotes/docker/resolver.go
generated
vendored
55
vendor/github.com/containerd/containerd/remotes/docker/resolver.go
generated
vendored
@ -32,12 +32,13 @@ import (
|
||||
"github.com/containerd/containerd/log"
|
||||
"github.com/containerd/containerd/reference"
|
||||
"github.com/containerd/containerd/remotes"
|
||||
"github.com/containerd/containerd/remotes/docker/schema1"
|
||||
"github.com/containerd/containerd/remotes/docker/schema1" //nolint:staticcheck // Ignore SA1019. Need to keep deprecated package for compatibility.
|
||||
remoteerrors "github.com/containerd/containerd/remotes/errors"
|
||||
"github.com/containerd/containerd/tracing"
|
||||
"github.com/containerd/containerd/version"
|
||||
digest "github.com/opencontainers/go-digest"
|
||||
"github.com/opencontainers/go-digest"
|
||||
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
"github.com/sirupsen/logrus"
|
||||
"golang.org/x/net/context/ctxhttp"
|
||||
)
|
||||
|
||||
var (
|
||||
@ -70,6 +71,9 @@ type Authorizer interface {
|
||||
// unmodified. It may also add an `Authorization` header as
|
||||
// "bearer <some bearer token>"
|
||||
// "basic <base64 encoded credentials>"
|
||||
//
|
||||
// It may return remotes/errors.ErrUnexpectedStatus, which for example,
|
||||
// can be used by the caller to find out the status code returned by the registry.
|
||||
Authorize(context.Context, *http.Request) error
|
||||
|
||||
// AddResponses adds a 401 response for the authorizer to consider when
|
||||
@ -152,7 +156,8 @@ func NewResolver(options ResolverOptions) remotes.Resolver {
|
||||
images.MediaTypeDockerSchema2Manifest,
|
||||
images.MediaTypeDockerSchema2ManifestList,
|
||||
ocispec.MediaTypeImageManifest,
|
||||
ocispec.MediaTypeImageIndex, "*/*"}, ", "))
|
||||
ocispec.MediaTypeImageIndex, "*/*",
|
||||
}, ", "))
|
||||
} else {
|
||||
resolveHeader["Accept"] = options.Headers["Accept"]
|
||||
delete(options.Headers, "Accept")
|
||||
@ -299,11 +304,11 @@ func (r *dockerResolver) Resolve(ctx context.Context, ref string) (string, ocisp
|
||||
if resp.StatusCode > 399 {
|
||||
// Set firstErr when encountering the first non-404 status code.
|
||||
if firstErr == nil {
|
||||
firstErr = fmt.Errorf("pulling from host %s failed with status code %v: %v", host.Host, u, resp.Status)
|
||||
firstErr = remoteerrors.NewUnexpectedStatusErr(resp)
|
||||
}
|
||||
continue // try another host
|
||||
}
|
||||
return "", ocispec.Descriptor{}, fmt.Errorf("pulling from host %s failed with unexpected status code %v: %v", host.Host, u, resp.Status)
|
||||
return "", ocispec.Descriptor{}, remoteerrors.NewUnexpectedStatusErr(resp)
|
||||
}
|
||||
size := resp.ContentLength
|
||||
contentType := getManifestMediaType(resp)
|
||||
@ -340,26 +345,31 @@ func (r *dockerResolver) Resolve(ctx context.Context, ref string) (string, ocisp
|
||||
if err != nil {
|
||||
return "", ocispec.Descriptor{}, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
bodyReader := countingReader{reader: resp.Body}
|
||||
|
||||
contentType = getManifestMediaType(resp)
|
||||
if dgst == "" {
|
||||
err = func() error {
|
||||
defer resp.Body.Close()
|
||||
if dgst != "" {
|
||||
_, err = io.Copy(io.Discard, &bodyReader)
|
||||
return err
|
||||
}
|
||||
|
||||
if contentType == images.MediaTypeDockerSchema1Manifest {
|
||||
b, err := schema1.ReadStripSignature(&bodyReader)
|
||||
if err != nil {
|
||||
return "", ocispec.Descriptor{}, err
|
||||
return err
|
||||
}
|
||||
|
||||
dgst = digest.FromBytes(b)
|
||||
} else {
|
||||
dgst, err = digest.FromReader(&bodyReader)
|
||||
if err != nil {
|
||||
return "", ocispec.Descriptor{}, err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
} else if _, err := io.Copy(io.Discard, &bodyReader); err != nil {
|
||||
|
||||
dgst, err = digest.FromReader(&bodyReader)
|
||||
return err
|
||||
}()
|
||||
if err != nil {
|
||||
return "", ocispec.Descriptor{}, err
|
||||
}
|
||||
size = bodyReader.bytesRead
|
||||
@ -525,7 +535,7 @@ type request struct {
|
||||
|
||||
func (r *request) do(ctx context.Context) (*http.Response, error) {
|
||||
u := r.host.Scheme + "://" + r.host.Host + r.path
|
||||
req, err := http.NewRequest(r.method, u, nil)
|
||||
req, err := http.NewRequestWithContext(ctx, r.method, u, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -551,7 +561,7 @@ func (r *request) do(ctx context.Context) (*http.Response, error) {
|
||||
return nil, fmt.Errorf("failed to authorize: %w", err)
|
||||
}
|
||||
|
||||
var client = &http.Client{}
|
||||
client := &http.Client{}
|
||||
if r.host.Client != nil {
|
||||
*client = *r.host.Client
|
||||
}
|
||||
@ -566,11 +576,18 @@ func (r *request) do(ctx context.Context) (*http.Response, error) {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
resp, err := ctxhttp.Do(ctx, client, req)
|
||||
_, httpSpan := tracing.StartSpan(
|
||||
ctx,
|
||||
tracing.Name("remotes.docker.resolver", "HTTPRequest"),
|
||||
tracing.WithHTTPRequest(req),
|
||||
)
|
||||
defer httpSpan.End()
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
httpSpan.SetStatus(err)
|
||||
return nil, fmt.Errorf("failed to do request: %w", err)
|
||||
}
|
||||
httpSpan.SetAttributes(tracing.HTTPStatusCodeAttributes(resp.StatusCode)...)
|
||||
log.G(ctx).WithFields(responseFields(resp)).Debug("fetch response received")
|
||||
return resp, nil
|
||||
}
|
||||
|
12
vendor/github.com/containerd/containerd/remotes/docker/schema1/converter.go
generated
vendored
12
vendor/github.com/containerd/containerd/remotes/docker/schema1/converter.go
generated
vendored
@ -14,6 +14,9 @@
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// Package schema1 provides a converter to fetch an image formatted in Docker Image Manifest v2, Schema 1.
|
||||
//
|
||||
// Deprecated: use images formatted in Docker Image Manifest v2, Schema 2, or OCI Image Spec v1.
|
||||
package schema1
|
||||
|
||||
import (
|
||||
@ -33,6 +36,7 @@ import (
|
||||
"github.com/containerd/containerd/content"
|
||||
"github.com/containerd/containerd/errdefs"
|
||||
"github.com/containerd/containerd/images"
|
||||
"github.com/containerd/containerd/labels"
|
||||
"github.com/containerd/containerd/log"
|
||||
"github.com/containerd/containerd/remotes"
|
||||
digest "github.com/opencontainers/go-digest"
|
||||
@ -363,12 +367,12 @@ func (c *Converter) fetchBlob(ctx context.Context, desc ocispec.Descriptor) erro
|
||||
cinfo := content.Info{
|
||||
Digest: desc.Digest,
|
||||
Labels: map[string]string{
|
||||
"containerd.io/uncompressed": state.diffID.String(),
|
||||
labels.LabelUncompressed: state.diffID.String(),
|
||||
labelDockerSchema1EmptyLayer: strconv.FormatBool(state.empty),
|
||||
},
|
||||
}
|
||||
|
||||
if _, err := c.contentStore.Update(ctx, cinfo, "labels.containerd.io/uncompressed", fmt.Sprintf("labels.%s", labelDockerSchema1EmptyLayer)); err != nil {
|
||||
if _, err := c.contentStore.Update(ctx, cinfo, "labels."+labels.LabelUncompressed, fmt.Sprintf("labels.%s", labelDockerSchema1EmptyLayer)); err != nil {
|
||||
return fmt.Errorf("failed to update uncompressed label: %w", err)
|
||||
}
|
||||
|
||||
@ -387,7 +391,7 @@ func (c *Converter) reuseLabelBlobState(ctx context.Context, desc ocispec.Descri
|
||||
}
|
||||
desc.Size = cinfo.Size
|
||||
|
||||
diffID, ok := cinfo.Labels["containerd.io/uncompressed"]
|
||||
diffID, ok := cinfo.Labels[labels.LabelUncompressed]
|
||||
if !ok {
|
||||
return false, nil
|
||||
}
|
||||
@ -406,7 +410,7 @@ func (c *Converter) reuseLabelBlobState(ctx context.Context, desc ocispec.Descri
|
||||
bState := blobState{empty: isEmpty}
|
||||
|
||||
if bState.diffID, err = digest.Parse(diffID); err != nil {
|
||||
log.G(ctx).WithField("id", desc.Digest).Warnf("failed to parse digest from label containerd.io/uncompressed: %v", diffID)
|
||||
log.G(ctx).WithField("id", desc.Digest).Warnf("failed to parse digest from label %s: %v", labels.LabelUncompressed, diffID)
|
||||
return false, nil
|
||||
}
|
||||
|
||||
|
2
vendor/github.com/containerd/containerd/remotes/errors/errors.go
generated
vendored
2
vendor/github.com/containerd/containerd/remotes/errors/errors.go
generated
vendored
@ -33,7 +33,7 @@ type ErrUnexpectedStatus struct {
|
||||
}
|
||||
|
||||
func (e ErrUnexpectedStatus) Error() string {
|
||||
return fmt.Sprintf("unexpected status: %s", e.Status)
|
||||
return fmt.Sprintf("unexpected status from %s request to %s: %s", e.RequestMethod, e.RequestURL, e.Status)
|
||||
}
|
||||
|
||||
// NewUnexpectedStatusErr creates an ErrUnexpectedStatus from HTTP response
|
||||
|
56
vendor/github.com/containerd/containerd/remotes/handlers.go
generated
vendored
56
vendor/github.com/containerd/containerd/remotes/handlers.go
generated
vendored
@ -100,20 +100,21 @@ func FetchHandler(ingester content.Ingester, fetcher Fetcher) images.HandlerFunc
|
||||
case images.MediaTypeDockerSchema1Manifest:
|
||||
return nil, fmt.Errorf("%v not supported", desc.MediaType)
|
||||
default:
|
||||
err := fetch(ctx, ingester, fetcher, desc)
|
||||
err := Fetch(ctx, ingester, fetcher, desc)
|
||||
if errdefs.IsAlreadyExists(err) {
|
||||
return nil, nil
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func fetch(ctx context.Context, ingester content.Ingester, fetcher Fetcher, desc ocispec.Descriptor) error {
|
||||
// Fetch fetches the given digest into the provided ingester
|
||||
func Fetch(ctx context.Context, ingester content.Ingester, fetcher Fetcher, desc ocispec.Descriptor) error {
|
||||
log.G(ctx).Debug("fetch")
|
||||
|
||||
cw, err := content.OpenWriter(ctx, ingester, content.WithRef(MakeRefKey(ctx, desc)), content.WithDescriptor(desc))
|
||||
if err != nil {
|
||||
if errdefs.IsAlreadyExists(err) {
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
}
|
||||
defer cw.Close()
|
||||
@ -135,7 +136,7 @@ func fetch(ctx context.Context, ingester content.Ingester, fetcher Fetcher, desc
|
||||
if err != nil && !errdefs.IsAlreadyExists(err) {
|
||||
return fmt.Errorf("failed commit on ref %q: %w", ws.Ref, err)
|
||||
}
|
||||
return nil
|
||||
return err
|
||||
}
|
||||
|
||||
rc, err := fetcher.Fetch(ctx, desc)
|
||||
@ -197,17 +198,25 @@ func push(ctx context.Context, provider content.Provider, pusher Pusher, desc oc
|
||||
//
|
||||
// Base handlers can be provided which will be called before any push specific
|
||||
// handlers.
|
||||
func PushContent(ctx context.Context, pusher Pusher, desc ocispec.Descriptor, store content.Store, limiter *semaphore.Weighted, platform platforms.MatchComparer, wrapper func(h images.Handler) images.Handler) error {
|
||||
//
|
||||
// If the passed in content.Provider is also a content.Manager then this will
|
||||
// also annotate the distribution sources in the manager.
|
||||
func PushContent(ctx context.Context, pusher Pusher, desc ocispec.Descriptor, store content.Provider, limiter *semaphore.Weighted, platform platforms.MatchComparer, wrapper func(h images.Handler) images.Handler) error {
|
||||
|
||||
var m sync.Mutex
|
||||
manifestStack := []ocispec.Descriptor{}
|
||||
manifests := []ocispec.Descriptor{}
|
||||
indexStack := []ocispec.Descriptor{}
|
||||
|
||||
filterHandler := images.HandlerFunc(func(ctx context.Context, desc ocispec.Descriptor) ([]ocispec.Descriptor, error) {
|
||||
switch desc.MediaType {
|
||||
case images.MediaTypeDockerSchema2Manifest, ocispec.MediaTypeImageManifest,
|
||||
images.MediaTypeDockerSchema2ManifestList, ocispec.MediaTypeImageIndex:
|
||||
case images.MediaTypeDockerSchema2Manifest, ocispec.MediaTypeImageManifest:
|
||||
m.Lock()
|
||||
manifestStack = append(manifestStack, desc)
|
||||
manifests = append(manifests, desc)
|
||||
m.Unlock()
|
||||
return nil, images.ErrStopHandler
|
||||
case images.MediaTypeDockerSchema2ManifestList, ocispec.MediaTypeImageIndex:
|
||||
m.Lock()
|
||||
indexStack = append(indexStack, desc)
|
||||
m.Unlock()
|
||||
return nil, images.ErrStopHandler
|
||||
default:
|
||||
@ -219,13 +228,14 @@ func PushContent(ctx context.Context, pusher Pusher, desc ocispec.Descriptor, st
|
||||
|
||||
platformFilterhandler := images.FilterPlatforms(images.ChildrenHandler(store), platform)
|
||||
|
||||
annotateHandler := annotateDistributionSourceHandler(platformFilterhandler, store)
|
||||
var handler images.Handler
|
||||
if m, ok := store.(content.Manager); ok {
|
||||
annotateHandler := annotateDistributionSourceHandler(platformFilterhandler, m)
|
||||
handler = images.Handlers(annotateHandler, filterHandler, pushHandler)
|
||||
} else {
|
||||
handler = images.Handlers(platformFilterhandler, filterHandler, pushHandler)
|
||||
}
|
||||
|
||||
var handler images.Handler = images.Handlers(
|
||||
annotateHandler,
|
||||
filterHandler,
|
||||
pushHandler,
|
||||
)
|
||||
if wrapper != nil {
|
||||
handler = wrapper(handler)
|
||||
}
|
||||
@ -234,16 +244,18 @@ func PushContent(ctx context.Context, pusher Pusher, desc ocispec.Descriptor, st
|
||||
return err
|
||||
}
|
||||
|
||||
if err := images.Dispatch(ctx, pushHandler, limiter, manifests...); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Iterate in reverse order as seen, parent always uploaded after child
|
||||
for i := len(manifestStack) - 1; i >= 0; i-- {
|
||||
_, err := pushHandler(ctx, manifestStack[i])
|
||||
for i := len(indexStack) - 1; i >= 0; i-- {
|
||||
err := images.Dispatch(ctx, pushHandler, limiter, indexStack[i])
|
||||
if err != nil {
|
||||
// TODO(estesp): until we have a more complete method for index push, we need to report
|
||||
// missing dependencies in an index/manifest list by sensing the "400 Bad Request"
|
||||
// as a marker for this problem
|
||||
if (manifestStack[i].MediaType == ocispec.MediaTypeImageIndex ||
|
||||
manifestStack[i].MediaType == images.MediaTypeDockerSchema2ManifestList) &&
|
||||
errors.Unwrap(err) != nil && strings.Contains(errors.Unwrap(err).Error(), "400 Bad Request") {
|
||||
if errors.Unwrap(err) != nil && strings.Contains(errors.Unwrap(err).Error(), "400 Bad Request") {
|
||||
return fmt.Errorf("manifest list/index references to blobs and/or manifests are missing in your target registry: %w", err)
|
||||
}
|
||||
return err
|
||||
|
14
vendor/github.com/containerd/containerd/remotes/resolver.go
generated
vendored
14
vendor/github.com/containerd/containerd/remotes/resolver.go
generated
vendored
@ -21,6 +21,7 @@ import (
|
||||
"io"
|
||||
|
||||
"github.com/containerd/containerd/content"
|
||||
"github.com/opencontainers/go-digest"
|
||||
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
)
|
||||
|
||||
@ -50,12 +51,23 @@ type Resolver interface {
|
||||
Pusher(ctx context.Context, ref string) (Pusher, error)
|
||||
}
|
||||
|
||||
// Fetcher fetches content
|
||||
// Fetcher fetches content.
|
||||
// A fetcher implementation may implement the FetcherByDigest interface too.
|
||||
type Fetcher interface {
|
||||
// Fetch the resource identified by the descriptor.
|
||||
Fetch(ctx context.Context, desc ocispec.Descriptor) (io.ReadCloser, error)
|
||||
}
|
||||
|
||||
// FetcherByDigest fetches content by the digest.
|
||||
type FetcherByDigest interface {
|
||||
// FetchByDigest fetches the resource identified by the digest.
|
||||
//
|
||||
// FetcherByDigest usually returns an incomplete descriptor.
|
||||
// Typically, the media type is always set to "application/octet-stream",
|
||||
// and the annotations are unset.
|
||||
FetchByDigest(ctx context.Context, dgst digest.Digest) (io.ReadCloser, ocispec.Descriptor, error)
|
||||
}
|
||||
|
||||
// Pusher pushes content
|
||||
type Pusher interface {
|
||||
// Push returns a content writer for the given resource identified
|
||||
|
101
vendor/github.com/containerd/containerd/services/content/contentserver/contentserver.go
generated
vendored
101
vendor/github.com/containerd/containerd/services/content/contentserver/contentserver.go
generated
vendored
@ -26,7 +26,8 @@ import (
|
||||
"github.com/containerd/containerd/content"
|
||||
"github.com/containerd/containerd/errdefs"
|
||||
"github.com/containerd/containerd/log"
|
||||
ptypes "github.com/gogo/protobuf/types"
|
||||
"github.com/containerd/containerd/protobuf"
|
||||
ptypes "github.com/containerd/containerd/protobuf/types"
|
||||
digest "github.com/opencontainers/go-digest"
|
||||
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
"github.com/sirupsen/logrus"
|
||||
@ -37,6 +38,7 @@ import (
|
||||
|
||||
type service struct {
|
||||
store content.Store
|
||||
api.UnimplementedContentServer
|
||||
}
|
||||
|
||||
var bufPool = sync.Pool{
|
||||
@ -57,11 +59,12 @@ func (s *service) Register(server *grpc.Server) error {
|
||||
}
|
||||
|
||||
func (s *service) Info(ctx context.Context, req *api.InfoRequest) (*api.InfoResponse, error) {
|
||||
if err := req.Digest.Validate(); err != nil {
|
||||
dg, err := digest.Parse(req.Digest)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.InvalidArgument, "%q failed validation", req.Digest)
|
||||
}
|
||||
|
||||
bi, err := s.store.Info(ctx, req.Digest)
|
||||
bi, err := s.store.Info(ctx, dg)
|
||||
if err != nil {
|
||||
return nil, errdefs.ToGRPC(err)
|
||||
}
|
||||
@ -72,7 +75,8 @@ func (s *service) Info(ctx context.Context, req *api.InfoRequest) (*api.InfoResp
|
||||
}
|
||||
|
||||
func (s *service) Update(ctx context.Context, req *api.UpdateRequest) (*api.UpdateResponse, error) {
|
||||
if err := req.Info.Digest.Validate(); err != nil {
|
||||
_, err := digest.Parse(req.Info.Digest)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.InvalidArgument, "%q failed validation", req.Info.Digest)
|
||||
}
|
||||
|
||||
@ -88,8 +92,8 @@ func (s *service) Update(ctx context.Context, req *api.UpdateRequest) (*api.Upda
|
||||
|
||||
func (s *service) List(req *api.ListContentRequest, session api.Content_ListServer) error {
|
||||
var (
|
||||
buffer []api.Info
|
||||
sendBlock = func(block []api.Info) error {
|
||||
buffer []*api.Info
|
||||
sendBlock = func(block []*api.Info) error {
|
||||
// send last block
|
||||
return session.Send(&api.ListContentResponse{
|
||||
Info: block,
|
||||
@ -98,10 +102,10 @@ func (s *service) List(req *api.ListContentRequest, session api.Content_ListServ
|
||||
)
|
||||
|
||||
if err := s.store.Walk(session.Context(), func(info content.Info) error {
|
||||
buffer = append(buffer, api.Info{
|
||||
Digest: info.Digest,
|
||||
Size_: info.Size,
|
||||
CreatedAt: info.CreatedAt,
|
||||
buffer = append(buffer, &api.Info{
|
||||
Digest: info.Digest.String(),
|
||||
Size: info.Size,
|
||||
CreatedAt: protobuf.ToTimestamp(info.CreatedAt),
|
||||
Labels: info.Labels,
|
||||
})
|
||||
|
||||
@ -130,11 +134,12 @@ func (s *service) List(req *api.ListContentRequest, session api.Content_ListServ
|
||||
|
||||
func (s *service) Delete(ctx context.Context, req *api.DeleteContentRequest) (*ptypes.Empty, error) {
|
||||
log.G(ctx).WithField("digest", req.Digest).Debugf("delete content")
|
||||
if err := req.Digest.Validate(); err != nil {
|
||||
dg, err := digest.Parse(req.Digest)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.InvalidArgument, err.Error())
|
||||
}
|
||||
|
||||
if err := s.store.Delete(ctx, req.Digest); err != nil {
|
||||
if err := s.store.Delete(ctx, dg); err != nil {
|
||||
return nil, errdefs.ToGRPC(err)
|
||||
}
|
||||
|
||||
@ -142,16 +147,17 @@ func (s *service) Delete(ctx context.Context, req *api.DeleteContentRequest) (*p
|
||||
}
|
||||
|
||||
func (s *service) Read(req *api.ReadContentRequest, session api.Content_ReadServer) error {
|
||||
if err := req.Digest.Validate(); err != nil {
|
||||
dg, err := digest.Parse(req.Digest)
|
||||
if err != nil {
|
||||
return status.Errorf(codes.InvalidArgument, "%v: %v", req.Digest, err)
|
||||
}
|
||||
|
||||
oi, err := s.store.Info(session.Context(), req.Digest)
|
||||
oi, err := s.store.Info(session.Context(), dg)
|
||||
if err != nil {
|
||||
return errdefs.ToGRPC(err)
|
||||
}
|
||||
|
||||
ra, err := s.store.ReaderAt(session.Context(), ocispec.Descriptor{Digest: req.Digest})
|
||||
ra, err := s.store.ReaderAt(session.Context(), ocispec.Descriptor{Digest: dg})
|
||||
if err != nil {
|
||||
return errdefs.ToGRPC(err)
|
||||
}
|
||||
@ -161,7 +167,7 @@ func (s *service) Read(req *api.ReadContentRequest, session api.Content_ReadServ
|
||||
offset = req.Offset
|
||||
// size is read size, not the expected size of the blob (oi.Size), which the caller might not be aware of.
|
||||
// offset+size can be larger than oi.Size.
|
||||
size = req.Size_
|
||||
size = req.Size
|
||||
|
||||
// TODO(stevvooe): Using the global buffer pool. At 32KB, it is probably
|
||||
// little inefficient for work over a fast network. We can tune this later.
|
||||
@ -216,12 +222,12 @@ func (s *service) Status(ctx context.Context, req *api.StatusRequest) (*api.Stat
|
||||
|
||||
var resp api.StatusResponse
|
||||
resp.Status = &api.Status{
|
||||
StartedAt: status.StartedAt,
|
||||
UpdatedAt: status.UpdatedAt,
|
||||
StartedAt: protobuf.ToTimestamp(status.StartedAt),
|
||||
UpdatedAt: protobuf.ToTimestamp(status.UpdatedAt),
|
||||
Ref: status.Ref,
|
||||
Offset: status.Offset,
|
||||
Total: status.Total,
|
||||
Expected: status.Expected,
|
||||
Expected: status.Expected.String(),
|
||||
}
|
||||
|
||||
return &resp, nil
|
||||
@ -235,13 +241,13 @@ func (s *service) ListStatuses(ctx context.Context, req *api.ListStatusesRequest
|
||||
|
||||
var resp api.ListStatusesResponse
|
||||
for _, status := range statuses {
|
||||
resp.Statuses = append(resp.Statuses, api.Status{
|
||||
StartedAt: status.StartedAt,
|
||||
UpdatedAt: status.UpdatedAt,
|
||||
resp.Statuses = append(resp.Statuses, &api.Status{
|
||||
StartedAt: protobuf.ToTimestamp(status.StartedAt),
|
||||
UpdatedAt: protobuf.ToTimestamp(status.UpdatedAt),
|
||||
Ref: status.Ref,
|
||||
Offset: status.Offset,
|
||||
Total: status.Total,
|
||||
Expected: status.Expected,
|
||||
Expected: status.Expected.String(),
|
||||
})
|
||||
}
|
||||
|
||||
@ -293,7 +299,7 @@ func (s *service) Write(session api.Content_WriteServer) (err error) {
|
||||
"ref": ref,
|
||||
}
|
||||
total = req.Total
|
||||
expected = req.Expected
|
||||
expected = digest.Digest(req.Expected)
|
||||
if total > 0 {
|
||||
fields["total"] = total
|
||||
}
|
||||
@ -341,12 +347,13 @@ func (s *service) Write(session api.Content_WriteServer) (err error) {
|
||||
// Supporting these two paths is quite awkward but it lets both API
|
||||
// users use the same writer style for each with a minimum of overhead.
|
||||
if req.Expected != "" {
|
||||
if expected != "" && expected != req.Expected {
|
||||
log.G(ctx).Debugf("commit digest differs from writer digest: %v != %v", req.Expected, expected)
|
||||
dg := digest.Digest(req.Expected)
|
||||
if expected != "" && expected != dg {
|
||||
log.G(ctx).Debugf("commit digest differs from writer digest: %v != %v", dg, expected)
|
||||
}
|
||||
expected = req.Expected
|
||||
expected = dg
|
||||
|
||||
if _, err := s.store.Info(session.Context(), req.Expected); err == nil {
|
||||
if _, err := s.store.Info(session.Context(), dg); err == nil {
|
||||
if err := wr.Close(); err != nil {
|
||||
log.G(ctx).WithError(err).Error("failed to close writer")
|
||||
}
|
||||
@ -368,12 +375,12 @@ func (s *service) Write(session api.Content_WriteServer) (err error) {
|
||||
}
|
||||
|
||||
switch req.Action {
|
||||
case api.WriteActionStat:
|
||||
msg.Digest = wr.Digest()
|
||||
msg.StartedAt = ws.StartedAt
|
||||
msg.UpdatedAt = ws.UpdatedAt
|
||||
case api.WriteAction_STAT:
|
||||
msg.Digest = wr.Digest().String()
|
||||
msg.StartedAt = protobuf.ToTimestamp(ws.StartedAt)
|
||||
msg.UpdatedAt = protobuf.ToTimestamp(ws.UpdatedAt)
|
||||
msg.Total = total
|
||||
case api.WriteActionWrite, api.WriteActionCommit:
|
||||
case api.WriteAction_WRITE, api.WriteAction_COMMIT:
|
||||
if req.Offset > 0 {
|
||||
// validate the offset if provided
|
||||
if req.Offset != ws.Offset {
|
||||
@ -406,7 +413,7 @@ func (s *service) Write(session api.Content_WriteServer) (err error) {
|
||||
msg.Offset += int64(n)
|
||||
}
|
||||
|
||||
if req.Action == api.WriteActionCommit {
|
||||
if req.Action == api.WriteAction_COMMIT {
|
||||
var opts []content.Opt
|
||||
if req.Labels != nil {
|
||||
opts = append(opts, content.WithLabels(req.Labels))
|
||||
@ -416,14 +423,14 @@ func (s *service) Write(session api.Content_WriteServer) (err error) {
|
||||
}
|
||||
}
|
||||
|
||||
msg.Digest = wr.Digest()
|
||||
msg.Digest = wr.Digest().String()
|
||||
}
|
||||
|
||||
if err := session.Send(&msg); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if req.Action == api.WriteActionCommit {
|
||||
if req.Action == api.WriteAction_COMMIT {
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -446,22 +453,22 @@ func (s *service) Abort(ctx context.Context, req *api.AbortRequest) (*ptypes.Emp
|
||||
return &ptypes.Empty{}, nil
|
||||
}
|
||||
|
||||
func infoToGRPC(info content.Info) api.Info {
|
||||
return api.Info{
|
||||
Digest: info.Digest,
|
||||
Size_: info.Size,
|
||||
CreatedAt: info.CreatedAt,
|
||||
UpdatedAt: info.UpdatedAt,
|
||||
func infoToGRPC(info content.Info) *api.Info {
|
||||
return &api.Info{
|
||||
Digest: info.Digest.String(),
|
||||
Size: info.Size,
|
||||
CreatedAt: protobuf.ToTimestamp(info.CreatedAt),
|
||||
UpdatedAt: protobuf.ToTimestamp(info.UpdatedAt),
|
||||
Labels: info.Labels,
|
||||
}
|
||||
}
|
||||
|
||||
func infoFromGRPC(info api.Info) content.Info {
|
||||
func infoFromGRPC(info *api.Info) content.Info {
|
||||
return content.Info{
|
||||
Digest: info.Digest,
|
||||
Size: info.Size_,
|
||||
CreatedAt: info.CreatedAt,
|
||||
UpdatedAt: info.UpdatedAt,
|
||||
Digest: digest.Digest(info.Digest),
|
||||
Size: info.Size,
|
||||
CreatedAt: protobuf.FromTimestamp(info.CreatedAt),
|
||||
UpdatedAt: protobuf.FromTimestamp(info.UpdatedAt),
|
||||
Labels: info.Labels,
|
||||
}
|
||||
}
|
||||
|
94
vendor/github.com/containerd/containerd/tracing/helpers.go
generated
vendored
Normal file
94
vendor/github.com/containerd/containerd/tracing/helpers.go
generated
vendored
Normal file
@ -0,0 +1,94 @@
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package tracing
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
)
|
||||
|
||||
const (
|
||||
spanDelimiter = "."
|
||||
)
|
||||
|
||||
func makeSpanName(names ...string) string {
|
||||
return strings.Join(names, spanDelimiter)
|
||||
}
|
||||
|
||||
func any(k string, v interface{}) attribute.KeyValue {
|
||||
if v == nil {
|
||||
return attribute.String(k, "<nil>")
|
||||
}
|
||||
|
||||
switch typed := v.(type) {
|
||||
case bool:
|
||||
return attribute.Bool(k, typed)
|
||||
case []bool:
|
||||
return attribute.BoolSlice(k, typed)
|
||||
case int:
|
||||
return attribute.Int(k, typed)
|
||||
case []int:
|
||||
return attribute.IntSlice(k, typed)
|
||||
case int8:
|
||||
return attribute.Int(k, int(typed))
|
||||
case []int8:
|
||||
ls := make([]int, 0, len(typed))
|
||||
for _, i := range typed {
|
||||
ls = append(ls, int(i))
|
||||
}
|
||||
return attribute.IntSlice(k, ls)
|
||||
case int16:
|
||||
return attribute.Int(k, int(typed))
|
||||
case []int16:
|
||||
ls := make([]int, 0, len(typed))
|
||||
for _, i := range typed {
|
||||
ls = append(ls, int(i))
|
||||
}
|
||||
return attribute.IntSlice(k, ls)
|
||||
case int32:
|
||||
return attribute.Int64(k, int64(typed))
|
||||
case []int32:
|
||||
ls := make([]int64, 0, len(typed))
|
||||
for _, i := range typed {
|
||||
ls = append(ls, int64(i))
|
||||
}
|
||||
return attribute.Int64Slice(k, ls)
|
||||
case int64:
|
||||
return attribute.Int64(k, typed)
|
||||
case []int64:
|
||||
return attribute.Int64Slice(k, typed)
|
||||
case float64:
|
||||
return attribute.Float64(k, typed)
|
||||
case []float64:
|
||||
return attribute.Float64Slice(k, typed)
|
||||
case string:
|
||||
return attribute.String(k, typed)
|
||||
case []string:
|
||||
return attribute.StringSlice(k, typed)
|
||||
}
|
||||
|
||||
if stringer, ok := v.(fmt.Stringer); ok {
|
||||
return attribute.String(k, stringer.String())
|
||||
}
|
||||
if b, err := json.Marshal(v); b != nil && err == nil {
|
||||
return attribute.String(k, string(b))
|
||||
}
|
||||
return attribute.String(k, fmt.Sprintf("%v", v))
|
||||
}
|
66
vendor/github.com/containerd/containerd/tracing/log.go
generated
vendored
Normal file
66
vendor/github.com/containerd/containerd/tracing/log.go
generated
vendored
Normal file
@ -0,0 +1,66 @@
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package tracing
|
||||
|
||||
import (
|
||||
"github.com/sirupsen/logrus"
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
"go.opentelemetry.io/otel/trace"
|
||||
)
|
||||
|
||||
// NewLogrusHook creates a new logrus hook
|
||||
func NewLogrusHook() *LogrusHook {
|
||||
return &LogrusHook{}
|
||||
}
|
||||
|
||||
// LogrusHook is a logrus hook which adds logrus events to active spans.
|
||||
// If the span is not recording or the span context is invalid, the hook is a no-op.
|
||||
type LogrusHook struct{}
|
||||
|
||||
// Levels returns the logrus levels that this hook is interested in.
|
||||
func (h *LogrusHook) Levels() []logrus.Level {
|
||||
return logrus.AllLevels
|
||||
}
|
||||
|
||||
// Fire is called when a log event occurs.
|
||||
func (h *LogrusHook) Fire(entry *logrus.Entry) error {
|
||||
span := trace.SpanFromContext(entry.Context)
|
||||
if span == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
if !span.SpanContext().IsValid() || !span.IsRecording() {
|
||||
return nil
|
||||
}
|
||||
|
||||
span.AddEvent(
|
||||
entry.Message,
|
||||
trace.WithAttributes(logrusDataToAttrs(entry.Data)...),
|
||||
trace.WithAttributes(attribute.String("level", entry.Level.String())),
|
||||
trace.WithTimestamp(entry.Time),
|
||||
)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func logrusDataToAttrs(data logrus.Fields) []attribute.KeyValue {
|
||||
attrs := make([]attribute.KeyValue, 0, len(data))
|
||||
for k, v := range data {
|
||||
attrs = append(attrs, any(k, v))
|
||||
}
|
||||
return attrs
|
||||
}
|
116
vendor/github.com/containerd/containerd/tracing/tracing.go
generated
vendored
Normal file
116
vendor/github.com/containerd/containerd/tracing/tracing.go
generated
vendored
Normal file
@ -0,0 +1,116 @@
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package tracing
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
|
||||
"go.opentelemetry.io/otel"
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
"go.opentelemetry.io/otel/codes"
|
||||
semconv "go.opentelemetry.io/otel/semconv/v1.12.0"
|
||||
"go.opentelemetry.io/otel/trace"
|
||||
)
|
||||
|
||||
// StartConfig defines configuration for a new span object.
|
||||
type StartConfig struct {
|
||||
spanOpts []trace.SpanStartOption
|
||||
}
|
||||
|
||||
type SpanOpt func(config *StartConfig)
|
||||
|
||||
// WithHTTPRequest marks span as a HTTP request operation from client to server.
|
||||
// It'll append attributes from the HTTP request object and mark it with `SpanKindClient` type.
|
||||
func WithHTTPRequest(request *http.Request) SpanOpt {
|
||||
return func(config *StartConfig) {
|
||||
config.spanOpts = append(config.spanOpts,
|
||||
trace.WithSpanKind(trace.SpanKindClient), // A client making a request to a server
|
||||
trace.WithAttributes(semconv.HTTPClientAttributesFromHTTPRequest(request)...), // Add HTTP attributes
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// StartSpan starts child span in a context.
|
||||
func StartSpan(ctx context.Context, opName string, opts ...SpanOpt) (context.Context, *Span) {
|
||||
config := StartConfig{}
|
||||
for _, fn := range opts {
|
||||
fn(&config)
|
||||
}
|
||||
tracer := otel.Tracer("")
|
||||
if parent := trace.SpanFromContext(ctx); parent != nil && parent.SpanContext().IsValid() {
|
||||
tracer = parent.TracerProvider().Tracer("")
|
||||
}
|
||||
ctx, span := tracer.Start(ctx, opName, config.spanOpts...)
|
||||
return ctx, &Span{otelSpan: span}
|
||||
}
|
||||
|
||||
// SpanFromContext returns the current Span from the context.
|
||||
func SpanFromContext(ctx context.Context) *Span {
|
||||
return &Span{
|
||||
otelSpan: trace.SpanFromContext(ctx),
|
||||
}
|
||||
}
|
||||
|
||||
// Span is wrapper around otel trace.Span.
|
||||
// Span is the individual component of a trace. It represents a
|
||||
// single named and timed operation of a workflow that is traced.
|
||||
type Span struct {
|
||||
otelSpan trace.Span
|
||||
}
|
||||
|
||||
// End completes the span.
|
||||
func (s *Span) End() {
|
||||
s.otelSpan.End()
|
||||
}
|
||||
|
||||
// AddEvent adds an event with provided name and options.
|
||||
func (s *Span) AddEvent(name string, options ...trace.EventOption) {
|
||||
s.otelSpan.AddEvent(name, options...)
|
||||
}
|
||||
|
||||
// SetStatus sets the status of the current span.
|
||||
// If an error is encountered, it records the error and sets span status to Error.
|
||||
func (s *Span) SetStatus(err error) {
|
||||
if err != nil {
|
||||
s.otelSpan.RecordError(err)
|
||||
s.otelSpan.SetStatus(codes.Error, err.Error())
|
||||
} else {
|
||||
s.otelSpan.SetStatus(codes.Ok, "")
|
||||
}
|
||||
}
|
||||
|
||||
// SetAttributes sets kv as attributes of the span.
|
||||
func (s *Span) SetAttributes(kv ...attribute.KeyValue) {
|
||||
s.otelSpan.SetAttributes(kv...)
|
||||
}
|
||||
|
||||
// Name sets the span name by joining a list of strings in dot separated format.
|
||||
func Name(names ...string) string {
|
||||
return makeSpanName(names...)
|
||||
}
|
||||
|
||||
// Attribute takes a key value pair and returns attribute.KeyValue type.
|
||||
func Attribute(k string, v interface{}) attribute.KeyValue {
|
||||
return any(k, v)
|
||||
}
|
||||
|
||||
// HTTPStatusCodeAttributes generates attributes of the HTTP namespace as specified by the OpenTelemetry
|
||||
// specification for a span.
|
||||
func HTTPStatusCodeAttributes(code int) []attribute.KeyValue {
|
||||
return semconv.HTTPAttributesFromHTTPStatusCode(code)
|
||||
}
|
2
vendor/github.com/containerd/containerd/version/version.go
generated
vendored
2
vendor/github.com/containerd/containerd/version/version.go
generated
vendored
@ -23,7 +23,7 @@ var (
|
||||
Package = "github.com/containerd/containerd"
|
||||
|
||||
// Version holds the complete version number. Filled in at linking time.
|
||||
Version = "1.6.16+unknown"
|
||||
Version = "1.7.0-beta.3+unknown"
|
||||
|
||||
// Revision is filled with the VCS (e.g. git) revision being used to build
|
||||
// the program at linking time.
|
||||
|
Reference in New Issue
Block a user