Merge pull request #3321 from crosbymichael/ttrpc-namespace
Update ttrpc for metadata and namespace support
This commit is contained in:
commit
04e7747e29
@ -36,10 +36,9 @@ type namespaceKey struct{}
|
|||||||
// WithNamespace sets a given namespace on the context
|
// WithNamespace sets a given namespace on the context
|
||||||
func WithNamespace(ctx context.Context, namespace string) context.Context {
|
func WithNamespace(ctx context.Context, namespace string) context.Context {
|
||||||
ctx = context.WithValue(ctx, namespaceKey{}, namespace) // set our key for namespace
|
ctx = context.WithValue(ctx, namespaceKey{}, namespace) // set our key for namespace
|
||||||
|
// also store on the grpc and ttrpc headers so it gets picked up by any clients that
|
||||||
// also store on the grpc headers so it gets picked up by any clients that
|
|
||||||
// are using this.
|
// are using this.
|
||||||
return withGRPCNamespaceHeader(ctx, namespace)
|
return withTTRPCNamespaceHeader(withGRPCNamespaceHeader(ctx, namespace), namespace)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NamespaceFromEnv uses the namespace defined in CONTAINERD_NAMESPACE or
|
// NamespaceFromEnv uses the namespace defined in CONTAINERD_NAMESPACE or
|
||||||
@ -58,9 +57,10 @@ func NamespaceFromEnv(ctx context.Context) context.Context {
|
|||||||
func Namespace(ctx context.Context) (string, bool) {
|
func Namespace(ctx context.Context) (string, bool) {
|
||||||
namespace, ok := ctx.Value(namespaceKey{}).(string)
|
namespace, ok := ctx.Value(namespaceKey{}).(string)
|
||||||
if !ok {
|
if !ok {
|
||||||
return fromGRPCHeader(ctx)
|
if namespace, ok = fromGRPCHeader(ctx); !ok {
|
||||||
|
return fromTTRPCHeader(ctx)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return namespace, ok
|
return namespace, ok
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -70,10 +70,8 @@ func NamespaceRequired(ctx context.Context) (string, error) {
|
|||||||
if !ok || namespace == "" {
|
if !ok || namespace == "" {
|
||||||
return "", errors.Wrapf(errdefs.ErrFailedPrecondition, "namespace is required")
|
return "", errors.Wrapf(errdefs.ErrFailedPrecondition, "namespace is required")
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := Validate(namespace); err != nil {
|
if err := Validate(namespace); err != nil {
|
||||||
return "", errors.Wrap(err, "namespace validation")
|
return "", errors.Wrap(err, "namespace validation")
|
||||||
}
|
}
|
||||||
|
|
||||||
return namespace, nil
|
return namespace, nil
|
||||||
}
|
}
|
||||||
|
41
namespaces/ttrpc.go
Normal file
41
namespaces/ttrpc.go
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 namespaces
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"github.com/containerd/ttrpc"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// TTRPCHeader defines the header name for specifying a containerd namespace
|
||||||
|
TTRPCHeader = "containerd-namespace-ttrpc"
|
||||||
|
)
|
||||||
|
|
||||||
|
func withTTRPCNamespaceHeader(ctx context.Context, namespace string) context.Context {
|
||||||
|
md, ok := ttrpc.GetMetadata(ctx)
|
||||||
|
if !ok {
|
||||||
|
md = ttrpc.Metadata{}
|
||||||
|
}
|
||||||
|
md.Set(TTRPCHeader, namespace)
|
||||||
|
return ttrpc.WithMetadata(ctx, md)
|
||||||
|
}
|
||||||
|
|
||||||
|
func fromTTRPCHeader(ctx context.Context) (string, bool) {
|
||||||
|
return ttrpc.GetMetadataValue(ctx, TTRPCHeader)
|
||||||
|
}
|
@ -37,7 +37,7 @@ github.com/Microsoft/go-winio 84b4ab48a50763fe7b3abcef38e5205c12027fac
|
|||||||
github.com/Microsoft/hcsshim 8abdbb8205e4192c68b5f84c31197156f31be517
|
github.com/Microsoft/hcsshim 8abdbb8205e4192c68b5f84c31197156f31be517
|
||||||
google.golang.org/genproto d80a6e20e776b0b17a324d0ba1ab50a39c8e8944
|
google.golang.org/genproto d80a6e20e776b0b17a324d0ba1ab50a39c8e8944
|
||||||
golang.org/x/text 19e51611da83d6be54ddafce4a4af510cb3e9ea4
|
golang.org/x/text 19e51611da83d6be54ddafce4a4af510cb3e9ea4
|
||||||
github.com/containerd/ttrpc f82148331ad2181edea8f3f649a1f7add6c3f9c2
|
github.com/containerd/ttrpc a5bd8ce9e40bc7c065a11c6936f4d032ce6bfa2b
|
||||||
github.com/syndtr/gocapability d98352740cb2c55f81556b63d4a1ec64c5a319c2
|
github.com/syndtr/gocapability d98352740cb2c55f81556b63d4a1ec64c5a319c2
|
||||||
gotest.tools v2.3.0
|
gotest.tools v2.3.0
|
||||||
github.com/google/go-cmp v0.2.0
|
github.com/google/go-cmp v0.2.0
|
||||||
|
4
vendor/github.com/containerd/ttrpc/client.go
generated
vendored
4
vendor/github.com/containerd/ttrpc/client.go
generated
vendored
@ -99,6 +99,10 @@ func (c *Client) Call(ctx context.Context, service, method string, req, resp int
|
|||||||
cresp = &Response{}
|
cresp = &Response{}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if metadata, ok := GetMetadata(ctx); ok {
|
||||||
|
creq.Metadata = metadata
|
||||||
|
}
|
||||||
|
|
||||||
if dl, ok := ctx.Deadline(); ok {
|
if dl, ok := ctx.Deadline(); ok {
|
||||||
creq.TimeoutNano = dl.Sub(time.Now()).Nanoseconds()
|
creq.TimeoutNano = dl.Sub(time.Now()).Nanoseconds()
|
||||||
}
|
}
|
||||||
|
86
vendor/github.com/containerd/ttrpc/metadata.go
generated
vendored
Normal file
86
vendor/github.com/containerd/ttrpc/metadata.go
generated
vendored
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
/*
|
||||||
|
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 ttrpc
|
||||||
|
|
||||||
|
import "context"
|
||||||
|
|
||||||
|
// Metadata represents the key-value pairs (similar to http.Header) to be passed to ttrpc server from a client.
|
||||||
|
type Metadata map[string]StringList
|
||||||
|
|
||||||
|
// Get returns the metadata for a given key when they exist.
|
||||||
|
// If there is no metadata, a nil slice and false are returned.
|
||||||
|
func (m Metadata) Get(key string) ([]string, bool) {
|
||||||
|
list, ok := m[key]
|
||||||
|
if !ok || len(list.List) == 0 {
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
|
||||||
|
return list.List, true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set sets the provided values for a given key.
|
||||||
|
// The values will overwrite any existing values.
|
||||||
|
// If no values provided, a key will be deleted.
|
||||||
|
func (m Metadata) Set(key string, values ...string) {
|
||||||
|
if len(values) == 0 {
|
||||||
|
delete(m, key)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
m[key] = StringList{List: values}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Append appends additional values to the given key.
|
||||||
|
func (m Metadata) Append(key string, values ...string) {
|
||||||
|
if len(values) == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
list, ok := m[key]
|
||||||
|
if ok {
|
||||||
|
m.Set(key, append(list.List, values...)...)
|
||||||
|
} else {
|
||||||
|
m.Set(key, values...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type metadataKey struct{}
|
||||||
|
|
||||||
|
// GetMetadata retrieves metadata from context.Context (previously attached with WithMetadata)
|
||||||
|
func GetMetadata(ctx context.Context) (Metadata, bool) {
|
||||||
|
metadata, ok := ctx.Value(metadataKey{}).(Metadata)
|
||||||
|
return metadata, ok
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetMetadataValue gets a specific metadata value by name from context.Context
|
||||||
|
func GetMetadataValue(ctx context.Context, name string) (string, bool) {
|
||||||
|
metadata, ok := GetMetadata(ctx)
|
||||||
|
if !ok {
|
||||||
|
return "", false
|
||||||
|
}
|
||||||
|
|
||||||
|
if list, ok := metadata.Get(name); ok {
|
||||||
|
return list[0], true
|
||||||
|
}
|
||||||
|
|
||||||
|
return "", false
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithMetadata attaches metadata map to a context.Context
|
||||||
|
func WithMetadata(ctx context.Context, headers Metadata) context.Context {
|
||||||
|
return context.WithValue(ctx, metadataKey{}, headers)
|
||||||
|
}
|
4
vendor/github.com/containerd/ttrpc/server.go
generated
vendored
4
vendor/github.com/containerd/ttrpc/server.go
generated
vendored
@ -466,6 +466,10 @@ func (c *serverConn) run(sctx context.Context) {
|
|||||||
var noopFunc = func() {}
|
var noopFunc = func() {}
|
||||||
|
|
||||||
func getRequestContext(ctx context.Context, req *Request) (retCtx context.Context, cancel func()) {
|
func getRequestContext(ctx context.Context, req *Request) (retCtx context.Context, cancel func()) {
|
||||||
|
if req.Metadata != nil {
|
||||||
|
ctx = WithMetadata(ctx, req.Metadata)
|
||||||
|
}
|
||||||
|
|
||||||
cancel = noopFunc
|
cancel = noopFunc
|
||||||
if req.TimeoutNano == 0 {
|
if req.TimeoutNano == 0 {
|
||||||
return ctx, cancel
|
return ctx, cancel
|
||||||
|
11
vendor/github.com/containerd/ttrpc/types.go
generated
vendored
11
vendor/github.com/containerd/ttrpc/types.go
generated
vendored
@ -27,6 +27,7 @@ type Request struct {
|
|||||||
Method string `protobuf:"bytes,2,opt,name=method,proto3"`
|
Method string `protobuf:"bytes,2,opt,name=method,proto3"`
|
||||||
Payload []byte `protobuf:"bytes,3,opt,name=payload,proto3"`
|
Payload []byte `protobuf:"bytes,3,opt,name=payload,proto3"`
|
||||||
TimeoutNano int64 `protobuf:"varint,4,opt,name=timeout_nano,proto3"`
|
TimeoutNano int64 `protobuf:"varint,4,opt,name=timeout_nano,proto3"`
|
||||||
|
Metadata Metadata `protobuf:"bytes,5,opt,name=metadata,proto3" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Request) Reset() { *r = Request{} }
|
func (r *Request) Reset() { *r = Request{} }
|
||||||
@ -41,3 +42,13 @@ type Response struct {
|
|||||||
func (r *Response) Reset() { *r = Response{} }
|
func (r *Response) Reset() { *r = Response{} }
|
||||||
func (r *Response) String() string { return fmt.Sprintf("%+#v", r) }
|
func (r *Response) String() string { return fmt.Sprintf("%+#v", r) }
|
||||||
func (r *Response) ProtoMessage() {}
|
func (r *Response) ProtoMessage() {}
|
||||||
|
|
||||||
|
type StringList struct {
|
||||||
|
List []string `protobuf:"bytes,1,rep,name=list,proto3"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *StringList) Reset() { *r = StringList{} }
|
||||||
|
func (r *StringList) String() string { return fmt.Sprintf("%+#v", r) }
|
||||||
|
func (r *StringList) ProtoMessage() {}
|
||||||
|
|
||||||
|
func makeStringList(item ...string) StringList { return StringList{List: item} }
|
||||||
|
Loading…
Reference in New Issue
Block a user